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_showsurfaces = {0, "r_showsurfaces", "0", "shows surfaces as different colors"};
38 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
39 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
40 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"};
41 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"};
42 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
43 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"};
44 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"};
45 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"};
46 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
47 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
48 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
49 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
50 cvar_t r_fullbright = {0, "r_fullbright","0", "make everything bright cheat (not allowed in multiplayer)"};
51 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
52 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
53 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
54 cvar_t r_q1bsp_skymasking = {0, "r_qb1sp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
56 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
57 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
58 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
59 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
60 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
61 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
62 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
64 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)"};
66 cvar_t r_glsl = {0, "r_glsl", "1", "enables use of OpenGL 2.0 pixel shaders for lighting"};
67 cvar_t r_glsl_offsetmapping = {0, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
68 cvar_t r_glsl_offsetmapping_reliefmapping = {0, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
69 cvar_t r_glsl_offsetmapping_scale = {0, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
70 cvar_t r_glsl_deluxemapping = {0, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"};
72 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1", "enables animation smoothing on sprites (requires r_lerpmodels 1)"};
73 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
74 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
76 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
77 cvar_t r_bloom_intensity = {CVAR_SAVE, "r_bloom_intensity", "1.5", "how bright the glow is"};
78 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
79 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
80 cvar_t r_bloom_power = {CVAR_SAVE, "r_bloom_power", "2", "how much to darken the image before blurring to make the bloom effect"};
82 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
83 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
84 cvar_t r_hdr_bloomintensity = {CVAR_SAVE, "r_hdr_bloomintensity", "0.5", "amount of bloom"};
85 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
87 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"};
89 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"};
91 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
93 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"}; // used for testing renderer code changes, otherwise does nothing
94 cvar_t r_batchmode = {0, "r_batchmode", "1", "selects method of rendering multiple surfaces with one driver call (values are 0, 1, 2, etc...)"};
96 rtexture_t *r_bloom_texture_screen;
97 rtexture_t *r_bloom_texture_bloom;
98 rtexture_t *r_texture_blanknormalmap;
99 rtexture_t *r_texture_white;
100 rtexture_t *r_texture_black;
101 rtexture_t *r_texture_notexture;
102 rtexture_t *r_texture_whitecube;
103 rtexture_t *r_texture_normalizationcube;
104 rtexture_t *r_texture_fogattenuation;
105 //rtexture_t *r_texture_fogintensity;
107 // information about each possible shader permutation
108 r_glsl_permutation_t r_glsl_permutations[SHADERPERMUTATION_COUNT];
109 // currently selected permutation
110 r_glsl_permutation_t *r_glsl_permutation;
112 // temporary variable used by a macro
115 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
118 for (i = 0;i < verts;i++)
129 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
132 for (i = 0;i < verts;i++)
142 // FIXME: move this to client?
145 if (gamemode == GAME_NEHAHRA)
147 Cvar_Set("gl_fogenable", "0");
148 Cvar_Set("gl_fogdensity", "0.2");
149 Cvar_Set("gl_fogred", "0.3");
150 Cvar_Set("gl_foggreen", "0.3");
151 Cvar_Set("gl_fogblue", "0.3");
153 r_refdef.fog_density = r_refdef.fog_red = r_refdef.fog_green = r_refdef.fog_blue = 0.0f;
156 // FIXME: move this to client?
157 void FOG_registercvars(void)
162 if (gamemode == GAME_NEHAHRA)
164 Cvar_RegisterVariable (&gl_fogenable);
165 Cvar_RegisterVariable (&gl_fogdensity);
166 Cvar_RegisterVariable (&gl_fogred);
167 Cvar_RegisterVariable (&gl_foggreen);
168 Cvar_RegisterVariable (&gl_fogblue);
169 Cvar_RegisterVariable (&gl_fogstart);
170 Cvar_RegisterVariable (&gl_fogend);
173 r = (-1.0/256.0) * (FOGTABLEWIDTH * FOGTABLEWIDTH);
174 for (x = 0;x < FOGTABLEWIDTH;x++)
176 alpha = exp(r / ((double)x*(double)x));
177 if (x == FOGTABLEWIDTH - 1)
179 r_refdef.fogtable[x] = bound(0, alpha, 1);
183 static void R_BuildBlankTextures(void)
185 unsigned char data[4];
186 data[0] = 128; // normal X
187 data[1] = 128; // normal Y
188 data[2] = 255; // normal Z
189 data[3] = 128; // height
190 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
195 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
200 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
203 static void R_BuildNoTexture(void)
206 unsigned char pix[16][16][4];
207 // this makes a light grey/dark grey checkerboard texture
208 for (y = 0;y < 16;y++)
210 for (x = 0;x < 16;x++)
212 if ((y < 8) ^ (x < 8))
228 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_RGBA, TEXF_MIPMAP, NULL);
231 static void R_BuildWhiteCube(void)
233 unsigned char data[6*1*1*4];
234 data[ 0] = 255;data[ 1] = 255;data[ 2] = 255;data[ 3] = 255;
235 data[ 4] = 255;data[ 5] = 255;data[ 6] = 255;data[ 7] = 255;
236 data[ 8] = 255;data[ 9] = 255;data[10] = 255;data[11] = 255;
237 data[12] = 255;data[13] = 255;data[14] = 255;data[15] = 255;
238 data[16] = 255;data[17] = 255;data[18] = 255;data[19] = 255;
239 data[20] = 255;data[21] = 255;data[22] = 255;data[23] = 255;
240 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
243 static void R_BuildNormalizationCube(void)
247 vec_t s, t, intensity;
249 unsigned char data[6][NORMSIZE][NORMSIZE][4];
250 for (side = 0;side < 6;side++)
252 for (y = 0;y < NORMSIZE;y++)
254 for (x = 0;x < NORMSIZE;x++)
256 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
257 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
292 intensity = 127.0f / sqrt(DotProduct(v, v));
293 data[side][y][x][0] = (unsigned char)(128.0f + intensity * v[0]);
294 data[side][y][x][1] = (unsigned char)(128.0f + intensity * v[1]);
295 data[side][y][x][2] = (unsigned char)(128.0f + intensity * v[2]);
296 data[side][y][x][3] = 255;
300 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, &data[0][0][0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
303 static void R_BuildFogTexture(void)
308 unsigned char data1[FOGWIDTH][4];
309 //unsigned char data2[FOGWIDTH][4];
310 r = (-1.0/256.0) * (FOGWIDTH * FOGWIDTH);
311 for (x = 0;x < FOGWIDTH;x++)
313 alpha = exp(r / ((double)x*(double)x));
314 if (x == FOGWIDTH - 1)
316 b = (int)(256.0 * alpha);
317 b = bound(0, b, 255);
318 data1[x][0] = 255 - b;
319 data1[x][1] = 255 - b;
320 data1[x][2] = 255 - b;
327 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
328 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
331 static const char *builtinshaderstring =
332 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
333 "// written by Forest 'LordHavoc' Hale\n"
335 "// common definitions between vertex shader and fragment shader:\n"
337 "varying vec2 TexCoord;\n"
338 "varying vec2 TexCoordLightmap;\n"
340 "varying vec3 CubeVector;\n"
341 "varying vec3 LightVector;\n"
342 "varying vec3 EyeVector;\n"
344 "varying vec3 EyeVectorModelSpace;\n"
347 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
348 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
349 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
354 "// vertex shader specific:\n"
355 "#ifdef VERTEX_SHADER\n"
357 "uniform vec3 LightPosition;\n"
358 "uniform vec3 EyePosition;\n"
359 "uniform vec3 LightDir;\n"
361 "// TODO: get rid of tangentt (texcoord2) and use a crossproduct to regenerate it from tangents (texcoord1) and normal (texcoord3)\n"
365 " gl_FrontColor = gl_Color;\n"
366 " // copy the surface texcoord\n"
367 " TexCoord = vec2(gl_TextureMatrix[0] * gl_MultiTexCoord0);\n"
368 "#if !defined(MODE_LIGHTSOURCE) && !defined(MODE_LIGHTDIRECTION)\n"
369 " TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
372 "#ifdef MODE_LIGHTSOURCE\n"
373 " // transform vertex position into light attenuation/cubemap space\n"
374 " // (-1 to +1 across the light box)\n"
375 " CubeVector = vec3(gl_TextureMatrix[3] * gl_Vertex);\n"
377 " // transform unnormalized light direction into tangent space\n"
378 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
379 " // normalize it per pixel)\n"
380 " vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
381 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
382 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
383 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
386 "#ifdef MODE_LIGHTDIRECTION\n"
387 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
388 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
389 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
392 " // transform unnormalized eye direction into tangent space\n"
394 " vec3 EyeVectorModelSpace;\n"
396 " EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
397 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
398 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
399 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
401 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
402 " VectorS = gl_MultiTexCoord1.xyz;\n"
403 " VectorT = gl_MultiTexCoord2.xyz;\n"
404 " VectorR = gl_MultiTexCoord3.xyz;\n"
407 " // transform vertex to camera space, using ftransform to match non-VS\n"
409 " gl_Position = ftransform();\n"
412 "#endif // VERTEX_SHADER\n"
417 "// fragment shader specific:\n"
418 "#ifdef FRAGMENT_SHADER\n"
420 "uniform sampler2D Texture_Normal;\n"
421 "uniform sampler2D Texture_Color;\n"
422 "uniform sampler2D Texture_Gloss;\n"
423 "uniform samplerCube Texture_Cube;\n"
424 "uniform sampler2D Texture_FogMask;\n"
425 "uniform sampler2D Texture_Pants;\n"
426 "uniform sampler2D Texture_Shirt;\n"
427 "uniform sampler2D Texture_Lightmap;\n"
428 "uniform sampler2D Texture_Deluxemap;\n"
429 "uniform sampler2D Texture_Glow;\n"
431 "uniform vec3 LightColor;\n"
432 "uniform vec3 AmbientColor;\n"
433 "uniform vec3 DiffuseColor;\n"
434 "uniform vec3 SpecularColor;\n"
435 "uniform vec3 Color_Pants;\n"
436 "uniform vec3 Color_Shirt;\n"
437 "uniform vec3 FogColor;\n"
439 "uniform float GlowScale;\n"
440 "uniform float SceneBrightness;\n"
442 "uniform float OffsetMapping_Scale;\n"
443 "uniform float OffsetMapping_Bias;\n"
444 "uniform float FogRangeRecip;\n"
446 "uniform float AmbientScale;\n"
447 "uniform float DiffuseScale;\n"
448 "uniform float SpecularScale;\n"
449 "uniform float SpecularPower;\n"
453 " // apply offsetmapping\n"
454 "#ifdef USEOFFSETMAPPING\n"
455 " vec2 TexCoordOffset = TexCoord;\n"
456 "#define TexCoord TexCoordOffset\n"
458 " vec3 eyedir = vec3(normalize(EyeVector));\n"
459 " float depthbias = 1.0 - eyedir.z; // should this be a -?\n"
460 " depthbias = 1.0 - depthbias * depthbias;\n"
462 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
463 " // 14 sample relief mapping: linear search and then binary search\n"
464 " vec3 OffsetVector = vec3(EyeVector.xy * (1.0 / EyeVector.z) * depthbias * OffsetMapping_Scale * vec2(-0.1, 0.1), -0.1);\n"
465 " vec3 RT = vec3(TexCoord - OffsetVector.xy * 10.0, 1.0) + OffsetVector;\n"
466 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
467 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
468 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
469 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
470 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
471 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
472 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
473 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
474 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;OffsetVector *= 0.5;RT -= OffsetVector;\n"
475 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;OffsetVector *= 0.5;RT -= OffsetVector;\n"
476 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;OffsetVector *= 0.5;RT -= OffsetVector;\n"
477 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;OffsetVector *= 0.5;RT -= OffsetVector;\n"
478 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;OffsetVector *= 0.5;RT -= OffsetVector;\n"
479 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;OffsetVector *= 0.5;RT -= OffsetVector;\n"
480 " TexCoord = RT.xy;\n"
482 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
483 " vec2 OffsetVector = vec2((EyeVector.xy * (1.0 / EyeVector.z) * depthbias) * OffsetMapping_Scale * vec2(-0.333, 0.333));\n"
484 " //TexCoord += OffsetVector * 3.0;\n"
485 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
486 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
487 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
491 " // combine the diffuse textures (base, pants, shirt)\n"
492 " vec4 color = vec4(texture2D(Texture_Color, TexCoord));\n"
493 "#ifdef USECOLORMAPPING\n"
494 " color.rgb += vec3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + vec3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
500 "#ifdef MODE_LIGHTSOURCE\n"
503 " // get the surface normal and light normal\n"
504 " vec3 surfacenormal = normalize(vec3(texture2D(Texture_Normal, TexCoord)) - 0.5);\n"
505 " vec3 diffusenormal = vec3(normalize(LightVector));\n"
507 " // calculate directional shading\n"
508 " color.rgb *= (AmbientScale + DiffuseScale * max(dot(surfacenormal, diffusenormal), 0.0));\n"
509 "#ifdef USESPECULAR\n"
510 " vec3 specularnormal = vec3(normalize(diffusenormal + vec3(normalize(EyeVector))));\n"
511 " color.rgb += vec3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(max(dot(surfacenormal, specularnormal), 0.0), SpecularPower);\n"
514 "#ifdef USECUBEFILTER\n"
515 " // apply light cubemap filter\n"
516 " //color.rgb *= normalize(CubeVector) * 0.5 + 0.5;//vec3(textureCube(Texture_Cube, CubeVector));\n"
517 " color.rgb *= vec3(textureCube(Texture_Cube, CubeVector));\n"
520 " // apply light color\n"
521 " color.rgb *= LightColor;\n"
523 " // apply attenuation\n"
525 " // the attenuation is (1-(x*x+y*y+z*z)) which gives a large bright\n"
526 " // center and sharp falloff at the edge, this is about the most efficient\n"
527 " // we can get away with as far as providing illumination.\n"
529 " // pow(1-(x*x+y*y+z*z), 4) is far more realistic but needs large lights to\n"
530 " // provide significant illumination, large = slow = pain.\n"
531 " color.rgb *= max(1.0 - dot(CubeVector, CubeVector), 0.0);\n"
536 "#elif defined(MODE_LIGHTDIRECTION)\n"
537 " // directional model lighting\n"
539 " // get the surface normal and light normal\n"
540 " vec3 surfacenormal = normalize(vec3(texture2D(Texture_Normal, TexCoord)) - 0.5);\n"
541 " vec3 diffusenormal = vec3(normalize(LightVector));\n"
543 " // calculate directional shading\n"
544 " color.rgb *= AmbientColor + DiffuseColor * max(dot(surfacenormal, diffusenormal), 0.0);\n"
545 "#ifdef USESPECULAR\n"
546 " vec3 specularnormal = vec3(normalize(diffusenormal + vec3(normalize(EyeVector))));\n"
547 " color.rgb += vec3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(max(dot(surfacenormal, specularnormal), 0.0), SpecularPower);\n"
553 "#elif defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE)\n"
554 " // deluxemap lightmapping using light vectors in modelspace (evil q3map2)\n"
556 " // get the surface normal and light normal\n"
557 " vec3 surfacenormal = normalize(vec3(texture2D(Texture_Normal, TexCoord)) - 0.5);\n"
558 " vec3 diffusenormal_modelspace = vec3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - 0.5;\n"
559 " vec3 diffusenormal = normalize(vec3(dot(diffusenormal_modelspace, VectorS), dot(diffusenormal_modelspace, VectorT), dot(diffusenormal_modelspace, VectorR)));\n"
561 " // calculate directional shading\n"
562 " vec3 tempcolor = color.rgb * (DiffuseScale * max(dot(surfacenormal, diffusenormal), 0.0));\n"
563 "#ifdef USESPECULAR\n"
564 " vec3 specularnormal = vec3(normalize(diffusenormal + vec3(normalize(EyeVector))));\n"
565 " tempcolor += vec3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(max(dot(surfacenormal, specularnormal), 0.0), SpecularPower);\n"
568 " // apply lightmap color\n"
569 " color.rgb = tempcolor * vec3(texture2D(Texture_Lightmap, TexCoordLightmap)) + color.rgb * vec3(AmbientScale);\n"
574 "#elif defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
575 " // deluxemap lightmapping using light vectors in tangentspace\n"
577 " // get the surface normal and light normal\n"
578 " vec3 surfacenormal = normalize(vec3(texture2D(Texture_Normal, TexCoord)) - 0.5);\n"
579 " vec3 diffusenormal = normalize(vec3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - 0.5);\n"
581 " // calculate directional shading\n"
582 " vec3 tempcolor = color.rgb * (DiffuseScale * max(dot(surfacenormal, diffusenormal), 0.0));\n"
583 "#ifdef USESPECULAR\n"
584 " vec3 specularnormal = vec3(normalize(diffusenormal + vec3(normalize(EyeVector))));\n"
585 " tempcolor += vec3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(max(dot(surfacenormal, specularnormal), 0.0), SpecularPower);\n"
588 " // apply lightmap color\n"
589 " color.rgb = tempcolor * vec3(texture2D(Texture_Lightmap, TexCoordLightmap)) + color.rgb * vec3(AmbientScale);\n"
594 "#else // MODE none (lightmap)\n"
595 " // apply lightmap color\n"
596 " color.rgb *= vec3(texture2D(Texture_Lightmap, TexCoordLightmap)) * DiffuseScale + vec3(AmbientScale);\n"
599 " color *= gl_Color;\n"
602 " color.rgb += vec3(texture2D(Texture_Glow, TexCoord)) * GlowScale;\n"
607 " float fog = texture2D(Texture_FogMask, vec2(length(EyeVectorModelSpace)*FogRangeRecip, 0.0)).x;\n"
608 " color.rgb = color.rgb * fog + FogColor * (1.0 - fog);\n"
611 " color.rgb *= SceneBrightness;\n"
613 " gl_FragColor = color;\n"
616 "#endif // FRAGMENT_SHADER\n"
619 void R_GLSL_CompilePermutation(int permutation)
621 r_glsl_permutation_t *p = r_glsl_permutations + permutation;
622 int vertstrings_count;
623 int fragstrings_count;
625 const char *vertstrings_list[SHADERPERMUTATION_COUNT+1];
626 const char *fragstrings_list[SHADERPERMUTATION_COUNT+1];
627 char permutationname[256];
631 vertstrings_list[0] = "#define VERTEX_SHADER\n";
632 fragstrings_list[0] = "#define FRAGMENT_SHADER\n";
633 vertstrings_count = 1;
634 fragstrings_count = 1;
635 permutationname[0] = 0;
636 if (permutation & SHADERPERMUTATION_MODE_LIGHTSOURCE)
638 vertstrings_list[vertstrings_count++] = "#define MODE_LIGHTSOURCE\n";
639 fragstrings_list[fragstrings_count++] = "#define MODE_LIGHTSOURCE\n";
640 strlcat(permutationname, " lightsource", sizeof(permutationname));
642 if (permutation & SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_MODELSPACE)
644 vertstrings_list[vertstrings_count++] = "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n";
645 fragstrings_list[fragstrings_count++] = "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n";
646 strlcat(permutationname, " lightdirectionmap_modelspace", sizeof(permutationname));
648 if (permutation & SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)
650 vertstrings_list[vertstrings_count++] = "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n";
651 fragstrings_list[fragstrings_count++] = "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n";
652 strlcat(permutationname, " lightdirectionmap_tangentspace", sizeof(permutationname));
654 if (permutation & SHADERPERMUTATION_MODE_LIGHTDIRECTION)
656 vertstrings_list[vertstrings_count++] = "#define MODE_LIGHTDIRECTION\n";
657 fragstrings_list[fragstrings_count++] = "#define MODE_LIGHTDIRECTION\n";
658 strlcat(permutationname, " lightdirection", sizeof(permutationname));
660 if (permutation & SHADERPERMUTATION_GLOW)
662 vertstrings_list[vertstrings_count++] = "#define USEGLOW\n";
663 fragstrings_list[fragstrings_count++] = "#define USEGLOW\n";
664 strlcat(permutationname, " glow", sizeof(permutationname));
666 if (permutation & SHADERPERMUTATION_COLORMAPPING)
668 vertstrings_list[vertstrings_count++] = "#define USECOLORMAPPING\n";
669 fragstrings_list[fragstrings_count++] = "#define USECOLORMAPPING\n";
670 strlcat(permutationname, " colormapping", sizeof(permutationname));
672 if (permutation & SHADERPERMUTATION_SPECULAR)
674 vertstrings_list[vertstrings_count++] = "#define USESPECULAR\n";
675 fragstrings_list[fragstrings_count++] = "#define USESPECULAR\n";
676 strlcat(permutationname, " specular", sizeof(permutationname));
678 if (permutation & SHADERPERMUTATION_FOG)
680 vertstrings_list[vertstrings_count++] = "#define USEFOG\n";
681 fragstrings_list[fragstrings_count++] = "#define USEFOG\n";
682 strlcat(permutationname, " fog", sizeof(permutationname));
684 if (permutation & SHADERPERMUTATION_CUBEFILTER)
686 vertstrings_list[vertstrings_count++] = "#define USECUBEFILTER\n";
687 fragstrings_list[fragstrings_count++] = "#define USECUBEFILTER\n";
688 strlcat(permutationname, " cubefilter", sizeof(permutationname));
690 if (permutation & SHADERPERMUTATION_OFFSETMAPPING)
692 vertstrings_list[vertstrings_count++] = "#define USEOFFSETMAPPING\n";
693 fragstrings_list[fragstrings_count++] = "#define USEOFFSETMAPPING\n";
694 strlcat(permutationname, " offsetmapping", sizeof(permutationname));
696 if (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING)
698 vertstrings_list[vertstrings_count++] = "#define USEOFFSETMAPPING_RELIEFMAPPING\n";
699 fragstrings_list[fragstrings_count++] = "#define USEOFFSETMAPPING_RELIEFMAPPING\n";
700 strlcat(permutationname, " OFFSETMAPPING_RELIEFMAPPING", sizeof(permutationname));
702 shaderstring = (char *)FS_LoadFile("glsl/default.glsl", r_main_mempool, false, NULL);
705 Con_DPrintf("GLSL shader text loaded from disk\n");
706 vertstrings_list[vertstrings_count++] = shaderstring;
707 fragstrings_list[fragstrings_count++] = shaderstring;
711 vertstrings_list[vertstrings_count++] = builtinshaderstring;
712 fragstrings_list[fragstrings_count++] = builtinshaderstring;
714 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, fragstrings_count, fragstrings_list);
718 qglUseProgramObjectARB(p->program);CHECKGLERROR
719 p->loc_Texture_Normal = qglGetUniformLocationARB(p->program, "Texture_Normal");
720 p->loc_Texture_Color = qglGetUniformLocationARB(p->program, "Texture_Color");
721 p->loc_Texture_Gloss = qglGetUniformLocationARB(p->program, "Texture_Gloss");
722 p->loc_Texture_Cube = qglGetUniformLocationARB(p->program, "Texture_Cube");
723 p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
724 p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
725 p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
726 p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
727 p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
728 p->loc_Texture_Glow = qglGetUniformLocationARB(p->program, "Texture_Glow");
729 p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
730 p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
731 p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
732 p->loc_LightColor = qglGetUniformLocationARB(p->program, "LightColor");
733 p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants");
734 p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt");
735 p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip");
736 p->loc_AmbientScale = qglGetUniformLocationARB(p->program, "AmbientScale");
737 p->loc_DiffuseScale = qglGetUniformLocationARB(p->program, "DiffuseScale");
738 p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
739 p->loc_SpecularScale = qglGetUniformLocationARB(p->program, "SpecularScale");
740 p->loc_GlowScale = qglGetUniformLocationARB(p->program, "GlowScale");
741 p->loc_SceneBrightness = qglGetUniformLocationARB(p->program, "SceneBrightness");
742 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
743 p->loc_AmbientColor = qglGetUniformLocationARB(p->program, "AmbientColor");
744 p->loc_DiffuseColor = qglGetUniformLocationARB(p->program, "DiffuseColor");
745 p->loc_SpecularColor = qglGetUniformLocationARB(p->program, "SpecularColor");
746 p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
747 if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal, 0);
748 if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color, 1);
749 if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss, 2);
750 if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube, 3);
751 if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask, 4);
752 if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants, 5);
753 if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt, 6);
754 if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap, 7);
755 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap, 8);
756 if (p->loc_Texture_Glow >= 0) qglUniform1iARB(p->loc_Texture_Glow, 9);
758 qglUseProgramObjectARB(0);CHECKGLERROR
761 Con_Printf("permutation%s failed for shader %s, some features may not work properly!\n", permutationname, "glsl/default.glsl");
763 Mem_Free(shaderstring);
766 void R_GLSL_Restart_f(void)
769 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
770 if (r_glsl_permutations[i].program)
771 GL_Backend_FreeProgram(r_glsl_permutations[i].program);
772 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
775 int R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting)
777 // select a permutation of the lighting shader appropriate to this
778 // combination of texture, entity, light source, and fogging, only use the
779 // minimum features necessary to avoid wasting rendering time in the
780 // fragment shader on features that are not being used
782 float specularscale = rsurface_texture->specularscale;
783 r_glsl_permutation = NULL;
784 if (r_shadow_rtlight)
786 permutation |= SHADERPERMUTATION_MODE_LIGHTSOURCE;
787 specularscale *= r_shadow_rtlight->specularscale;
788 if (r_shadow_rtlight->currentcubemap != r_texture_whitecube)
789 permutation |= SHADERPERMUTATION_CUBEFILTER;
793 if (!(rsurface_texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
796 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTION;
799 if (r_glsl_deluxemapping.integer >= 1 && r_refdef.worldmodel && r_refdef.worldmodel->brushq3.deluxemapping && rsurface_lightmaptexture)
801 if (r_refdef.worldmodel->brushq3.deluxemapping_modelspace)
802 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_MODELSPACE;
804 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
806 else if (r_glsl_deluxemapping.integer >= 2) // fake mode
807 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
810 if (rsurface_texture->skin.glow)
811 permutation |= SHADERPERMUTATION_GLOW;
813 if (specularscale > 0)
814 permutation |= SHADERPERMUTATION_SPECULAR;
815 if (r_refdef.fogenabled)
816 permutation |= SHADERPERMUTATION_FOG;
817 if (rsurface_texture->colormapping)
818 permutation |= SHADERPERMUTATION_COLORMAPPING;
819 if (r_glsl_offsetmapping.integer)
821 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
822 if (r_glsl_offsetmapping_reliefmapping.integer)
823 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
825 if (!r_glsl_permutations[permutation].program)
827 if (!r_glsl_permutations[permutation].compiled)
828 R_GLSL_CompilePermutation(permutation);
829 if (!r_glsl_permutations[permutation].program)
831 // remove features until we find a valid permutation
833 for (i = SHADERPERMUTATION_COUNT-1;;i>>=1)
835 // reduce i more quickly whenever it would not remove any bits
839 if (!r_glsl_permutations[permutation].compiled)
840 R_GLSL_CompilePermutation(permutation);
841 if (r_glsl_permutations[permutation].program)
844 return 0; // utterly failed
848 r_glsl_permutation = r_glsl_permutations + permutation;
850 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
851 R_Mesh_TexMatrix(0, &rsurface_texture->currenttexmatrix);
852 if (permutation & SHADERPERMUTATION_MODE_LIGHTSOURCE)
854 if (r_glsl_permutation->loc_Texture_Cube >= 0 && r_shadow_rtlight) R_Mesh_TexBindCubeMap(3, R_GetTexture(r_shadow_rtlight->currentcubemap));
855 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]);
856 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
857 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_shadow_rtlight->ambientscale);
858 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_shadow_rtlight->diffusescale);
859 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, specularscale);
861 else if (permutation & SHADERPERMUTATION_MODE_LIGHTDIRECTION)
863 if (r_glsl_permutation->loc_AmbientColor >= 0)
864 qglUniform3fARB(r_glsl_permutation->loc_AmbientColor, rsurface_entity->modellight_ambient[0], rsurface_entity->modellight_ambient[1], rsurface_entity->modellight_ambient[2]);
865 if (r_glsl_permutation->loc_DiffuseColor >= 0)
866 qglUniform3fARB(r_glsl_permutation->loc_DiffuseColor, rsurface_entity->modellight_diffuse[0], rsurface_entity->modellight_diffuse[1], rsurface_entity->modellight_diffuse[2]);
867 if (r_glsl_permutation->loc_SpecularColor >= 0)
868 qglUniform3fARB(r_glsl_permutation->loc_SpecularColor, rsurface_entity->modellight_diffuse[0] * rsurface_texture->specularscale, rsurface_entity->modellight_diffuse[1] * rsurface_texture->specularscale, rsurface_entity->modellight_diffuse[2] * rsurface_texture->specularscale);
869 if (r_glsl_permutation->loc_LightDir >= 0)
870 qglUniform3fARB(r_glsl_permutation->loc_LightDir, rsurface_entity->modellight_lightdir[0], rsurface_entity->modellight_lightdir[1], rsurface_entity->modellight_lightdir[2]);
874 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_ambient.value * 2.0f / 128.0f);
875 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_refdef.lightmapintensity * 2.0f);
876 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, r_refdef.lightmapintensity * specularscale * 2.0f);
878 if (r_glsl_permutation->loc_Texture_Normal >= 0) R_Mesh_TexBind(0, R_GetTexture(rsurface_texture->skin.nmap));
879 if (r_glsl_permutation->loc_Texture_Color >= 0) R_Mesh_TexBind(1, R_GetTexture(rsurface_texture->basetexture));
880 if (r_glsl_permutation->loc_Texture_Gloss >= 0) R_Mesh_TexBind(2, R_GetTexture(rsurface_texture->glosstexture));
881 //if (r_glsl_permutation->loc_Texture_Cube >= 0 && permutation & SHADERPERMUTATION_MODE_LIGHTSOURCE) R_Mesh_TexBindCubeMap(3, R_GetTexture(r_shadow_rtlight->currentcubemap));
882 if (r_glsl_permutation->loc_Texture_FogMask >= 0) R_Mesh_TexBind(4, R_GetTexture(r_texture_fogattenuation));
883 if (r_glsl_permutation->loc_Texture_Pants >= 0) R_Mesh_TexBind(5, R_GetTexture(rsurface_texture->skin.pants));
884 if (r_glsl_permutation->loc_Texture_Shirt >= 0) R_Mesh_TexBind(6, R_GetTexture(rsurface_texture->skin.shirt));
885 //if (r_glsl_permutation->loc_Texture_Lightmap >= 0) R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
886 //if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
887 if (r_glsl_permutation->loc_Texture_Glow >= 0) R_Mesh_TexBind(9, R_GetTexture(rsurface_texture->skin.glow));
888 if (r_glsl_permutation->loc_GlowScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_GlowScale, r_hdr_glowintensity.value);
889 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_view.colorscale);
890 if (r_glsl_permutation->loc_FogColor >= 0)
892 // additive passes are only darkened by fog, not tinted
893 if (r_shadow_rtlight || (rsurface_texture->currentmaterialflags & MATERIALFLAG_ADD))
894 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
896 qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
898 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface_modelorg[0], rsurface_modelorg[1], rsurface_modelorg[2]);
899 if (r_glsl_permutation->loc_Color_Pants >= 0)
901 if (rsurface_texture->skin.pants)
902 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface_entity->colormap_pantscolor[0], rsurface_entity->colormap_pantscolor[1], rsurface_entity->colormap_pantscolor[2]);
904 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
906 if (r_glsl_permutation->loc_Color_Shirt >= 0)
908 if (rsurface_texture->skin.shirt)
909 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface_entity->colormap_shirtcolor[0], rsurface_entity->colormap_shirtcolor[1], rsurface_entity->colormap_shirtcolor[2]);
911 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
913 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, r_refdef.fograngerecip);
914 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface_texture->specularpower);
915 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
920 void R_SwitchSurfaceShader(int permutation)
922 if (r_glsl_permutation != r_glsl_permutations + permutation)
924 r_glsl_permutation = r_glsl_permutations + permutation;
926 qglUseProgramObjectARB(r_glsl_permutation->program);
931 void gl_main_start(void)
933 r_main_texturepool = R_AllocTexturePool();
934 r_bloom_texture_screen = NULL;
935 r_bloom_texture_bloom = NULL;
936 R_BuildBlankTextures();
938 if (gl_texturecubemap)
941 R_BuildNormalizationCube();
944 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
947 void gl_main_shutdown(void)
949 R_FreeTexturePool(&r_main_texturepool);
950 r_bloom_texture_screen = NULL;
951 r_bloom_texture_bloom = NULL;
952 r_texture_blanknormalmap = NULL;
953 r_texture_white = NULL;
954 r_texture_black = NULL;
955 r_texture_whitecube = NULL;
956 r_texture_normalizationcube = NULL;
960 extern void CL_ParseEntityLump(char *entitystring);
961 void gl_main_newmap(void)
963 // FIXME: move this code to client
965 char *entities, entname[MAX_QPATH];
968 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
969 l = (int)strlen(entname) - 4;
970 if (l >= 0 && !strcmp(entname + l, ".bsp"))
972 strcpy(entname + l, ".ent");
973 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
975 CL_ParseEntityLump(entities);
980 if (cl.worldmodel->brush.entities)
981 CL_ParseEntityLump(cl.worldmodel->brush.entities);
985 void GL_Main_Init(void)
987 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
989 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed\n");
990 FOG_registercvars(); // FIXME: move this fog stuff to client?
991 Cvar_RegisterVariable(&r_nearclip);
992 Cvar_RegisterVariable(&r_showsurfaces);
993 Cvar_RegisterVariable(&r_showtris);
994 Cvar_RegisterVariable(&r_shownormals);
995 Cvar_RegisterVariable(&r_showlighting);
996 Cvar_RegisterVariable(&r_showshadowvolumes);
997 Cvar_RegisterVariable(&r_showcollisionbrushes);
998 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
999 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
1000 Cvar_RegisterVariable(&r_showdisabledepthtest);
1001 Cvar_RegisterVariable(&r_drawportals);
1002 Cvar_RegisterVariable(&r_drawentities);
1003 Cvar_RegisterVariable(&r_drawviewmodel);
1004 Cvar_RegisterVariable(&r_speeds);
1005 Cvar_RegisterVariable(&r_fullbrights);
1006 Cvar_RegisterVariable(&r_wateralpha);
1007 Cvar_RegisterVariable(&r_dynamic);
1008 Cvar_RegisterVariable(&r_fullbright);
1009 Cvar_RegisterVariable(&r_q1bsp_skymasking);
1010 Cvar_RegisterVariable(&r_textureunits);
1011 Cvar_RegisterVariable(&r_glsl);
1012 Cvar_RegisterVariable(&r_glsl_offsetmapping);
1013 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
1014 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
1015 Cvar_RegisterVariable(&r_glsl_deluxemapping);
1016 Cvar_RegisterVariable(&r_lerpsprites);
1017 Cvar_RegisterVariable(&r_lerpmodels);
1018 Cvar_RegisterVariable(&r_waterscroll);
1019 Cvar_RegisterVariable(&r_bloom);
1020 Cvar_RegisterVariable(&r_bloom_intensity);
1021 Cvar_RegisterVariable(&r_bloom_blur);
1022 Cvar_RegisterVariable(&r_bloom_resolution);
1023 Cvar_RegisterVariable(&r_bloom_power);
1024 Cvar_RegisterVariable(&r_hdr);
1025 Cvar_RegisterVariable(&r_hdr_scenebrightness);
1026 Cvar_RegisterVariable(&r_hdr_bloomintensity);
1027 Cvar_RegisterVariable(&r_hdr_glowintensity);
1028 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
1029 Cvar_RegisterVariable(&developer_texturelogging);
1030 Cvar_RegisterVariable(&gl_lightmaps);
1031 Cvar_RegisterVariable(&r_test);
1032 Cvar_RegisterVariable(&r_batchmode);
1033 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
1034 Cvar_SetValue("r_fullbrights", 0);
1035 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
1038 extern void R_Textures_Init(void);
1039 extern void GL_Draw_Init(void);
1040 extern void GL_Main_Init(void);
1041 extern void R_Shadow_Init(void);
1042 extern void R_Sky_Init(void);
1043 extern void GL_Surf_Init(void);
1044 extern void R_Light_Init(void);
1045 extern void R_Particles_Init(void);
1046 extern void R_Explosion_Init(void);
1047 extern void gl_backend_init(void);
1048 extern void Sbar_Init(void);
1049 extern void R_LightningBeams_Init(void);
1050 extern void Mod_RenderInit(void);
1052 void Render_Init(void)
1065 R_LightningBeams_Init();
1074 extern char *ENGINE_EXTENSIONS;
1077 VID_CheckExtensions();
1079 // LordHavoc: report supported extensions
1080 Con_DPrintf("\nengine extensions: %s\n", vm_sv_extensions );
1082 // clear to black (loading plaque will be seen over this)
1084 qglClearColor(0,0,0,1);CHECKGLERROR
1085 qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
1088 int R_CullBox(const vec3_t mins, const vec3_t maxs)
1092 for (i = 0;i < 4;i++)
1094 p = r_view.frustum + i;
1099 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1103 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1107 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1111 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1115 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1119 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1123 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1127 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1135 //==================================================================================
1137 static void R_UpdateEntityLighting(entity_render_t *ent)
1139 vec3_t tempdiffusenormal;
1140 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));
1141 VectorClear(ent->modellight_diffuse);
1142 VectorClear(ent->modellight_lightdir);
1143 if ((ent->flags & RENDER_LIGHT) && r_refdef.worldmodel && r_refdef.worldmodel->brush.LightPoint)
1144 r_refdef.worldmodel->brush.LightPoint(r_refdef.worldmodel, ent->origin, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
1146 VectorSet(ent->modellight_ambient, 1, 1, 1);
1147 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
1148 VectorNormalize(ent->modellight_lightdir);
1149 ent->modellight_ambient[0] *= ent->colormod[0] * r_refdef.lightmapintensity;
1150 ent->modellight_ambient[1] *= ent->colormod[1] * r_refdef.lightmapintensity;
1151 ent->modellight_ambient[2] *= ent->colormod[2] * r_refdef.lightmapintensity;
1152 ent->modellight_diffuse[0] *= ent->colormod[0] * r_refdef.lightmapintensity;
1153 ent->modellight_diffuse[1] *= ent->colormod[1] * r_refdef.lightmapintensity;
1154 ent->modellight_diffuse[2] *= ent->colormod[2] * r_refdef.lightmapintensity;
1157 static void R_View_UpdateEntityVisible (void)
1160 entity_render_t *ent;
1162 if (!r_drawentities.integer)
1165 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : (chase_active.integer ? 0 : RENDER_EXTERIORMODEL);
1166 if (r_refdef.worldmodel && r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs)
1168 // worldmodel can check visibility
1169 for (i = 0;i < r_refdef.numentities;i++)
1171 ent = r_refdef.entities[i];
1172 r_viewcache.entityvisible[i] = !(ent->flags & renderimask) && !R_CullBox(ent->mins, ent->maxs) && ((ent->effects & EF_NODEPTHTEST) || r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs(r_refdef.worldmodel, r_viewcache.world_leafvisible, ent->mins, ent->maxs));
1177 // no worldmodel or it can't check visibility
1178 for (i = 0;i < r_refdef.numentities;i++)
1180 ent = r_refdef.entities[i];
1181 r_viewcache.entityvisible[i] = !(ent->flags & renderimask) && !R_CullBox(ent->mins, ent->maxs) && (ent->effects & EF_NODEPTHTEST);
1186 // only used if skyrendermasked, and normally returns false
1187 int R_DrawBrushModelsSky (void)
1190 entity_render_t *ent;
1192 if (!r_drawentities.integer)
1196 for (i = 0;i < r_refdef.numentities;i++)
1198 if (!r_viewcache.entityvisible[i])
1200 ent = r_refdef.entities[i];
1201 if (!ent->model || !ent->model->DrawSky)
1203 ent->model->DrawSky(ent);
1209 void R_DrawNoModel(entity_render_t *ent);
1210 void R_DrawModels(void)
1213 entity_render_t *ent;
1215 if (!r_drawentities.integer)
1218 for (i = 0;i < r_refdef.numentities;i++)
1220 if (!r_viewcache.entityvisible[i])
1222 ent = r_refdef.entities[i];
1223 r_refdef.stats.entities++;
1224 if (ent->model && ent->model->Draw != NULL)
1225 ent->model->Draw(ent);
1231 static void R_View_SetFrustum(void)
1233 // break apart the view matrix into vectors for various purposes
1234 Matrix4x4_ToVectors(&r_view.matrix, r_view.forward, r_view.left, r_view.up, r_view.origin);
1235 VectorNegate(r_view.left, r_view.right);
1238 r_view.frustum[0].normal[0] = 0 - 1.0 / r_view.frustum_x;
1239 r_view.frustum[0].normal[1] = 0 - 0;
1240 r_view.frustum[0].normal[2] = -1 - 0;
1241 r_view.frustum[1].normal[0] = 0 + 1.0 / r_view.frustum_x;
1242 r_view.frustum[1].normal[1] = 0 + 0;
1243 r_view.frustum[1].normal[2] = -1 + 0;
1244 r_view.frustum[2].normal[0] = 0 - 0;
1245 r_view.frustum[2].normal[1] = 0 - 1.0 / r_view.frustum_y;
1246 r_view.frustum[2].normal[2] = -1 - 0;
1247 r_view.frustum[3].normal[0] = 0 + 0;
1248 r_view.frustum[3].normal[1] = 0 + 1.0 / r_view.frustum_y;
1249 r_view.frustum[3].normal[2] = -1 + 0;
1253 zNear = r_refdef.nearclip;
1254 nudge = 1.0 - 1.0 / (1<<23);
1255 r_view.frustum[4].normal[0] = 0 - 0;
1256 r_view.frustum[4].normal[1] = 0 - 0;
1257 r_view.frustum[4].normal[2] = -1 - -nudge;
1258 r_view.frustum[4].dist = 0 - -2 * zNear * nudge;
1259 r_view.frustum[5].normal[0] = 0 + 0;
1260 r_view.frustum[5].normal[1] = 0 + 0;
1261 r_view.frustum[5].normal[2] = -1 + -nudge;
1262 r_view.frustum[5].dist = 0 + -2 * zNear * nudge;
1268 r_view.frustum[0].normal[0] = m[3] - m[0];
1269 r_view.frustum[0].normal[1] = m[7] - m[4];
1270 r_view.frustum[0].normal[2] = m[11] - m[8];
1271 r_view.frustum[0].dist = m[15] - m[12];
1273 r_view.frustum[1].normal[0] = m[3] + m[0];
1274 r_view.frustum[1].normal[1] = m[7] + m[4];
1275 r_view.frustum[1].normal[2] = m[11] + m[8];
1276 r_view.frustum[1].dist = m[15] + m[12];
1278 r_view.frustum[2].normal[0] = m[3] - m[1];
1279 r_view.frustum[2].normal[1] = m[7] - m[5];
1280 r_view.frustum[2].normal[2] = m[11] - m[9];
1281 r_view.frustum[2].dist = m[15] - m[13];
1283 r_view.frustum[3].normal[0] = m[3] + m[1];
1284 r_view.frustum[3].normal[1] = m[7] + m[5];
1285 r_view.frustum[3].normal[2] = m[11] + m[9];
1286 r_view.frustum[3].dist = m[15] + m[13];
1288 r_view.frustum[4].normal[0] = m[3] - m[2];
1289 r_view.frustum[4].normal[1] = m[7] - m[6];
1290 r_view.frustum[4].normal[2] = m[11] - m[10];
1291 r_view.frustum[4].dist = m[15] - m[14];
1293 r_view.frustum[5].normal[0] = m[3] + m[2];
1294 r_view.frustum[5].normal[1] = m[7] + m[6];
1295 r_view.frustum[5].normal[2] = m[11] + m[10];
1296 r_view.frustum[5].dist = m[15] + m[14];
1301 VectorMAM(1, r_view.forward, 1.0 / -r_view.frustum_x, r_view.left, r_view.frustum[0].normal);
1302 VectorMAM(1, r_view.forward, 1.0 / r_view.frustum_x, r_view.left, r_view.frustum[1].normal);
1303 VectorMAM(1, r_view.forward, 1.0 / -r_view.frustum_y, r_view.up, r_view.frustum[2].normal);
1304 VectorMAM(1, r_view.forward, 1.0 / r_view.frustum_y, r_view.up, r_view.frustum[3].normal);
1305 VectorCopy(r_view.forward, r_view.frustum[4].normal);
1306 VectorNormalize(r_view.frustum[0].normal);
1307 VectorNormalize(r_view.frustum[1].normal);
1308 VectorNormalize(r_view.frustum[2].normal);
1309 VectorNormalize(r_view.frustum[3].normal);
1310 r_view.frustum[0].dist = DotProduct (r_view.origin, r_view.frustum[0].normal);
1311 r_view.frustum[1].dist = DotProduct (r_view.origin, r_view.frustum[1].normal);
1312 r_view.frustum[2].dist = DotProduct (r_view.origin, r_view.frustum[2].normal);
1313 r_view.frustum[3].dist = DotProduct (r_view.origin, r_view.frustum[3].normal);
1314 r_view.frustum[4].dist = DotProduct (r_view.origin, r_view.frustum[4].normal) + r_refdef.nearclip;
1315 PlaneClassify(&r_view.frustum[0]);
1316 PlaneClassify(&r_view.frustum[1]);
1317 PlaneClassify(&r_view.frustum[2]);
1318 PlaneClassify(&r_view.frustum[3]);
1319 PlaneClassify(&r_view.frustum[4]);
1321 // LordHavoc: note to all quake engine coders, Quake had a special case
1322 // for 90 degrees which assumed a square view (wrong), so I removed it,
1323 // Quake2 has it disabled as well.
1325 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
1326 //RotatePointAroundVector( r_view.frustum[0].normal, r_view.up, r_view.forward, -(90 - r_refdef.fov_x / 2));
1327 //r_view.frustum[0].dist = DotProduct (r_view.origin, frustum[0].normal);
1328 //PlaneClassify(&frustum[0]);
1330 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
1331 //RotatePointAroundVector( r_view.frustum[1].normal, r_view.up, r_view.forward, (90 - r_refdef.fov_x / 2));
1332 //r_view.frustum[1].dist = DotProduct (r_view.origin, frustum[1].normal);
1333 //PlaneClassify(&frustum[1]);
1335 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
1336 //RotatePointAroundVector( r_view.frustum[2].normal, r_view.left, r_view.forward, -(90 - r_refdef.fov_y / 2));
1337 //r_view.frustum[2].dist = DotProduct (r_view.origin, frustum[2].normal);
1338 //PlaneClassify(&frustum[2]);
1340 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
1341 //RotatePointAroundVector( r_view.frustum[3].normal, r_view.left, r_view.forward, (90 - r_refdef.fov_y / 2));
1342 //r_view.frustum[3].dist = DotProduct (r_view.origin, frustum[3].normal);
1343 //PlaneClassify(&frustum[3]);
1346 //VectorCopy(r_view.forward, r_view.frustum[4].normal);
1347 //r_view.frustum[4].dist = DotProduct (r_view.origin, frustum[4].normal) + r_nearclip.value;
1348 //PlaneClassify(&frustum[4]);
1351 void R_View_Update(void)
1353 R_View_SetFrustum();
1354 R_View_WorldVisibility();
1355 R_View_UpdateEntityVisible();
1358 void R_ResetViewRendering(void)
1360 if (gl_support_fragment_shader)
1362 qglUseProgramObjectARB(0);CHECKGLERROR
1365 // GL is weird because it's bottom to top, r_view.y is top to bottom
1366 qglViewport(r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
1367 GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
1368 GL_Scissor(r_view.x, r_view.y, r_view.width, r_view.height);
1369 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
1370 GL_ScissorTest(true);
1373 R_Mesh_Matrix(&identitymatrix);
1374 R_Mesh_ResetTextureState();
1377 void R_RenderScene(void);
1379 void R_Bloom_MakeTexture(qboolean darken)
1381 int screenwidth, screenheight;
1382 int screentexturewidth, screentextureheight;
1383 int bloomtexturewidth, bloomtextureheight;
1384 int bloomwidth, bloomheight, x, range;
1385 float xoffset, yoffset, r;
1387 float texcoord2f[3][8];
1389 // set bloomwidth and bloomheight to the bloom resolution that will be
1390 // used (often less than the screen resolution for faster rendering)
1391 bloomwidth = bound(1, r_bloom_resolution.integer, r_view.width);
1392 bloomheight = bound(1, bloomwidth * r_view.height / r_view.width, r_view.height);
1394 // set the (poorly named) screenwidth and screenheight variables to
1395 // a power of 2 at least as large as the screen, these will define the
1396 // size of the texture to allocate
1397 for (screenwidth = 1;screenwidth < vid.width;screenwidth *= 2);
1398 for (screenheight = 1;screenheight < vid.height;screenheight *= 2);
1400 r_refdef.stats.bloom++;
1402 // allocate textures as needed
1403 // TODO: reallocate these when size settings change
1404 if (!r_bloom_texture_screen)
1405 r_bloom_texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", screenwidth, screenheight, NULL, TEXTYPE_RGBA, TEXF_FORCENEAREST | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
1406 if (!r_bloom_texture_bloom)
1407 r_bloom_texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", screenwidth, screenheight, NULL, TEXTYPE_RGBA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
1409 screentexturewidth = R_TextureWidth(r_bloom_texture_screen);
1410 screentextureheight = R_TextureHeight(r_bloom_texture_screen);
1411 bloomtexturewidth = R_TextureWidth(r_bloom_texture_bloom);
1412 bloomtextureheight = R_TextureHeight(r_bloom_texture_bloom);
1414 // vertex coordinates for a quad that covers the screen exactly
1415 vertex3f[0] = 0;vertex3f[1] = 0;vertex3f[2] = 0;
1416 vertex3f[3] = 1;vertex3f[4] = 0;vertex3f[5] = 0;
1417 vertex3f[6] = 1;vertex3f[7] = 1;vertex3f[8] = 0;
1418 vertex3f[9] = 0;vertex3f[10] = 1;vertex3f[11] = 0;
1420 // set up a texcoord array for the full resolution screen image
1421 // (we have to keep this around to copy back during final render)
1422 texcoord2f[0][0] = 0;
1423 texcoord2f[0][1] = (float)r_view.height / (float)screentextureheight;
1424 texcoord2f[0][2] = (float)r_view.width / (float)screentexturewidth;
1425 texcoord2f[0][3] = (float)r_view.height / (float)screentextureheight;
1426 texcoord2f[0][4] = (float)r_view.width / (float)screentexturewidth;
1427 texcoord2f[0][5] = 0;
1428 texcoord2f[0][6] = 0;
1429 texcoord2f[0][7] = 0;
1431 // set up a texcoord array for the reduced resolution bloom image
1432 // (which will be additive blended over the screen image)
1433 texcoord2f[1][0] = 0;
1434 texcoord2f[1][1] = (float)bloomheight / (float)bloomtextureheight;
1435 texcoord2f[1][2] = (float)bloomwidth / (float)bloomtexturewidth;
1436 texcoord2f[1][3] = (float)bloomheight / (float)bloomtextureheight;
1437 texcoord2f[1][4] = (float)bloomwidth / (float)bloomtexturewidth;
1438 texcoord2f[1][5] = 0;
1439 texcoord2f[1][6] = 0;
1440 texcoord2f[1][7] = 0;
1442 R_ResetViewRendering();
1443 GL_DepthTest(false);
1444 R_Mesh_VertexPointer(vertex3f);
1445 R_Mesh_ColorPointer(NULL);
1447 R_Mesh_TexCoordPointer(0, 2, texcoord2f[0]);
1448 R_Mesh_TexBind(0, R_GetTexture(r_bloom_texture_screen));
1450 // copy view into the screen texture
1451 GL_ActiveTexture(0);
1453 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
1454 r_refdef.stats.bloom_copypixels += r_view.width * r_view.height;
1456 // now scale it down to the bloom texture size
1458 qglViewport(r_view.x, vid.height - (r_view.y + bloomheight), bloomwidth, bloomheight);CHECKGLERROR
1459 GL_BlendFunc(GL_ONE, GL_ZERO);
1460 GL_Color(1, 1, 1, 1);
1461 // TODO: optimize with multitexture or GLSL
1462 R_Mesh_Draw(0, 4, 2, polygonelements);
1463 r_refdef.stats.bloom_drawpixels += bloomwidth * bloomheight;
1467 // raise to a power of itself to darken it (this leaves the really
1468 // bright stuff bright, and everything else becomes very dark)
1469 // render multiple times with a multiply blendfunc to raise to a power
1470 GL_BlendFunc(GL_DST_COLOR, GL_ZERO);
1471 for (x = 1;x < r_bloom_power.integer;x++)
1473 R_Mesh_Draw(0, 4, 2, polygonelements);
1474 r_refdef.stats.bloom_drawpixels += bloomwidth * bloomheight;
1478 // we now have a darkened bloom image in the framebuffer
1479 // copy it into the bloom image texture for more processing
1480 R_Mesh_TexBind(0, R_GetTexture(r_bloom_texture_bloom));
1481 R_Mesh_TexCoordPointer(0, 2, texcoord2f[2]);
1482 GL_ActiveTexture(0);
1484 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view.x, vid.height - (r_view.y + bloomheight), bloomwidth, bloomheight);CHECKGLERROR
1485 r_refdef.stats.bloom_copypixels += bloomwidth * bloomheight;
1487 // blend on at multiple vertical offsets to achieve a vertical blur
1488 // TODO: do offset blends using GLSL
1489 range = r_bloom_blur.integer * bloomwidth / 320;
1490 GL_BlendFunc(GL_ONE, GL_ZERO);
1491 for (x = -range;x <= range;x++)
1493 xoffset = 0 / (float)bloomwidth * (float)bloomwidth / (float)screenwidth;
1494 yoffset = x / (float)bloomheight * (float)bloomheight / (float)screenheight;
1495 // compute a texcoord array with the specified x and y offset
1496 texcoord2f[2][0] = xoffset+0;
1497 texcoord2f[2][1] = yoffset+(float)bloomheight / (float)screenheight;
1498 texcoord2f[2][2] = xoffset+(float)bloomwidth / (float)screenwidth;
1499 texcoord2f[2][3] = yoffset+(float)bloomheight / (float)screenheight;
1500 texcoord2f[2][4] = xoffset+(float)bloomwidth / (float)screenwidth;
1501 texcoord2f[2][5] = yoffset+0;
1502 texcoord2f[2][6] = xoffset+0;
1503 texcoord2f[2][7] = yoffset+0;
1504 // this r value looks like a 'dot' particle, fading sharply to
1505 // black at the edges
1506 // (probably not realistic but looks good enough)
1507 r = r_bloom_intensity.value/(range*2+1)*(1 - x*x/(float)(range*range));
1510 GL_Color(r, r, r, 1);
1511 R_Mesh_Draw(0, 4, 2, polygonelements);
1512 r_refdef.stats.bloom_drawpixels += bloomwidth * bloomheight;
1513 GL_BlendFunc(GL_ONE, GL_ONE);
1516 // copy the vertically blurred bloom view to a texture
1517 GL_ActiveTexture(0);
1519 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view.x, vid.height - (r_view.y + bloomheight), bloomwidth, bloomheight);CHECKGLERROR
1520 r_refdef.stats.bloom_copypixels += bloomwidth * bloomheight;
1522 // blend the vertically blurred image at multiple offsets horizontally
1523 // to finish the blur effect
1524 // TODO: do offset blends using GLSL
1525 range = r_bloom_blur.integer * bloomwidth / 320;
1526 GL_BlendFunc(GL_ONE, GL_ZERO);
1527 for (x = -range;x <= range;x++)
1529 xoffset = x / (float)bloomwidth * (float)bloomwidth / (float)screenwidth;
1530 yoffset = 0 / (float)bloomheight * (float)bloomheight / (float)screenheight;
1531 // compute a texcoord array with the specified x and y offset
1532 texcoord2f[2][0] = xoffset+0;
1533 texcoord2f[2][1] = yoffset+(float)bloomheight / (float)screenheight;
1534 texcoord2f[2][2] = xoffset+(float)bloomwidth / (float)screenwidth;
1535 texcoord2f[2][3] = yoffset+(float)bloomheight / (float)screenheight;
1536 texcoord2f[2][4] = xoffset+(float)bloomwidth / (float)screenwidth;
1537 texcoord2f[2][5] = yoffset+0;
1538 texcoord2f[2][6] = xoffset+0;
1539 texcoord2f[2][7] = yoffset+0;
1540 // this r value looks like a 'dot' particle, fading sharply to
1541 // black at the edges
1542 // (probably not realistic but looks good enough)
1543 r = r_bloom_intensity.value/(range*2+1)*(1 - x*x/(float)(range*range));
1546 GL_Color(r, r, r, 1);
1547 R_Mesh_Draw(0, 4, 2, polygonelements);
1548 r_refdef.stats.bloom_drawpixels += bloomwidth * bloomheight;
1549 GL_BlendFunc(GL_ONE, GL_ONE);
1552 // copy the blurred bloom view to a texture
1553 GL_ActiveTexture(0);
1555 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view.x, vid.height - (r_view.y + bloomheight), bloomwidth, bloomheight);CHECKGLERROR
1556 r_refdef.stats.bloom_copypixels += bloomwidth * bloomheight;
1559 void R_HDR_RenderBloomTexture(void)
1561 int oldwidth, oldheight;
1563 oldwidth = r_view.width;
1564 oldheight = r_view.height;
1565 r_view.width = bound(1, r_bloom_resolution.integer, min(r_view.width, gl_max_texture_size));
1566 r_view.height = r_view.width * oldheight / oldwidth;
1568 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
1569 // FIXME: change global lightmapintensity and light intensity according to r_hdr_bloomintensity cvar
1570 // FIXME: change global lightmapintensity and light intensity according to r_hdr_scenebrightness cvar
1571 // TODO: add exposure compensation features
1573 r_view.colorscale = r_hdr_bloomintensity.value * r_hdr_scenebrightness.value;
1576 R_ResetViewRendering();
1578 R_Bloom_MakeTexture(false);
1581 if (r_timereport_active)
1582 R_TimeReport("clear");
1584 // restore the view settings
1585 r_view.width = oldwidth;
1586 r_view.height = oldheight;
1588 // go back to full view area
1589 R_ResetViewRendering();
1592 static void R_BlendView(void)
1594 int screenwidth, screenheight;
1595 int bloomwidth, bloomheight;
1600 float texcoord2f[3][8];
1602 // set the (poorly named) screenwidth and screenheight variables to
1603 // a power of 2 at least as large as the screen, these will define the
1604 // size of the texture to allocate
1605 for (screenwidth = 1;screenwidth < vid.width;screenwidth *= 2);
1606 for (screenheight = 1;screenheight < vid.height;screenheight *= 2);
1608 doblend = r_refdef.viewblend[3] >= 0.01f;
1609 dobloom = !r_hdr.integer && r_bloom.integer && screenwidth <= gl_max_texture_size && screenheight <= gl_max_texture_size && r_bloom_resolution.value >= 32 && r_bloom_power.integer >= 1 && r_bloom_power.integer < 100 && r_bloom_blur.value >= 0 && r_bloom_blur.value < 512;
1610 dohdr = r_hdr.integer && screenwidth <= gl_max_texture_size && screenheight <= gl_max_texture_size && r_bloom_resolution.value >= 32 && r_bloom_power.integer >= 1 && r_bloom_power.integer < 100 && r_bloom_blur.value >= 0 && r_bloom_blur.value < 512;
1612 if (!dobloom && !dohdr && !doblend)
1615 // vertex coordinates for a quad that covers the screen exactly
1616 vertex3f[0] = 0;vertex3f[1] = 0;vertex3f[2] = 0;
1617 vertex3f[3] = 1;vertex3f[4] = 0;vertex3f[5] = 0;
1618 vertex3f[6] = 1;vertex3f[7] = 1;vertex3f[8] = 0;
1619 vertex3f[9] = 0;vertex3f[10] = 1;vertex3f[11] = 0;
1621 // set bloomwidth and bloomheight to the bloom resolution that will be
1622 // used (often less than the screen resolution for faster rendering)
1623 bloomwidth = min(r_view.width, r_bloom_resolution.integer);
1624 bloomheight = min(r_view.height, bloomwidth * r_view.height / r_view.width);
1625 // set up a texcoord array for the full resolution screen image
1626 // (we have to keep this around to copy back during final render)
1627 texcoord2f[0][0] = 0;
1628 texcoord2f[0][1] = (float)r_view.height / (float)screenheight;
1629 texcoord2f[0][2] = (float)r_view.width / (float)screenwidth;
1630 texcoord2f[0][3] = (float)r_view.height / (float)screenheight;
1631 texcoord2f[0][4] = (float)r_view.width / (float)screenwidth;
1632 texcoord2f[0][5] = 0;
1633 texcoord2f[0][6] = 0;
1634 texcoord2f[0][7] = 0;
1635 // set up a texcoord array for the reduced resolution bloom image
1636 // (which will be additive blended over the screen image)
1637 texcoord2f[1][0] = 0;
1638 texcoord2f[1][1] = (float)bloomheight / (float)screenheight;
1639 texcoord2f[1][2] = (float)bloomwidth / (float)screenwidth;
1640 texcoord2f[1][3] = (float)bloomheight / (float)screenheight;
1641 texcoord2f[1][4] = (float)bloomwidth / (float)screenwidth;
1642 texcoord2f[1][5] = 0;
1643 texcoord2f[1][6] = 0;
1644 texcoord2f[1][7] = 0;
1648 // render high dynamic range bloom effect
1649 // the bloom texture was made earlier this render, so we just need to
1650 // blend it onto the screen...
1651 R_ResetViewRendering();
1652 GL_DepthTest(false);
1653 R_Mesh_VertexPointer(vertex3f);
1654 R_Mesh_ColorPointer(NULL);
1655 GL_Color(1, 1, 1, 1);
1656 GL_BlendFunc(GL_ONE, GL_ONE);
1657 R_Mesh_TexBind(0, R_GetTexture(r_bloom_texture_bloom));
1658 R_Mesh_TexCoordPointer(0, 2, texcoord2f[1]);
1659 R_Mesh_Draw(0, 4, 2, polygonelements);
1660 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
1664 // render simple bloom effect
1665 // make the bloom texture
1666 R_Bloom_MakeTexture(true);
1667 // put the original screen image back in place and blend the bloom
1669 R_ResetViewRendering();
1670 GL_DepthTest(false);
1671 R_Mesh_VertexPointer(vertex3f);
1672 R_Mesh_ColorPointer(NULL);
1673 GL_Color(1, 1, 1, 1);
1674 GL_BlendFunc(GL_ONE, GL_ZERO);
1675 // do both in one pass if possible
1676 R_Mesh_TexBind(0, R_GetTexture(r_bloom_texture_screen));
1677 R_Mesh_TexCoordPointer(0, 2, texcoord2f[0]);
1678 if (r_textureunits.integer >= 2 && gl_combine.integer)
1680 R_Mesh_TexCombine(1, GL_ADD, GL_ADD, 1, 1);
1681 R_Mesh_TexBind(1, R_GetTexture(r_bloom_texture_bloom));
1682 R_Mesh_TexCoordPointer(1, 2, texcoord2f[1]);
1686 R_Mesh_Draw(0, 4, 2, polygonelements);
1687 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
1688 // now blend on the bloom texture
1689 GL_BlendFunc(GL_ONE, GL_ONE);
1690 R_Mesh_TexBind(0, R_GetTexture(r_bloom_texture_bloom));
1691 R_Mesh_TexCoordPointer(0, 2, texcoord2f[1]);
1693 R_Mesh_Draw(0, 4, 2, polygonelements);
1694 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
1698 // apply a color tint to the whole view
1699 R_ResetViewRendering();
1700 GL_DepthTest(false);
1701 R_Mesh_VertexPointer(vertex3f);
1702 R_Mesh_ColorPointer(NULL);
1703 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1704 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
1705 R_Mesh_Draw(0, 4, 2, polygonelements);
1709 void R_RenderScene(void);
1711 matrix4x4_t r_waterscrollmatrix;
1713 void R_UpdateVariables(void)
1719 r_refdef.farclip = 4096;
1720 if (r_refdef.worldmodel)
1721 r_refdef.farclip += VectorDistance(r_refdef.worldmodel->normalmins, r_refdef.worldmodel->normalmaxs);
1722 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
1724 r_refdef.polygonfactor = 0;
1725 r_refdef.polygonoffset = 0;
1726 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_shadow_polygonfactor.value;
1727 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_shadow_polygonoffset.value;
1729 r_refdef.rtworld = r_shadow_realtime_world.integer;
1730 r_refdef.rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
1731 r_refdef.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer;
1732 r_refdef.rtdlightshadows = r_refdef.rtdlight && (r_refdef.rtworld ? r_shadow_realtime_world_dlightshadows.integer : r_shadow_realtime_dlight_shadows.integer) && gl_stencil;
1733 r_refdef.lightmapintensity = r_refdef.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
1734 if (r_showsurfaces.integer)
1736 r_refdef.rtworld = false;
1737 r_refdef.rtworldshadows = false;
1738 r_refdef.rtdlight = false;
1739 r_refdef.rtdlightshadows = false;
1740 r_refdef.lightmapintensity = 0;
1743 if (gamemode == GAME_NEHAHRA)
1745 if (gl_fogenable.integer)
1747 r_refdef.oldgl_fogenable = true;
1748 r_refdef.fog_density = gl_fogdensity.value;
1749 r_refdef.fog_red = gl_fogred.value;
1750 r_refdef.fog_green = gl_foggreen.value;
1751 r_refdef.fog_blue = gl_fogblue.value;
1753 else if (r_refdef.oldgl_fogenable)
1755 r_refdef.oldgl_fogenable = false;
1756 r_refdef.fog_density = 0;
1757 r_refdef.fog_red = 0;
1758 r_refdef.fog_green = 0;
1759 r_refdef.fog_blue = 0;
1762 if (r_refdef.fog_density)
1764 r_refdef.fogcolor[0] = bound(0.0f, r_refdef.fog_red , 1.0f);
1765 r_refdef.fogcolor[1] = bound(0.0f, r_refdef.fog_green, 1.0f);
1766 r_refdef.fogcolor[2] = bound(0.0f, r_refdef.fog_blue , 1.0f);
1768 if (r_refdef.fog_density)
1770 r_refdef.fogenabled = true;
1771 // this is the point where the fog reaches 0.9986 alpha, which we
1772 // consider a good enough cutoff point for the texture
1773 // (0.9986 * 256 == 255.6)
1774 r_refdef.fogrange = 400 / r_refdef.fog_density;
1775 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
1776 r_refdef.fogtabledistmultiplier = FOGTABLEWIDTH * r_refdef.fograngerecip;
1777 // fog color was already set
1780 r_refdef.fogenabled = false;
1782 // update some cached entity properties...
1783 for (i = 0;i < r_refdef.numentities;i++)
1785 entity_render_t *ent = r_refdef.entities[i];
1786 // some of the renderer still relies on origin...
1787 Matrix4x4_OriginFromMatrix(&ent->matrix, ent->origin);
1788 // some of the renderer still relies on scale...
1789 ent->scale = Matrix4x4_ScaleFromMatrix(&ent->matrix);
1790 R_UpdateEntityLighting(ent);
1799 void R_RenderView(void)
1801 if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
1802 return; //Host_Error ("R_RenderView: NULL worldmodel");
1805 if (r_timereport_active)
1806 R_TimeReport("setup");
1809 if (r_timereport_active)
1810 R_TimeReport("visibility");
1812 // GL is weird because it's bottom to top, r_view.y is top to bottom
1813 R_ResetViewRendering();
1816 if (r_timereport_active)
1817 R_TimeReport("clear");
1819 // this produces a bloom texture to be used in R_BlendView() later
1821 R_HDR_RenderBloomTexture();
1823 r_view.colorscale = r_hdr_scenebrightness.value;
1827 if (r_timereport_active)
1828 R_TimeReport("blendview");
1830 GL_Scissor(0, 0, vid.width, vid.height);
1831 GL_ScissorTest(false);
1836 void CSQC_R_ClearScreen (void)
1838 if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
1839 return; //Host_Error ("R_RenderView: NULL worldmodel");
1842 GL_ScissorTest(true);
1844 if (r_timereport_active)
1845 R_TimeReport("setup");
1848 if (r_timereport_active)
1849 R_TimeReport("visibility");
1851 R_ResetViewRendering();
1854 if (r_timereport_active)
1855 R_TimeReport("clear");
1860 void CSQC_R_RenderScene (void)
1862 R_ResetViewRendering();
1865 if (r_timereport_active)
1866 R_TimeReport("clear");
1868 // this produces a bloom texture to be used in R_BlendView() later
1870 R_HDR_RenderBloomTexture();
1872 r_view.colorscale = r_hdr_scenebrightness.value;
1876 if (r_timereport_active)
1877 R_TimeReport("blendview");
1879 GL_Scissor(0, 0, vid.width, vid.height);
1880 GL_ScissorTest(false);
1884 extern void R_DrawLightningBeams (void);
1885 extern void VM_AddPolygonsToMeshQueue (void);
1886 extern void R_DrawPortals (void);
1887 void R_RenderScene(void)
1889 // don't let sound skip if going slow
1890 if (r_refdef.extraupdate)
1894 if (gl_support_fragment_shader)
1896 qglUseProgramObjectARB(0);CHECKGLERROR
1898 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
1899 qglPolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR
1900 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
1902 R_ResetViewRendering();
1904 R_MeshQueue_BeginScene();
1906 if (r_refdef.rtworldshadows || r_refdef.rtdlightshadows)
1907 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_view.frustum_x, r_view.frustum_y, r_refdef.nearclip);
1909 GL_SetupView_Mode_Perspective(r_view.frustum_x, r_view.frustum_y, r_refdef.nearclip, r_refdef.farclip);
1911 GL_SetupView_Orientation_FromEntity(&r_view.matrix);
1913 R_Shadow_UpdateWorldLightSelection();
1917 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);
1919 if (cl.csqc_vidvars.drawworld)
1921 // don't let sound skip if going slow
1922 if (r_refdef.extraupdate)
1925 if (r_refdef.worldmodel && r_refdef.worldmodel->DrawSky)
1927 r_refdef.worldmodel->DrawSky(r_refdef.worldentity);
1928 if (r_timereport_active)
1929 R_TimeReport("worldsky");
1932 if (R_DrawBrushModelsSky() && r_timereport_active)
1933 R_TimeReport("bmodelsky");
1935 if (r_refdef.worldmodel && r_refdef.worldmodel->Draw)
1937 r_refdef.worldmodel->Draw(r_refdef.worldentity);
1938 if (r_timereport_active)
1939 R_TimeReport("world");
1943 // don't let sound skip if going slow
1944 if (r_refdef.extraupdate)
1948 if (r_timereport_active)
1949 R_TimeReport("models");
1951 // don't let sound skip if going slow
1952 if (r_refdef.extraupdate)
1955 R_ShadowVolumeLighting(false);
1956 if (r_timereport_active)
1957 R_TimeReport("rtlights");
1959 // don't let sound skip if going slow
1960 if (r_refdef.extraupdate)
1963 if (cl.csqc_vidvars.drawworld)
1965 R_DrawLightningBeams();
1966 if (r_timereport_active)
1967 R_TimeReport("lightning");
1970 if (r_timereport_active)
1971 R_TimeReport("particles");
1974 if (r_timereport_active)
1975 R_TimeReport("explosions");
1978 if (gl_support_fragment_shader)
1980 qglUseProgramObjectARB(0);CHECKGLERROR
1982 VM_AddPolygonsToMeshQueue();
1984 if (r_drawportals.integer)
1987 if (r_timereport_active)
1988 R_TimeReport("portals");
1991 if (gl_support_fragment_shader)
1993 qglUseProgramObjectARB(0);CHECKGLERROR
1995 R_MeshQueue_RenderTransparent();
1996 if (r_timereport_active)
1997 R_TimeReport("drawtrans");
1999 if (gl_support_fragment_shader)
2001 qglUseProgramObjectARB(0);CHECKGLERROR
2004 if (cl.csqc_vidvars.drawworld)
2007 if (r_timereport_active)
2008 R_TimeReport("coronas");
2011 // don't let sound skip if going slow
2012 if (r_refdef.extraupdate)
2016 if (gl_support_fragment_shader)
2018 qglUseProgramObjectARB(0);CHECKGLERROR
2020 qglPolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR
2021 qglDisable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
2025 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
2028 float *v, *c, f1, f2, diff[3], vertex3f[8*3], color4f[8*4];
2029 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2030 GL_DepthMask(false);
2032 R_Mesh_Matrix(&identitymatrix);
2034 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2];
2035 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
2036 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
2037 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
2038 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
2039 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
2040 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
2041 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
2042 R_FillColors(color, 8, cr, cg, cb, ca);
2043 if (r_refdef.fogenabled)
2045 for (i = 0, v = vertex, c = color;i < 8;i++, v += 4, c += 4)
2047 f2 = VERTEXFOGTABLE(VectorDistance(v, r_view.origin));
2049 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
2050 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
2051 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
2054 R_Mesh_VertexPointer(vertex3f);
2055 R_Mesh_ColorPointer(color);
2056 R_Mesh_ResetTextureState();
2061 int nomodelelements[24] =
2073 float nomodelvertex3f[6*3] =
2083 float nomodelcolor4f[6*4] =
2085 0.0f, 0.0f, 0.5f, 1.0f,
2086 0.0f, 0.0f, 0.5f, 1.0f,
2087 0.0f, 0.5f, 0.0f, 1.0f,
2088 0.0f, 0.5f, 0.0f, 1.0f,
2089 0.5f, 0.0f, 0.0f, 1.0f,
2090 0.5f, 0.0f, 0.0f, 1.0f
2093 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
2098 // this is only called once per entity so numsurfaces is always 1, and
2099 // surfacelist is always {0}, so this code does not handle batches
2100 R_Mesh_Matrix(&ent->matrix);
2102 if (ent->flags & EF_ADDITIVE)
2104 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2105 GL_DepthMask(false);
2107 else if (ent->alpha < 1)
2109 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2110 GL_DepthMask(false);
2114 GL_BlendFunc(GL_ONE, GL_ZERO);
2117 GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
2118 R_Mesh_VertexPointer(nomodelvertex3f);
2119 if (r_refdef.fogenabled)
2121 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
2122 R_Mesh_ColorPointer(color4f);
2123 f2 = VERTEXFOGTABLE(VectorDistance(ent->origin, r_view.origin));
2125 for (i = 0, c = color4f;i < 6;i++, c += 4)
2127 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
2128 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
2129 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
2133 else if (ent->alpha != 1)
2135 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
2136 R_Mesh_ColorPointer(color4f);
2137 for (i = 0, c = color4f;i < 6;i++, c += 4)
2141 R_Mesh_ColorPointer(nomodelcolor4f);
2142 R_Mesh_ResetTextureState();
2143 R_Mesh_Draw(0, 6, 8, nomodelelements);
2146 void R_DrawNoModel(entity_render_t *ent)
2148 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
2149 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_view.origin : ent->origin, R_DrawNoModel_TransparentCallback, ent, 0, r_shadow_rtlight);
2151 // R_DrawNoModelCallback(ent, 0);
2154 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
2156 vec3_t right1, right2, diff, normal;
2158 VectorSubtract (org2, org1, normal);
2160 // calculate 'right' vector for start
2161 VectorSubtract (r_view.origin, org1, diff);
2162 CrossProduct (normal, diff, right1);
2163 VectorNormalize (right1);
2165 // calculate 'right' vector for end
2166 VectorSubtract (r_view.origin, org2, diff);
2167 CrossProduct (normal, diff, right2);
2168 VectorNormalize (right2);
2170 vert[ 0] = org1[0] + width * right1[0];
2171 vert[ 1] = org1[1] + width * right1[1];
2172 vert[ 2] = org1[2] + width * right1[2];
2173 vert[ 3] = org1[0] - width * right1[0];
2174 vert[ 4] = org1[1] - width * right1[1];
2175 vert[ 5] = org1[2] - width * right1[2];
2176 vert[ 6] = org2[0] - width * right2[0];
2177 vert[ 7] = org2[1] - width * right2[1];
2178 vert[ 8] = org2[2] - width * right2[2];
2179 vert[ 9] = org2[0] + width * right2[0];
2180 vert[10] = org2[1] + width * right2[1];
2181 vert[11] = org2[2] + width * right2[2];
2184 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
2186 void R_DrawSprite(int blendfunc1, int blendfunc2, rtexture_t *texture, rtexture_t *fogtexture, int depthdisable, 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)
2188 float fog = 0.0f, ifog;
2191 if (r_refdef.fogenabled)
2192 fog = VERTEXFOGTABLE(VectorDistance(origin, r_view.origin));
2195 R_Mesh_Matrix(&identitymatrix);
2196 GL_BlendFunc(blendfunc1, blendfunc2);
2197 GL_DepthMask(false);
2198 GL_DepthTest(!depthdisable);
2200 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
2201 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
2202 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
2203 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
2204 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
2205 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
2206 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
2207 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
2208 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
2209 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
2210 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
2211 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
2213 R_Mesh_VertexPointer(vertex3f);
2214 R_Mesh_ColorPointer(NULL);
2215 R_Mesh_ResetTextureState();
2216 R_Mesh_TexBind(0, R_GetTexture(texture));
2217 R_Mesh_TexCoordPointer(0, 2, spritetexcoord2f);
2218 // FIXME: fixed function path can't properly handle r_view.colorscale > 1
2219 GL_Color(cr * ifog * r_view.colorscale, cg * ifog * r_view.colorscale, cb * ifog * r_view.colorscale, ca);
2220 R_Mesh_Draw(0, 4, 2, polygonelements);
2222 if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
2224 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
2225 GL_BlendFunc(blendfunc1, GL_ONE);
2226 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);
2227 R_Mesh_Draw(0, 4, 2, polygonelements);
2231 int R_Mesh_AddVertex3f(rmesh_t *mesh, const float *v)
2235 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
2236 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
2238 if (i == mesh->numvertices)
2240 if (mesh->numvertices < mesh->maxvertices)
2242 VectorCopy(v, vertex3f);
2243 mesh->numvertices++;
2245 return mesh->numvertices;
2251 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
2255 element[0] = R_Mesh_AddVertex3f(mesh, vertex3f);vertex3f += 3;
2256 element[1] = R_Mesh_AddVertex3f(mesh, vertex3f);vertex3f += 3;
2257 e = mesh->element3i + mesh->numtriangles * 3;
2258 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
2260 element[2] = R_Mesh_AddVertex3f(mesh, vertex3f);
2261 if (mesh->numtriangles < mesh->maxtriangles)
2266 mesh->numtriangles++;
2268 element[1] = element[2];
2272 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
2274 int planenum, planenum2;
2277 mplane_t *plane, *plane2;
2278 float temppoints[2][256*3];
2279 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
2283 PolygonF_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->normal[3], 1024.0*1024.0*1024.0);
2284 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
2286 if (planenum2 == planenum)
2288 PolygonF_Divide(tempnumpoints, temppoints[w], plane2->normal[0], plane2->normal[1], plane2->normal[2], plane2->dist, 1.0/32.0, 0, NULL, NULL, 256, temppoints[!w], &tempnumpoints, NULL);
2291 if (tempnumpoints < 3)
2293 // generate elements forming a triangle fan for this polygon
2294 R_Mesh_AddPolygon3f(mesh, tempnumpoints, temppoints[w]);
2298 static void R_DrawCollisionBrush(const colbrushf_t *brush)
2301 R_Mesh_VertexPointer(brush->points->v);
2302 i = (int)(((size_t)brush) / sizeof(colbrushf_t));
2303 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);
2304 GL_LockArrays(0, brush->numpoints);
2305 R_Mesh_Draw(0, brush->numpoints, brush->numtriangles, brush->elements);
2306 GL_LockArrays(0, 0);
2309 static void R_DrawCollisionSurface(const entity_render_t *ent, const msurface_t *surface)
2312 if (!surface->num_collisiontriangles)
2314 R_Mesh_VertexPointer(surface->data_collisionvertex3f);
2315 i = (int)(((size_t)surface) / sizeof(msurface_t));
2316 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);
2317 GL_LockArrays(0, surface->num_collisionvertices);
2318 R_Mesh_Draw(0, surface->num_collisionvertices, surface->num_collisiontriangles, surface->data_collisionelement3i);
2319 GL_LockArrays(0, 0);
2322 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)
2324 texturelayer_t *layer;
2325 layer = t->currentlayers + t->currentnumlayers++;
2327 layer->depthmask = depthmask;
2328 layer->blendfunc1 = blendfunc1;
2329 layer->blendfunc2 = blendfunc2;
2330 layer->texture = texture;
2331 layer->texmatrix = *matrix;
2332 layer->color[0] = r * r_view.colorscale;
2333 layer->color[1] = g * r_view.colorscale;
2334 layer->color[2] = b * r_view.colorscale;
2335 layer->color[3] = a;
2338 void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
2340 // FIXME: identify models using a better check than ent->model->brush.shadowmesh
2341 //int lightmode = ((ent->effects & EF_FULLBRIGHT) || ent->model->brush.shadowmesh) ? 0 : 2;
2344 texture_t *texture = t;
2345 model_t *model = ent->model;
2346 int s = ent->skinnum;
2347 if ((unsigned int)s >= (unsigned int)model->numskins)
2349 if (model->skinscenes)
2351 if (model->skinscenes[s].framecount > 1)
2352 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
2354 s = model->skinscenes[s].firstframe;
2357 t = t + s * model->num_surfaces;
2360 // use an alternate animation if the entity's frame is not 0,
2361 // and only if the texture has an alternate animation
2362 if (ent->frame != 0 && t->anim_total[1])
2363 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.time * 5.0f) % t->anim_total[1]) : 0];
2365 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.time * 5.0f) % t->anim_total[0]) : 0];
2367 texture->currentframe = t;
2370 t->currentmaterialflags = t->basematerialflags;
2371 t->currentalpha = ent->alpha;
2372 if (t->basematerialflags & MATERIALFLAG_WATERALPHA)
2373 t->currentalpha *= r_wateralpha.value;
2374 if (!(ent->flags & RENDER_LIGHT))
2375 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
2376 if (ent->effects & EF_ADDITIVE)
2377 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_TRANSPARENT;
2378 else if (t->currentalpha < 1)
2379 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_TRANSPARENT;
2380 if (ent->effects & EF_NODEPTHTEST)
2381 t->currentmaterialflags |= MATERIALFLAG_NODEPTHTEST;
2382 if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
2383 t->currenttexmatrix = r_waterscrollmatrix;
2385 t->currenttexmatrix = identitymatrix;
2387 t->colormapping = VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f);
2388 t->basetexture = (!t->colormapping && t->skin.merged) ? t->skin.merged : t->skin.base;
2389 t->glosstexture = r_texture_white;
2390 t->specularpower = 8;
2391 t->specularscale = 0;
2392 if (r_shadow_gloss.integer > 0)
2396 if (r_shadow_glossintensity.value > 0)
2398 t->glosstexture = t->skin.gloss;
2399 t->specularscale = r_shadow_glossintensity.value;
2402 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
2403 t->specularscale = r_shadow_gloss2intensity.value;
2406 t->currentnumlayers = 0;
2407 if (!(t->currentmaterialflags & MATERIALFLAG_NODRAW))
2409 if (gl_lightmaps.integer)
2410 R_Texture_AddLayer(t, true, GL_ONE, GL_ZERO, TEXTURELAYERTYPE_LITTEXTURE, r_texture_white, &identitymatrix, 1, 1, 1, 1);
2411 else if (!(t->currentmaterialflags & MATERIALFLAG_SKY))
2413 int blendfunc1, blendfunc2, depthmask;
2414 if (t->currentmaterialflags & MATERIALFLAG_ADD)
2416 blendfunc1 = GL_SRC_ALPHA;
2417 blendfunc2 = GL_ONE;
2419 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
2421 blendfunc1 = GL_SRC_ALPHA;
2422 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
2424 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
2426 blendfunc1 = t->customblendfunc[0];
2427 blendfunc2 = t->customblendfunc[1];
2431 blendfunc1 = GL_ONE;
2432 blendfunc2 = GL_ZERO;
2434 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
2435 if (t->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL))
2437 rtexture_t *currentbasetexture;
2439 if (r_refdef.fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED))
2440 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
2441 currentbasetexture = (VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) < (1.0f / 1048576.0f) && t->skin.merged) ? t->skin.merged : t->skin.base;
2442 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2444 // fullbright is not affected by r_refdef.lightmapintensity
2445 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
2446 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->skin.pants)
2447 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.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);
2448 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->skin.shirt)
2449 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.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);
2455 // q3bsp has no lightmap updates, so the lightstylevalue that
2456 // would normally be baked into the lightmap must be
2457 // applied to the color
2458 if (ent->model->type == mod_brushq3)
2459 colorscale *= r_refdef.lightstylevalue[0] * (1.0f / 256.0f);
2460 colorscale *= r_refdef.lightmapintensity;
2461 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);
2462 if (r_ambient.value >= (1.0f/64.0f))
2463 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);
2464 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->skin.pants)
2466 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->skin.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);
2467 if (r_ambient.value >= (1.0f/64.0f))
2468 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.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);
2470 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->skin.shirt)
2472 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->skin.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);
2473 if (r_ambient.value >= (1.0f/64.0f))
2474 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.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);
2477 if (t->skin.glow != NULL)
2478 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.glow, &t->currenttexmatrix, r_hdr_glowintensity.value, r_hdr_glowintensity.value, r_hdr_glowintensity.value, t->currentalpha);
2479 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
2481 // if this is opaque use alpha blend which will darken the earlier
2484 // if this is an alpha blended material, all the earlier passes
2485 // were darkened by fog already, so we only need to add the fog
2486 // color ontop through the fog mask texture
2488 // if this is an additive blended material, all the earlier passes
2489 // were darkened by fog already, and we should not add fog color
2490 // (because the background was not darkened, there is no fog color
2491 // that was lost behind it).
2492 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, (t->currentmaterialflags & MATERIALFLAG_BLENDED) ? GL_ONE : GL_ONE_MINUS_SRC_ALPHA, TEXTURELAYERTYPE_FOG, t->skin.fog, &identitymatrix, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], t->currentalpha);
2499 void R_UpdateAllTextureInfo(entity_render_t *ent)
2503 for (i = 0;i < ent->model->num_textures;i++)
2504 R_UpdateTextureInfo(ent, ent->model->data_textures + i);
2507 int rsurface_array_size = 0;
2508 float *rsurface_array_modelvertex3f = NULL;
2509 float *rsurface_array_modelsvector3f = NULL;
2510 float *rsurface_array_modeltvector3f = NULL;
2511 float *rsurface_array_modelnormal3f = NULL;
2512 float *rsurface_array_deformedvertex3f = NULL;
2513 float *rsurface_array_deformedsvector3f = NULL;
2514 float *rsurface_array_deformedtvector3f = NULL;
2515 float *rsurface_array_deformednormal3f = NULL;
2516 float *rsurface_array_color4f = NULL;
2517 float *rsurface_array_texcoord3f = NULL;
2519 void R_Mesh_ResizeArrays(int newvertices)
2522 if (rsurface_array_size >= newvertices)
2524 if (rsurface_array_modelvertex3f)
2525 Mem_Free(rsurface_array_modelvertex3f);
2526 rsurface_array_size = (newvertices + 1023) & ~1023;
2527 base = (float *)Mem_Alloc(r_main_mempool, rsurface_array_size * sizeof(float[31]));
2528 rsurface_array_modelvertex3f = base + rsurface_array_size * 0;
2529 rsurface_array_modelsvector3f = base + rsurface_array_size * 3;
2530 rsurface_array_modeltvector3f = base + rsurface_array_size * 6;
2531 rsurface_array_modelnormal3f = base + rsurface_array_size * 9;
2532 rsurface_array_deformedvertex3f = base + rsurface_array_size * 12;
2533 rsurface_array_deformedsvector3f = base + rsurface_array_size * 15;
2534 rsurface_array_deformedtvector3f = base + rsurface_array_size * 18;
2535 rsurface_array_deformednormal3f = base + rsurface_array_size * 21;
2536 rsurface_array_texcoord3f = base + rsurface_array_size * 24;
2537 rsurface_array_color4f = base + rsurface_array_size * 27;
2540 float *rsurface_modelvertex3f;
2541 float *rsurface_modelsvector3f;
2542 float *rsurface_modeltvector3f;
2543 float *rsurface_modelnormal3f;
2544 float *rsurface_vertex3f;
2545 float *rsurface_svector3f;
2546 float *rsurface_tvector3f;
2547 float *rsurface_normal3f;
2548 float *rsurface_lightmapcolor4f;
2549 vec3_t rsurface_modelorg;
2550 qboolean rsurface_generatedvertex;
2551 const entity_render_t *rsurface_entity;
2552 const model_t *rsurface_model;
2553 texture_t *rsurface_texture;
2554 rtexture_t *rsurface_lightmaptexture;
2555 rsurfmode_t rsurface_mode;
2556 texture_t *rsurface_glsl_texture;
2557 qboolean rsurface_glsl_uselightmap;
2559 void RSurf_ActiveEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
2561 Matrix4x4_Transform(&ent->inversematrix, r_view.origin, rsurface_modelorg);
2562 rsurface_entity = ent;
2563 rsurface_model = ent->model;
2564 if (rsurface_array_size < rsurface_model->surfmesh.num_vertices)
2565 R_Mesh_ResizeArrays(rsurface_model->surfmesh.num_vertices);
2566 R_Mesh_Matrix(&ent->matrix);
2567 Matrix4x4_Transform(&ent->inversematrix, r_view.origin, rsurface_modelorg);
2568 if ((rsurface_entity->frameblend[0].lerp != 1 || rsurface_entity->frameblend[0].frame != 0) && rsurface_model->surfmesh.isanimated)
2572 rsurface_modelvertex3f = rsurface_array_modelvertex3f;
2573 rsurface_modelsvector3f = rsurface_array_modelsvector3f;
2574 rsurface_modeltvector3f = rsurface_array_modeltvector3f;
2575 rsurface_modelnormal3f = rsurface_array_modelnormal3f;
2576 Mod_Alias_GetMesh_Vertices(rsurface_model, rsurface_entity->frameblend, rsurface_array_modelvertex3f, rsurface_array_modelnormal3f, rsurface_array_modelsvector3f, rsurface_array_modeltvector3f);
2578 else if (wantnormals)
2580 rsurface_modelvertex3f = rsurface_array_modelvertex3f;
2581 rsurface_modelsvector3f = NULL;
2582 rsurface_modeltvector3f = NULL;
2583 rsurface_modelnormal3f = rsurface_array_modelnormal3f;
2584 Mod_Alias_GetMesh_Vertices(rsurface_model, rsurface_entity->frameblend, rsurface_array_modelvertex3f, rsurface_array_modelnormal3f, NULL, NULL);
2588 rsurface_modelvertex3f = rsurface_array_modelvertex3f;
2589 rsurface_modelsvector3f = NULL;
2590 rsurface_modeltvector3f = NULL;
2591 rsurface_modelnormal3f = NULL;
2592 Mod_Alias_GetMesh_Vertices(rsurface_model, rsurface_entity->frameblend, rsurface_array_modelvertex3f, NULL, NULL, NULL);
2594 rsurface_generatedvertex = true;
2598 rsurface_modelvertex3f = rsurface_model->surfmesh.data_vertex3f;
2599 rsurface_modelsvector3f = rsurface_model->surfmesh.data_svector3f;
2600 rsurface_modeltvector3f = rsurface_model->surfmesh.data_tvector3f;
2601 rsurface_modelnormal3f = rsurface_model->surfmesh.data_normal3f;
2602 rsurface_generatedvertex = false;
2604 rsurface_vertex3f = rsurface_modelvertex3f;
2605 rsurface_svector3f = rsurface_modelsvector3f;
2606 rsurface_tvector3f = rsurface_modeltvector3f;
2607 rsurface_normal3f = rsurface_modelnormal3f;
2608 rsurface_mode = RSURFMODE_NONE;
2609 rsurface_lightmaptexture = NULL;
2610 rsurface_texture = NULL;
2611 rsurface_glsl_texture = NULL;
2612 rsurface_glsl_uselightmap = false;
2615 void RSurf_CleanUp(void)
2618 if (rsurface_mode == RSURFMODE_GLSL)
2620 qglUseProgramObjectARB(0);CHECKGLERROR
2622 GL_AlphaTest(false);
2623 rsurface_mode = RSURFMODE_NONE;
2624 rsurface_lightmaptexture = NULL;
2625 rsurface_texture = NULL;
2626 rsurface_glsl_texture = NULL;
2627 rsurface_glsl_uselightmap = false;
2630 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, msurface_t **texturesurfacelist)
2632 if (rsurface_generatedvertex)
2634 if (rsurface_texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
2635 generatetangents = true;
2636 if (generatetangents)
2637 generatenormals = true;
2638 if (generatenormals && !rsurface_modelnormal3f)
2640 rsurface_normal3f = rsurface_modelnormal3f = rsurface_array_modelnormal3f;
2641 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);
2643 if (generatetangents && !rsurface_modelsvector3f)
2645 rsurface_svector3f = rsurface_modelsvector3f = rsurface_array_modelsvector3f;
2646 rsurface_tvector3f = rsurface_modeltvector3f = rsurface_array_modeltvector3f;
2647 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);
2650 if (rsurface_texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
2652 int texturesurfaceindex;
2653 float center[3], forward[3], right[3], up[3], v[4][3];
2654 matrix4x4_t matrix1, imatrix1;
2655 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_view.forward, forward);
2656 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_view.right, right);
2657 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_view.up, up);
2658 // make deformed versions of only the vertices used by the specified surfaces
2659 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2662 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2663 // a single autosprite surface can contain multiple sprites...
2664 for (j = 0;j < surface->num_vertices - 3;j += 4)
2666 VectorClear(center);
2667 for (i = 0;i < 4;i++)
2668 VectorAdd(center, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
2669 VectorScale(center, 0.25f, center);
2670 if (rsurface_texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE2)
2672 forward[0] = rsurface_modelorg[0] - center[0];
2673 forward[1] = rsurface_modelorg[1] - center[1];
2675 VectorNormalize(forward);
2676 right[0] = forward[1];
2677 right[1] = -forward[0];
2679 VectorSet(up, 0, 0, 1);
2681 // FIXME: calculate vectors from triangle edges instead of using texture vectors as an easy way out?
2682 Matrix4x4_FromVectors(&matrix1, (rsurface_normal3f + 3 * surface->num_firstvertex) + j*3, (rsurface_svector3f + 3 * surface->num_firstvertex) + j*3, (rsurface_tvector3f + 3 * surface->num_firstvertex) + j*3, center);
2683 Matrix4x4_Invert_Simple(&imatrix1, &matrix1);
2684 for (i = 0;i < 4;i++)
2685 Matrix4x4_Transform(&imatrix1, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, v[i]);
2686 for (i = 0;i < 4;i++)
2687 VectorMAMAMAM(1, center, v[i][0], forward, v[i][1], right, v[i][2], up, rsurface_array_modelvertex3f + (surface->num_firstvertex+i+j) * 3);
2689 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);
2690 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);
2692 rsurface_vertex3f = rsurface_array_deformedvertex3f;
2693 rsurface_svector3f = rsurface_array_deformedsvector3f;
2694 rsurface_tvector3f = rsurface_array_deformedtvector3f;
2695 rsurface_normal3f = rsurface_array_deformednormal3f;
2697 R_Mesh_VertexPointer(rsurface_vertex3f);
2700 void RSurf_DrawBatch_Simple(int texturenumsurfaces, msurface_t **texturesurfacelist)
2702 int texturesurfaceindex;
2703 const msurface_t *surface = texturesurfacelist[0];
2704 int firstvertex = surface->num_firstvertex;
2705 int endvertex = surface->num_firstvertex + surface->num_vertices;
2706 if (texturenumsurfaces == 1)
2708 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2709 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
2711 else if (r_batchmode.integer == 2)
2713 #define MAXBATCHTRIANGLES 4096
2714 int batchtriangles = 0;
2715 int batchelements[MAXBATCHTRIANGLES*3];
2716 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2718 surface = texturesurfacelist[texturesurfaceindex];
2719 if (surface->num_triangles >= 256 || (batchtriangles == 0 && texturesurfaceindex + 1 >= texturenumsurfaces))
2721 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
2724 if (batchtriangles + surface->num_triangles > MAXBATCHTRIANGLES)
2726 R_Mesh_Draw(firstvertex, endvertex - firstvertex, batchtriangles, batchelements);
2728 firstvertex = surface->num_firstvertex;
2729 endvertex = surface->num_firstvertex + surface->num_vertices;
2733 firstvertex = min(firstvertex, surface->num_firstvertex);
2734 endvertex = max(endvertex, surface->num_firstvertex + surface->num_vertices);
2736 memcpy(batchelements + batchtriangles * 3, rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
2737 batchtriangles += surface->num_triangles;
2740 R_Mesh_Draw(firstvertex, endvertex - firstvertex, batchtriangles, batchelements);
2742 else if (r_batchmode.integer == 1)
2744 int firsttriangle = 0;
2745 int endtriangle = -1;
2746 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2748 surface = texturesurfacelist[texturesurfaceindex];
2749 if (surface->num_firsttriangle != endtriangle)
2751 if (endtriangle > firsttriangle)
2753 GL_LockArrays(firstvertex, endvertex - firstvertex);
2754 R_Mesh_Draw(firstvertex, endvertex - firstvertex, endtriangle - firsttriangle, (rsurface_model->surfmesh.data_element3i + 3 * firsttriangle));
2756 firstvertex = surface->num_firstvertex;
2757 endvertex = surface->num_firstvertex + surface->num_vertices;
2758 firsttriangle = surface->num_firsttriangle;
2762 firstvertex = min(firstvertex, surface->num_firstvertex);
2763 endvertex = max(endvertex, surface->num_firstvertex + surface->num_vertices);
2765 endtriangle = surface->num_firsttriangle + surface->num_triangles;
2767 if (endtriangle > firsttriangle)
2769 GL_LockArrays(firstvertex, endvertex - firstvertex);
2770 R_Mesh_Draw(firstvertex, endvertex - firstvertex, endtriangle - firsttriangle, (rsurface_model->surfmesh.data_element3i + 3 * firsttriangle));
2775 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2777 surface = texturesurfacelist[texturesurfaceindex];
2778 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2779 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
2784 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
2786 int texturesurfaceindex;
2787 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2789 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2790 int k = (int)(((size_t)surface) / sizeof(msurface_t));
2791 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, 0.2f);
2792 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2793 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
2797 static void RSurf_DrawBatch_Lightmap(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, int lightmode, qboolean applycolor, qboolean applyfog)
2799 int texturesurfaceindex;
2807 vec3_t ambientcolor;
2808 vec3_t diffusecolor;
2810 VectorCopy(rsurface_entity->modellight_lightdir, lightdir);
2811 ambientcolor[0] = rsurface_entity->modellight_ambient[0] * r * 0.5f;
2812 ambientcolor[1] = rsurface_entity->modellight_ambient[1] * g * 0.5f;
2813 ambientcolor[2] = rsurface_entity->modellight_ambient[2] * b * 0.5f;
2814 diffusecolor[0] = rsurface_entity->modellight_diffuse[0] * r * 0.5f;
2815 diffusecolor[1] = rsurface_entity->modellight_diffuse[1] * g * 0.5f;
2816 diffusecolor[2] = rsurface_entity->modellight_diffuse[2] * b * 0.5f;
2817 if (VectorLength2(diffusecolor) > 0)
2819 // generate color arrays for the surfaces in this list
2820 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2822 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2823 int numverts = surface->num_vertices;
2824 v = rsurface_vertex3f + 3 * surface->num_firstvertex;
2825 c2 = rsurface_normal3f + 3 * surface->num_firstvertex;
2826 c = rsurface_array_color4f + 4 * surface->num_firstvertex;
2827 // q3-style directional shading
2828 for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
2830 if ((f = DotProduct(c2, lightdir)) > 0)
2831 VectorMA(ambientcolor, f, diffusecolor, c);
2833 VectorCopy(ambientcolor, c);
2842 rsurface_lightmapcolor4f = rsurface_array_color4f;
2846 r = ambientcolor[0];
2847 g = ambientcolor[1];
2848 b = ambientcolor[2];
2849 rsurface_lightmapcolor4f = NULL;
2852 else if (lightmode >= 1 || !rsurface_lightmaptexture)
2854 if (texturesurfacelist[0]->lightmapinfo && texturesurfacelist[0]->lightmapinfo->stainsamples)
2856 // generate color arrays for the surfaces in this list
2857 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2859 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2860 for (i = 0, c = rsurface_array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
2862 if (surface->lightmapinfo->samples)
2864 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface_model->surfmesh.data_lightmapoffsets + surface->num_firstvertex)[i];
2865 float scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
2866 VectorScale(lm, scale, c);
2867 if (surface->lightmapinfo->styles[1] != 255)
2869 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
2871 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
2872 VectorMA(c, scale, lm, c);
2873 if (surface->lightmapinfo->styles[2] != 255)
2876 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
2877 VectorMA(c, scale, lm, c);
2878 if (surface->lightmapinfo->styles[3] != 255)
2881 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
2882 VectorMA(c, scale, lm, c);
2892 rsurface_lightmapcolor4f = rsurface_array_color4f;
2895 rsurface_lightmapcolor4f = rsurface_model->surfmesh.data_lightmapcolor4f;
2900 rsurface_lightmapcolor4f = NULL;
2904 if (rsurface_lightmapcolor4f)
2906 // generate color arrays for the surfaces in this list
2907 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2909 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2910 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)
2912 f = 1 - VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
2922 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2924 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2925 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)
2927 f = 1 - VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
2935 rsurface_lightmapcolor4f = rsurface_array_color4f;
2937 if (applycolor && rsurface_lightmapcolor4f)
2939 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2941 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2942 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)
2950 rsurface_lightmapcolor4f = rsurface_array_color4f;
2952 R_Mesh_ColorPointer(rsurface_lightmapcolor4f);
2953 GL_Color(r, g, b, a);
2954 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
2957 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
2959 if (rsurface_mode != RSURFMODE_SHOWSURFACES)
2961 rsurface_mode = RSURFMODE_SHOWSURFACES;
2963 GL_BlendFunc(GL_ONE, GL_ZERO);
2964 R_Mesh_ColorPointer(NULL);
2965 R_Mesh_ResetTextureState();
2967 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
2968 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
2971 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, msurface_t **texturesurfacelist)
2973 // transparent sky would be ridiculous
2974 if ((rsurface_texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
2976 if (rsurface_mode != RSURFMODE_SKY)
2978 if (rsurface_mode == RSURFMODE_GLSL)
2980 qglUseProgramObjectARB(0);CHECKGLERROR
2982 rsurface_mode = RSURFMODE_SKY;
2986 skyrendernow = false;
2988 // restore entity matrix
2989 R_Mesh_Matrix(&rsurface_entity->matrix);
2992 // LordHavoc: HalfLife maps have freaky skypolys so don't use
2993 // skymasking on them, and Quake3 never did sky masking (unlike
2994 // software Quake and software Quake2), so disable the sky masking
2995 // in Quake3 maps as it causes problems with q3map2 sky tricks,
2996 // and skymasking also looks very bad when noclipping outside the
2997 // level, so don't use it then either.
2998 if (rsurface_model->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_viewcache.world_novis)
3000 GL_Color(r_refdef.fogcolor[0] * r_view.colorscale, r_refdef.fogcolor[1] * r_view.colorscale, r_refdef.fogcolor[2] * r_view.colorscale, 1);
3001 R_Mesh_ColorPointer(NULL);
3002 R_Mesh_ResetTextureState();
3003 if (skyrendermasked)
3005 // depth-only (masking)
3006 GL_ColorMask(0,0,0,0);
3007 // just to make sure that braindead drivers don't draw
3008 // anything despite that colormask...
3009 GL_BlendFunc(GL_ZERO, GL_ONE);
3014 GL_BlendFunc(GL_ONE, GL_ZERO);
3016 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
3017 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3018 if (skyrendermasked)
3019 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
3023 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, msurface_t **texturesurfacelist)
3026 // FIXME: identify models using a better check than rsurface_model->brush.shadowmesh
3027 lightmode = ((rsurface_entity->effects & EF_FULLBRIGHT) || rsurface_model->brush.shadowmesh) ? 0 : 2;
3028 if (rsurface_mode != RSURFMODE_GLSL)
3030 rsurface_mode = RSURFMODE_GLSL;
3031 rsurface_glsl_texture = NULL;
3032 rsurface_glsl_uselightmap = false;
3033 R_Mesh_ResetTextureState();
3035 if (rsurface_glsl_texture != rsurface_texture || rsurface_glsl_uselightmap != (rsurface_lightmaptexture != NULL))
3037 rsurface_glsl_texture = rsurface_texture;
3038 rsurface_glsl_uselightmap = rsurface_lightmaptexture != NULL;
3039 GL_BlendFunc(rsurface_texture->currentlayers[0].blendfunc1, rsurface_texture->currentlayers[0].blendfunc2);
3040 GL_DepthMask(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_BLENDED));
3041 GL_Color(rsurface_entity->colormod[0], rsurface_entity->colormod[1], rsurface_entity->colormod[2], rsurface_texture->currentalpha);
3042 R_SetupSurfaceShader(vec3_origin, lightmode == 2);
3043 //permutation_deluxemapping = permutation_lightmapping = R_SetupSurfaceShader(vec3_origin, lightmode == 2, false);
3044 //if (r_glsl_deluxemapping.integer)
3045 // permutation_deluxemapping = R_SetupSurfaceShader(vec3_origin, lightmode == 2, true);
3046 R_Mesh_TexCoordPointer(0, 2, rsurface_model->surfmesh.data_texcoordtexture2f);
3047 R_Mesh_TexCoordPointer(4, 2, rsurface_model->surfmesh.data_texcoordlightmap2f);
3048 GL_AlphaTest((rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
3050 if (!r_glsl_permutation)
3052 RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
3053 R_Mesh_TexCoordPointer(1, 3, rsurface_svector3f);
3054 R_Mesh_TexCoordPointer(2, 3, rsurface_tvector3f);
3055 R_Mesh_TexCoordPointer(3, 3, rsurface_normal3f);
3056 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
3058 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
3059 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
3060 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
3061 R_Mesh_ColorPointer(NULL);
3063 else if (rsurface_lightmaptexture)
3065 R_Mesh_TexBind(7, R_GetTexture(rsurface_lightmaptexture));
3066 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
3067 R_Mesh_TexBind(8, R_GetTexture(texturesurfacelist[0]->deluxemaptexture));
3068 R_Mesh_ColorPointer(NULL);
3072 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
3073 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
3074 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
3075 R_Mesh_ColorPointer(rsurface_model->surfmesh.data_lightmapcolor4f);
3077 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3080 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, msurface_t **texturesurfacelist)
3082 // OpenGL 1.3 path - anything not completely ancient
3083 int texturesurfaceindex;
3085 qboolean applycolor;
3089 const texturelayer_t *layer;
3091 // FIXME: identify models using a better check than rsurface_model->brush.shadowmesh
3092 lightmode = ((rsurface_entity->effects & EF_FULLBRIGHT) || rsurface_model->brush.shadowmesh) ? 0 : 2;
3093 if (rsurface_mode != RSURFMODE_MULTIPASS)
3094 rsurface_mode = RSURFMODE_MULTIPASS;
3095 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
3096 for (layerindex = 0, layer = rsurface_texture->currentlayers;layerindex < rsurface_texture->currentnumlayers;layerindex++, layer++)
3099 int layertexrgbscale;
3100 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
3102 if (layerindex == 0)
3106 GL_AlphaTest(false);
3107 qglDepthFunc(GL_EQUAL);CHECKGLERROR
3110 GL_DepthMask(layer->depthmask);
3111 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
3112 if ((layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2) && (gl_combine.integer || layer->depthmask))
3114 layertexrgbscale = 4;
3115 VectorScale(layer->color, 0.25f, layercolor);
3117 else if ((layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1) && (gl_combine.integer || layer->depthmask))
3119 layertexrgbscale = 2;
3120 VectorScale(layer->color, 0.5f, layercolor);
3124 layertexrgbscale = 1;
3125 VectorScale(layer->color, 1.0f, layercolor);
3127 layercolor[3] = layer->color[3];
3128 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
3129 R_Mesh_ColorPointer(NULL);
3130 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
3131 switch (layer->type)
3133 case TEXTURELAYERTYPE_LITTEXTURE:
3134 memset(&m, 0, sizeof(m));
3135 if (lightmode >= 1 || !rsurface_lightmaptexture)
3136 m.tex[0] = R_GetTexture(r_texture_white);
3138 m.tex[0] = R_GetTexture(rsurface_lightmaptexture);
3139 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordlightmap2f;
3140 m.tex[1] = R_GetTexture(layer->texture);
3141 m.texmatrix[1] = layer->texmatrix;
3142 m.texrgbscale[1] = layertexrgbscale;
3143 m.pointer_texcoord[1] = rsurface_model->surfmesh.data_texcoordtexture2f;
3144 R_Mesh_TextureState(&m);
3145 RSurf_DrawBatch_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], lightmode, applycolor, applyfog);
3147 case TEXTURELAYERTYPE_TEXTURE:
3148 memset(&m, 0, sizeof(m));
3149 m.tex[0] = R_GetTexture(layer->texture);
3150 m.texmatrix[0] = layer->texmatrix;
3151 m.texrgbscale[0] = layertexrgbscale;
3152 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3153 R_Mesh_TextureState(&m);
3154 RSurf_DrawBatch_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, applyfog);
3156 case TEXTURELAYERTYPE_FOG:
3157 memset(&m, 0, sizeof(m));
3158 m.texrgbscale[0] = layertexrgbscale;
3161 m.tex[0] = R_GetTexture(layer->texture);
3162 m.texmatrix[0] = layer->texmatrix;
3163 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3165 R_Mesh_TextureState(&m);
3166 // generate a color array for the fog pass
3167 R_Mesh_ColorPointer(rsurface_array_color4f);
3168 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3172 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3173 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)
3175 f = VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
3176 c[0] = layercolor[0];
3177 c[1] = layercolor[1];
3178 c[2] = layercolor[2];
3179 c[3] = f * layercolor[3];
3182 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3185 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
3187 GL_LockArrays(0, 0);
3190 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
3192 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3193 GL_AlphaTest(false);
3197 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, msurface_t **texturesurfacelist)
3199 // OpenGL 1.1 - crusty old voodoo path
3200 int texturesurfaceindex;
3205 const texturelayer_t *layer;
3207 // FIXME: identify models using a better check than rsurface_model->brush.shadowmesh
3208 lightmode = ((rsurface_entity->effects & EF_FULLBRIGHT) || rsurface_model->brush.shadowmesh) ? 0 : 2;
3209 if (rsurface_mode != RSURFMODE_MULTIPASS)
3210 rsurface_mode = RSURFMODE_MULTIPASS;
3211 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
3212 for (layerindex = 0, layer = rsurface_texture->currentlayers;layerindex < rsurface_texture->currentnumlayers;layerindex++, layer++)
3214 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
3216 if (layerindex == 0)
3220 GL_AlphaTest(false);
3221 qglDepthFunc(GL_EQUAL);CHECKGLERROR
3224 GL_DepthMask(layer->depthmask);
3225 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
3226 R_Mesh_ColorPointer(NULL);
3227 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
3228 switch (layer->type)
3230 case TEXTURELAYERTYPE_LITTEXTURE:
3231 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
3233 // two-pass lit texture with 2x rgbscale
3234 // first the lightmap pass
3235 memset(&m, 0, sizeof(m));
3236 if (lightmode >= 1 || !rsurface_lightmaptexture)
3237 m.tex[0] = R_GetTexture(r_texture_white);
3239 m.tex[0] = R_GetTexture(rsurface_lightmaptexture);
3240 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordlightmap2f;
3241 R_Mesh_TextureState(&m);
3242 RSurf_DrawBatch_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, lightmode, false, false);
3243 GL_LockArrays(0, 0);
3244 // then apply the texture to it
3245 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
3246 memset(&m, 0, sizeof(m));
3247 m.tex[0] = R_GetTexture(layer->texture);
3248 m.texmatrix[0] = layer->texmatrix;
3249 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3250 R_Mesh_TextureState(&m);
3251 RSurf_DrawBatch_Lightmap(texturenumsurfaces, texturesurfacelist, layer->color[0] * 0.5f, layer->color[1] * 0.5f, layer->color[2] * 0.5f, layer->color[3], 0, layer->color[0] != 2 || layer->color[1] != 2 || layer->color[2] != 2 || layer->color[3] != 1, false);
3255 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
3256 memset(&m, 0, sizeof(m));
3257 m.tex[0] = R_GetTexture(layer->texture);
3258 m.texmatrix[0] = layer->texmatrix;
3259 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3260 R_Mesh_TextureState(&m);
3261 RSurf_DrawBatch_Lightmap(texturenumsurfaces, texturesurfacelist, layer->color[0], layer->color[1], layer->color[2], layer->color[3], lightmode == 2 ? 2 : 1, layer->color[0] != 1 || layer->color[1] != 1 || layer->color[2] != 1 || layer->color[3] != 1, applyfog);
3264 case TEXTURELAYERTYPE_TEXTURE:
3265 // singletexture unlit texture with transparency support
3266 memset(&m, 0, sizeof(m));
3267 m.tex[0] = R_GetTexture(layer->texture);
3268 m.texmatrix[0] = layer->texmatrix;
3269 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3270 R_Mesh_TextureState(&m);
3271 RSurf_DrawBatch_Lightmap(texturenumsurfaces, texturesurfacelist, layer->color[0], layer->color[1], layer->color[2], layer->color[3], 0, layer->color[0] != 1 || layer->color[1] != 1 || layer->color[2] != 1 || layer->color[3] != 1, applyfog);
3273 case TEXTURELAYERTYPE_FOG:
3274 // singletexture fogging
3275 R_Mesh_ColorPointer(rsurface_array_color4f);
3278 memset(&m, 0, sizeof(m));
3279 m.tex[0] = R_GetTexture(layer->texture);
3280 m.texmatrix[0] = layer->texmatrix;
3281 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3282 R_Mesh_TextureState(&m);
3285 R_Mesh_ResetTextureState();
3286 // generate a color array for the fog pass
3287 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3291 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3292 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)
3294 f = VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
3295 c[0] = layer->color[0];
3296 c[1] = layer->color[1];
3297 c[2] = layer->color[2];
3298 c[3] = f * layer->color[3];
3301 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3304 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
3306 GL_LockArrays(0, 0);
3309 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
3311 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3312 GL_AlphaTest(false);
3316 static void R_DrawTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist)
3318 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_NODRAW)
3320 r_shadow_rtlight = NULL;
3321 r_refdef.stats.entities_surfaces += texturenumsurfaces;
3323 GL_DepthTest(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
3324 if ((rsurface_texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (rsurface_entity->flags & RENDER_NOCULLFACE))
3326 qglDisable(GL_CULL_FACE);CHECKGLERROR
3328 if (r_showsurfaces.integer)
3329 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
3330 else if (rsurface_texture->currentmaterialflags & MATERIALFLAG_SKY)
3331 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
3332 else if (rsurface_texture->currentnumlayers)
3334 if (r_glsl.integer && gl_support_fragment_shader)
3335 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist);
3336 else if (gl_combine.integer && r_textureunits.integer >= 2)
3337 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist);
3339 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist);
3342 GL_LockArrays(0, 0);
3343 if ((rsurface_texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (rsurface_entity->flags & RENDER_NOCULLFACE))
3345 qglEnable(GL_CULL_FACE);CHECKGLERROR
3349 #define BATCHSIZE 256
3350 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
3352 int surfacelistindex;
3355 msurface_t *texturesurfacelist[BATCHSIZE];
3356 // if the model is static it doesn't matter what value we give for
3357 // wantnormals and wanttangents, so this logic uses only rules applicable
3358 // to a model, knowing that they are meaningless otherwise
3359 if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
3360 RSurf_ActiveEntity(ent, false, false);
3362 RSurf_ActiveEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
3365 for (surfacelistindex = 0;surfacelistindex < numsurfaces;surfacelistindex++)
3367 msurface_t *surface = ent->model->data_surfaces + surfacelist[surfacelistindex];
3369 if (t != surface->texture || rsurface_lightmaptexture != surface->lightmaptexture)
3372 R_DrawTextureSurfaceList(batchcount, texturesurfacelist);
3374 t = surface->texture;
3375 rsurface_lightmaptexture = surface->lightmaptexture;
3376 R_UpdateTextureInfo(ent, t);
3377 rsurface_texture = t->currentframe;
3379 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_SKY)
3380 continue; // transparent sky is too difficult
3382 texturesurfacelist[batchcount++] = surface;
3385 R_DrawTextureSurfaceList(batchcount, texturesurfacelist);
3389 void R_QueueTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist)
3391 int texturesurfaceindex;
3392 vec3_t tempcenter, center;
3393 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_BLENDED)
3395 // drawing sky transparently would be too difficult
3396 if (!(rsurface_texture->currentmaterialflags & MATERIALFLAG_SKY))
3398 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3400 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3401 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
3402 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
3403 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
3404 Matrix4x4_Transform(&rsurface_entity->matrix, tempcenter, center);
3405 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);
3410 R_DrawTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
3413 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
3414 void R_DrawSurfaces(entity_render_t *ent, qboolean skysurfaces)
3416 int i, j, f, flagsmask;
3417 int counttriangles = 0;
3419 model_t *model = ent->model;
3420 const int maxsurfacelist = 1024;
3421 int numsurfacelist = 0;
3422 msurface_t *surfacelist[1024];
3426 // if the model is static it doesn't matter what value we give for
3427 // wantnormals and wanttangents, so this logic uses only rules applicable
3428 // to a model, knowing that they are meaningless otherwise
3429 if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
3430 RSurf_ActiveEntity(ent, false, false);
3432 RSurf_ActiveEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
3434 // update light styles
3435 if (!skysurfaces && model->brushq1.light_styleupdatechains)
3437 msurface_t *surface, **surfacechain;
3438 for (i = 0;i < model->brushq1.light_styles;i++)
3440 if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
3442 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
3443 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
3444 for (;(surface = *surfacechain);surfacechain++)
3445 surface->cached_dlight = true;
3450 R_UpdateAllTextureInfo(ent);
3451 flagsmask = skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL);
3454 rsurface_lightmaptexture = NULL;
3455 rsurface_texture = NULL;
3457 if (ent == r_refdef.worldentity)
3459 msurface_t *surface;
3460 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
3462 if (!r_viewcache.world_surfacevisible[j])
3464 if (t != surface->texture || rsurface_lightmaptexture != surface->lightmaptexture)
3468 R_QueueTextureSurfaceList(numsurfacelist, surfacelist);
3471 t = surface->texture;
3472 rsurface_lightmaptexture = surface->lightmaptexture;
3473 rsurface_texture = t->currentframe;
3474 f = rsurface_texture->currentmaterialflags & flagsmask;
3476 if (f && surface->num_triangles)
3478 // if lightmap parameters changed, rebuild lightmap texture
3479 if (surface->cached_dlight)
3480 R_BuildLightMap(ent, surface);
3481 // add face to draw list
3482 surfacelist[numsurfacelist++] = surface;
3483 counttriangles += surface->num_triangles;
3484 if (numsurfacelist >= maxsurfacelist)
3486 R_QueueTextureSurfaceList(numsurfacelist, surfacelist);
3494 msurface_t *surface;
3495 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
3497 if (t != surface->texture || rsurface_lightmaptexture != surface->lightmaptexture)
3501 R_QueueTextureSurfaceList(numsurfacelist, surfacelist);
3504 t = surface->texture;
3505 rsurface_lightmaptexture = surface->lightmaptexture;
3506 rsurface_texture = t->currentframe;
3507 f = rsurface_texture->currentmaterialflags & flagsmask;
3509 if (f && surface->num_triangles)
3511 // if lightmap parameters changed, rebuild lightmap texture
3512 if (surface->cached_dlight)
3513 R_BuildLightMap(ent, surface);
3514 // add face to draw list
3515 surfacelist[numsurfacelist++] = surface;
3516 counttriangles += surface->num_triangles;
3517 if (numsurfacelist >= maxsurfacelist)
3519 R_QueueTextureSurfaceList(numsurfacelist, surfacelist);
3526 R_QueueTextureSurfaceList(numsurfacelist, surfacelist);
3527 r_refdef.stats.entities_triangles += counttriangles;
3530 if (r_showcollisionbrushes.integer && model->brush.num_brushes && !skysurfaces)
3533 const msurface_t *surface;
3536 R_Mesh_Matrix(&ent->matrix);
3537 R_Mesh_ColorPointer(NULL);
3538 R_Mesh_ResetTextureState();
3539 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
3540 GL_DepthMask(false);
3541 GL_DepthTest(!r_showdisabledepthtest.integer);
3542 qglPolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);CHECKGLERROR
3543 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
3544 if (brush->colbrushf && brush->colbrushf->numtriangles)
3545 R_DrawCollisionBrush(brush->colbrushf);
3546 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
3547 if (surface->num_collisiontriangles)
3548 R_DrawCollisionSurface(ent, surface);
3549 qglPolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR
3552 if (r_showtris.integer || r_shownormals.integer)
3555 msurface_t *surface;
3556 const int *elements;
3561 if (r_showdisabledepthtest.integer)
3563 qglDepthFunc(GL_ALWAYS);CHECKGLERROR
3565 GL_BlendFunc(GL_ONE, GL_ZERO);
3566 R_Mesh_ColorPointer(NULL);
3567 R_Mesh_ResetTextureState();
3568 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
3570 if (ent == r_refdef.worldentity && !r_viewcache.world_surfacevisible[j])
3572 rsurface_texture = surface->texture->currentframe;
3573 if ((rsurface_texture->currentmaterialflags & flagsmask) && surface->num_triangles)
3575 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
3576 if (r_showtris.integer)
3578 if (!rsurface_texture->currentlayers->depthmask)
3579 GL_Color(r_showtris.value * r_view.colorscale, 0, 0, 1);
3580 else if (ent == r_refdef.worldentity)
3581 GL_Color(r_showtris.value * r_view.colorscale, r_showtris.value * r_view.colorscale, r_showtris.value * r_view.colorscale, 1);
3583 GL_Color(0, r_showtris.value * r_view.colorscale, 0, 1);
3584 elements = (ent->model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
3587 for (k = 0;k < surface->num_triangles;k++, elements += 3)
3589 qglArrayElement(elements[0]);qglArrayElement(elements[1]);
3590 qglArrayElement(elements[1]);qglArrayElement(elements[2]);
3591 qglArrayElement(elements[2]);qglArrayElement(elements[0]);
3596 if (r_shownormals.integer)
3598 GL_Color(r_shownormals.value * r_view.colorscale, 0, 0, 1);
3600 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
3602 VectorCopy(rsurface_vertex3f + l * 3, v);
3603 qglVertex3f(v[0], v[1], v[2]);
3604 VectorMA(v, 8, rsurface_svector3f + l * 3, v);
3605 qglVertex3f(v[0], v[1], v[2]);
3609 GL_Color(0, 0, r_shownormals.value * r_view.colorscale, 1);
3611 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
3613 VectorCopy(rsurface_vertex3f + l * 3, v);
3614 qglVertex3f(v[0], v[1], v[2]);
3615 VectorMA(v, 8, rsurface_tvector3f + l * 3, v);
3616 qglVertex3f(v[0], v[1], v[2]);
3620 GL_Color(0, r_shownormals.value * r_view.colorscale, 0, 1);
3622 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
3624 VectorCopy(rsurface_vertex3f + l * 3, v);
3625 qglVertex3f(v[0], v[1], v[2]);
3626 VectorMA(v, 8, rsurface_normal3f + l * 3, v);
3627 qglVertex3f(v[0], v[1], v[2]);
3634 rsurface_texture = NULL;
3635 if (r_showdisabledepthtest.integer)
3637 qglDepthFunc(GL_LEQUAL);CHECKGLERROR