2 Copyright (C) 1996-1997 Id Software, Inc.
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26 mempool_t *r_main_mempool;
27 rtexturepool_t *r_main_texturepool;
34 r_viewcache_t r_viewcache;
36 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
37 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%, 10 = 100%)"};
38 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
39 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
40 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
41 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
42 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
43 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
44 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
45 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
46 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
47 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
48 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
49 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
50 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
51 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling"};
52 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
53 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
54 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
55 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
56 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
57 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
58 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
59 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this)"};
60 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
61 cvar_t r_q1bsp_skymasking = {0, "r_qb1sp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
63 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
64 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
65 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
66 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
67 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
68 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
69 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
71 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of hardware texture units reported by driver (note: setting this to 1 turns off gl_combine)"};
73 cvar_t r_glsl = {CVAR_SAVE, "r_glsl", "1", "enables use of OpenGL 2.0 pixel shaders for lighting"};
74 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
75 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
76 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
77 cvar_t r_glsl_deluxemapping = {CVAR_SAVE, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"};
79 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1", "enables animation smoothing on sprites (requires r_lerpmodels 1)"};
80 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
81 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
83 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
84 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
85 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
86 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
87 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
88 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
89 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
91 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
92 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
93 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
94 cvar_t r_hdr_range = {CVAR_SAVE, "r_hdr_range", "4", "how much dynamic range to render bloom with (equivilant to multiplying r_bloom_brighten by this value and dividing r_bloom_colorscale by this value)"};
96 cvar_t r_smoothnormals_areaweighting = {0, "r_smoothnormals_areaweighting", "1", "uses significantly faster (and supposedly higher quality) area-weighted vertex normals and tangent vectors rather than summing normalized triangle normals and tangents"};
98 cvar_t developer_texturelogging = {0, "developer_texturelogging", "0", "produces a textures.log file containing names of skins and map textures the engine tried to load"};
100 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
102 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
103 cvar_t r_batchmode = {0, "r_batchmode", "1", "selects method of rendering multiple surfaces with one driver call (values are 0, 1, 2, etc...)"};
105 typedef struct r_glsl_bloomshader_s
108 int loc_Texture_Bloom;
110 r_glsl_bloomshader_t;
112 static struct r_bloomstate_s
117 int bloomwidth, bloomheight;
119 int screentexturewidth, screentextureheight;
120 rtexture_t *texture_screen;
122 int bloomtexturewidth, bloomtextureheight;
123 rtexture_t *texture_bloom;
125 r_glsl_bloomshader_t *shader;
127 // arrays for rendering the screen passes
128 float screentexcoord2f[8];
129 float bloomtexcoord2f[8];
130 float offsettexcoord2f[8];
134 // shadow volume bsp struct with automatically growing nodes buffer
137 rtexture_t *r_texture_blanknormalmap;
138 rtexture_t *r_texture_white;
139 rtexture_t *r_texture_black;
140 rtexture_t *r_texture_notexture;
141 rtexture_t *r_texture_whitecube;
142 rtexture_t *r_texture_normalizationcube;
143 rtexture_t *r_texture_fogattenuation;
144 //rtexture_t *r_texture_fogintensity;
146 // information about each possible shader permutation
147 r_glsl_permutation_t r_glsl_permutations[SHADERPERMUTATION_MAX];
148 // currently selected permutation
149 r_glsl_permutation_t *r_glsl_permutation;
151 // vertex coordinates for a quad that covers the screen exactly
152 const static float r_screenvertex3f[12] =
160 extern void R_DrawModelShadows(void);
162 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
165 for (i = 0;i < verts;i++)
176 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
179 for (i = 0;i < verts;i++)
189 // FIXME: move this to client?
192 if (gamemode == GAME_NEHAHRA)
194 Cvar_Set("gl_fogenable", "0");
195 Cvar_Set("gl_fogdensity", "0.2");
196 Cvar_Set("gl_fogred", "0.3");
197 Cvar_Set("gl_foggreen", "0.3");
198 Cvar_Set("gl_fogblue", "0.3");
200 r_refdef.fog_density = r_refdef.fog_red = r_refdef.fog_green = r_refdef.fog_blue = 0.0f;
203 float FogPoint_World(const vec3_t p)
205 int fogmasktableindex = (int)(VectorDistance((p), r_view.origin) * r_refdef.fogmasktabledistmultiplier);
206 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
209 float FogPoint_Model(const vec3_t p)
211 int fogmasktableindex = (int)(VectorDistance((p), rsurface_modelorg) * r_refdef.fogmasktabledistmultiplier);
212 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
215 static void R_BuildBlankTextures(void)
217 unsigned char data[4];
218 data[0] = 128; // normal X
219 data[1] = 128; // normal Y
220 data[2] = 255; // normal Z
221 data[3] = 128; // height
222 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
227 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
232 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
235 static void R_BuildNoTexture(void)
238 unsigned char pix[16][16][4];
239 // this makes a light grey/dark grey checkerboard texture
240 for (y = 0;y < 16;y++)
242 for (x = 0;x < 16;x++)
244 if ((y < 8) ^ (x < 8))
260 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_RGBA, TEXF_MIPMAP, NULL);
263 static void R_BuildWhiteCube(void)
265 unsigned char data[6*1*1*4];
266 data[ 0] = 255;data[ 1] = 255;data[ 2] = 255;data[ 3] = 255;
267 data[ 4] = 255;data[ 5] = 255;data[ 6] = 255;data[ 7] = 255;
268 data[ 8] = 255;data[ 9] = 255;data[10] = 255;data[11] = 255;
269 data[12] = 255;data[13] = 255;data[14] = 255;data[15] = 255;
270 data[16] = 255;data[17] = 255;data[18] = 255;data[19] = 255;
271 data[20] = 255;data[21] = 255;data[22] = 255;data[23] = 255;
272 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
275 static void R_BuildNormalizationCube(void)
279 vec_t s, t, intensity;
281 unsigned char data[6][NORMSIZE][NORMSIZE][4];
282 for (side = 0;side < 6;side++)
284 for (y = 0;y < NORMSIZE;y++)
286 for (x = 0;x < NORMSIZE;x++)
288 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
289 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
324 intensity = 127.0f / sqrt(DotProduct(v, v));
325 data[side][y][x][0] = (unsigned char)(128.0f + intensity * v[0]);
326 data[side][y][x][1] = (unsigned char)(128.0f + intensity * v[1]);
327 data[side][y][x][2] = (unsigned char)(128.0f + intensity * v[2]);
328 data[side][y][x][3] = 255;
332 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, &data[0][0][0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
335 static void R_BuildFogTexture(void)
339 unsigned char data1[FOGWIDTH][4];
340 //unsigned char data2[FOGWIDTH][4];
341 for (x = 0;x < FOGWIDTH;x++)
343 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
348 //data2[x][0] = 255 - b;
349 //data2[x][1] = 255 - b;
350 //data2[x][2] = 255 - b;
353 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
354 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
357 static const char *builtinshaderstring =
358 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
359 "// written by Forest 'LordHavoc' Hale\n"
361 "// common definitions between vertex shader and fragment shader:\n"
363 "#ifdef __GLSL_CG_DATA_TYPES\n"
364 "#define myhalf half\n"
365 "#define myhvec2 hvec2\n"
366 "#define myhvec3 hvec3\n"
367 "#define myhvec4 hvec4\n"
369 "#define myhalf float\n"
370 "#define myhvec2 vec2\n"
371 "#define myhvec3 vec3\n"
372 "#define myhvec4 vec4\n"
375 "varying vec2 TexCoord;\n"
376 "varying vec2 TexCoordLightmap;\n"
378 "varying vec3 CubeVector;\n"
379 "varying vec3 LightVector;\n"
380 "varying vec3 EyeVector;\n"
382 "varying vec3 EyeVectorModelSpace;\n"
385 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
386 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
387 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
392 "// vertex shader specific:\n"
393 "#ifdef VERTEX_SHADER\n"
395 "uniform vec3 LightPosition;\n"
396 "uniform vec3 EyePosition;\n"
397 "uniform vec3 LightDir;\n"
399 "// TODO: get rid of tangentt (texcoord2) and use a crossproduct to regenerate it from tangents (texcoord1) and normal (texcoord3)\n"
403 " gl_FrontColor = gl_Color;\n"
404 " // copy the surface texcoord\n"
405 " TexCoord = vec2(gl_TextureMatrix[0] * gl_MultiTexCoord0);\n"
406 "#if !defined(MODE_LIGHTSOURCE) && !defined(MODE_LIGHTDIRECTION)\n"
407 " TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
410 "#ifdef MODE_LIGHTSOURCE\n"
411 " // transform vertex position into light attenuation/cubemap space\n"
412 " // (-1 to +1 across the light box)\n"
413 " CubeVector = vec3(gl_TextureMatrix[3] * gl_Vertex);\n"
415 " // transform unnormalized light direction into tangent space\n"
416 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
417 " // normalize it per pixel)\n"
418 " vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
419 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
420 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
421 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
424 "#ifdef MODE_LIGHTDIRECTION\n"
425 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
426 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
427 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
430 " // transform unnormalized eye direction into tangent space\n"
432 " vec3 EyeVectorModelSpace;\n"
434 " EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
435 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
436 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
437 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
439 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
440 " VectorS = gl_MultiTexCoord1.xyz;\n"
441 " VectorT = gl_MultiTexCoord2.xyz;\n"
442 " VectorR = gl_MultiTexCoord3.xyz;\n"
445 " // transform vertex to camera space, using ftransform to match non-VS\n"
447 " gl_Position = ftransform();\n"
450 "#endif // VERTEX_SHADER\n"
455 "// fragment shader specific:\n"
456 "#ifdef FRAGMENT_SHADER\n"
458 "// 11 textures, we can only use up to 16 on DX9-class hardware\n"
459 "uniform sampler2D Texture_Normal;\n"
460 "uniform sampler2D Texture_Color;\n"
461 "uniform sampler2D Texture_Gloss;\n"
462 "uniform samplerCube Texture_Cube;\n"
463 "uniform sampler2D Texture_Attenuation;\n"
464 "uniform sampler2D Texture_FogMask;\n"
465 "uniform sampler2D Texture_Pants;\n"
466 "uniform sampler2D Texture_Shirt;\n"
467 "uniform sampler2D Texture_Lightmap;\n"
468 "uniform sampler2D Texture_Deluxemap;\n"
469 "uniform sampler2D Texture_Glow;\n"
471 "uniform myhvec3 LightColor;\n"
472 "uniform myhvec3 AmbientColor;\n"
473 "uniform myhvec3 DiffuseColor;\n"
474 "uniform myhvec3 SpecularColor;\n"
475 "uniform myhvec3 Color_Pants;\n"
476 "uniform myhvec3 Color_Shirt;\n"
477 "uniform myhvec3 FogColor;\n"
479 "uniform myhalf GlowScale;\n"
480 "uniform myhalf SceneBrightness;\n"
482 "uniform float OffsetMapping_Scale;\n"
483 "uniform float OffsetMapping_Bias;\n"
484 "uniform float FogRangeRecip;\n"
486 "uniform myhalf AmbientScale;\n"
487 "uniform myhalf DiffuseScale;\n"
488 "uniform myhalf SpecularScale;\n"
489 "uniform myhalf SpecularPower;\n"
491 "#ifdef USEOFFSETMAPPING\n"
492 "vec2 OffsetMapping(vec2 TexCoord)\n"
494 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
495 " // 14 sample relief mapping: linear search and then binary search\n"
496 " // this basically steps forward a small amount repeatedly until it finds\n"
497 " // itself inside solid, then jitters forward and back using decreasing\n"
498 " // amounts to find the impact\n"
499 " //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
500 " //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
501 " vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
502 " vec3 RT = vec3(TexCoord, 1);\n"
503 " OffsetVector *= 0.1;\n"
504 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
505 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
506 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
507 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
508 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
509 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
510 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
511 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
512 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
513 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) - 0.5);\n"
514 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5 - 0.25);\n"
515 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25 - 0.125);\n"
516 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125 - 0.0625);\n"
517 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
520 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
521 " // this basically moves forward the full distance, and then backs up based\n"
522 " // on height of samples\n"
523 " //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
524 " //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
525 " vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
526 " TexCoord += OffsetVector;\n"
527 " OffsetVector *= 0.333;\n"
528 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
529 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
530 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
531 " return TexCoord;\n"
538 "#ifdef USEOFFSETMAPPING\n"
539 " // apply offsetmapping\n"
540 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
541 "#define TexCoord TexCoordOffset\n"
544 " // combine the diffuse textures (base, pants, shirt)\n"
545 " myhvec4 color = myhvec4(texture2D(Texture_Color, TexCoord));\n"
546 "#ifdef USECOLORMAPPING\n"
547 " color.rgb += myhvec3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhvec3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
553 "#ifdef MODE_LIGHTSOURCE\n"
556 " // calculate surface normal, light normal, and specular normal\n"
557 " // compute color intensity for the two textures (colormap and glossmap)\n"
558 " // scale by light color and attenuation as efficiently as possible\n"
559 " // (do as much scalar math as possible rather than vector math)\n"
560 "#ifdef USESPECULAR\n"
561 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
562 " myhvec3 diffusenormal = myhvec3(normalize(LightVector));\n"
563 " myhvec3 specularnormal = normalize(diffusenormal + myhvec3(normalize(EyeVector)));\n"
565 " // calculate directional shading\n"
566 " color.rgb = LightColor * myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0))) * (color.rgb * (AmbientScale + DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0))) + (SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower)) * myhvec3(texture2D(Texture_Gloss, TexCoord)));\n"
568 "#ifdef USEDIFFUSE\n"
569 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
570 " myhvec3 diffusenormal = myhvec3(normalize(LightVector));\n"
572 " // calculate directional shading\n"
573 " color.rgb = color.rgb * LightColor * (myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0))) * (AmbientScale + DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0))));\n"
575 " // calculate directionless shading\n"
576 " color.rgb = color.rgb * LightColor * myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
580 "#ifdef USECUBEFILTER\n"
581 " // apply light cubemap filter\n"
582 " //color.rgb *= normalize(CubeVector) * 0.5 + 0.5;//vec3(textureCube(Texture_Cube, CubeVector));\n"
583 " color.rgb *= myhvec3(textureCube(Texture_Cube, CubeVector));\n"
589 "#elif defined(MODE_LIGHTDIRECTION)\n"
590 " // directional model lighting\n"
592 " // get the surface normal and light normal\n"
593 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
594 " myhvec3 diffusenormal = myhvec3(normalize(LightVector));\n"
596 " // calculate directional shading\n"
597 " color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
598 "#ifdef USESPECULAR\n"
599 " myhvec3 specularnormal = normalize(diffusenormal + myhvec3(normalize(EyeVector)));\n"
600 " color.rgb += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
606 "#elif defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
607 " // deluxemap lightmapping using light vectors in modelspace (evil q3map2)\n"
609 " // get the surface normal and light normal\n"
610 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
612 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
613 " myhvec3 diffusenormal_modelspace = myhvec3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - myhvec3(0.5);\n"
614 " myhvec3 diffusenormal = normalize(myhvec3(dot(diffusenormal_modelspace, myhvec3(VectorS)), dot(diffusenormal_modelspace, myhvec3(VectorT)), dot(diffusenormal_modelspace, myhvec3(VectorR))));\n"
616 " myhvec3 diffusenormal = normalize(myhvec3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - myhvec3(0.5));\n"
618 " // calculate directional shading\n"
619 " myhvec3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0)));\n"
620 "#ifdef USESPECULAR\n"
621 " myhvec3 specularnormal = myhvec3(normalize(diffusenormal + myhvec3(normalize(EyeVector))));\n"
622 " tempcolor += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
625 " // apply lightmap color\n"
626 " color.rgb = tempcolor * myhvec3(texture2D(Texture_Lightmap, TexCoordLightmap)) + color.rgb * AmbientScale;\n"
629 "#else // MODE none (lightmap)\n"
630 " // apply lightmap color\n"
631 " color.rgb *= myhvec3(texture2D(Texture_Lightmap, TexCoordLightmap)) * DiffuseScale + myhvec3(AmbientScale);\n"
634 " color *= myhvec4(gl_Color);\n"
637 " color.rgb += myhvec3(texture2D(Texture_Glow, TexCoord)) * GlowScale;\n"
642 " color.rgb = mix(FogColor, color.rgb, myhalf(texture2D(Texture_FogMask, myhvec2(length(EyeVectorModelSpace)*FogRangeRecip, 0.0))));\n"
645 " color.rgb *= SceneBrightness;\n"
647 " gl_FragColor = vec4(color);\n"
650 "#endif // FRAGMENT_SHADER\n"
653 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
654 const char *permutationinfo[][2] =
656 {"#define MODE_LIGHTSOURCE\n", " lightsource"},
657 {"#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
658 {"#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
659 {"#define MODE_LIGHTDIRECTION\n", " lightdirection"},
660 {"#define USEGLOW\n", " glow"},
661 {"#define USEFOG\n", " fog"},
662 {"#define USECOLORMAPPING\n", " colormapping"},
663 {"#define USEDIFFUSE\n", " diffuse"},
664 {"#define USESPECULAR\n", " specular"},
665 {"#define USECUBEFILTER\n", " cubefilter"},
666 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
667 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
671 void R_GLSL_CompilePermutation(const char *filename, int permutation)
674 qboolean shaderfound;
675 r_glsl_permutation_t *p = r_glsl_permutations + (permutation & SHADERPERMUTATION_MASK);
676 int vertstrings_count;
677 int geomstrings_count;
678 int fragstrings_count;
680 const char *vertstrings_list[32+1];
681 const char *geomstrings_list[32+1];
682 const char *fragstrings_list[32+1];
683 char permutationname[256];
688 vertstrings_list[0] = "#define VERTEX_SHADER\n";
689 geomstrings_list[0] = "#define GEOMETRY_SHADER\n";
690 fragstrings_list[0] = "#define FRAGMENT_SHADER\n";
691 vertstrings_count = 1;
692 geomstrings_count = 1;
693 fragstrings_count = 1;
694 permutationname[0] = 0;
695 for (i = 0;permutationinfo[i][0];i++)
697 if (permutation & (1<<i))
699 vertstrings_list[vertstrings_count++] = permutationinfo[i][0];
700 geomstrings_list[geomstrings_count++] = permutationinfo[i][0];
701 fragstrings_list[fragstrings_count++] = permutationinfo[i][0];
702 strlcat(permutationname, permutationinfo[i][1], sizeof(permutationname));
706 // keep line numbers correct
707 vertstrings_list[vertstrings_count++] = "\n";
708 geomstrings_list[geomstrings_count++] = "\n";
709 fragstrings_list[fragstrings_count++] = "\n";
712 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
716 Con_DPrintf("GLSL shader text for \"%s\" loaded from disk\n", filename);
717 vertstrings_list[vertstrings_count++] = shaderstring;
718 geomstrings_list[geomstrings_count++] = shaderstring;
719 fragstrings_list[fragstrings_count++] = shaderstring;
722 else if (!strcmp(filename, "glsl/default.glsl"))
724 Con_DPrintf("GLSL shader text for \"%s\" loaded from engine\n", filename);
725 vertstrings_list[vertstrings_count++] = builtinshaderstring;
726 geomstrings_list[geomstrings_count++] = builtinshaderstring;
727 fragstrings_list[fragstrings_count++] = builtinshaderstring;
730 // clear any lists that are not needed by this shader
731 if (!(permutation & SHADERPERMUTATION_USES_VERTEXSHADER))
732 vertstrings_count = 0;
733 if (!(permutation & SHADERPERMUTATION_USES_GEOMETRYSHADER))
734 geomstrings_count = 0;
735 if (!(permutation & SHADERPERMUTATION_USES_FRAGMENTSHADER))
736 fragstrings_count = 0;
737 // compile the shader program
738 if (shaderfound && vertstrings_count + geomstrings_count + fragstrings_count)
739 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
743 qglUseProgramObjectARB(p->program);CHECKGLERROR
744 // look up all the uniform variable names we care about, so we don't
745 // have to look them up every time we set them
746 p->loc_Texture_Normal = qglGetUniformLocationARB(p->program, "Texture_Normal");
747 p->loc_Texture_Color = qglGetUniformLocationARB(p->program, "Texture_Color");
748 p->loc_Texture_Gloss = qglGetUniformLocationARB(p->program, "Texture_Gloss");
749 p->loc_Texture_Cube = qglGetUniformLocationARB(p->program, "Texture_Cube");
750 p->loc_Texture_Attenuation = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
751 p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
752 p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
753 p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
754 p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
755 p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
756 p->loc_Texture_Glow = qglGetUniformLocationARB(p->program, "Texture_Glow");
757 p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
758 p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
759 p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
760 p->loc_LightColor = qglGetUniformLocationARB(p->program, "LightColor");
761 p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants");
762 p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt");
763 p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip");
764 p->loc_AmbientScale = qglGetUniformLocationARB(p->program, "AmbientScale");
765 p->loc_DiffuseScale = qglGetUniformLocationARB(p->program, "DiffuseScale");
766 p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
767 p->loc_SpecularScale = qglGetUniformLocationARB(p->program, "SpecularScale");
768 p->loc_GlowScale = qglGetUniformLocationARB(p->program, "GlowScale");
769 p->loc_SceneBrightness = qglGetUniformLocationARB(p->program, "SceneBrightness");
770 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
771 p->loc_AmbientColor = qglGetUniformLocationARB(p->program, "AmbientColor");
772 p->loc_DiffuseColor = qglGetUniformLocationARB(p->program, "DiffuseColor");
773 p->loc_SpecularColor = qglGetUniformLocationARB(p->program, "SpecularColor");
774 p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
775 // initialize the samplers to refer to the texture units we use
776 if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal, 0);
777 if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color, 1);
778 if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss, 2);
779 if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube, 3);
780 if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask, 4);
781 if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants, 5);
782 if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt, 6);
783 if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap, 7);
784 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap, 8);
785 if (p->loc_Texture_Glow >= 0) qglUniform1iARB(p->loc_Texture_Glow, 9);
786 if (p->loc_Texture_Attenuation >= 0) qglUniform1iARB(p->loc_Texture_Attenuation, 10);
788 qglUseProgramObjectARB(0);CHECKGLERROR
791 Con_Printf("permutation%s failed for shader %s, some features may not work properly!\n", permutationname, "glsl/default.glsl");
793 Mem_Free(shaderstring);
796 void R_GLSL_Restart_f(void)
799 for (i = 0;i < SHADERPERMUTATION_MAX;i++)
800 if (r_glsl_permutations[i].program)
801 GL_Backend_FreeProgram(r_glsl_permutations[i].program);
802 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
805 extern rtexture_t *r_shadow_attenuationgradienttexture;
806 extern rtexture_t *r_shadow_attenuation2dtexture;
807 extern rtexture_t *r_shadow_attenuation3dtexture;
808 int R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale)
810 // select a permutation of the lighting shader appropriate to this
811 // combination of texture, entity, light source, and fogging, only use the
812 // minimum features necessary to avoid wasting rendering time in the
813 // fragment shader on features that are not being used
814 const char *shaderfilename = NULL;
815 unsigned int permutation = 0;
816 r_glsl_permutation = NULL;
817 // TODO: implement geometry-shader based shadow volumes someday
818 if (r_shadow_rtlight)
821 shaderfilename = "glsl/default.glsl";
822 permutation = SHADERPERMUTATION_MODE_LIGHTSOURCE | SHADERPERMUTATION_USES_VERTEXSHADER | SHADERPERMUTATION_USES_FRAGMENTSHADER;
823 if (r_shadow_rtlight->currentcubemap != r_texture_whitecube)
824 permutation |= SHADERPERMUTATION_CUBEFILTER;
825 if (diffusescale > 0)
826 permutation |= SHADERPERMUTATION_DIFFUSE;
827 if (specularscale > 0)
828 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
829 if (r_refdef.fogenabled)
830 permutation |= SHADERPERMUTATION_FOG;
831 if (rsurface_texture->colormapping)
832 permutation |= SHADERPERMUTATION_COLORMAPPING;
833 if (r_glsl_offsetmapping.integer)
835 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
836 if (r_glsl_offsetmapping_reliefmapping.integer)
837 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
840 else if (rsurface_texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
842 // bright unshaded geometry
843 shaderfilename = "glsl/default.glsl";
844 permutation = SHADERPERMUTATION_USES_VERTEXSHADER | SHADERPERMUTATION_USES_FRAGMENTSHADER;
845 if (rsurface_texture->currentskinframe->glow)
846 permutation |= SHADERPERMUTATION_GLOW;
847 if (r_refdef.fogenabled)
848 permutation |= SHADERPERMUTATION_FOG;
849 if (rsurface_texture->colormapping)
850 permutation |= SHADERPERMUTATION_COLORMAPPING;
851 if (r_glsl_offsetmapping.integer)
853 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
854 if (r_glsl_offsetmapping_reliefmapping.integer)
855 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
858 else if (modellighting)
860 // directional model lighting
861 shaderfilename = "glsl/default.glsl";
862 permutation = SHADERPERMUTATION_USES_VERTEXSHADER | SHADERPERMUTATION_USES_FRAGMENTSHADER;
863 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTION;
864 if (rsurface_texture->currentskinframe->glow)
865 permutation |= SHADERPERMUTATION_GLOW;
866 if (specularscale > 0)
867 permutation |= SHADERPERMUTATION_SPECULAR;
868 if (r_refdef.fogenabled)
869 permutation |= SHADERPERMUTATION_FOG;
870 if (rsurface_texture->colormapping)
871 permutation |= SHADERPERMUTATION_COLORMAPPING;
872 if (r_glsl_offsetmapping.integer)
874 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
875 if (r_glsl_offsetmapping_reliefmapping.integer)
876 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
882 shaderfilename = "glsl/default.glsl";
883 permutation = SHADERPERMUTATION_USES_VERTEXSHADER | SHADERPERMUTATION_USES_FRAGMENTSHADER;
884 if (r_glsl_deluxemapping.integer >= 1 && rsurface_uselightmaptexture && r_refdef.worldmodel && r_refdef.worldmodel->brushq3.deluxemapping)
886 // deluxemapping (light direction texture)
887 if (rsurface_uselightmaptexture && r_refdef.worldmodel && r_refdef.worldmodel->brushq3.deluxemapping && r_refdef.worldmodel->brushq3.deluxemapping_modelspace)
888 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_MODELSPACE;
890 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
891 if (specularscale > 0)
892 permutation |= SHADERPERMUTATION_SPECULAR;
894 else if (r_glsl_deluxemapping.integer >= 2)
896 // fake deluxemapping (uniform light direction in tangentspace)
897 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
898 if (specularscale > 0)
899 permutation |= SHADERPERMUTATION_SPECULAR;
903 // ordinary lightmapping
906 if (rsurface_texture->currentskinframe->glow)
907 permutation |= SHADERPERMUTATION_GLOW;
908 if (r_refdef.fogenabled)
909 permutation |= SHADERPERMUTATION_FOG;
910 if (rsurface_texture->colormapping)
911 permutation |= SHADERPERMUTATION_COLORMAPPING;
912 if (r_glsl_offsetmapping.integer)
914 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
915 if (r_glsl_offsetmapping_reliefmapping.integer)
916 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
919 if (!r_glsl_permutations[permutation & SHADERPERMUTATION_MASK].program)
921 if (!r_glsl_permutations[permutation & SHADERPERMUTATION_MASK].compiled)
922 R_GLSL_CompilePermutation(shaderfilename, permutation);
923 if (!r_glsl_permutations[permutation & SHADERPERMUTATION_MASK].program)
925 // remove features until we find a valid permutation
927 for (i = SHADERPERMUTATION_MASK;;i>>=1)
930 return 0; // utterly failed
931 // reduce i more quickly whenever it would not remove any bits
935 if (!r_glsl_permutations[permutation & SHADERPERMUTATION_MASK].compiled)
936 R_GLSL_CompilePermutation(shaderfilename, permutation);
937 if (r_glsl_permutations[permutation & SHADERPERMUTATION_MASK].program)
942 r_glsl_permutation = r_glsl_permutations + (permutation & SHADERPERMUTATION_MASK);
944 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
945 R_Mesh_TexMatrix(0, &rsurface_texture->currenttexmatrix);
946 if (permutation & SHADERPERMUTATION_MODE_LIGHTSOURCE)
948 if (r_glsl_permutation->loc_Texture_Cube >= 0 && r_shadow_rtlight) R_Mesh_TexBindCubeMap(3, R_GetTexture(r_shadow_rtlight->currentcubemap));
949 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, r_shadow_entitylightorigin[0], r_shadow_entitylightorigin[1], r_shadow_entitylightorigin[2]);
950 if (permutation & SHADERPERMUTATION_DIFFUSE)
952 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
953 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, ambientscale);
954 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, diffusescale);
955 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, specularscale);
959 // ambient only is simpler
960 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0] * ambientscale, lightcolorbase[1] * ambientscale, lightcolorbase[2] * ambientscale);
961 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, 1);
962 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, 0);
963 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, 0);
966 else if (permutation & SHADERPERMUTATION_MODE_LIGHTDIRECTION)
968 if (r_glsl_permutation->loc_AmbientColor >= 0)
969 qglUniform3fARB(r_glsl_permutation->loc_AmbientColor, rsurface_entity->modellight_ambient[0] * ambientscale, rsurface_entity->modellight_ambient[1] * ambientscale, rsurface_entity->modellight_ambient[2] * ambientscale);
970 if (r_glsl_permutation->loc_DiffuseColor >= 0)
971 qglUniform3fARB(r_glsl_permutation->loc_DiffuseColor, rsurface_entity->modellight_diffuse[0] * diffusescale, rsurface_entity->modellight_diffuse[1] * diffusescale, rsurface_entity->modellight_diffuse[2] * diffusescale);
972 if (r_glsl_permutation->loc_SpecularColor >= 0)
973 qglUniform3fARB(r_glsl_permutation->loc_SpecularColor, rsurface_entity->modellight_diffuse[0] * specularscale, rsurface_entity->modellight_diffuse[1] * specularscale, rsurface_entity->modellight_diffuse[2] * specularscale);
974 if (r_glsl_permutation->loc_LightDir >= 0)
975 qglUniform3fARB(r_glsl_permutation->loc_LightDir, rsurface_entity->modellight_lightdir[0], rsurface_entity->modellight_lightdir[1], rsurface_entity->modellight_lightdir[2]);
979 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_ambient.value * 2.0f / 128.0f);
980 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_refdef.lightmapintensity * 2.0f);
981 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, r_refdef.lightmapintensity * specularscale * 2.0f);
983 if (r_glsl_permutation->loc_Texture_Normal >= 0) R_Mesh_TexBind(0, R_GetTexture(rsurface_texture->currentskinframe->nmap));
984 if (r_glsl_permutation->loc_Texture_Color >= 0) R_Mesh_TexBind(1, R_GetTexture(rsurface_texture->basetexture));
985 if (r_glsl_permutation->loc_Texture_Gloss >= 0) R_Mesh_TexBind(2, R_GetTexture(rsurface_texture->glosstexture));
986 //if (r_glsl_permutation->loc_Texture_Cube >= 0 && permutation & SHADERPERMUTATION_MODE_LIGHTSOURCE) R_Mesh_TexBindCubeMap(3, R_GetTexture(r_shadow_rtlight->currentcubemap));
987 if (r_glsl_permutation->loc_Texture_Attenuation >= 0) R_Mesh_TexBind(10, R_GetTexture(r_shadow_attenuationgradienttexture));
988 if (r_glsl_permutation->loc_Texture_FogMask >= 0) R_Mesh_TexBind(4, R_GetTexture(r_texture_fogattenuation));
989 if (r_glsl_permutation->loc_Texture_Pants >= 0) R_Mesh_TexBind(5, R_GetTexture(rsurface_texture->currentskinframe->pants));
990 if (r_glsl_permutation->loc_Texture_Shirt >= 0) R_Mesh_TexBind(6, R_GetTexture(rsurface_texture->currentskinframe->shirt));
991 //if (r_glsl_permutation->loc_Texture_Lightmap >= 0) R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
992 //if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
993 if (r_glsl_permutation->loc_Texture_Glow >= 0) R_Mesh_TexBind(9, R_GetTexture(rsurface_texture->currentskinframe->glow));
994 if (r_glsl_permutation->loc_GlowScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_GlowScale, r_hdr_glowintensity.value);
995 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_view.colorscale);
996 if (r_glsl_permutation->loc_FogColor >= 0)
998 // additive passes are only darkened by fog, not tinted
999 if (r_shadow_rtlight || (rsurface_texture->currentmaterialflags & MATERIALFLAG_ADD))
1000 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
1002 qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
1004 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface_modelorg[0], rsurface_modelorg[1], rsurface_modelorg[2]);
1005 if (r_glsl_permutation->loc_Color_Pants >= 0)
1007 if (rsurface_texture->currentskinframe->pants)
1008 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface_entity->colormap_pantscolor[0], rsurface_entity->colormap_pantscolor[1], rsurface_entity->colormap_pantscolor[2]);
1010 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
1012 if (r_glsl_permutation->loc_Color_Shirt >= 0)
1014 if (rsurface_texture->currentskinframe->shirt)
1015 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface_entity->colormap_shirtcolor[0], rsurface_entity->colormap_shirtcolor[1], rsurface_entity->colormap_shirtcolor[2]);
1017 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
1019 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, r_refdef.fograngerecip);
1020 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface_texture->specularpower);
1021 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
1026 void R_SwitchSurfaceShader(int permutation)
1028 if (r_glsl_permutation != r_glsl_permutations + (permutation & SHADERPERMUTATION_MASK))
1030 r_glsl_permutation = r_glsl_permutations + (permutation & SHADERPERMUTATION_MASK);
1032 qglUseProgramObjectARB(r_glsl_permutation->program);
1037 void gl_main_start(void)
1042 r = (-1.0/256.0) * (FOGMASKTABLEWIDTH * FOGMASKTABLEWIDTH);
1043 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
1045 alpha = 1 - exp(r / ((double)x*(double)x));
1046 if (x == FOGMASKTABLEWIDTH - 1)
1048 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
1051 r_main_texturepool = R_AllocTexturePool();
1052 R_BuildBlankTextures();
1054 if (gl_texturecubemap)
1057 R_BuildNormalizationCube();
1059 R_BuildFogTexture();
1060 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
1061 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
1062 memset(&r_svbsp, 0, sizeof (r_svbsp));
1065 void gl_main_shutdown(void)
1068 Mem_Free(r_svbsp.nodes);
1069 memset(&r_svbsp, 0, sizeof (r_svbsp));
1070 R_FreeTexturePool(&r_main_texturepool);
1071 r_texture_blanknormalmap = NULL;
1072 r_texture_white = NULL;
1073 r_texture_black = NULL;
1074 r_texture_whitecube = NULL;
1075 r_texture_normalizationcube = NULL;
1076 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
1080 extern void CL_ParseEntityLump(char *entitystring);
1081 void gl_main_newmap(void)
1083 // FIXME: move this code to client
1085 char *entities, entname[MAX_QPATH];
1088 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
1089 l = (int)strlen(entname) - 4;
1090 if (l >= 0 && !strcmp(entname + l, ".bsp"))
1092 memcpy(entname + l, ".ent", 5);
1093 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
1095 CL_ParseEntityLump(entities);
1100 if (cl.worldmodel->brush.entities)
1101 CL_ParseEntityLump(cl.worldmodel->brush.entities);
1105 void GL_Main_Init(void)
1107 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
1109 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
1110 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
1111 if (gamemode == GAME_NEHAHRA)
1113 Cvar_RegisterVariable (&gl_fogenable);
1114 Cvar_RegisterVariable (&gl_fogdensity);
1115 Cvar_RegisterVariable (&gl_fogred);
1116 Cvar_RegisterVariable (&gl_foggreen);
1117 Cvar_RegisterVariable (&gl_fogblue);
1118 Cvar_RegisterVariable (&gl_fogstart);
1119 Cvar_RegisterVariable (&gl_fogend);
1121 Cvar_RegisterVariable(&r_nearclip);
1122 Cvar_RegisterVariable(&r_showbboxes);
1123 Cvar_RegisterVariable(&r_showsurfaces);
1124 Cvar_RegisterVariable(&r_showtris);
1125 Cvar_RegisterVariable(&r_shownormals);
1126 Cvar_RegisterVariable(&r_showlighting);
1127 Cvar_RegisterVariable(&r_showshadowvolumes);
1128 Cvar_RegisterVariable(&r_showcollisionbrushes);
1129 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
1130 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
1131 Cvar_RegisterVariable(&r_showdisabledepthtest);
1132 Cvar_RegisterVariable(&r_drawportals);
1133 Cvar_RegisterVariable(&r_drawentities);
1134 Cvar_RegisterVariable(&r_cullentities_trace);
1135 Cvar_RegisterVariable(&r_cullentities_trace_samples);
1136 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
1137 Cvar_RegisterVariable(&r_cullentities_trace_delay);
1138 Cvar_RegisterVariable(&r_drawviewmodel);
1139 Cvar_RegisterVariable(&r_speeds);
1140 Cvar_RegisterVariable(&r_fullbrights);
1141 Cvar_RegisterVariable(&r_wateralpha);
1142 Cvar_RegisterVariable(&r_dynamic);
1143 Cvar_RegisterVariable(&r_fullbright);
1144 Cvar_RegisterVariable(&r_shadows);
1145 Cvar_RegisterVariable(&r_shadows_throwdistance);
1146 Cvar_RegisterVariable(&r_q1bsp_skymasking);
1147 Cvar_RegisterVariable(&r_textureunits);
1148 Cvar_RegisterVariable(&r_glsl);
1149 Cvar_RegisterVariable(&r_glsl_offsetmapping);
1150 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
1151 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
1152 Cvar_RegisterVariable(&r_glsl_deluxemapping);
1153 Cvar_RegisterVariable(&r_lerpsprites);
1154 Cvar_RegisterVariable(&r_lerpmodels);
1155 Cvar_RegisterVariable(&r_waterscroll);
1156 Cvar_RegisterVariable(&r_bloom);
1157 Cvar_RegisterVariable(&r_bloom_colorscale);
1158 Cvar_RegisterVariable(&r_bloom_brighten);
1159 Cvar_RegisterVariable(&r_bloom_blur);
1160 Cvar_RegisterVariable(&r_bloom_resolution);
1161 Cvar_RegisterVariable(&r_bloom_colorexponent);
1162 Cvar_RegisterVariable(&r_bloom_colorsubtract);
1163 Cvar_RegisterVariable(&r_hdr);
1164 Cvar_RegisterVariable(&r_hdr_scenebrightness);
1165 Cvar_RegisterVariable(&r_hdr_glowintensity);
1166 Cvar_RegisterVariable(&r_hdr_range);
1167 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
1168 Cvar_RegisterVariable(&developer_texturelogging);
1169 Cvar_RegisterVariable(&gl_lightmaps);
1170 Cvar_RegisterVariable(&r_test);
1171 Cvar_RegisterVariable(&r_batchmode);
1172 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
1173 Cvar_SetValue("r_fullbrights", 0);
1174 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
1177 extern void R_Textures_Init(void);
1178 extern void GL_Draw_Init(void);
1179 extern void GL_Main_Init(void);
1180 extern void R_Shadow_Init(void);
1181 extern void R_Sky_Init(void);
1182 extern void GL_Surf_Init(void);
1183 extern void R_Light_Init(void);
1184 extern void R_Particles_Init(void);
1185 extern void R_Explosion_Init(void);
1186 extern void gl_backend_init(void);
1187 extern void Sbar_Init(void);
1188 extern void R_LightningBeams_Init(void);
1189 extern void Mod_RenderInit(void);
1191 void Render_Init(void)
1204 R_LightningBeams_Init();
1213 extern char *ENGINE_EXTENSIONS;
1216 VID_CheckExtensions();
1218 // LordHavoc: report supported extensions
1219 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
1221 // clear to black (loading plaque will be seen over this)
1223 qglClearColor(0,0,0,1);CHECKGLERROR
1224 qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
1227 int R_CullBox(const vec3_t mins, const vec3_t maxs)
1231 for (i = 0;i < 4;i++)
1233 p = r_view.frustum + i;
1238 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1242 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1246 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1250 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1254 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1258 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1262 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1266 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1274 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
1278 for (i = 0;i < numplanes;i++)
1285 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1289 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1293 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1297 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1301 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1305 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1309 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1313 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1321 //==================================================================================
1323 static void R_UpdateEntityLighting(entity_render_t *ent)
1325 vec3_t tempdiffusenormal;
1327 // fetch the lighting from the worldmodel data
1328 VectorSet(ent->modellight_ambient, r_ambient.value * (2.0f / 128.0f), r_ambient.value * (2.0f / 128.0f), r_ambient.value * (2.0f / 128.0f));
1329 VectorClear(ent->modellight_diffuse);
1330 VectorClear(tempdiffusenormal);
1331 if ((ent->flags & RENDER_LIGHT) && r_refdef.worldmodel && r_refdef.worldmodel->brush.LightPoint)
1334 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
1335 r_refdef.worldmodel->brush.LightPoint(r_refdef.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
1338 VectorSet(ent->modellight_ambient, 1, 1, 1);
1340 // move the light direction into modelspace coordinates for lighting code
1341 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
1342 VectorNormalize(ent->modellight_lightdir);
1344 // scale ambient and directional light contributions according to rendering variables
1345 ent->modellight_ambient[0] *= ent->colormod[0] * r_refdef.lightmapintensity;
1346 ent->modellight_ambient[1] *= ent->colormod[1] * r_refdef.lightmapintensity;
1347 ent->modellight_ambient[2] *= ent->colormod[2] * r_refdef.lightmapintensity;
1348 ent->modellight_diffuse[0] *= ent->colormod[0] * r_refdef.lightmapintensity;
1349 ent->modellight_diffuse[1] *= ent->colormod[1] * r_refdef.lightmapintensity;
1350 ent->modellight_diffuse[2] *= ent->colormod[2] * r_refdef.lightmapintensity;
1353 static void R_View_UpdateEntityVisible (void)
1356 entity_render_t *ent;
1358 if (!r_drawentities.integer)
1361 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : (chase_active.integer ? 0 : RENDER_EXTERIORMODEL);
1362 if (r_refdef.worldmodel && r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs)
1364 // worldmodel can check visibility
1365 for (i = 0;i < r_refdef.numentities;i++)
1367 ent = r_refdef.entities[i];
1368 r_viewcache.entityvisible[i] = !(ent->flags & renderimask) && !R_CullBox(ent->mins, ent->maxs) && ((ent->effects & EF_NODEPTHTEST) || (ent->flags & RENDER_VIEWMODEL) || r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs(r_refdef.worldmodel, r_viewcache.world_leafvisible, ent->mins, ent->maxs));
1370 if(r_cullentities_trace.integer)
1372 for (i = 0;i < r_refdef.numentities;i++)
1374 ent = r_refdef.entities[i];
1375 if(r_viewcache.entityvisible[i] && !(ent->effects & EF_NODEPTHTEST) && !(ent->flags & RENDER_VIEWMODEL) && !(ent->model && (ent->model->name[0] == '*')))
1377 if(Mod_CanSeeBox_Trace(r_cullentities_trace_samples.integer, r_cullentities_trace_enlarge.value, r_refdef.worldmodel, r_view.origin, ent->mins, ent->maxs))
1378 ent->last_trace_visibility = realtime;
1379 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
1380 r_viewcache.entityvisible[i] = 0;
1387 // no worldmodel or it can't check visibility
1388 for (i = 0;i < r_refdef.numentities;i++)
1390 ent = r_refdef.entities[i];
1391 r_viewcache.entityvisible[i] = !(ent->flags & renderimask) && !R_CullBox(ent->mins, ent->maxs);
1395 // update entity lighting (even on hidden entities for r_shadows)
1396 for (i = 0;i < r_refdef.numentities;i++)
1397 R_UpdateEntityLighting(r_refdef.entities[i]);
1400 // only used if skyrendermasked, and normally returns false
1401 int R_DrawBrushModelsSky (void)
1404 entity_render_t *ent;
1406 if (!r_drawentities.integer)
1410 for (i = 0;i < r_refdef.numentities;i++)
1412 if (!r_viewcache.entityvisible[i])
1414 ent = r_refdef.entities[i];
1415 if (!ent->model || !ent->model->DrawSky)
1417 ent->model->DrawSky(ent);
1423 void R_DrawNoModel(entity_render_t *ent);
1424 void R_DrawModels(void)
1427 entity_render_t *ent;
1429 if (!r_drawentities.integer)
1432 for (i = 0;i < r_refdef.numentities;i++)
1434 if (!r_viewcache.entityvisible[i])
1436 ent = r_refdef.entities[i];
1437 r_refdef.stats.entities++;
1438 if (ent->model && ent->model->Draw != NULL)
1439 ent->model->Draw(ent);
1445 static void R_View_SetFrustum(void)
1447 double slopex, slopey;
1449 // break apart the view matrix into vectors for various purposes
1450 Matrix4x4_ToVectors(&r_view.matrix, r_view.forward, r_view.left, r_view.up, r_view.origin);
1451 VectorNegate(r_view.left, r_view.right);
1454 r_view.frustum[0].normal[0] = 0 - 1.0 / r_view.frustum_x;
1455 r_view.frustum[0].normal[1] = 0 - 0;
1456 r_view.frustum[0].normal[2] = -1 - 0;
1457 r_view.frustum[1].normal[0] = 0 + 1.0 / r_view.frustum_x;
1458 r_view.frustum[1].normal[1] = 0 + 0;
1459 r_view.frustum[1].normal[2] = -1 + 0;
1460 r_view.frustum[2].normal[0] = 0 - 0;
1461 r_view.frustum[2].normal[1] = 0 - 1.0 / r_view.frustum_y;
1462 r_view.frustum[2].normal[2] = -1 - 0;
1463 r_view.frustum[3].normal[0] = 0 + 0;
1464 r_view.frustum[3].normal[1] = 0 + 1.0 / r_view.frustum_y;
1465 r_view.frustum[3].normal[2] = -1 + 0;
1469 zNear = r_refdef.nearclip;
1470 nudge = 1.0 - 1.0 / (1<<23);
1471 r_view.frustum[4].normal[0] = 0 - 0;
1472 r_view.frustum[4].normal[1] = 0 - 0;
1473 r_view.frustum[4].normal[2] = -1 - -nudge;
1474 r_view.frustum[4].dist = 0 - -2 * zNear * nudge;
1475 r_view.frustum[5].normal[0] = 0 + 0;
1476 r_view.frustum[5].normal[1] = 0 + 0;
1477 r_view.frustum[5].normal[2] = -1 + -nudge;
1478 r_view.frustum[5].dist = 0 + -2 * zNear * nudge;
1484 r_view.frustum[0].normal[0] = m[3] - m[0];
1485 r_view.frustum[0].normal[1] = m[7] - m[4];
1486 r_view.frustum[0].normal[2] = m[11] - m[8];
1487 r_view.frustum[0].dist = m[15] - m[12];
1489 r_view.frustum[1].normal[0] = m[3] + m[0];
1490 r_view.frustum[1].normal[1] = m[7] + m[4];
1491 r_view.frustum[1].normal[2] = m[11] + m[8];
1492 r_view.frustum[1].dist = m[15] + m[12];
1494 r_view.frustum[2].normal[0] = m[3] - m[1];
1495 r_view.frustum[2].normal[1] = m[7] - m[5];
1496 r_view.frustum[2].normal[2] = m[11] - m[9];
1497 r_view.frustum[2].dist = m[15] - m[13];
1499 r_view.frustum[3].normal[0] = m[3] + m[1];
1500 r_view.frustum[3].normal[1] = m[7] + m[5];
1501 r_view.frustum[3].normal[2] = m[11] + m[9];
1502 r_view.frustum[3].dist = m[15] + m[13];
1504 r_view.frustum[4].normal[0] = m[3] - m[2];
1505 r_view.frustum[4].normal[1] = m[7] - m[6];
1506 r_view.frustum[4].normal[2] = m[11] - m[10];
1507 r_view.frustum[4].dist = m[15] - m[14];
1509 r_view.frustum[5].normal[0] = m[3] + m[2];
1510 r_view.frustum[5].normal[1] = m[7] + m[6];
1511 r_view.frustum[5].normal[2] = m[11] + m[10];
1512 r_view.frustum[5].dist = m[15] + m[14];
1517 slopex = 1.0 / r_view.frustum_x;
1518 slopey = 1.0 / r_view.frustum_y;
1519 VectorMA(r_view.forward, -slopex, r_view.left, r_view.frustum[0].normal);
1520 VectorMA(r_view.forward, slopex, r_view.left, r_view.frustum[1].normal);
1521 VectorMA(r_view.forward, -slopey, r_view.up , r_view.frustum[2].normal);
1522 VectorMA(r_view.forward, slopey, r_view.up , r_view.frustum[3].normal);
1523 VectorCopy(r_view.forward, r_view.frustum[4].normal);
1524 VectorNormalize(r_view.frustum[0].normal);
1525 VectorNormalize(r_view.frustum[1].normal);
1526 VectorNormalize(r_view.frustum[2].normal);
1527 VectorNormalize(r_view.frustum[3].normal);
1528 r_view.frustum[0].dist = DotProduct (r_view.origin, r_view.frustum[0].normal);
1529 r_view.frustum[1].dist = DotProduct (r_view.origin, r_view.frustum[1].normal);
1530 r_view.frustum[2].dist = DotProduct (r_view.origin, r_view.frustum[2].normal);
1531 r_view.frustum[3].dist = DotProduct (r_view.origin, r_view.frustum[3].normal);
1532 r_view.frustum[4].dist = DotProduct (r_view.origin, r_view.frustum[4].normal) + r_refdef.nearclip;
1533 PlaneClassify(&r_view.frustum[0]);
1534 PlaneClassify(&r_view.frustum[1]);
1535 PlaneClassify(&r_view.frustum[2]);
1536 PlaneClassify(&r_view.frustum[3]);
1537 PlaneClassify(&r_view.frustum[4]);
1539 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
1540 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, -1024 * slopex, r_view.left, -1024 * slopey, r_view.up, r_view.frustumcorner[0]);
1541 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, 1024 * slopex, r_view.left, -1024 * slopey, r_view.up, r_view.frustumcorner[1]);
1542 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, -1024 * slopex, r_view.left, 1024 * slopey, r_view.up, r_view.frustumcorner[2]);
1543 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, 1024 * slopex, r_view.left, 1024 * slopey, r_view.up, r_view.frustumcorner[3]);
1545 // LordHavoc: note to all quake engine coders, Quake had a special case
1546 // for 90 degrees which assumed a square view (wrong), so I removed it,
1547 // Quake2 has it disabled as well.
1549 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
1550 //RotatePointAroundVector( r_view.frustum[0].normal, r_view.up, r_view.forward, -(90 - r_refdef.fov_x / 2));
1551 //r_view.frustum[0].dist = DotProduct (r_view.origin, frustum[0].normal);
1552 //PlaneClassify(&frustum[0]);
1554 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
1555 //RotatePointAroundVector( r_view.frustum[1].normal, r_view.up, r_view.forward, (90 - r_refdef.fov_x / 2));
1556 //r_view.frustum[1].dist = DotProduct (r_view.origin, frustum[1].normal);
1557 //PlaneClassify(&frustum[1]);
1559 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
1560 //RotatePointAroundVector( r_view.frustum[2].normal, r_view.left, r_view.forward, -(90 - r_refdef.fov_y / 2));
1561 //r_view.frustum[2].dist = DotProduct (r_view.origin, frustum[2].normal);
1562 //PlaneClassify(&frustum[2]);
1564 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
1565 //RotatePointAroundVector( r_view.frustum[3].normal, r_view.left, r_view.forward, (90 - r_refdef.fov_y / 2));
1566 //r_view.frustum[3].dist = DotProduct (r_view.origin, frustum[3].normal);
1567 //PlaneClassify(&frustum[3]);
1570 //VectorCopy(r_view.forward, r_view.frustum[4].normal);
1571 //r_view.frustum[4].dist = DotProduct (r_view.origin, frustum[4].normal) + r_nearclip.value;
1572 //PlaneClassify(&frustum[4]);
1575 void R_View_Update(void)
1577 R_View_SetFrustum();
1578 R_View_WorldVisibility();
1579 R_View_UpdateEntityVisible();
1582 void R_SetupView(const matrix4x4_t *matrix)
1584 if (r_refdef.rtworldshadows || r_refdef.rtdlightshadows)
1585 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_view.frustum_x, r_view.frustum_y, r_refdef.nearclip);
1587 GL_SetupView_Mode_Perspective(r_view.frustum_x, r_view.frustum_y, r_refdef.nearclip, r_refdef.farclip);
1589 GL_SetupView_Orientation_FromEntity(matrix);
1592 void R_ResetViewRendering2D(void)
1594 if (gl_support_fragment_shader)
1596 qglUseProgramObjectARB(0);CHECKGLERROR
1601 // GL is weird because it's bottom to top, r_view.y is top to bottom
1602 qglViewport(r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
1603 GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
1604 GL_Scissor(r_view.x, r_view.y, r_view.width, r_view.height);
1605 GL_Color(1, 1, 1, 1);
1606 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
1607 GL_BlendFunc(GL_ONE, GL_ZERO);
1608 GL_AlphaTest(false);
1609 GL_ScissorTest(false);
1610 GL_DepthMask(false);
1611 GL_DepthRange(0, 1);
1612 GL_DepthTest(false);
1613 R_Mesh_Matrix(&identitymatrix);
1614 R_Mesh_ResetTextureState();
1615 qglPolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR
1616 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
1617 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
1618 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
1619 qglStencilMask(~0);CHECKGLERROR
1620 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
1621 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
1622 GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
1625 void R_ResetViewRendering3D(void)
1627 if (gl_support_fragment_shader)
1629 qglUseProgramObjectARB(0);CHECKGLERROR
1634 // GL is weird because it's bottom to top, r_view.y is top to bottom
1635 qglViewport(r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
1636 R_SetupView(&r_view.matrix);
1637 GL_Scissor(r_view.x, r_view.y, r_view.width, r_view.height);
1638 GL_Color(1, 1, 1, 1);
1639 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
1640 GL_BlendFunc(GL_ONE, GL_ZERO);
1641 GL_AlphaTest(false);
1642 GL_ScissorTest(true);
1644 GL_DepthRange(0, 1);
1646 R_Mesh_Matrix(&identitymatrix);
1647 R_Mesh_ResetTextureState();
1648 qglPolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR
1649 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
1650 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
1651 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
1652 qglStencilMask(~0);CHECKGLERROR
1653 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
1654 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
1655 GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
1659 R_Bloom_SetupShader(
1661 "// written by Forest 'LordHavoc' Hale\n"
1663 "// common definitions between vertex shader and fragment shader:\n"
1665 "#ifdef __GLSL_CG_DATA_TYPES\n"
1666 "#define myhalf half\n"
1667 "#define myhvec2 hvec2\n"
1668 "#define myhvec3 hvec3\n"
1669 "#define myhvec4 hvec4\n"
1671 "#define myhalf float\n"
1672 "#define myhvec2 vec2\n"
1673 "#define myhvec3 vec3\n"
1674 "#define myhvec4 vec4\n"
1677 "varying vec2 ScreenTexCoord;\n"
1678 "varying vec2 BloomTexCoord;\n"
1683 "// vertex shader specific:\n"
1684 "#ifdef VERTEX_SHADER\n"
1688 " ScreenTexCoord = vec2(gl_MultiTexCoord0);\n"
1689 " BloomTexCoord = vec2(gl_MultiTexCoord1);\n"
1690 " // transform vertex to camera space, using ftransform to match non-VS\n"
1692 " gl_Position = ftransform();\n"
1695 "#endif // VERTEX_SHADER\n"
1700 "// fragment shader specific:\n"
1701 "#ifdef FRAGMENT_SHADER\n"
1706 " myhvec3 color = myhvec3(texture2D(Texture_Screen, ScreenTexCoord));\n"
1707 " for (x = -BLUR_X;x <= BLUR_X;x++)
1708 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
1709 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
1710 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
1711 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
1713 " gl_FragColor = vec4(color);\n"
1716 "#endif // FRAGMENT_SHADER\n"
1719 void R_RenderScene(void);
1721 void R_Bloom_StartFrame(void)
1723 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
1725 // set bloomwidth and bloomheight to the bloom resolution that will be
1726 // used (often less than the screen resolution for faster rendering)
1727 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_view.width);
1728 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_view.height / r_view.width;
1729 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_view.height);
1731 // calculate desired texture sizes
1732 if (gl_support_arb_texture_non_power_of_two)
1734 screentexturewidth = r_view.width;
1735 screentextureheight = r_view.height;
1736 bloomtexturewidth = r_bloomstate.bloomwidth;
1737 bloomtextureheight = r_bloomstate.bloomheight;
1741 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
1742 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
1743 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
1744 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
1749 screentexturewidth = screentextureheight = 0;
1751 else if (r_bloom.integer)
1756 screentexturewidth = screentextureheight = 0;
1757 bloomtexturewidth = bloomtextureheight = 0;
1760 if ((!bloomtexturewidth && !bloomtextureheight) || r_bloom_resolution.integer < 4 || r_bloom_blur.value < 1 || r_bloom_blur.value >= 512 || screentexturewidth > gl_max_texture_size || screentextureheight > gl_max_texture_size || bloomtexturewidth > gl_max_texture_size || bloomtextureheight > gl_max_texture_size)
1762 // can't use bloom if the parameters are too weird
1763 // can't use bloom if the card does not support the texture size
1764 if (r_bloomstate.texture_screen)
1765 R_FreeTexture(r_bloomstate.texture_screen);
1766 if (r_bloomstate.texture_bloom)
1767 R_FreeTexture(r_bloomstate.texture_bloom);
1768 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
1772 r_bloomstate.enabled = true;
1773 r_bloomstate.hdr = r_hdr.integer != 0;
1775 // allocate textures as needed
1776 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
1778 if (r_bloomstate.texture_screen)
1779 R_FreeTexture(r_bloomstate.texture_screen);
1780 r_bloomstate.texture_screen = NULL;
1781 r_bloomstate.screentexturewidth = screentexturewidth;
1782 r_bloomstate.screentextureheight = screentextureheight;
1783 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
1784 r_bloomstate.texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, TEXTYPE_RGBA, TEXF_FORCENEAREST | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
1786 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
1788 if (r_bloomstate.texture_bloom)
1789 R_FreeTexture(r_bloomstate.texture_bloom);
1790 r_bloomstate.texture_bloom = NULL;
1791 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
1792 r_bloomstate.bloomtextureheight = bloomtextureheight;
1793 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
1794 r_bloomstate.texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", r_bloomstate.bloomtexturewidth, r_bloomstate.bloomtextureheight, NULL, TEXTYPE_RGBA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
1797 // set up a texcoord array for the full resolution screen image
1798 // (we have to keep this around to copy back during final render)
1799 r_bloomstate.screentexcoord2f[0] = 0;
1800 r_bloomstate.screentexcoord2f[1] = (float)r_view.height / (float)r_bloomstate.screentextureheight;
1801 r_bloomstate.screentexcoord2f[2] = (float)r_view.width / (float)r_bloomstate.screentexturewidth;
1802 r_bloomstate.screentexcoord2f[3] = (float)r_view.height / (float)r_bloomstate.screentextureheight;
1803 r_bloomstate.screentexcoord2f[4] = (float)r_view.width / (float)r_bloomstate.screentexturewidth;
1804 r_bloomstate.screentexcoord2f[5] = 0;
1805 r_bloomstate.screentexcoord2f[6] = 0;
1806 r_bloomstate.screentexcoord2f[7] = 0;
1808 // set up a texcoord array for the reduced resolution bloom image
1809 // (which will be additive blended over the screen image)
1810 r_bloomstate.bloomtexcoord2f[0] = 0;
1811 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
1812 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
1813 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
1814 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
1815 r_bloomstate.bloomtexcoord2f[5] = 0;
1816 r_bloomstate.bloomtexcoord2f[6] = 0;
1817 r_bloomstate.bloomtexcoord2f[7] = 0;
1820 void R_Bloom_CopyScreenTexture(float colorscale)
1822 r_refdef.stats.bloom++;
1824 R_ResetViewRendering2D();
1825 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
1826 R_Mesh_ColorPointer(NULL, 0, 0);
1827 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
1828 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
1830 // copy view into the screen texture
1831 GL_ActiveTexture(0);
1833 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
1834 r_refdef.stats.bloom_copypixels += r_view.width * r_view.height;
1836 // now scale it down to the bloom texture size
1838 qglViewport(r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
1839 GL_BlendFunc(GL_ONE, GL_ZERO);
1840 GL_Color(colorscale, colorscale, colorscale, 1);
1841 // TODO: optimize with multitexture or GLSL
1842 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
1843 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
1845 // we now have a bloom image in the framebuffer
1846 // copy it into the bloom image texture for later processing
1847 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
1848 GL_ActiveTexture(0);
1850 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
1851 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
1854 void R_Bloom_CopyHDRTexture(void)
1856 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
1857 GL_ActiveTexture(0);
1859 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
1860 r_refdef.stats.bloom_copypixels += r_view.width * r_view.height;
1863 void R_Bloom_MakeTexture(void)
1866 float xoffset, yoffset, r, brighten;
1868 r_refdef.stats.bloom++;
1870 R_ResetViewRendering2D();
1871 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
1872 R_Mesh_ColorPointer(NULL, 0, 0);
1874 // we have a bloom image in the framebuffer
1876 qglViewport(r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
1878 for (x = 1;x < r_bloom_colorexponent.value;)
1881 r = bound(0, r_bloom_colorexponent.value / x, 1);
1882 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
1883 GL_Color(r, r, r, 1);
1884 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
1885 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
1886 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
1887 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
1889 // copy the vertically blurred bloom view to a texture
1890 GL_ActiveTexture(0);
1892 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
1893 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
1896 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
1897 brighten = r_bloom_brighten.value;
1899 brighten *= r_hdr_range.value;
1900 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
1901 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
1903 for (dir = 0;dir < 2;dir++)
1905 // blend on at multiple vertical offsets to achieve a vertical blur
1906 // TODO: do offset blends using GLSL
1907 GL_BlendFunc(GL_ONE, GL_ZERO);
1908 for (x = -range;x <= range;x++)
1910 if (!dir){xoffset = 0;yoffset = x;}
1911 else {xoffset = x;yoffset = 0;}
1912 xoffset /= (float)r_bloomstate.bloomtexturewidth;
1913 yoffset /= (float)r_bloomstate.bloomtextureheight;
1914 // compute a texcoord array with the specified x and y offset
1915 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
1916 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
1917 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
1918 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
1919 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
1920 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
1921 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
1922 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
1923 // this r value looks like a 'dot' particle, fading sharply to
1924 // black at the edges
1925 // (probably not realistic but looks good enough)
1926 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
1927 //r = (dir ? 1.0f : brighten)/(range*2+1);
1928 r = (dir ? 1.0f : brighten)/(range*2+1)*(1 - x*x/(float)(range*range));
1929 GL_Color(r, r, r, 1);
1930 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
1931 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
1932 GL_BlendFunc(GL_ONE, GL_ONE);
1935 // copy the vertically blurred bloom view to a texture
1936 GL_ActiveTexture(0);
1938 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
1939 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
1942 // apply subtract last
1943 // (just like it would be in a GLSL shader)
1944 if (r_bloom_colorsubtract.value > 0 && gl_support_ext_blend_subtract)
1946 GL_BlendFunc(GL_ONE, GL_ZERO);
1947 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
1948 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
1949 GL_Color(1, 1, 1, 1);
1950 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
1951 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
1953 GL_BlendFunc(GL_ONE, GL_ONE);
1954 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
1955 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
1956 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
1957 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
1958 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
1959 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
1960 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
1962 // copy the darkened bloom view to a texture
1963 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
1964 GL_ActiveTexture(0);
1966 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
1967 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
1971 void R_HDR_RenderBloomTexture(void)
1973 int oldwidth, oldheight;
1975 oldwidth = r_view.width;
1976 oldheight = r_view.height;
1977 r_view.width = r_bloomstate.bloomwidth;
1978 r_view.height = r_bloomstate.bloomheight;
1980 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
1981 // TODO: add exposure compensation features
1982 // TODO: add fp16 framebuffer support
1984 r_view.colorscale = r_bloom_colorscale.value * r_hdr_scenebrightness.value;
1986 r_view.colorscale /= r_hdr_range.value;
1989 R_ResetViewRendering2D();
1991 R_Bloom_CopyHDRTexture();
1992 R_Bloom_MakeTexture();
1994 R_ResetViewRendering3D();
1997 if (r_timereport_active)
1998 R_TimeReport("clear");
2001 // restore the view settings
2002 r_view.width = oldwidth;
2003 r_view.height = oldheight;
2006 static void R_BlendView(void)
2008 if (r_bloomstate.enabled && r_bloomstate.hdr)
2010 // render high dynamic range bloom effect
2011 // the bloom texture was made earlier this render, so we just need to
2012 // blend it onto the screen...
2013 R_ResetViewRendering2D();
2014 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
2015 R_Mesh_ColorPointer(NULL, 0, 0);
2016 GL_Color(1, 1, 1, 1);
2017 GL_BlendFunc(GL_ONE, GL_ONE);
2018 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2019 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
2020 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2021 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
2023 else if (r_bloomstate.enabled)
2025 // render simple bloom effect
2026 // copy the screen and shrink it and darken it for the bloom process
2027 R_Bloom_CopyScreenTexture(r_bloom_colorscale.value);
2028 // make the bloom texture
2029 R_Bloom_MakeTexture();
2030 // put the original screen image back in place and blend the bloom
2032 R_ResetViewRendering2D();
2033 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
2034 R_Mesh_ColorPointer(NULL, 0, 0);
2035 GL_Color(1, 1, 1, 1);
2036 GL_BlendFunc(GL_ONE, GL_ZERO);
2037 // do both in one pass if possible
2038 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2039 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
2040 if (r_textureunits.integer >= 2 && gl_combine.integer)
2042 R_Mesh_TexCombine(1, GL_ADD, GL_ADD, 1, 1);
2043 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_screen));
2044 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.screentexcoord2f, 0, 0);
2048 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2049 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
2050 // now blend on the bloom texture
2051 GL_BlendFunc(GL_ONE, GL_ONE);
2052 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
2053 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
2055 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2056 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
2058 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
2060 // apply a color tint to the whole view
2061 R_ResetViewRendering2D();
2062 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
2063 R_Mesh_ColorPointer(NULL, 0, 0);
2064 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2065 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
2066 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2070 void R_RenderScene(void);
2072 matrix4x4_t r_waterscrollmatrix;
2074 void R_UpdateVariables(void)
2078 r_refdef.farclip = 4096;
2079 if (r_refdef.worldmodel)
2080 r_refdef.farclip += VectorDistance(r_refdef.worldmodel->normalmins, r_refdef.worldmodel->normalmaxs);
2081 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
2083 r_refdef.polygonfactor = 0;
2084 r_refdef.polygonoffset = 0;
2085 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_shadow_polygonfactor.value;
2086 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_shadow_polygonoffset.value;
2088 r_refdef.rtworld = r_shadow_realtime_world.integer;
2089 r_refdef.rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
2090 r_refdef.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
2091 r_refdef.rtdlightshadows = r_refdef.rtdlight && (r_refdef.rtworld ? r_shadow_realtime_world_dlightshadows.integer : r_shadow_realtime_dlight_shadows.integer) && gl_stencil;
2092 r_refdef.lightmapintensity = r_refdef.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
2093 if (r_showsurfaces.integer)
2095 r_refdef.rtworld = false;
2096 r_refdef.rtworldshadows = false;
2097 r_refdef.rtdlight = false;
2098 r_refdef.rtdlightshadows = false;
2099 r_refdef.lightmapintensity = 0;
2102 if (gamemode == GAME_NEHAHRA)
2104 if (gl_fogenable.integer)
2106 r_refdef.oldgl_fogenable = true;
2107 r_refdef.fog_density = gl_fogdensity.value;
2108 r_refdef.fog_red = gl_fogred.value;
2109 r_refdef.fog_green = gl_foggreen.value;
2110 r_refdef.fog_blue = gl_fogblue.value;
2112 else if (r_refdef.oldgl_fogenable)
2114 r_refdef.oldgl_fogenable = false;
2115 r_refdef.fog_density = 0;
2116 r_refdef.fog_red = 0;
2117 r_refdef.fog_green = 0;
2118 r_refdef.fog_blue = 0;
2121 if (r_refdef.fog_density)
2123 r_refdef.fogcolor[0] = bound(0.0f, r_refdef.fog_red , 1.0f);
2124 r_refdef.fogcolor[1] = bound(0.0f, r_refdef.fog_green, 1.0f);
2125 r_refdef.fogcolor[2] = bound(0.0f, r_refdef.fog_blue , 1.0f);
2127 if (r_refdef.fog_density)
2129 r_refdef.fogenabled = true;
2130 // this is the point where the fog reaches 0.9986 alpha, which we
2131 // consider a good enough cutoff point for the texture
2132 // (0.9986 * 256 == 255.6)
2133 r_refdef.fogrange = 400 / r_refdef.fog_density;
2134 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
2135 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
2136 // fog color was already set
2139 r_refdef.fogenabled = false;
2147 void R_RenderView(void)
2149 if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
2150 return; //Host_Error ("R_RenderView: NULL worldmodel");
2152 R_Shadow_UpdateWorldLightSelection();
2155 if (r_timereport_active)
2156 R_TimeReport("setup");
2159 if (r_timereport_active)
2160 R_TimeReport("visibility");
2162 R_ResetViewRendering3D();
2165 if (r_timereport_active)
2166 R_TimeReport("clear");
2168 R_Bloom_StartFrame();
2170 // this produces a bloom texture to be used in R_BlendView() later
2172 R_HDR_RenderBloomTexture();
2174 r_view.colorscale = r_hdr_scenebrightness.value;
2178 if (r_timereport_active)
2179 R_TimeReport("blendview");
2181 GL_Scissor(0, 0, vid.width, vid.height);
2182 GL_ScissorTest(false);
2186 extern void R_DrawLightningBeams (void);
2187 extern void VM_CL_AddPolygonsToMeshQueue (void);
2188 extern void R_DrawPortals (void);
2189 extern cvar_t cl_locs_show;
2190 static void R_DrawLocs(void);
2191 static void R_DrawEntityBBoxes(void);
2192 void R_RenderScene(void)
2194 // don't let sound skip if going slow
2195 if (r_refdef.extraupdate)
2198 R_ResetViewRendering3D();
2200 R_MeshQueue_BeginScene();
2204 Matrix4x4_CreateTranslate(&r_waterscrollmatrix, sin(r_refdef.time) * 0.025 * r_waterscroll.value, sin(r_refdef.time * 0.8f) * 0.025 * r_waterscroll.value, 0);
2206 if (cl.csqc_vidvars.drawworld)
2208 // don't let sound skip if going slow
2209 if (r_refdef.extraupdate)
2212 if (r_refdef.worldmodel && r_refdef.worldmodel->DrawSky)
2214 r_refdef.worldmodel->DrawSky(r_refdef.worldentity);
2215 if (r_timereport_active)
2216 R_TimeReport("worldsky");
2219 if (R_DrawBrushModelsSky() && r_timereport_active)
2220 R_TimeReport("bmodelsky");
2222 if (r_refdef.worldmodel && r_refdef.worldmodel->Draw)
2224 r_refdef.worldmodel->Draw(r_refdef.worldentity);
2225 if (r_timereport_active)
2226 R_TimeReport("world");
2230 // don't let sound skip if going slow
2231 if (r_refdef.extraupdate)
2235 if (r_timereport_active)
2236 R_TimeReport("models");
2238 // don't let sound skip if going slow
2239 if (r_refdef.extraupdate)
2242 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
2244 R_DrawModelShadows();
2246 R_ResetViewRendering3D();
2248 // don't let sound skip if going slow
2249 if (r_refdef.extraupdate)
2253 R_ShadowVolumeLighting(false);
2254 if (r_timereport_active)
2255 R_TimeReport("rtlights");
2257 // don't let sound skip if going slow
2258 if (r_refdef.extraupdate)
2261 if (cl.csqc_vidvars.drawworld)
2263 R_DrawLightningBeams();
2264 if (r_timereport_active)
2265 R_TimeReport("lightning");
2268 if (r_timereport_active)
2269 R_TimeReport("particles");
2272 if (r_timereport_active)
2273 R_TimeReport("explosions");
2276 if (gl_support_fragment_shader)
2278 qglUseProgramObjectARB(0);CHECKGLERROR
2280 VM_CL_AddPolygonsToMeshQueue();
2282 if (cl_locs_show.integer)
2285 if (r_timereport_active)
2286 R_TimeReport("showlocs");
2289 if (r_drawportals.integer)
2292 if (r_timereport_active)
2293 R_TimeReport("portals");
2296 if (r_showbboxes.value > 0)
2298 R_DrawEntityBBoxes();
2299 if (r_timereport_active)
2300 R_TimeReport("bboxes");
2303 if (gl_support_fragment_shader)
2305 qglUseProgramObjectARB(0);CHECKGLERROR
2307 R_MeshQueue_RenderTransparent();
2308 if (r_timereport_active)
2309 R_TimeReport("drawtrans");
2311 if (gl_support_fragment_shader)
2313 qglUseProgramObjectARB(0);CHECKGLERROR
2316 if (cl.csqc_vidvars.drawworld)
2319 if (r_timereport_active)
2320 R_TimeReport("coronas");
2323 // don't let sound skip if going slow
2324 if (r_refdef.extraupdate)
2327 R_ResetViewRendering2D();
2330 static const int bboxelements[36] =
2340 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
2343 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
2344 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2345 GL_DepthMask(false);
2346 GL_DepthRange(0, 1);
2347 R_Mesh_Matrix(&identitymatrix);
2348 R_Mesh_ResetTextureState();
2350 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
2351 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
2352 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
2353 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
2354 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
2355 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
2356 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
2357 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
2358 R_FillColors(color4f, 8, cr, cg, cb, ca);
2359 if (r_refdef.fogenabled)
2361 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
2363 f1 = FogPoint_World(v);
2365 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
2366 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
2367 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
2370 R_Mesh_VertexPointer(vertex3f, 0, 0);
2371 R_Mesh_ColorPointer(color4f, 0, 0);
2372 R_Mesh_ResetTextureState();
2373 R_Mesh_Draw(0, 8, 12, bboxelements, 0, 0);
2376 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
2380 prvm_edict_t *edict;
2381 // this function draws bounding boxes of server entities
2385 for (i = 0;i < numsurfaces;i++)
2387 edict = PRVM_EDICT_NUM(surfacelist[i]);
2388 switch ((int)edict->fields.server->solid)
2390 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
2391 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
2392 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
2393 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
2394 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
2395 default: Vector4Set(color, 0, 0, 0, 0.50);break;
2397 color[3] *= r_showbboxes.value;
2398 color[3] = bound(0, color[3], 1);
2399 GL_DepthTest(!r_showdisabledepthtest.integer);
2400 GL_CullFace(GL_BACK);
2401 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
2406 static void R_DrawEntityBBoxes(void)
2409 prvm_edict_t *edict;
2411 // this function draws bounding boxes of server entities
2415 for (i = 0;i < prog->num_edicts;i++)
2417 edict = PRVM_EDICT_NUM(i);
2418 if (edict->priv.server->free)
2420 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
2421 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
2426 int nomodelelements[24] =
2438 float nomodelvertex3f[6*3] =
2448 float nomodelcolor4f[6*4] =
2450 0.0f, 0.0f, 0.5f, 1.0f,
2451 0.0f, 0.0f, 0.5f, 1.0f,
2452 0.0f, 0.5f, 0.0f, 1.0f,
2453 0.0f, 0.5f, 0.0f, 1.0f,
2454 0.5f, 0.0f, 0.0f, 1.0f,
2455 0.5f, 0.0f, 0.0f, 1.0f
2458 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
2463 // this is only called once per entity so numsurfaces is always 1, and
2464 // surfacelist is always {0}, so this code does not handle batches
2465 R_Mesh_Matrix(&ent->matrix);
2467 if (ent->flags & EF_ADDITIVE)
2469 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2470 GL_DepthMask(false);
2472 else if (ent->alpha < 1)
2474 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2475 GL_DepthMask(false);
2479 GL_BlendFunc(GL_ONE, GL_ZERO);
2482 GL_DepthRange(0, (ent->flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
2483 GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
2484 GL_CullFace((ent->effects & EF_DOUBLESIDED) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
2485 R_Mesh_VertexPointer(nomodelvertex3f, 0, 0);
2486 if (r_refdef.fogenabled)
2489 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
2490 R_Mesh_ColorPointer(color4f, 0, 0);
2491 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
2492 f1 = FogPoint_World(org);
2494 for (i = 0, c = color4f;i < 6;i++, c += 4)
2496 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
2497 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
2498 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
2502 else if (ent->alpha != 1)
2504 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
2505 R_Mesh_ColorPointer(color4f, 0, 0);
2506 for (i = 0, c = color4f;i < 6;i++, c += 4)
2510 R_Mesh_ColorPointer(nomodelcolor4f, 0, 0);
2511 R_Mesh_ResetTextureState();
2512 R_Mesh_Draw(0, 6, 8, nomodelelements, 0, 0);
2515 void R_DrawNoModel(entity_render_t *ent)
2518 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
2519 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
2520 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, r_shadow_rtlight);
2522 // R_DrawNoModelCallback(ent, 0);
2525 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
2527 vec3_t right1, right2, diff, normal;
2529 VectorSubtract (org2, org1, normal);
2531 // calculate 'right' vector for start
2532 VectorSubtract (r_view.origin, org1, diff);
2533 CrossProduct (normal, diff, right1);
2534 VectorNormalize (right1);
2536 // calculate 'right' vector for end
2537 VectorSubtract (r_view.origin, org2, diff);
2538 CrossProduct (normal, diff, right2);
2539 VectorNormalize (right2);
2541 vert[ 0] = org1[0] + width * right1[0];
2542 vert[ 1] = org1[1] + width * right1[1];
2543 vert[ 2] = org1[2] + width * right1[2];
2544 vert[ 3] = org1[0] - width * right1[0];
2545 vert[ 4] = org1[1] - width * right1[1];
2546 vert[ 5] = org1[2] - width * right1[2];
2547 vert[ 6] = org2[0] - width * right2[0];
2548 vert[ 7] = org2[1] - width * right2[1];
2549 vert[ 8] = org2[2] - width * right2[2];
2550 vert[ 9] = org2[0] + width * right2[0];
2551 vert[10] = org2[1] + width * right2[1];
2552 vert[11] = org2[2] + width * right2[2];
2555 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
2557 void R_DrawSprite(int blendfunc1, int blendfunc2, rtexture_t *texture, rtexture_t *fogtexture, qboolean depthdisable, qboolean depthshort, const vec3_t origin, const vec3_t left, const vec3_t up, float scalex1, float scalex2, float scaley1, float scaley2, float cr, float cg, float cb, float ca)
2562 if (r_refdef.fogenabled)
2563 fog = FogPoint_World(origin);
2565 R_Mesh_Matrix(&identitymatrix);
2566 GL_BlendFunc(blendfunc1, blendfunc2);
2567 GL_DepthMask(false);
2568 GL_DepthRange(0, depthshort ? 0.0625 : 1);
2569 GL_DepthTest(!depthdisable);
2571 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
2572 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
2573 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
2574 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
2575 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
2576 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
2577 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
2578 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
2579 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
2580 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
2581 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
2582 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
2584 R_Mesh_VertexPointer(vertex3f, 0, 0);
2585 R_Mesh_ColorPointer(NULL, 0, 0);
2586 R_Mesh_ResetTextureState();
2587 R_Mesh_TexBind(0, R_GetTexture(texture));
2588 R_Mesh_TexCoordPointer(0, 2, spritetexcoord2f, 0, 0);
2589 // FIXME: fixed function path can't properly handle r_view.colorscale > 1
2590 GL_Color(cr * fog * r_view.colorscale, cg * fog * r_view.colorscale, cb * fog * r_view.colorscale, ca);
2591 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2593 if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
2595 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
2596 GL_BlendFunc(blendfunc1, GL_ONE);
2598 GL_Color(r_refdef.fogcolor[0] * fog * r_view.colorscale, r_refdef.fogcolor[1] * fog * r_view.colorscale, r_refdef.fogcolor[2] * fog * r_view.colorscale, ca);
2599 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2603 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
2608 VectorSet(v, x, y, z);
2609 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
2610 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
2612 if (i == mesh->numvertices)
2614 if (mesh->numvertices < mesh->maxvertices)
2616 VectorCopy(v, vertex3f);
2617 mesh->numvertices++;
2619 return mesh->numvertices;
2625 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
2629 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
2630 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
2631 e = mesh->element3i + mesh->numtriangles * 3;
2632 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
2634 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
2635 if (mesh->numtriangles < mesh->maxtriangles)
2640 mesh->numtriangles++;
2642 element[1] = element[2];
2646 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
2650 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
2651 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
2652 e = mesh->element3i + mesh->numtriangles * 3;
2653 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
2655 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
2656 if (mesh->numtriangles < mesh->maxtriangles)
2661 mesh->numtriangles++;
2663 element[1] = element[2];
2667 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
2668 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
2670 int planenum, planenum2;
2673 mplane_t *plane, *plane2;
2675 double temppoints[2][256*3];
2676 // figure out how large a bounding box we need to properly compute this brush
2678 for (w = 0;w < numplanes;w++)
2679 maxdist = max(maxdist, planes[w].dist);
2680 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
2681 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
2682 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
2686 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
2687 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
2689 if (planenum2 == planenum)
2691 PolygonD_Divide(tempnumpoints, temppoints[w], plane2->normal[0], plane2->normal[1], plane2->normal[2], plane2->dist, R_MESH_PLANE_DIST_EPSILON, 0, NULL, NULL, 256, temppoints[!w], &tempnumpoints, NULL);
2694 if (tempnumpoints < 3)
2696 // generate elements forming a triangle fan for this polygon
2697 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
2701 static void R_DrawCollisionBrush(const colbrushf_t *brush)
2704 R_Mesh_VertexPointer(brush->points->v, 0, 0);
2705 i = (int)(((size_t)brush) / sizeof(colbrushf_t));
2706 GL_Color((i & 31) * (1.0f / 32.0f) * r_view.colorscale, ((i >> 5) & 31) * (1.0f / 32.0f) * r_view.colorscale, ((i >> 10) & 31) * (1.0f / 32.0f) * r_view.colorscale, 0.2f);
2707 GL_LockArrays(0, brush->numpoints);
2708 R_Mesh_Draw(0, brush->numpoints, brush->numtriangles, brush->elements, 0, 0);
2709 GL_LockArrays(0, 0);
2712 static void R_DrawCollisionSurface(const entity_render_t *ent, const msurface_t *surface)
2715 if (!surface->num_collisiontriangles)
2717 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
2718 i = (int)(((size_t)surface) / sizeof(msurface_t));
2719 GL_Color((i & 31) * (1.0f / 32.0f) * r_view.colorscale, ((i >> 5) & 31) * (1.0f / 32.0f) * r_view.colorscale, ((i >> 10) & 31) * (1.0f / 32.0f) * r_view.colorscale, 0.2f);
2720 GL_LockArrays(0, surface->num_collisionvertices);
2721 R_Mesh_Draw(0, surface->num_collisionvertices, surface->num_collisiontriangles, surface->data_collisionelement3i, 0, 0);
2722 GL_LockArrays(0, 0);
2725 static void R_Texture_AddLayer(texture_t *t, qboolean depthmask, int blendfunc1, int blendfunc2, texturelayertype_t type, rtexture_t *texture, const matrix4x4_t *matrix, float r, float g, float b, float a)
2727 texturelayer_t *layer;
2728 layer = t->currentlayers + t->currentnumlayers++;
2730 layer->depthmask = depthmask;
2731 layer->blendfunc1 = blendfunc1;
2732 layer->blendfunc2 = blendfunc2;
2733 layer->texture = texture;
2734 layer->texmatrix = *matrix;
2735 layer->color[0] = r * r_view.colorscale;
2736 layer->color[1] = g * r_view.colorscale;
2737 layer->color[2] = b * r_view.colorscale;
2738 layer->color[3] = a;
2741 void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
2743 model_t *model = ent->model;
2745 // switch to an alternate material if this is a q1bsp animated material
2747 texture_t *texture = t;
2748 int s = ent->skinnum;
2749 if ((unsigned int)s >= (unsigned int)model->numskins)
2751 if (model->skinscenes)
2753 if (model->skinscenes[s].framecount > 1)
2754 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
2756 s = model->skinscenes[s].firstframe;
2759 t = t + s * model->num_surfaces;
2762 // use an alternate animation if the entity's frame is not 0,
2763 // and only if the texture has an alternate animation
2764 if (ent->frame != 0 && t->anim_total[1])
2765 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.time * 5.0f) % t->anim_total[1]) : 0];
2767 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.time * 5.0f) % t->anim_total[0]) : 0];
2769 texture->currentframe = t;
2772 // pick a new currentskinframe if the material is animated
2773 if (t->numskinframes >= 2)
2774 t->currentskinframe = t->skinframes + ((int)(t->skinframerate * (cl.time - ent->frame2time)) % t->numskinframes);
2775 if (t->backgroundnumskinframes >= 2)
2776 t->backgroundcurrentskinframe = t->backgroundskinframes + ((int)(t->backgroundskinframerate * (cl.time - ent->frame2time)) % t->backgroundnumskinframes);
2778 t->currentmaterialflags = t->basematerialflags;
2779 t->currentalpha = ent->alpha;
2780 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
2781 t->currentalpha *= r_wateralpha.value;
2782 if (!(ent->flags & RENDER_LIGHT))
2783 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
2784 if (ent->effects & EF_ADDITIVE)
2785 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
2786 else if (t->currentalpha < 1)
2787 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
2788 if (ent->effects & EF_DOUBLESIDED)
2789 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
2790 if (ent->effects & EF_NODEPTHTEST)
2791 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
2792 if (ent->flags & RENDER_VIEWMODEL)
2793 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
2794 if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
2795 t->currenttexmatrix = r_waterscrollmatrix;
2797 t->currenttexmatrix = identitymatrix;
2798 if (t->backgroundnumskinframes && !(t->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED))
2799 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
2801 t->colormapping = VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f);
2802 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
2803 t->glosstexture = r_texture_white;
2804 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
2805 t->backgroundglosstexture = r_texture_white;
2806 t->specularpower = r_shadow_glossexponent.value;
2807 // TODO: store reference values for these in the texture?
2808 t->specularscale = 0;
2809 if (r_shadow_gloss.integer > 0)
2811 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
2813 if (r_shadow_glossintensity.value > 0)
2815 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_black;
2816 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_black;
2817 t->specularscale = r_shadow_glossintensity.value;
2820 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
2821 t->specularscale = r_shadow_gloss2intensity.value;
2824 t->currentnumlayers = 0;
2825 if (!(t->currentmaterialflags & MATERIALFLAG_NODRAW))
2827 if (gl_lightmaps.integer)
2828 R_Texture_AddLayer(t, true, GL_ONE, GL_ZERO, TEXTURELAYERTYPE_LITTEXTURE, r_texture_white, &identitymatrix, 1, 1, 1, 1);
2829 else if (!(t->currentmaterialflags & MATERIALFLAG_SKY))
2831 int blendfunc1, blendfunc2, depthmask;
2832 if (t->currentmaterialflags & MATERIALFLAG_ADD)
2834 blendfunc1 = GL_SRC_ALPHA;
2835 blendfunc2 = GL_ONE;
2837 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
2839 blendfunc1 = GL_SRC_ALPHA;
2840 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
2842 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
2844 blendfunc1 = t->customblendfunc[0];
2845 blendfunc2 = t->customblendfunc[1];
2849 blendfunc1 = GL_ONE;
2850 blendfunc2 = GL_ZERO;
2852 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
2853 if (t->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL))
2855 rtexture_t *currentbasetexture;
2857 if (r_refdef.fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED))
2858 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
2859 currentbasetexture = (VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) < (1.0f / 1048576.0f) && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
2860 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2862 // fullbright is not affected by r_refdef.lightmapintensity
2863 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
2864 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
2865 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->pants, &t->currenttexmatrix, ent->colormap_pantscolor[0] * ent->colormod[0], ent->colormap_pantscolor[1] * ent->colormod[1], ent->colormap_pantscolor[2] * ent->colormod[2], t->currentalpha);
2866 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
2867 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->shirt, &t->currenttexmatrix, ent->colormap_shirtcolor[0] * ent->colormod[0], ent->colormap_shirtcolor[1] * ent->colormod[1], ent->colormap_shirtcolor[2] * ent->colormod[2], t->currentalpha);
2873 // q3bsp has no lightmap updates, so the lightstylevalue that
2874 // would normally be baked into the lightmap must be
2875 // applied to the color
2876 if (ent->model->type == mod_brushq3)
2877 colorscale *= r_refdef.lightstylevalue[0] * (1.0f / 256.0f);
2878 colorscale *= r_refdef.lightmapintensity;
2879 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_LITTEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0] * colorscale, ent->colormod[1] * colorscale, ent->colormod[2] * colorscale, t->currentalpha);
2880 if (r_ambient.value >= (1.0f/64.0f))
2881 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0] * r_ambient.value * (1.0f / 64.0f), ent->colormod[1] * r_ambient.value * (1.0f / 64.0f), ent->colormod[2] * r_ambient.value * (1.0f / 64.0f), t->currentalpha);
2882 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
2884 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->currentskinframe->pants, &t->currenttexmatrix, ent->colormap_pantscolor[0] * ent->colormod[0] * colorscale, ent->colormap_pantscolor[1] * ent->colormod[1] * colorscale, ent->colormap_pantscolor[2] * ent->colormod[2] * colorscale, t->currentalpha);
2885 if (r_ambient.value >= (1.0f/64.0f))
2886 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->pants, &t->currenttexmatrix, ent->colormap_pantscolor[0] * ent->colormod[0] * r_ambient.value * (1.0f / 64.0f), ent->colormap_pantscolor[1] * ent->colormod[1] * r_ambient.value * (1.0f / 64.0f), ent->colormap_pantscolor[2] * ent->colormod[2] * r_ambient.value * (1.0f / 64.0f), t->currentalpha);
2888 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
2890 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->currentskinframe->shirt, &t->currenttexmatrix, ent->colormap_shirtcolor[0] * ent->colormod[0] * colorscale, ent->colormap_shirtcolor[1] * ent->colormod[1] * colorscale, ent->colormap_shirtcolor[2] * ent->colormod[2] * colorscale, t->currentalpha);
2891 if (r_ambient.value >= (1.0f/64.0f))
2892 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->shirt, &t->currenttexmatrix, ent->colormap_shirtcolor[0] * ent->colormod[0] * r_ambient.value * (1.0f / 64.0f), ent->colormap_shirtcolor[1] * ent->colormod[1] * r_ambient.value * (1.0f / 64.0f), ent->colormap_shirtcolor[2] * ent->colormod[2] * r_ambient.value * (1.0f / 64.0f), t->currentalpha);
2895 if (t->currentskinframe->glow != NULL)
2896 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->glow, &t->currenttexmatrix, r_hdr_glowintensity.value, r_hdr_glowintensity.value, r_hdr_glowintensity.value, t->currentalpha);
2897 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
2899 // if this is opaque use alpha blend which will darken the earlier
2902 // if this is an alpha blended material, all the earlier passes
2903 // were darkened by fog already, so we only need to add the fog
2904 // color ontop through the fog mask texture
2906 // if this is an additive blended material, all the earlier passes
2907 // were darkened by fog already, and we should not add fog color
2908 // (because the background was not darkened, there is no fog color
2909 // that was lost behind it).
2910 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, (t->currentmaterialflags & MATERIALFLAG_BLENDED) ? GL_ONE : GL_ONE_MINUS_SRC_ALPHA, TEXTURELAYERTYPE_FOG, t->currentskinframe->fog, &identitymatrix, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], t->currentalpha);
2917 void R_UpdateAllTextureInfo(entity_render_t *ent)
2921 for (i = 0;i < ent->model->num_textures;i++)
2922 R_UpdateTextureInfo(ent, ent->model->data_textures + i);
2925 int rsurface_array_size = 0;
2926 float *rsurface_array_modelvertex3f = NULL;
2927 float *rsurface_array_modelsvector3f = NULL;
2928 float *rsurface_array_modeltvector3f = NULL;
2929 float *rsurface_array_modelnormal3f = NULL;
2930 float *rsurface_array_deformedvertex3f = NULL;
2931 float *rsurface_array_deformedsvector3f = NULL;
2932 float *rsurface_array_deformedtvector3f = NULL;
2933 float *rsurface_array_deformednormal3f = NULL;
2934 float *rsurface_array_color4f = NULL;
2935 float *rsurface_array_texcoord3f = NULL;
2937 void R_Mesh_ResizeArrays(int newvertices)
2940 if (rsurface_array_size >= newvertices)
2942 if (rsurface_array_modelvertex3f)
2943 Mem_Free(rsurface_array_modelvertex3f);
2944 rsurface_array_size = (newvertices + 1023) & ~1023;
2945 base = (float *)Mem_Alloc(r_main_mempool, rsurface_array_size * sizeof(float[31]));
2946 rsurface_array_modelvertex3f = base + rsurface_array_size * 0;
2947 rsurface_array_modelsvector3f = base + rsurface_array_size * 3;
2948 rsurface_array_modeltvector3f = base + rsurface_array_size * 6;
2949 rsurface_array_modelnormal3f = base + rsurface_array_size * 9;
2950 rsurface_array_deformedvertex3f = base + rsurface_array_size * 12;
2951 rsurface_array_deformedsvector3f = base + rsurface_array_size * 15;
2952 rsurface_array_deformedtvector3f = base + rsurface_array_size * 18;
2953 rsurface_array_deformednormal3f = base + rsurface_array_size * 21;
2954 rsurface_array_texcoord3f = base + rsurface_array_size * 24;
2955 rsurface_array_color4f = base + rsurface_array_size * 27;
2958 float *rsurface_modelvertex3f;
2959 int rsurface_modelvertex3f_bufferobject;
2960 size_t rsurface_modelvertex3f_bufferoffset;
2961 float *rsurface_modelsvector3f;
2962 int rsurface_modelsvector3f_bufferobject;
2963 size_t rsurface_modelsvector3f_bufferoffset;
2964 float *rsurface_modeltvector3f;
2965 int rsurface_modeltvector3f_bufferobject;
2966 size_t rsurface_modeltvector3f_bufferoffset;
2967 float *rsurface_modelnormal3f;
2968 int rsurface_modelnormal3f_bufferobject;
2969 size_t rsurface_modelnormal3f_bufferoffset;
2970 float *rsurface_vertex3f;
2971 int rsurface_vertex3f_bufferobject;
2972 size_t rsurface_vertex3f_bufferoffset;
2973 float *rsurface_svector3f;
2974 int rsurface_svector3f_bufferobject;
2975 size_t rsurface_svector3f_bufferoffset;
2976 float *rsurface_tvector3f;
2977 int rsurface_tvector3f_bufferobject;
2978 size_t rsurface_tvector3f_bufferoffset;
2979 float *rsurface_normal3f;
2980 int rsurface_normal3f_bufferobject;
2981 size_t rsurface_normal3f_bufferoffset;
2982 float *rsurface_lightmapcolor4f;
2983 int rsurface_lightmapcolor4f_bufferobject;
2984 size_t rsurface_lightmapcolor4f_bufferoffset;
2985 vec3_t rsurface_modelorg;
2986 qboolean rsurface_generatedvertex;
2987 const entity_render_t *rsurface_entity;
2988 const model_t *rsurface_model;
2989 texture_t *rsurface_texture;
2990 qboolean rsurface_uselightmaptexture;
2991 rsurfmode_t rsurface_mode;
2992 int rsurface_lightmode; // 0 = lightmap or fullbright, 1 = color array from q3bsp, 2 = vertex shaded model
2994 void RSurf_CleanUp(void)
2997 if (rsurface_mode == RSURFMODE_GLSL)
2999 qglUseProgramObjectARB(0);CHECKGLERROR
3001 GL_AlphaTest(false);
3002 rsurface_mode = RSURFMODE_NONE;
3003 rsurface_uselightmaptexture = false;
3004 rsurface_texture = NULL;
3007 void RSurf_ActiveWorldEntity(void)
3010 rsurface_entity = r_refdef.worldentity;
3011 rsurface_model = r_refdef.worldmodel;
3012 if (rsurface_array_size < rsurface_model->surfmesh.num_vertices)
3013 R_Mesh_ResizeArrays(rsurface_model->surfmesh.num_vertices);
3014 R_Mesh_Matrix(&identitymatrix);
3015 VectorCopy(r_view.origin, rsurface_modelorg);
3016 rsurface_modelvertex3f = rsurface_model->surfmesh.data_vertex3f;
3017 rsurface_modelvertex3f_bufferobject = rsurface_model->surfmesh.vbo;
3018 rsurface_modelvertex3f_bufferoffset = rsurface_model->surfmesh.vbooffset_vertex3f;
3019 rsurface_modelsvector3f = rsurface_model->surfmesh.data_svector3f;
3020 rsurface_modelsvector3f_bufferobject = rsurface_model->surfmesh.vbo;
3021 rsurface_modelsvector3f_bufferoffset = rsurface_model->surfmesh.vbooffset_svector3f;
3022 rsurface_modeltvector3f = rsurface_model->surfmesh.data_tvector3f;
3023 rsurface_modeltvector3f_bufferobject = rsurface_model->surfmesh.vbo;
3024 rsurface_modeltvector3f_bufferoffset = rsurface_model->surfmesh.vbooffset_tvector3f;
3025 rsurface_modelnormal3f = rsurface_model->surfmesh.data_normal3f;
3026 rsurface_modelnormal3f_bufferobject = rsurface_model->surfmesh.vbo;
3027 rsurface_modelnormal3f_bufferoffset = rsurface_model->surfmesh.vbooffset_normal3f;
3028 rsurface_generatedvertex = false;
3029 rsurface_vertex3f = rsurface_modelvertex3f;
3030 rsurface_vertex3f_bufferobject = rsurface_modelvertex3f_bufferobject;
3031 rsurface_vertex3f_bufferoffset = rsurface_modelvertex3f_bufferoffset;
3032 rsurface_svector3f = rsurface_modelsvector3f;
3033 rsurface_svector3f_bufferobject = rsurface_modelsvector3f_bufferobject;
3034 rsurface_svector3f_bufferoffset = rsurface_modelsvector3f_bufferoffset;
3035 rsurface_tvector3f = rsurface_modeltvector3f;
3036 rsurface_tvector3f_bufferobject = rsurface_modeltvector3f_bufferobject;
3037 rsurface_tvector3f_bufferoffset = rsurface_modeltvector3f_bufferoffset;
3038 rsurface_normal3f = rsurface_modelnormal3f;
3039 rsurface_normal3f_bufferobject = rsurface_modelnormal3f_bufferobject;
3040 rsurface_normal3f_bufferoffset = rsurface_modelnormal3f_bufferoffset;
3043 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
3046 rsurface_entity = ent;
3047 rsurface_model = ent->model;
3048 if (rsurface_array_size < rsurface_model->surfmesh.num_vertices)
3049 R_Mesh_ResizeArrays(rsurface_model->surfmesh.num_vertices);
3050 R_Mesh_Matrix(&ent->matrix);
3051 Matrix4x4_Transform(&ent->inversematrix, r_view.origin, rsurface_modelorg);
3052 if (rsurface_model->surfmesh.isanimated && (rsurface_entity->frameblend[0].lerp != 1 || rsurface_entity->frameblend[0].frame != 0))
3056 rsurface_modelvertex3f = rsurface_array_modelvertex3f;
3057 rsurface_modelsvector3f = rsurface_array_modelsvector3f;
3058 rsurface_modeltvector3f = rsurface_array_modeltvector3f;
3059 rsurface_modelnormal3f = rsurface_array_modelnormal3f;
3060 Mod_Alias_GetMesh_Vertices(rsurface_model, rsurface_entity->frameblend, rsurface_array_modelvertex3f, rsurface_array_modelnormal3f, rsurface_array_modelsvector3f, rsurface_array_modeltvector3f);
3062 else if (wantnormals)
3064 rsurface_modelvertex3f = rsurface_array_modelvertex3f;
3065 rsurface_modelsvector3f = NULL;
3066 rsurface_modeltvector3f = NULL;
3067 rsurface_modelnormal3f = rsurface_array_modelnormal3f;
3068 Mod_Alias_GetMesh_Vertices(rsurface_model, rsurface_entity->frameblend, rsurface_array_modelvertex3f, rsurface_array_modelnormal3f, NULL, NULL);
3072 rsurface_modelvertex3f = rsurface_array_modelvertex3f;
3073 rsurface_modelsvector3f = NULL;
3074 rsurface_modeltvector3f = NULL;
3075 rsurface_modelnormal3f = NULL;
3076 Mod_Alias_GetMesh_Vertices(rsurface_model, rsurface_entity->frameblend, rsurface_array_modelvertex3f, NULL, NULL, NULL);
3078 rsurface_modelvertex3f_bufferobject = 0;
3079 rsurface_modelvertex3f_bufferoffset = 0;
3080 rsurface_modelsvector3f_bufferobject = 0;
3081 rsurface_modelsvector3f_bufferoffset = 0;
3082 rsurface_modeltvector3f_bufferobject = 0;
3083 rsurface_modeltvector3f_bufferoffset = 0;
3084 rsurface_modelnormal3f_bufferobject = 0;
3085 rsurface_modelnormal3f_bufferoffset = 0;
3086 rsurface_generatedvertex = true;
3090 rsurface_modelvertex3f = rsurface_model->surfmesh.data_vertex3f;
3091 rsurface_modelvertex3f_bufferobject = rsurface_model->surfmesh.vbo;
3092 rsurface_modelvertex3f_bufferoffset = rsurface_model->surfmesh.vbooffset_vertex3f;
3093 rsurface_modelsvector3f = rsurface_model->surfmesh.data_svector3f;
3094 rsurface_modelsvector3f_bufferobject = rsurface_model->surfmesh.vbo;
3095 rsurface_modelsvector3f_bufferoffset = rsurface_model->surfmesh.vbooffset_svector3f;
3096 rsurface_modeltvector3f = rsurface_model->surfmesh.data_tvector3f;
3097 rsurface_modeltvector3f_bufferobject = rsurface_model->surfmesh.vbo;
3098 rsurface_modeltvector3f_bufferoffset = rsurface_model->surfmesh.vbooffset_tvector3f;
3099 rsurface_modelnormal3f = rsurface_model->surfmesh.data_normal3f;
3100 rsurface_modelnormal3f_bufferobject = rsurface_model->surfmesh.vbo;
3101 rsurface_modelnormal3f_bufferoffset = rsurface_model->surfmesh.vbooffset_normal3f;
3102 rsurface_generatedvertex = false;
3104 rsurface_vertex3f = rsurface_modelvertex3f;
3105 rsurface_vertex3f_bufferobject = rsurface_modelvertex3f_bufferobject;
3106 rsurface_vertex3f_bufferoffset = rsurface_modelvertex3f_bufferoffset;
3107 rsurface_svector3f = rsurface_modelsvector3f;
3108 rsurface_svector3f_bufferobject = rsurface_modelsvector3f_bufferobject;
3109 rsurface_svector3f_bufferoffset = rsurface_modelsvector3f_bufferoffset;
3110 rsurface_tvector3f = rsurface_modeltvector3f;
3111 rsurface_tvector3f_bufferobject = rsurface_modeltvector3f_bufferobject;
3112 rsurface_tvector3f_bufferoffset = rsurface_modeltvector3f_bufferoffset;
3113 rsurface_normal3f = rsurface_modelnormal3f;
3114 rsurface_normal3f_bufferobject = rsurface_modelnormal3f_bufferobject;
3115 rsurface_normal3f_bufferoffset = rsurface_modelnormal3f_bufferoffset;
3118 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, msurface_t **texturesurfacelist)
3120 // if vertices are dynamic (animated models), generate them into the temporary rsurface_array_model* arrays and point rsurface_model* at them instead of the static data from the model itself
3121 if (rsurface_generatedvertex)
3123 if (rsurface_texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
3124 generatetangents = true;
3125 if (generatetangents)
3126 generatenormals = true;
3127 if (generatenormals && !rsurface_modelnormal3f)
3129 rsurface_normal3f = rsurface_modelnormal3f = rsurface_array_modelnormal3f;
3130 rsurface_normal3f_bufferobject = rsurface_modelnormal3f_bufferobject = 0;
3131 rsurface_normal3f_bufferoffset = rsurface_modelnormal3f_bufferoffset = 0;
3132 Mod_BuildNormals(0, rsurface_model->surfmesh.num_vertices, rsurface_model->surfmesh.num_triangles, rsurface_modelvertex3f, rsurface_model->surfmesh.data_element3i, rsurface_array_modelnormal3f, r_smoothnormals_areaweighting.integer);
3134 if (generatetangents && !rsurface_modelsvector3f)
3136 rsurface_svector3f = rsurface_modelsvector3f = rsurface_array_modelsvector3f;
3137 rsurface_svector3f_bufferobject = rsurface_modelsvector3f_bufferobject = 0;
3138 rsurface_svector3f_bufferoffset = rsurface_modelsvector3f_bufferoffset = 0;
3139 rsurface_tvector3f = rsurface_modeltvector3f = rsurface_array_modeltvector3f;
3140 rsurface_tvector3f_bufferobject = rsurface_modeltvector3f_bufferobject = 0;
3141 rsurface_tvector3f_bufferoffset = rsurface_modeltvector3f_bufferoffset = 0;
3142 Mod_BuildTextureVectorsFromNormals(0, rsurface_model->surfmesh.num_vertices, rsurface_model->surfmesh.num_triangles, rsurface_modelvertex3f, rsurface_model->surfmesh.data_texcoordtexture2f, rsurface_modelnormal3f, rsurface_model->surfmesh.data_element3i, rsurface_array_modelsvector3f, rsurface_array_modeltvector3f, r_smoothnormals_areaweighting.integer);
3145 // if vertices are deformed (sprite flares and things in maps, possibly water waves, bulges and other deformations), generate them into rsurface_deform* arrays from whatever the rsurface_model* array pointers point to (may be static model data or generated data for an animated model)
3146 if (rsurface_texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
3148 int texturesurfaceindex;
3149 float center[3], forward[3], right[3], up[3], v[4][3];
3150 matrix4x4_t matrix1, imatrix1;
3151 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_view.forward, forward);
3152 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_view.right, right);
3153 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_view.up, up);
3154 // make deformed versions of only the model vertices used by the specified surfaces
3155 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3158 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3159 // a single autosprite surface can contain multiple sprites...
3160 for (j = 0;j < surface->num_vertices - 3;j += 4)
3162 VectorClear(center);
3163 for (i = 0;i < 4;i++)
3164 VectorAdd(center, (rsurface_modelvertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
3165 VectorScale(center, 0.25f, center);
3166 if (rsurface_texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE2)
3168 forward[0] = rsurface_modelorg[0] - center[0];
3169 forward[1] = rsurface_modelorg[1] - center[1];
3171 VectorNormalize(forward);
3172 right[0] = forward[1];
3173 right[1] = -forward[0];
3175 VectorSet(up, 0, 0, 1);
3177 // FIXME: calculate vectors from triangle edges instead of using texture vectors as an easy way out?
3178 Matrix4x4_FromVectors(&matrix1, (rsurface_modelnormal3f + 3 * surface->num_firstvertex) + j*3, (rsurface_modelsvector3f + 3 * surface->num_firstvertex) + j*3, (rsurface_modeltvector3f + 3 * surface->num_firstvertex) + j*3, center);
3179 Matrix4x4_Invert_Simple(&imatrix1, &matrix1);
3180 for (i = 0;i < 4;i++)
3181 Matrix4x4_Transform(&imatrix1, (rsurface_modelvertex3f + 3 * surface->num_firstvertex) + (j+i)*3, v[i]);
3182 for (i = 0;i < 4;i++)
3183 VectorMAMAMAM(1, center, v[i][0], forward, v[i][1], right, v[i][2], up, rsurface_array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
3185 Mod_BuildNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface_modelvertex3f, rsurface_model->surfmesh.data_element3i + surface->num_firsttriangle * 3, rsurface_array_deformednormal3f, r_smoothnormals_areaweighting.integer);
3186 Mod_BuildTextureVectorsFromNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface_modelvertex3f, rsurface_model->surfmesh.data_texcoordtexture2f, rsurface_array_deformednormal3f, rsurface_model->surfmesh.data_element3i + surface->num_firsttriangle * 3, rsurface_array_deformedsvector3f, rsurface_array_deformedtvector3f, r_smoothnormals_areaweighting.integer);
3188 rsurface_vertex3f = rsurface_array_deformedvertex3f;
3189 rsurface_vertex3f_bufferobject = 0;
3190 rsurface_vertex3f_bufferoffset = 0;
3191 rsurface_svector3f = rsurface_array_deformedsvector3f;
3192 rsurface_svector3f_bufferobject = 0;
3193 rsurface_svector3f_bufferoffset = 0;
3194 rsurface_tvector3f = rsurface_array_deformedtvector3f;
3195 rsurface_tvector3f_bufferobject = 0;
3196 rsurface_tvector3f_bufferoffset = 0;
3197 rsurface_normal3f = rsurface_array_deformednormal3f;
3198 rsurface_normal3f_bufferobject = 0;
3199 rsurface_normal3f_bufferoffset = 0;
3203 rsurface_vertex3f = rsurface_modelvertex3f;
3204 rsurface_vertex3f_bufferobject = rsurface_modelvertex3f_bufferobject;
3205 rsurface_vertex3f_bufferoffset = rsurface_modelvertex3f_bufferoffset;
3206 rsurface_svector3f = rsurface_modelsvector3f;
3207 rsurface_svector3f_bufferobject = rsurface_modelsvector3f_bufferobject;
3208 rsurface_svector3f_bufferoffset = rsurface_modelsvector3f_bufferoffset;
3209 rsurface_tvector3f = rsurface_modeltvector3f;
3210 rsurface_tvector3f_bufferobject = rsurface_modeltvector3f_bufferobject;
3211 rsurface_tvector3f_bufferoffset = rsurface_modeltvector3f_bufferoffset;
3212 rsurface_normal3f = rsurface_modelnormal3f;
3213 rsurface_normal3f_bufferobject = rsurface_modelnormal3f_bufferobject;
3214 rsurface_normal3f_bufferoffset = rsurface_modelnormal3f_bufferoffset;
3216 R_Mesh_VertexPointer(rsurface_vertex3f, rsurface_vertex3f_bufferobject, rsurface_vertex3f_bufferoffset);
3219 void RSurf_DrawBatch_Simple(int texturenumsurfaces, msurface_t **texturesurfacelist)
3222 const msurface_t *surface = texturesurfacelist[0];
3223 const msurface_t *surface2;
3228 // TODO: lock all array ranges before render, rather than on each surface
3229 if (texturenumsurfaces == 1)
3231 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
3232 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle), rsurface_model->surfmesh.ebo, (sizeof(int[3]) * surface->num_firsttriangle));
3234 else if (r_batchmode.integer == 2)
3236 #define MAXBATCHTRIANGLES 4096
3237 int batchtriangles = 0;
3238 int batchelements[MAXBATCHTRIANGLES*3];
3239 for (i = 0;i < texturenumsurfaces;i = j)
3241 surface = texturesurfacelist[i];
3243 if (surface->num_triangles > MAXBATCHTRIANGLES)
3245 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle), rsurface_model->surfmesh.ebo, (sizeof(int[3]) * surface->num_firsttriangle));
3248 memcpy(batchelements, rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
3249 batchtriangles = surface->num_triangles;
3250 firstvertex = surface->num_firstvertex;
3251 endvertex = surface->num_firstvertex + surface->num_vertices;
3252 for (;j < texturenumsurfaces;j++)
3254 surface2 = texturesurfacelist[j];
3255 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
3257 memcpy(batchelements + batchtriangles * 3, rsurface_model->surfmesh.data_element3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
3258 batchtriangles += surface2->num_triangles;
3259 firstvertex = min(firstvertex, surface2->num_firstvertex);
3260 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
3262 surface2 = texturesurfacelist[j-1];
3263 numvertices = endvertex - firstvertex;
3264 R_Mesh_Draw(firstvertex, numvertices, batchtriangles, batchelements, 0, 0);
3267 else if (r_batchmode.integer == 1)
3269 for (i = 0;i < texturenumsurfaces;i = j)
3271 surface = texturesurfacelist[i];
3272 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
3273 if (texturesurfacelist[j] != surface2)
3275 surface2 = texturesurfacelist[j-1];
3276 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
3277 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
3278 GL_LockArrays(surface->num_firstvertex, numvertices);
3279 R_Mesh_Draw(surface->num_firstvertex, numvertices, numtriangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle), rsurface_model->surfmesh.ebo, (sizeof(int[3]) * surface->num_firsttriangle));
3284 for (i = 0;i < texturenumsurfaces;i++)
3286 surface = texturesurfacelist[i];
3287 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
3288 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle), rsurface_model->surfmesh.ebo, (sizeof(int[3]) * surface->num_firsttriangle));
3293 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit)
3297 const msurface_t *surface = texturesurfacelist[0];
3298 const msurface_t *surface2;
3303 // TODO: lock all array ranges before render, rather than on each surface
3304 if (texturenumsurfaces == 1)
3306 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
3307 if (deluxemaptexunit >= 0)
3308 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
3309 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
3310 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle), rsurface_model->surfmesh.ebo, (sizeof(int[3]) * surface->num_firsttriangle));
3312 else if (r_batchmode.integer == 2)
3314 #define MAXBATCHTRIANGLES 4096
3315 int batchtriangles = 0;
3316 int batchelements[MAXBATCHTRIANGLES*3];
3317 for (i = 0;i < texturenumsurfaces;i = j)
3319 surface = texturesurfacelist[i];
3320 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
3321 if (deluxemaptexunit >= 0)
3322 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
3324 if (surface->num_triangles > MAXBATCHTRIANGLES)
3326 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle), rsurface_model->surfmesh.ebo, (sizeof(int[3]) * surface->num_firsttriangle));
3329 memcpy(batchelements, rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
3330 batchtriangles = surface->num_triangles;
3331 firstvertex = surface->num_firstvertex;
3332 endvertex = surface->num_firstvertex + surface->num_vertices;
3333 for (;j < texturenumsurfaces;j++)
3335 surface2 = texturesurfacelist[j];
3336 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
3338 memcpy(batchelements + batchtriangles * 3, rsurface_model->surfmesh.data_element3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
3339 batchtriangles += surface2->num_triangles;
3340 firstvertex = min(firstvertex, surface2->num_firstvertex);
3341 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
3343 surface2 = texturesurfacelist[j-1];
3344 numvertices = endvertex - firstvertex;
3345 R_Mesh_Draw(firstvertex, numvertices, batchtriangles, batchelements, 0, 0);
3348 else if (r_batchmode.integer == 1)
3351 Con_Printf("%s batch sizes ignoring lightmap:", rsurface_texture->name);
3352 for (i = 0;i < texturenumsurfaces;i = j)
3354 surface = texturesurfacelist[i];
3355 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
3356 if (texturesurfacelist[j] != surface2)
3358 Con_Printf(" %i", j - i);
3361 Con_Printf("%s batch sizes honoring lightmap:", rsurface_texture->name);
3363 for (i = 0;i < texturenumsurfaces;i = j)
3365 surface = texturesurfacelist[i];
3366 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
3367 if (deluxemaptexunit >= 0)
3368 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
3369 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
3370 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
3373 Con_Printf(" %i", j - i);
3375 surface2 = texturesurfacelist[j-1];
3376 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
3377 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
3378 GL_LockArrays(surface->num_firstvertex, numvertices);
3379 R_Mesh_Draw(surface->num_firstvertex, numvertices, numtriangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle), rsurface_model->surfmesh.ebo, (sizeof(int[3]) * surface->num_firsttriangle));
3387 for (i = 0;i < texturenumsurfaces;i++)
3389 surface = texturesurfacelist[i];
3390 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
3391 if (deluxemaptexunit >= 0)
3392 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
3393 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
3394 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle), rsurface_model->surfmesh.ebo, (sizeof(int[3]) * surface->num_firsttriangle));
3399 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
3402 int texturesurfaceindex;
3403 if (r_showsurfaces.integer == 2)
3405 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3407 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3408 for (j = 0;j < surface->num_triangles;j++)
3410 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_view.colorscale;
3411 GL_Color(f, f, f, 1);
3412 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, 1, (rsurface_model->surfmesh.data_element3i + 3 * (j + surface->num_firsttriangle)), rsurface_model->surfmesh.ebo, (sizeof(int[3]) * (j + surface->num_firsttriangle)));
3418 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3420 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3421 int k = (int)(((size_t)surface) / sizeof(msurface_t));
3422 GL_Color((k & 15) * (1.0f / 16.0f) * r_view.colorscale, ((k >> 4) & 15) * (1.0f / 16.0f) * r_view.colorscale, ((k >> 8) & 15) * (1.0f / 16.0f) * r_view.colorscale, 1);
3423 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
3424 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle), rsurface_model->surfmesh.ebo, (sizeof(int[3]) * surface->num_firsttriangle));
3429 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, msurface_t **texturesurfacelist)
3431 int texturesurfaceindex;
3435 if (rsurface_lightmapcolor4f)
3437 // generate color arrays for the surfaces in this list
3438 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3440 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3441 for (i = 0, v = (rsurface_vertex3f + 3 * surface->num_firstvertex), c = (rsurface_lightmapcolor4f + 4 * surface->num_firstvertex), c2 = (rsurface_array_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4, c2 += 4)
3443 f = FogPoint_Model(v);
3453 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3455 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3456 for (i = 0, v = (rsurface_vertex3f + 3 * surface->num_firstvertex), c2 = (rsurface_array_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c2 += 4)
3458 f = FogPoint_Model(v);
3466 rsurface_lightmapcolor4f = rsurface_array_color4f;
3467 rsurface_lightmapcolor4f_bufferobject = 0;
3468 rsurface_lightmapcolor4f_bufferoffset = 0;
3471 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a)
3473 int texturesurfaceindex;
3476 if (!rsurface_lightmapcolor4f)
3478 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3480 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3481 for (i = 0, c = (rsurface_lightmapcolor4f + 4 * surface->num_firstvertex), c2 = (rsurface_array_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, c += 4, c2 += 4)
3489 rsurface_lightmapcolor4f = rsurface_array_color4f;
3490 rsurface_lightmapcolor4f_bufferobject = 0;
3491 rsurface_lightmapcolor4f_bufferoffset = 0;
3494 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
3497 rsurface_lightmapcolor4f = NULL;
3498 rsurface_lightmapcolor4f_bufferobject = 0;
3499 rsurface_lightmapcolor4f_bufferoffset = 0;
3500 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
3501 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
3502 R_Mesh_ColorPointer(rsurface_lightmapcolor4f, rsurface_lightmapcolor4f_bufferobject, rsurface_lightmapcolor4f_bufferoffset);
3503 GL_Color(r, g, b, a);
3504 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 0, -1);
3507 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
3509 // TODO: optimize applyfog && applycolor case
3510 // just apply fog if necessary, and tint the fog color array if necessary
3511 rsurface_lightmapcolor4f = NULL;
3512 rsurface_lightmapcolor4f_bufferobject = 0;
3513 rsurface_lightmapcolor4f_bufferoffset = 0;
3514 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
3515 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
3516 R_Mesh_ColorPointer(rsurface_lightmapcolor4f, rsurface_lightmapcolor4f_bufferobject, rsurface_lightmapcolor4f_bufferoffset);
3517 GL_Color(r, g, b, a);
3518 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3521 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
3523 int texturesurfaceindex;
3527 if (texturesurfacelist[0]->lightmapinfo && texturesurfacelist[0]->lightmapinfo->stainsamples)
3529 // generate color arrays for the surfaces in this list
3530 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3532 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3533 for (i = 0, c = rsurface_array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
3535 if (surface->lightmapinfo->samples)
3537 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface_model->surfmesh.data_lightmapoffsets + surface->num_firstvertex)[i];
3538 float scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
3539 VectorScale(lm, scale, c);
3540 if (surface->lightmapinfo->styles[1] != 255)
3542 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
3544 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
3545 VectorMA(c, scale, lm, c);
3546 if (surface->lightmapinfo->styles[2] != 255)
3549 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
3550 VectorMA(c, scale, lm, c);
3551 if (surface->lightmapinfo->styles[3] != 255)
3554 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
3555 VectorMA(c, scale, lm, c);
3565 rsurface_lightmapcolor4f = rsurface_array_color4f;
3566 rsurface_lightmapcolor4f_bufferobject = 0;
3567 rsurface_lightmapcolor4f_bufferoffset = 0;
3571 rsurface_lightmapcolor4f = rsurface_model->surfmesh.data_lightmapcolor4f;
3572 rsurface_lightmapcolor4f_bufferobject = rsurface_model->surfmesh.vbo;
3573 rsurface_lightmapcolor4f_bufferoffset = rsurface_model->surfmesh.vbooffset_lightmapcolor4f;
3575 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
3576 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
3577 R_Mesh_ColorPointer(rsurface_lightmapcolor4f, rsurface_lightmapcolor4f_bufferobject, rsurface_lightmapcolor4f_bufferoffset);
3578 GL_Color(r, g, b, a);
3579 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3582 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
3584 int texturesurfaceindex;
3588 vec3_t ambientcolor;
3589 vec3_t diffusecolor;
3593 VectorCopy(rsurface_entity->modellight_lightdir, lightdir);
3594 ambientcolor[0] = rsurface_entity->modellight_ambient[0] * r * 0.5f;
3595 ambientcolor[1] = rsurface_entity->modellight_ambient[1] * g * 0.5f;
3596 ambientcolor[2] = rsurface_entity->modellight_ambient[2] * b * 0.5f;
3597 diffusecolor[0] = rsurface_entity->modellight_diffuse[0] * r * 0.5f;
3598 diffusecolor[1] = rsurface_entity->modellight_diffuse[1] * g * 0.5f;
3599 diffusecolor[2] = rsurface_entity->modellight_diffuse[2] * b * 0.5f;
3600 if (VectorLength2(diffusecolor) > 0)
3602 // generate color arrays for the surfaces in this list
3603 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3605 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3606 int numverts = surface->num_vertices;
3607 v = rsurface_vertex3f + 3 * surface->num_firstvertex;
3608 c2 = rsurface_normal3f + 3 * surface->num_firstvertex;
3609 c = rsurface_array_color4f + 4 * surface->num_firstvertex;
3610 // q3-style directional shading
3611 for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
3613 if ((f = DotProduct(c2, lightdir)) > 0)
3614 VectorMA(ambientcolor, f, diffusecolor, c);
3616 VectorCopy(ambientcolor, c);
3625 rsurface_lightmapcolor4f = rsurface_array_color4f;
3626 rsurface_lightmapcolor4f_bufferobject = 0;
3627 rsurface_lightmapcolor4f_bufferoffset = 0;
3631 r = ambientcolor[0];
3632 g = ambientcolor[1];
3633 b = ambientcolor[2];
3634 rsurface_lightmapcolor4f = NULL;
3635 rsurface_lightmapcolor4f_bufferobject = 0;
3636 rsurface_lightmapcolor4f_bufferoffset = 0;
3638 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
3639 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
3640 R_Mesh_ColorPointer(rsurface_lightmapcolor4f, rsurface_lightmapcolor4f_bufferobject, rsurface_lightmapcolor4f_bufferoffset);
3641 GL_Color(r, g, b, a);
3642 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3645 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
3647 GL_DepthRange(0, (rsurface_texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
3648 GL_DepthTest(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
3649 GL_CullFace((rsurface_texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
3650 if (rsurface_mode != RSURFMODE_SHOWSURFACES)
3652 rsurface_mode = RSURFMODE_SHOWSURFACES;
3654 GL_BlendFunc(GL_ONE, GL_ZERO);
3655 R_Mesh_ColorPointer(NULL, 0, 0);
3656 R_Mesh_ResetTextureState();
3658 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
3659 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
3662 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, msurface_t **texturesurfacelist)
3664 // transparent sky would be ridiculous
3665 if ((rsurface_texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED))
3667 if (rsurface_mode != RSURFMODE_SKY)
3669 if (rsurface_mode == RSURFMODE_GLSL)
3671 qglUseProgramObjectARB(0);CHECKGLERROR
3673 rsurface_mode = RSURFMODE_SKY;
3677 skyrendernow = false;
3679 // restore entity matrix
3680 R_Mesh_Matrix(&rsurface_entity->matrix);
3682 GL_DepthRange(0, (rsurface_texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
3683 GL_DepthTest(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
3684 GL_CullFace((rsurface_texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
3686 // LordHavoc: HalfLife maps have freaky skypolys so don't use
3687 // skymasking on them, and Quake3 never did sky masking (unlike
3688 // software Quake and software Quake2), so disable the sky masking
3689 // in Quake3 maps as it causes problems with q3map2 sky tricks,
3690 // and skymasking also looks very bad when noclipping outside the
3691 // level, so don't use it then either.
3692 if (rsurface_model->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_viewcache.world_novis)
3694 GL_Color(r_refdef.fogcolor[0] * r_view.colorscale, r_refdef.fogcolor[1] * r_view.colorscale, r_refdef.fogcolor[2] * r_view.colorscale, 1);
3695 R_Mesh_ColorPointer(NULL, 0, 0);
3696 R_Mesh_ResetTextureState();
3697 if (skyrendermasked)
3699 // depth-only (masking)
3700 GL_ColorMask(0,0,0,0);
3701 // just to make sure that braindead drivers don't draw
3702 // anything despite that colormask...
3703 GL_BlendFunc(GL_ZERO, GL_ONE);
3708 GL_BlendFunc(GL_ONE, GL_ZERO);
3710 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
3711 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3712 if (skyrendermasked)
3713 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
3717 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, msurface_t **texturesurfacelist)
3719 if (rsurface_mode != RSURFMODE_GLSL)
3721 rsurface_mode = RSURFMODE_GLSL;
3722 R_Mesh_ResetTextureState();
3725 R_SetupSurfaceShader(vec3_origin, rsurface_lightmode == 2, 1, 1, rsurface_texture->specularscale);
3726 if (!r_glsl_permutation)
3729 if (rsurface_lightmode == 2)
3730 RSurf_PrepareVerticesForBatch(true, r_glsl_permutation->loc_Texture_Normal, texturenumsurfaces, texturesurfacelist);
3732 RSurf_PrepareVerticesForBatch(r_glsl_permutation->loc_Texture_Normal, r_glsl_permutation->loc_Texture_Normal, texturenumsurfaces, texturesurfacelist);
3733 R_Mesh_TexCoordPointer(0, 2, rsurface_model->surfmesh.data_texcoordtexture2f, rsurface_model->surfmesh.vbo, rsurface_model->surfmesh.vbooffset_texcoordtexture2f);
3734 R_Mesh_TexCoordPointer(1, 3, rsurface_svector3f, rsurface_svector3f_bufferobject, rsurface_svector3f_bufferoffset);
3735 R_Mesh_TexCoordPointer(2, 3, rsurface_tvector3f, rsurface_tvector3f_bufferobject, rsurface_tvector3f_bufferoffset);
3736 R_Mesh_TexCoordPointer(3, 3, rsurface_normal3f, rsurface_normal3f_bufferobject, rsurface_normal3f_bufferoffset);
3737 R_Mesh_TexCoordPointer(4, 2, rsurface_model->surfmesh.data_texcoordlightmap2f, rsurface_model->surfmesh.vbo, rsurface_model->surfmesh.vbooffset_texcoordlightmap2f);
3739 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
3741 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
3742 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
3743 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
3744 R_Mesh_ColorPointer(NULL, 0, 0);
3746 else if (rsurface_uselightmaptexture)
3748 R_Mesh_TexBind(7, R_GetTexture(texturesurfacelist[0]->lightmaptexture));
3749 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
3750 R_Mesh_TexBind(8, R_GetTexture(texturesurfacelist[0]->deluxemaptexture));
3751 R_Mesh_ColorPointer(NULL, 0, 0);
3755 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
3756 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
3757 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
3758 R_Mesh_ColorPointer(rsurface_model->surfmesh.data_lightmapcolor4f, rsurface_model->surfmesh.vbo, rsurface_model->surfmesh.vbooffset_lightmapcolor4f);
3761 if (rsurface_uselightmaptexture && !(rsurface_texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
3762 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 7, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? 8 : -1);
3764 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3765 if (rsurface_texture->backgroundnumskinframes && !(rsurface_texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED))
3770 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, msurface_t **texturesurfacelist)
3772 // OpenGL 1.3 path - anything not completely ancient
3773 int texturesurfaceindex;
3774 qboolean applycolor;
3778 const texturelayer_t *layer;
3779 if (rsurface_mode != RSURFMODE_MULTIPASS)
3780 rsurface_mode = RSURFMODE_MULTIPASS;
3781 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
3782 for (layerindex = 0, layer = rsurface_texture->currentlayers;layerindex < rsurface_texture->currentnumlayers;layerindex++, layer++)
3785 int layertexrgbscale;
3786 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
3788 if (layerindex == 0)
3792 GL_AlphaTest(false);
3793 qglDepthFunc(GL_EQUAL);CHECKGLERROR
3796 GL_DepthMask(layer->depthmask);
3797 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
3798 if ((layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2) && (gl_combine.integer || layer->depthmask))
3800 layertexrgbscale = 4;
3801 VectorScale(layer->color, 0.25f, layercolor);
3803 else if ((layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1) && (gl_combine.integer || layer->depthmask))
3805 layertexrgbscale = 2;
3806 VectorScale(layer->color, 0.5f, layercolor);
3810 layertexrgbscale = 1;
3811 VectorScale(layer->color, 1.0f, layercolor);
3813 layercolor[3] = layer->color[3];
3814 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
3815 R_Mesh_ColorPointer(NULL, 0, 0);
3816 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
3817 switch (layer->type)
3819 case TEXTURELAYERTYPE_LITTEXTURE:
3820 memset(&m, 0, sizeof(m));
3821 m.tex[0] = R_GetTexture(r_texture_white);
3822 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordlightmap2f;
3823 m.pointer_texcoord_bufferobject[0] = rsurface_model->surfmesh.vbo;
3824 m.pointer_texcoord_bufferoffset[0] = rsurface_model->surfmesh.vbooffset_texcoordlightmap2f;
3825 m.tex[1] = R_GetTexture(layer->texture);
3826 m.texmatrix[1] = layer->texmatrix;
3827 m.texrgbscale[1] = layertexrgbscale;
3828 m.pointer_texcoord[1] = rsurface_model->surfmesh.data_texcoordtexture2f;
3829 m.pointer_texcoord_bufferobject[1] = rsurface_model->surfmesh.vbo;
3830 m.pointer_texcoord_bufferoffset[1] = rsurface_model->surfmesh.vbooffset_texcoordtexture2f;
3831 R_Mesh_TextureState(&m);
3832 if (rsurface_lightmode == 2)
3833 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
3834 else if (rsurface_uselightmaptexture)
3835 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
3837 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
3839 case TEXTURELAYERTYPE_TEXTURE:
3840 memset(&m, 0, sizeof(m));
3841 m.tex[0] = R_GetTexture(layer->texture);
3842 m.texmatrix[0] = layer->texmatrix;
3843 m.texrgbscale[0] = layertexrgbscale;
3844 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3845 m.pointer_texcoord_bufferobject[0] = rsurface_model->surfmesh.vbo;
3846 m.pointer_texcoord_bufferoffset[0] = rsurface_model->surfmesh.vbooffset_texcoordtexture2f;
3847 R_Mesh_TextureState(&m);
3848 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
3850 case TEXTURELAYERTYPE_FOG:
3851 memset(&m, 0, sizeof(m));
3852 m.texrgbscale[0] = layertexrgbscale;
3855 m.tex[0] = R_GetTexture(layer->texture);
3856 m.texmatrix[0] = layer->texmatrix;
3857 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3858 m.pointer_texcoord_bufferobject[0] = rsurface_model->surfmesh.vbo;
3859 m.pointer_texcoord_bufferoffset[0] = rsurface_model->surfmesh.vbooffset_texcoordtexture2f;
3861 R_Mesh_TextureState(&m);
3862 // generate a color array for the fog pass
3863 R_Mesh_ColorPointer(rsurface_array_color4f, 0, 0);
3864 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3868 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3869 for (i = 0, v = (rsurface_vertex3f + 3 * surface->num_firstvertex), c = (rsurface_array_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4)
3871 f = 1 - FogPoint_Model(v);
3872 c[0] = layercolor[0];
3873 c[1] = layercolor[1];
3874 c[2] = layercolor[2];
3875 c[3] = f * layercolor[3];
3878 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3881 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
3883 GL_LockArrays(0, 0);
3886 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
3888 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3889 GL_AlphaTest(false);
3893 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, msurface_t **texturesurfacelist)
3895 // OpenGL 1.1 - crusty old voodoo path
3896 int texturesurfaceindex;
3900 const texturelayer_t *layer;
3901 if (rsurface_mode != RSURFMODE_MULTIPASS)
3902 rsurface_mode = RSURFMODE_MULTIPASS;
3903 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
3904 for (layerindex = 0, layer = rsurface_texture->currentlayers;layerindex < rsurface_texture->currentnumlayers;layerindex++, layer++)
3906 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
3908 if (layerindex == 0)
3912 GL_AlphaTest(false);
3913 qglDepthFunc(GL_EQUAL);CHECKGLERROR
3916 GL_DepthMask(layer->depthmask);
3917 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
3918 R_Mesh_ColorPointer(NULL, 0, 0);
3919 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
3920 switch (layer->type)
3922 case TEXTURELAYERTYPE_LITTEXTURE:
3923 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
3925 // two-pass lit texture with 2x rgbscale
3926 // first the lightmap pass
3927 memset(&m, 0, sizeof(m));
3928 m.tex[0] = R_GetTexture(r_texture_white);
3929 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordlightmap2f;
3930 m.pointer_texcoord_bufferobject[0] = rsurface_model->surfmesh.vbo;
3931 m.pointer_texcoord_bufferoffset[0] = rsurface_model->surfmesh.vbooffset_texcoordlightmap2f;
3932 R_Mesh_TextureState(&m);
3933 if (rsurface_lightmode == 2)
3934 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
3935 else if (rsurface_uselightmaptexture)
3936 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
3938 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
3939 GL_LockArrays(0, 0);
3940 // then apply the texture to it
3941 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
3942 memset(&m, 0, sizeof(m));
3943 m.tex[0] = R_GetTexture(layer->texture);
3944 m.texmatrix[0] = layer->texmatrix;
3945 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3946 m.pointer_texcoord_bufferobject[0] = rsurface_model->surfmesh.vbo;
3947 m.pointer_texcoord_bufferoffset[0] = rsurface_model->surfmesh.vbooffset_texcoordtexture2f;
3948 R_Mesh_TextureState(&m);
3949 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layer->color[0] * 0.5f, layer->color[1] * 0.5f, layer->color[2] * 0.5f, layer->color[3], layer->color[0] != 2 || layer->color[1] != 2 || layer->color[2] != 2 || layer->color[3] != 1, false);
3953 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
3954 memset(&m, 0, sizeof(m));
3955 m.tex[0] = R_GetTexture(layer->texture);
3956 m.texmatrix[0] = layer->texmatrix;
3957 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3958 m.pointer_texcoord_bufferobject[0] = rsurface_model->surfmesh.vbo;
3959 m.pointer_texcoord_bufferoffset[0] = rsurface_model->surfmesh.vbooffset_texcoordtexture2f;
3960 R_Mesh_TextureState(&m);
3961 if (rsurface_lightmode == 2)
3962 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layer->color[0], layer->color[1], layer->color[2], layer->color[3], layer->color[0] != 1 || layer->color[1] != 1 || layer->color[2] != 1 || layer->color[3] != 1, applyfog);
3964 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layer->color[0], layer->color[1], layer->color[2], layer->color[3], layer->color[0] != 1 || layer->color[1] != 1 || layer->color[2] != 1 || layer->color[3] != 1, applyfog);
3967 case TEXTURELAYERTYPE_TEXTURE:
3968 // singletexture unlit texture with transparency support
3969 memset(&m, 0, sizeof(m));
3970 m.tex[0] = R_GetTexture(layer->texture);
3971 m.texmatrix[0] = layer->texmatrix;
3972 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3973 m.pointer_texcoord_bufferobject[0] = rsurface_model->surfmesh.vbo;
3974 m.pointer_texcoord_bufferoffset[0] = rsurface_model->surfmesh.vbooffset_texcoordtexture2f;
3975 R_Mesh_TextureState(&m);
3976 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layer->color[0], layer->color[1], layer->color[2], layer->color[3], layer->color[0] != 1 || layer->color[1] != 1 || layer->color[2] != 1 || layer->color[3] != 1, applyfog);
3978 case TEXTURELAYERTYPE_FOG:
3979 // singletexture fogging
3980 R_Mesh_ColorPointer(rsurface_array_color4f, 0, 0);
3983 memset(&m, 0, sizeof(m));
3984 m.tex[0] = R_GetTexture(layer->texture);
3985 m.texmatrix[0] = layer->texmatrix;
3986 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3987 m.pointer_texcoord_bufferobject[0] = rsurface_model->surfmesh.vbo;
3988 m.pointer_texcoord_bufferoffset[0] = rsurface_model->surfmesh.vbooffset_texcoordtexture2f;
3989 R_Mesh_TextureState(&m);
3992 R_Mesh_ResetTextureState();
3993 // generate a color array for the fog pass
3994 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3998 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3999 for (i = 0, v = (rsurface_vertex3f + 3 * surface->num_firstvertex), c = (rsurface_array_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4)
4001 f = 1 - FogPoint_Model(v);
4002 c[0] = layer->color[0];
4003 c[1] = layer->color[1];
4004 c[2] = layer->color[2];
4005 c[3] = f * layer->color[3];
4008 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
4011 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
4013 GL_LockArrays(0, 0);
4016 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
4018 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
4019 GL_AlphaTest(false);
4023 static void R_DrawTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist)
4025 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_NODRAW)
4027 r_shadow_rtlight = NULL;
4028 r_refdef.stats.entities_surfaces += texturenumsurfaces;
4030 if (r_showsurfaces.integer)
4031 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
4032 else if (rsurface_texture->currentmaterialflags & MATERIALFLAG_SKY)
4033 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
4034 else if (rsurface_texture->currentnumlayers)
4036 GL_DepthRange(0, (rsurface_texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
4037 GL_DepthTest(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
4038 GL_CullFace((rsurface_texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
4039 GL_BlendFunc(rsurface_texture->currentlayers[0].blendfunc1, rsurface_texture->currentlayers[0].blendfunc2);
4040 GL_DepthMask(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_BLENDED));
4041 GL_Color(rsurface_entity->colormod[0], rsurface_entity->colormod[1], rsurface_entity->colormod[2], rsurface_texture->currentalpha);
4042 GL_AlphaTest((rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4043 // FIXME: identify models using a better check than rsurface_model->brush.shadowmesh
4044 rsurface_lightmode = ((rsurface_texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT) || rsurface_model->brush.shadowmesh) ? 0 : 2;
4045 if (r_glsl.integer && gl_support_fragment_shader)
4046 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist);
4047 else if (gl_combine.integer && r_textureunits.integer >= 2)
4048 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist);
4050 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist);
4053 GL_LockArrays(0, 0);
4056 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
4059 int texturenumsurfaces, endsurface;
4061 msurface_t *surface;
4062 msurface_t *texturesurfacelist[1024];
4064 // if the model is static it doesn't matter what value we give for
4065 // wantnormals and wanttangents, so this logic uses only rules applicable
4066 // to a model, knowing that they are meaningless otherwise
4067 if (ent == r_refdef.worldentity)
4068 RSurf_ActiveWorldEntity();
4069 else if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
4070 RSurf_ActiveModelEntity(ent, false, false);
4072 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
4074 for (i = 0;i < numsurfaces;i = j)
4077 surface = rsurface_model->data_surfaces + surfacelist[i];
4078 texture = surface->texture;
4079 R_UpdateTextureInfo(ent, texture);
4080 rsurface_texture = texture->currentframe;
4081 rsurface_uselightmaptexture = surface->lightmaptexture != NULL;
4082 // scan ahead until we find a different texture
4083 endsurface = min(i + 1024, numsurfaces);
4084 texturenumsurfaces = 0;
4085 texturesurfacelist[texturenumsurfaces++] = surface;
4086 for (;j < endsurface;j++)
4088 surface = rsurface_model->data_surfaces + surfacelist[j];
4089 if (texture != surface->texture || rsurface_uselightmaptexture != (surface->lightmaptexture != NULL))
4091 texturesurfacelist[texturenumsurfaces++] = surface;
4093 // render the range of surfaces
4094 R_DrawTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
4100 void R_QueueSurfaceList(int numsurfaces, msurface_t **surfacelist, int flagsmask)
4103 vec3_t tempcenter, center;
4105 // break the surface list down into batches by texture and use of lightmapping
4106 for (i = 0;i < numsurfaces;i = j)
4109 // texture is the base texture pointer, rsurface_texture is the
4110 // current frame/skin the texture is directing us to use (for example
4111 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
4112 // use skin 1 instead)
4113 texture = surfacelist[i]->texture;
4114 rsurface_texture = texture->currentframe;
4115 rsurface_uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
4116 if (!(rsurface_texture->currentmaterialflags & flagsmask))
4118 // if this texture is not the kind we want, skip ahead to the next one
4119 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
4123 if (rsurface_texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
4125 // transparent surfaces get pushed off into the transparent queue
4126 const msurface_t *surface = surfacelist[i];
4127 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
4128 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
4129 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
4130 Matrix4x4_Transform(&rsurface_entity->matrix, tempcenter, center);
4131 R_MeshQueue_AddTransparent(rsurface_texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_view.origin : center, R_DrawSurface_TransparentCallback, rsurface_entity, surface - rsurface_model->data_surfaces, r_shadow_rtlight);
4135 // simply scan ahead until we find a different texture or lightmap state
4136 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface_uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
4138 // render the range of surfaces
4139 R_DrawTextureSurfaceList(j - i, surfacelist + i);
4144 float locboxvertex3f[6*4*3] =
4146 1,0,1, 1,0,0, 1,1,0, 1,1,1,
4147 0,1,1, 0,1,0, 0,0,0, 0,0,1,
4148 1,1,1, 1,1,0, 0,1,0, 0,1,1,
4149 0,0,1, 0,0,0, 1,0,0, 1,0,1,
4150 0,0,1, 1,0,1, 1,1,1, 0,1,1,
4151 1,0,0, 0,0,0, 0,1,0, 1,1,0
4154 int locboxelement3i[6*2*3] =
4164 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
4167 cl_locnode_t *loc = (cl_locnode_t *)ent;
4169 float vertex3f[6*4*3];
4171 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4172 GL_DepthMask(false);
4173 GL_DepthRange(0, 1);
4175 GL_CullFace(GL_NONE);
4176 R_Mesh_Matrix(&identitymatrix);
4178 R_Mesh_VertexPointer(vertex3f, 0, 0);
4179 R_Mesh_ColorPointer(NULL, 0, 0);
4180 R_Mesh_ResetTextureState();
4183 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_view.colorscale,
4184 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_view.colorscale,
4185 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_view.colorscale,
4186 surfacelist[0] < 0 ? 0.5f : 0.125f);
4188 if (VectorCompare(loc->mins, loc->maxs))
4190 VectorSet(size, 2, 2, 2);
4191 VectorMA(loc->mins, -0.5f, size, mins);
4195 VectorCopy(loc->mins, mins);
4196 VectorSubtract(loc->maxs, loc->mins, size);
4199 for (i = 0;i < 6*4*3;)
4200 for (j = 0;j < 3;j++, i++)
4201 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
4203 R_Mesh_Draw(0, 6*4, 6*2, locboxelement3i, 0, 0);
4206 void R_DrawLocs(void)
4209 cl_locnode_t *loc, *nearestloc;
4211 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
4212 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
4214 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
4215 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
4219 void R_DrawCollisionBrushes(entity_render_t *ent)
4223 msurface_t *surface;
4224 model_t *model = ent->model;
4225 if (!model->brush.num_brushes)
4228 R_Mesh_ColorPointer(NULL, 0, 0);
4229 R_Mesh_ResetTextureState();
4230 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
4231 GL_DepthMask(false);
4232 GL_DepthRange(0, 1);
4233 GL_DepthTest(!r_showdisabledepthtest.integer);
4234 qglPolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);CHECKGLERROR
4235 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
4236 if (brush->colbrushf && brush->colbrushf->numtriangles)
4237 R_DrawCollisionBrush(brush->colbrushf);
4238 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
4239 if (surface->num_collisiontriangles)
4240 R_DrawCollisionSurface(ent, surface);
4241 qglPolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR
4244 void R_DrawTrianglesAndNormals(entity_render_t *ent, qboolean drawtris, qboolean drawnormals, int flagsmask)
4247 const int *elements;
4248 msurface_t *surface;
4249 model_t *model = ent->model;
4252 GL_DepthRange(0, 1);
4253 GL_DepthTest(!r_showdisabledepthtest.integer);
4255 GL_BlendFunc(GL_ONE, GL_ZERO);
4256 R_Mesh_ColorPointer(NULL, 0, 0);
4257 R_Mesh_ResetTextureState();
4258 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
4260 if (ent == r_refdef.worldentity && !r_viewcache.world_surfacevisible[j])
4262 rsurface_texture = surface->texture->currentframe;
4263 if ((rsurface_texture->currentmaterialflags & flagsmask) && surface->num_triangles)
4265 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
4268 if (!rsurface_texture->currentlayers->depthmask)
4269 GL_Color(r_showtris.value * r_view.colorscale, 0, 0, 1);
4270 else if (ent == r_refdef.worldentity)
4271 GL_Color(r_showtris.value * r_view.colorscale, r_showtris.value * r_view.colorscale, r_showtris.value * r_view.colorscale, 1);
4273 GL_Color(0, r_showtris.value * r_view.colorscale, 0, 1);
4274 elements = (ent->model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
4277 for (k = 0;k < surface->num_triangles;k++, elements += 3)
4279 qglArrayElement(elements[0]);qglArrayElement(elements[1]);
4280 qglArrayElement(elements[1]);qglArrayElement(elements[2]);
4281 qglArrayElement(elements[2]);qglArrayElement(elements[0]);
4288 GL_Color(r_shownormals.value * r_view.colorscale, 0, 0, 1);
4290 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
4292 VectorCopy(rsurface_vertex3f + l * 3, v);
4293 qglVertex3f(v[0], v[1], v[2]);
4294 VectorMA(v, 8, rsurface_svector3f + l * 3, v);
4295 qglVertex3f(v[0], v[1], v[2]);
4299 GL_Color(0, 0, r_shownormals.value * r_view.colorscale, 1);
4301 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
4303 VectorCopy(rsurface_vertex3f + l * 3, v);
4304 qglVertex3f(v[0], v[1], v[2]);
4305 VectorMA(v, 8, rsurface_tvector3f + l * 3, v);
4306 qglVertex3f(v[0], v[1], v[2]);
4310 GL_Color(0, r_shownormals.value * r_view.colorscale, 0, 1);
4312 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
4314 VectorCopy(rsurface_vertex3f + l * 3, v);
4315 qglVertex3f(v[0], v[1], v[2]);
4316 VectorMA(v, 8, rsurface_normal3f + l * 3, v);
4317 qglVertex3f(v[0], v[1], v[2]);
4324 rsurface_texture = NULL;
4327 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
4328 void R_DrawWorldSurfaces(qboolean skysurfaces)
4330 int i, j, endj, f, flagsmask;
4331 int counttriangles = 0;
4332 msurface_t *surface, **surfacechain;
4334 model_t *model = r_refdef.worldmodel;
4335 const int maxsurfacelist = 1024;
4336 int numsurfacelist = 0;
4337 msurface_t *surfacelist[1024];
4341 RSurf_ActiveWorldEntity();
4343 // update light styles
4344 if (!skysurfaces && model->brushq1.light_styleupdatechains)
4346 for (i = 0;i < model->brushq1.light_styles;i++)
4348 if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
4350 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
4351 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
4352 for (;(surface = *surfacechain);surfacechain++)
4353 surface->cached_dlight = true;
4358 R_UpdateAllTextureInfo(r_refdef.worldentity);
4359 flagsmask = skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL);
4362 rsurface_uselightmaptexture = false;
4363 rsurface_texture = NULL;
4365 j = model->firstmodelsurface;
4366 endj = j + model->nummodelsurfaces;
4369 // quickly skip over non-visible surfaces
4370 for (;j < endj && !r_viewcache.world_surfacevisible[j];j++)
4372 // quickly iterate over visible surfaces
4373 for (;j < endj && r_viewcache.world_surfacevisible[j];j++)
4375 // process this surface
4376 surface = model->data_surfaces + j;
4377 // if this surface fits the criteria, add it to the list
4378 if (surface->num_triangles)
4380 // if lightmap parameters changed, rebuild lightmap texture
4381 if (surface->cached_dlight)
4382 R_BuildLightMap(r_refdef.worldentity, surface);
4383 // add face to draw list
4384 surfacelist[numsurfacelist++] = surface;
4385 counttriangles += surface->num_triangles;
4386 if (numsurfacelist >= maxsurfacelist)
4388 R_QueueSurfaceList(numsurfacelist, surfacelist, flagsmask);
4395 R_QueueSurfaceList(numsurfacelist, surfacelist, flagsmask);
4396 r_refdef.stats.entities_triangles += counttriangles;
4399 if (r_showcollisionbrushes.integer && !skysurfaces)
4400 R_DrawCollisionBrushes(r_refdef.worldentity);
4402 if (r_showtris.integer || r_shownormals.integer)
4403 R_DrawTrianglesAndNormals(r_refdef.worldentity, r_showtris.integer, r_shownormals.integer, flagsmask);
4406 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces)
4408 int i, f, flagsmask;
4409 int counttriangles = 0;
4410 msurface_t *surface, *endsurface, **surfacechain;
4412 model_t *model = ent->model;
4413 const int maxsurfacelist = 1024;
4414 int numsurfacelist = 0;
4415 msurface_t *surfacelist[1024];
4419 // if the model is static it doesn't matter what value we give for
4420 // wantnormals and wanttangents, so this logic uses only rules applicable
4421 // to a model, knowing that they are meaningless otherwise
4422 if (ent == r_refdef.worldentity)
4423 RSurf_ActiveWorldEntity();
4424 else if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
4425 RSurf_ActiveModelEntity(ent, false, false);
4427 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
4429 // update light styles
4430 if (!skysurfaces && model->brushq1.light_styleupdatechains)
4432 for (i = 0;i < model->brushq1.light_styles;i++)
4434 if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
4436 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
4437 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
4438 for (;(surface = *surfacechain);surfacechain++)
4439 surface->cached_dlight = true;
4444 R_UpdateAllTextureInfo(ent);
4445 flagsmask = skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL);
4448 rsurface_uselightmaptexture = false;
4449 rsurface_texture = NULL;
4451 surface = model->data_surfaces + model->firstmodelsurface;
4452 endsurface = surface + model->nummodelsurfaces;
4453 for (;surface < endsurface;surface++)
4455 // if this surface fits the criteria, add it to the list
4456 if (surface->num_triangles)
4458 // if lightmap parameters changed, rebuild lightmap texture
4459 if (surface->cached_dlight)
4460 R_BuildLightMap(ent, surface);
4461 // add face to draw list
4462 surfacelist[numsurfacelist++] = surface;
4463 counttriangles += surface->num_triangles;
4464 if (numsurfacelist >= maxsurfacelist)
4466 R_QueueSurfaceList(numsurfacelist, surfacelist, flagsmask);
4472 R_QueueSurfaceList(numsurfacelist, surfacelist, flagsmask);
4473 r_refdef.stats.entities_triangles += counttriangles;
4476 if (r_showcollisionbrushes.integer && !skysurfaces)
4477 R_DrawCollisionBrushes(ent);
4479 if (r_showtris.integer || r_shownormals.integer)
4480 R_DrawTrianglesAndNormals(ent, r_showtris.integer, r_shownormals.integer, flagsmask);