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 "#ifdef __GLSL_CG_DATA_TYPES\n"
338 "#define myhalf half\n"
339 "#define myhvec2 hvec2\n"
340 "#define myhvec3 hvec3\n"
341 "#define myhvec4 hvec4\n"
343 "#define myhalf float\n"
344 "#define myhvec2 vec2\n"
345 "#define myhvec3 vec3\n"
346 "#define myhvec4 vec4\n"
349 "varying vec2 TexCoord;\n"
350 "varying vec2 TexCoordLightmap;\n"
352 "varying vec3 CubeVector;\n"
353 "varying vec3 LightVector;\n"
354 "varying vec3 EyeVector;\n"
356 "varying vec3 EyeVectorModelSpace;\n"
359 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
360 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
361 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
366 "// vertex shader specific:\n"
367 "#ifdef VERTEX_SHADER\n"
369 "uniform vec3 LightPosition;\n"
370 "uniform vec3 EyePosition;\n"
371 "uniform vec3 LightDir;\n"
373 "// TODO: get rid of tangentt (texcoord2) and use a crossproduct to regenerate it from tangents (texcoord1) and normal (texcoord3)\n"
377 " gl_FrontColor = gl_Color;\n"
378 " // copy the surface texcoord\n"
379 " TexCoord = vec2(gl_TextureMatrix[0] * gl_MultiTexCoord0);\n"
380 "#if !defined(MODE_LIGHTSOURCE) && !defined(MODE_LIGHTDIRECTION)\n"
381 " TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
384 "#ifdef MODE_LIGHTSOURCE\n"
385 " // transform vertex position into light attenuation/cubemap space\n"
386 " // (-1 to +1 across the light box)\n"
387 " CubeVector = vec3(gl_TextureMatrix[3] * gl_Vertex);\n"
389 " // transform unnormalized light direction into tangent space\n"
390 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
391 " // normalize it per pixel)\n"
392 " vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
393 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
394 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
395 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
398 "#ifdef MODE_LIGHTDIRECTION\n"
399 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
400 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
401 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
404 " // transform unnormalized eye direction into tangent space\n"
406 " vec3 EyeVectorModelSpace;\n"
408 " EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
409 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
410 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
411 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
413 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
414 " VectorS = gl_MultiTexCoord1.xyz;\n"
415 " VectorT = gl_MultiTexCoord2.xyz;\n"
416 " VectorR = gl_MultiTexCoord3.xyz;\n"
419 " // transform vertex to camera space, using ftransform to match non-VS\n"
421 " gl_Position = ftransform();\n"
424 "#endif // VERTEX_SHADER\n"
429 "// fragment shader specific:\n"
430 "#ifdef FRAGMENT_SHADER\n"
432 "uniform sampler2D Texture_Normal;\n"
433 "uniform sampler2D Texture_Color;\n"
434 "uniform sampler2D Texture_Gloss;\n"
435 "uniform samplerCube Texture_Cube;\n"
436 "uniform sampler2D Texture_FogMask;\n"
437 "uniform sampler2D Texture_Pants;\n"
438 "uniform sampler2D Texture_Shirt;\n"
439 "uniform sampler2D Texture_Lightmap;\n"
440 "uniform sampler2D Texture_Deluxemap;\n"
441 "uniform sampler2D Texture_Glow;\n"
443 "uniform myhvec3 LightColor;\n"
444 "uniform myhvec3 AmbientColor;\n"
445 "uniform myhvec3 DiffuseColor;\n"
446 "uniform myhvec3 SpecularColor;\n"
447 "uniform myhvec3 Color_Pants;\n"
448 "uniform myhvec3 Color_Shirt;\n"
449 "uniform myhvec3 FogColor;\n"
451 "uniform myhalf GlowScale;\n"
452 "uniform myhalf SceneBrightness;\n"
454 "uniform float OffsetMapping_Scale;\n"
455 "uniform float OffsetMapping_Bias;\n"
456 "uniform float FogRangeRecip;\n"
458 "uniform myhalf AmbientScale;\n"
459 "uniform myhalf DiffuseScale;\n"
460 "uniform myhalf SpecularScale;\n"
461 "uniform myhalf SpecularPower;\n"
465 " // apply offsetmapping\n"
466 "#ifdef USEOFFSETMAPPING\n"
467 " vec2 TexCoordOffset = TexCoord;\n"
468 "#define TexCoord TexCoordOffset\n"
470 " vec3 eyedir = vec3(normalize(EyeVector));\n"
471 " float depthbias = 1.0 - eyedir.z; // should this be a -?\n"
472 " depthbias = 1.0 - depthbias * depthbias;\n"
474 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
475 " // 14 sample relief mapping: linear search and then binary search\n"
476 " //vec3 OffsetVector = vec3(EyeVector.xy * (1.0 / EyeVector.z) * depthbias * OffsetMapping_Scale * vec2(-0.1, 0.1), -0.1);\n"
477 " //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-0.1, 0.1), -0.1);\n"
478 " vec3 OffsetVector = vec3(eyedir.xy * OffsetMapping_Scale * vec2(-0.1, 0.1), -0.1);\n"
479 " vec3 RT = vec3(TexCoord - OffsetVector.xy * 10.0, 1.0) + OffsetVector;\n"
480 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
481 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
482 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
483 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
484 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
485 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
486 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
487 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
488 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;OffsetVector *= 0.5;RT -= OffsetVector;\n"
489 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;OffsetVector *= 0.5;RT -= OffsetVector;\n"
490 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;OffsetVector *= 0.5;RT -= OffsetVector;\n"
491 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;OffsetVector *= 0.5;RT -= OffsetVector;\n"
492 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;OffsetVector *= 0.5;RT -= OffsetVector;\n"
493 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;OffsetVector *= 0.5;RT -= OffsetVector;\n"
494 " TexCoord = RT.xy;\n"
496 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
497 " //vec2 OffsetVector = vec2(EyeVector.xy * (1.0 / EyeVector.z) * depthbias) * OffsetMapping_Scale * vec2(-0.333, 0.333);\n"
498 " //vec2 OffsetVector = vec2(normalize(EyeVector.xy)) * OffsetMapping_Scale * vec2(-0.333, 0.333);\n"
499 " vec2 OffsetVector = vec2(eyedir.xy) * OffsetMapping_Scale * vec2(-0.333, 0.333);\n"
500 " //TexCoord += OffsetVector * 3.0;\n"
501 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
502 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
503 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
505 " // 10 sample offset mapping\n"
506 " //vec2 OffsetVector = vec2(EyeVector.xy * (1.0 / EyeVector.z) * depthbias) * OffsetMapping_Scale * vec2(-0.333, 0.333);\n"
507 " //vec2 OffsetVector = vec2(normalize(EyeVector.xy)) * OffsetMapping_Scale * vec2(-0.333, 0.333);\n"
508 " vec2 OffsetVector = vec2(eyedir.xy) * OffsetMapping_Scale * vec2(-0.1, 0.1);\n"
509 " //TexCoord += OffsetVector * 3.0;\n"
510 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
511 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
512 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
513 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
514 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
515 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
516 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
517 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
518 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
519 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
521 " // parallax mapping as described in the paper\n"
522 " // 'Parallax Mapping with Offset Limiting: A Per-Pixel Approximation of Uneven Surfaces' by Terry Welsh\n"
523 " // The paper provides code in the ARB fragment program assembly language\n"
524 " // I translated it to GLSL but may have done something wrong - SavageX\n"
525 " // LordHavoc: removed bias and simplified to one line\n"
526 " // LordHavoc: this is just a single sample offsetmapping...\n"
527 " TexCoordOffset += vec2(eyedir.x, -1.0 * eyedir.y) * OffsetMapping_Scale * texture2D(Texture_Normal, TexCoord).a;\n"
529 " // parallax mapping as described in the paper\n"
530 " // 'Parallax Mapping with Offset Limiting: A Per-Pixel Approximation of Uneven Surfaces' by Terry Welsh\n"
531 " // The paper provides code in the ARB fragment program assembly language\n"
532 " // I translated it to GLSL but may have done something wrong - SavageX\n"
533 " float height = texture2D(Texture_Normal, TexCoord).a;\n"
534 " height = (height - 0.5) * OffsetMapping_Scale; // bias and scale\n"
535 " TexCoordOffset += height * vec2(eyedir.x, -1.0 * eyedir.y);\n"
539 " // combine the diffuse textures (base, pants, shirt)\n"
540 " myhvec4 color = myhvec4(texture2D(Texture_Color, TexCoord));\n"
541 "#ifdef USECOLORMAPPING\n"
542 " color.rgb += myhvec3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhvec3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
548 "#ifdef MODE_LIGHTSOURCE\n"
551 " // get the surface normal and light normal\n"
552 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
553 " myhvec3 diffusenormal = myhvec3(normalize(LightVector));\n"
555 " // calculate directional shading\n"
556 " color.rgb *= AmbientScale + DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
557 "#ifdef USESPECULAR\n"
558 " myhvec3 specularnormal = normalize(diffusenormal + myhvec3(normalize(EyeVector)));\n"
559 " color.rgb += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
562 "#ifdef USECUBEFILTER\n"
563 " // apply light cubemap filter\n"
564 " //color.rgb *= normalize(CubeVector) * 0.5 + 0.5;//vec3(textureCube(Texture_Cube, CubeVector));\n"
565 " color.rgb *= myhvec3(textureCube(Texture_Cube, CubeVector));\n"
568 " // apply light color\n"
569 " color.rgb *= LightColor;\n"
571 " // apply attenuation\n"
573 " // the attenuation is (1-(x*x+y*y+z*z)) which gives a large bright\n"
574 " // center and sharp falloff at the edge, this is about the most efficient\n"
575 " // we can get away with as far as providing illumination.\n"
577 " // pow(1-(x*x+y*y+z*z), 4) is far more realistic but needs large lights to\n"
578 " // provide significant illumination, large = slow = pain.\n"
579 " color.rgb *= myhalf(max(1.0 - dot(CubeVector, CubeVector), 0.0));\n"
584 "#elif defined(MODE_LIGHTDIRECTION)\n"
585 " // directional model lighting\n"
587 " // get the surface normal and light normal\n"
588 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
589 " myhvec3 diffusenormal = myhvec3(normalize(LightVector));\n"
591 " // calculate directional shading\n"
592 " color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
593 "#ifdef USESPECULAR\n"
594 " myhvec3 specularnormal = normalize(diffusenormal + myhvec3(normalize(EyeVector)));\n"
595 " color.rgb += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
601 "#elif defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
602 " // deluxemap lightmapping using light vectors in modelspace (evil q3map2)\n"
604 " // get the surface normal and light normal\n"
605 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
607 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
608 " myhvec3 diffusenormal_modelspace = myhvec3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - myhvec3(0.5);\n"
609 " myhvec3 diffusenormal = normalize(myhvec3(dot(diffusenormal_modelspace, myhvec3(VectorS)), dot(diffusenormal_modelspace, myhvec3(VectorT)), dot(diffusenormal_modelspace, myhvec3(VectorR))));\n"
611 " myhvec3 diffusenormal = normalize(myhvec3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - myhvec3(0.5));\n"
613 " // calculate directional shading\n"
614 " myhvec3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0)));\n"
615 "#ifdef USESPECULAR\n"
616 " myhvec3 specularnormal = myhvec3(normalize(diffusenormal + myhvec3(normalize(EyeVector))));\n"
617 " tempcolor += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
620 " // apply lightmap color\n"
621 " color.rgb = tempcolor * myhvec3(texture2D(Texture_Lightmap, TexCoordLightmap)) + color.rgb * AmbientScale;\n"
624 "#else // MODE none (lightmap)\n"
625 " // apply lightmap color\n"
626 " color.rgb *= myhvec3(texture2D(Texture_Lightmap, TexCoordLightmap)) * DiffuseScale + myhvec3(AmbientScale);\n"
629 " color *= myhvec4(gl_Color);\n"
632 " color.rgb += myhvec3(texture2D(Texture_Glow, TexCoord)) * GlowScale;\n"
637 " myhalf fog = myhalf(texture2D(Texture_FogMask, myhvec2(length(EyeVectorModelSpace)*FogRangeRecip, 0.0)).x);\n"
638 " color.rgb = color.rgb * fog + FogColor * (1.0 - fog);\n"
641 " color.rgb *= SceneBrightness;\n"
643 " gl_FragColor = vec4(color);\n"
646 "#endif // FRAGMENT_SHADER\n"
649 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
650 const char *permutationinfo[][2] =
652 {"#define MODE_LIGHTSOURCE\n", " lightsource"},
653 {"#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
654 {"#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
655 {"#define MODE_LIGHTDIRECTION\n", " lightdirection"},
656 {"#define USEGLOW\n", " glow"},
657 {"#define USEFOG\n", " fog"},
658 {"#define USECOLORMAPPING\n", " colormapping"},
659 {"#define USESPECULAR\n", " specular"},
660 {"#define USECUBEFILTER\n", " cubefilter"},
661 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
662 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
666 void R_GLSL_CompilePermutation(int permutation)
669 r_glsl_permutation_t *p = r_glsl_permutations + permutation;
670 int vertstrings_count;
671 int fragstrings_count;
673 const char *vertstrings_list[SHADERPERMUTATION_COUNT+1];
674 const char *fragstrings_list[SHADERPERMUTATION_COUNT+1];
675 char permutationname[256];
679 vertstrings_list[0] = "#define VERTEX_SHADER\n";
680 fragstrings_list[0] = "#define FRAGMENT_SHADER\n";
681 vertstrings_count = 1;
682 fragstrings_count = 1;
683 permutationname[0] = 0;
684 for (i = 0;permutationinfo[i][0];i++)
686 if (permutation & (1<<i))
688 vertstrings_list[vertstrings_count++] = permutationinfo[i][0];
689 fragstrings_list[fragstrings_count++] = permutationinfo[i][0];
690 strlcat(permutationname, permutationinfo[i][1], sizeof(permutationname));
694 // keep line numbers correct
695 vertstrings_list[vertstrings_count++] = "\n";
696 fragstrings_list[fragstrings_count++] = "\n";
699 shaderstring = (char *)FS_LoadFile("glsl/default.glsl", r_main_mempool, false, NULL);
702 Con_DPrintf("GLSL shader text loaded from disk\n");
703 vertstrings_list[vertstrings_count++] = shaderstring;
704 fragstrings_list[fragstrings_count++] = shaderstring;
708 vertstrings_list[vertstrings_count++] = builtinshaderstring;
709 fragstrings_list[fragstrings_count++] = builtinshaderstring;
711 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, fragstrings_count, fragstrings_list);
715 qglUseProgramObjectARB(p->program);CHECKGLERROR
716 p->loc_Texture_Normal = qglGetUniformLocationARB(p->program, "Texture_Normal");
717 p->loc_Texture_Color = qglGetUniformLocationARB(p->program, "Texture_Color");
718 p->loc_Texture_Gloss = qglGetUniformLocationARB(p->program, "Texture_Gloss");
719 p->loc_Texture_Cube = qglGetUniformLocationARB(p->program, "Texture_Cube");
720 p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
721 p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
722 p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
723 p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
724 p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
725 p->loc_Texture_Glow = qglGetUniformLocationARB(p->program, "Texture_Glow");
726 p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
727 p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
728 p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
729 p->loc_LightColor = qglGetUniformLocationARB(p->program, "LightColor");
730 p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants");
731 p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt");
732 p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip");
733 p->loc_AmbientScale = qglGetUniformLocationARB(p->program, "AmbientScale");
734 p->loc_DiffuseScale = qglGetUniformLocationARB(p->program, "DiffuseScale");
735 p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
736 p->loc_SpecularScale = qglGetUniformLocationARB(p->program, "SpecularScale");
737 p->loc_GlowScale = qglGetUniformLocationARB(p->program, "GlowScale");
738 p->loc_SceneBrightness = qglGetUniformLocationARB(p->program, "SceneBrightness");
739 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
740 p->loc_AmbientColor = qglGetUniformLocationARB(p->program, "AmbientColor");
741 p->loc_DiffuseColor = qglGetUniformLocationARB(p->program, "DiffuseColor");
742 p->loc_SpecularColor = qglGetUniformLocationARB(p->program, "SpecularColor");
743 p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
744 if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal, 0);
745 if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color, 1);
746 if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss, 2);
747 if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube, 3);
748 if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask, 4);
749 if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants, 5);
750 if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt, 6);
751 if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap, 7);
752 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap, 8);
753 if (p->loc_Texture_Glow >= 0) qglUniform1iARB(p->loc_Texture_Glow, 9);
755 qglUseProgramObjectARB(0);CHECKGLERROR
758 Con_Printf("permutation%s failed for shader %s, some features may not work properly!\n", permutationname, "glsl/default.glsl");
760 Mem_Free(shaderstring);
763 void R_GLSL_Restart_f(void)
766 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
767 if (r_glsl_permutations[i].program)
768 GL_Backend_FreeProgram(r_glsl_permutations[i].program);
769 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
772 int R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting)
774 // select a permutation of the lighting shader appropriate to this
775 // combination of texture, entity, light source, and fogging, only use the
776 // minimum features necessary to avoid wasting rendering time in the
777 // fragment shader on features that are not being used
779 float specularscale = rsurface_texture->specularscale;
780 r_glsl_permutation = NULL;
781 if (r_shadow_rtlight)
783 permutation |= SHADERPERMUTATION_MODE_LIGHTSOURCE;
784 specularscale *= r_shadow_rtlight->specularscale;
785 if (r_shadow_rtlight->currentcubemap != r_texture_whitecube)
786 permutation |= SHADERPERMUTATION_CUBEFILTER;
790 if (!(rsurface_texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
793 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTION;
794 else if (r_glsl_deluxemapping.integer >= 1 && rsurface_lightmaptexture)
796 if (r_refdef.worldmodel && r_refdef.worldmodel->brushq3.deluxemapping)
798 if (r_refdef.worldmodel->brushq3.deluxemapping_modelspace)
799 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_MODELSPACE;
801 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
803 else if (r_glsl_deluxemapping.integer >= 2) // fake mode
804 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
807 if (rsurface_texture->skin.glow)
808 permutation |= SHADERPERMUTATION_GLOW;
810 if (specularscale > 0)
811 permutation |= SHADERPERMUTATION_SPECULAR;
812 if (r_refdef.fogenabled)
813 permutation |= SHADERPERMUTATION_FOG;
814 if (rsurface_texture->colormapping)
815 permutation |= SHADERPERMUTATION_COLORMAPPING;
816 if (r_glsl_offsetmapping.integer)
818 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
819 if (r_glsl_offsetmapping_reliefmapping.integer)
820 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
822 if (!r_glsl_permutations[permutation].program)
824 if (!r_glsl_permutations[permutation].compiled)
825 R_GLSL_CompilePermutation(permutation);
826 if (!r_glsl_permutations[permutation].program)
828 // remove features until we find a valid permutation
830 for (i = SHADERPERMUTATION_COUNT-1;;i>>=1)
832 // reduce i more quickly whenever it would not remove any bits
836 if (!r_glsl_permutations[permutation].compiled)
837 R_GLSL_CompilePermutation(permutation);
838 if (r_glsl_permutations[permutation].program)
841 return 0; // utterly failed
845 r_glsl_permutation = r_glsl_permutations + permutation;
847 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
848 R_Mesh_TexMatrix(0, &rsurface_texture->currenttexmatrix);
849 if (permutation & SHADERPERMUTATION_MODE_LIGHTSOURCE)
851 if (r_glsl_permutation->loc_Texture_Cube >= 0 && r_shadow_rtlight) R_Mesh_TexBindCubeMap(3, R_GetTexture(r_shadow_rtlight->currentcubemap));
852 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]);
853 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
854 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_shadow_rtlight->ambientscale);
855 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_shadow_rtlight->diffusescale);
856 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, specularscale);
858 else if (permutation & SHADERPERMUTATION_MODE_LIGHTDIRECTION)
860 if (r_glsl_permutation->loc_AmbientColor >= 0)
861 qglUniform3fARB(r_glsl_permutation->loc_AmbientColor, rsurface_entity->modellight_ambient[0], rsurface_entity->modellight_ambient[1], rsurface_entity->modellight_ambient[2]);
862 if (r_glsl_permutation->loc_DiffuseColor >= 0)
863 qglUniform3fARB(r_glsl_permutation->loc_DiffuseColor, rsurface_entity->modellight_diffuse[0], rsurface_entity->modellight_diffuse[1], rsurface_entity->modellight_diffuse[2]);
864 if (r_glsl_permutation->loc_SpecularColor >= 0)
865 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);
866 if (r_glsl_permutation->loc_LightDir >= 0)
867 qglUniform3fARB(r_glsl_permutation->loc_LightDir, rsurface_entity->modellight_lightdir[0], rsurface_entity->modellight_lightdir[1], rsurface_entity->modellight_lightdir[2]);
871 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_ambient.value * 2.0f / 128.0f);
872 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_refdef.lightmapintensity * 2.0f);
873 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, r_refdef.lightmapintensity * specularscale * 2.0f);
875 if (r_glsl_permutation->loc_Texture_Normal >= 0) R_Mesh_TexBind(0, R_GetTexture(rsurface_texture->skin.nmap));
876 if (r_glsl_permutation->loc_Texture_Color >= 0) R_Mesh_TexBind(1, R_GetTexture(rsurface_texture->basetexture));
877 if (r_glsl_permutation->loc_Texture_Gloss >= 0) R_Mesh_TexBind(2, R_GetTexture(rsurface_texture->glosstexture));
878 //if (r_glsl_permutation->loc_Texture_Cube >= 0 && permutation & SHADERPERMUTATION_MODE_LIGHTSOURCE) R_Mesh_TexBindCubeMap(3, R_GetTexture(r_shadow_rtlight->currentcubemap));
879 if (r_glsl_permutation->loc_Texture_FogMask >= 0) R_Mesh_TexBind(4, R_GetTexture(r_texture_fogattenuation));
880 if (r_glsl_permutation->loc_Texture_Pants >= 0) R_Mesh_TexBind(5, R_GetTexture(rsurface_texture->skin.pants));
881 if (r_glsl_permutation->loc_Texture_Shirt >= 0) R_Mesh_TexBind(6, R_GetTexture(rsurface_texture->skin.shirt));
882 //if (r_glsl_permutation->loc_Texture_Lightmap >= 0) R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
883 //if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
884 if (r_glsl_permutation->loc_Texture_Glow >= 0) R_Mesh_TexBind(9, R_GetTexture(rsurface_texture->skin.glow));
885 if (r_glsl_permutation->loc_GlowScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_GlowScale, r_hdr_glowintensity.value);
886 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_view.colorscale);
887 if (r_glsl_permutation->loc_FogColor >= 0)
889 // additive passes are only darkened by fog, not tinted
890 if (r_shadow_rtlight || (rsurface_texture->currentmaterialflags & MATERIALFLAG_ADD))
891 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
893 qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
895 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface_modelorg[0], rsurface_modelorg[1], rsurface_modelorg[2]);
896 if (r_glsl_permutation->loc_Color_Pants >= 0)
898 if (rsurface_texture->skin.pants)
899 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface_entity->colormap_pantscolor[0], rsurface_entity->colormap_pantscolor[1], rsurface_entity->colormap_pantscolor[2]);
901 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
903 if (r_glsl_permutation->loc_Color_Shirt >= 0)
905 if (rsurface_texture->skin.shirt)
906 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface_entity->colormap_shirtcolor[0], rsurface_entity->colormap_shirtcolor[1], rsurface_entity->colormap_shirtcolor[2]);
908 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
910 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, r_refdef.fograngerecip);
911 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface_texture->specularpower);
912 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
917 void R_SwitchSurfaceShader(int permutation)
919 if (r_glsl_permutation != r_glsl_permutations + permutation)
921 r_glsl_permutation = r_glsl_permutations + permutation;
923 qglUseProgramObjectARB(r_glsl_permutation->program);
928 void gl_main_start(void)
930 r_main_texturepool = R_AllocTexturePool();
931 r_bloom_texture_screen = NULL;
932 r_bloom_texture_bloom = NULL;
933 R_BuildBlankTextures();
935 if (gl_texturecubemap)
938 R_BuildNormalizationCube();
941 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
944 void gl_main_shutdown(void)
946 R_FreeTexturePool(&r_main_texturepool);
947 r_bloom_texture_screen = NULL;
948 r_bloom_texture_bloom = NULL;
949 r_texture_blanknormalmap = NULL;
950 r_texture_white = NULL;
951 r_texture_black = NULL;
952 r_texture_whitecube = NULL;
953 r_texture_normalizationcube = NULL;
957 extern void CL_ParseEntityLump(char *entitystring);
958 void gl_main_newmap(void)
960 // FIXME: move this code to client
962 char *entities, entname[MAX_QPATH];
965 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
966 l = (int)strlen(entname) - 4;
967 if (l >= 0 && !strcmp(entname + l, ".bsp"))
969 memcpy(entname + l, ".ent", 5);
970 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
972 CL_ParseEntityLump(entities);
977 if (cl.worldmodel->brush.entities)
978 CL_ParseEntityLump(cl.worldmodel->brush.entities);
982 void GL_Main_Init(void)
984 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
986 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed\n");
987 FOG_registercvars(); // FIXME: move this fog stuff to client?
988 Cvar_RegisterVariable(&r_nearclip);
989 Cvar_RegisterVariable(&r_showsurfaces);
990 Cvar_RegisterVariable(&r_showtris);
991 Cvar_RegisterVariable(&r_shownormals);
992 Cvar_RegisterVariable(&r_showlighting);
993 Cvar_RegisterVariable(&r_showshadowvolumes);
994 Cvar_RegisterVariable(&r_showcollisionbrushes);
995 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
996 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
997 Cvar_RegisterVariable(&r_showdisabledepthtest);
998 Cvar_RegisterVariable(&r_drawportals);
999 Cvar_RegisterVariable(&r_drawentities);
1000 Cvar_RegisterVariable(&r_drawviewmodel);
1001 Cvar_RegisterVariable(&r_speeds);
1002 Cvar_RegisterVariable(&r_fullbrights);
1003 Cvar_RegisterVariable(&r_wateralpha);
1004 Cvar_RegisterVariable(&r_dynamic);
1005 Cvar_RegisterVariable(&r_fullbright);
1006 Cvar_RegisterVariable(&r_q1bsp_skymasking);
1007 Cvar_RegisterVariable(&r_textureunits);
1008 Cvar_RegisterVariable(&r_glsl);
1009 Cvar_RegisterVariable(&r_glsl_offsetmapping);
1010 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
1011 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
1012 Cvar_RegisterVariable(&r_glsl_deluxemapping);
1013 Cvar_RegisterVariable(&r_lerpsprites);
1014 Cvar_RegisterVariable(&r_lerpmodels);
1015 Cvar_RegisterVariable(&r_waterscroll);
1016 Cvar_RegisterVariable(&r_bloom);
1017 Cvar_RegisterVariable(&r_bloom_intensity);
1018 Cvar_RegisterVariable(&r_bloom_blur);
1019 Cvar_RegisterVariable(&r_bloom_resolution);
1020 Cvar_RegisterVariable(&r_bloom_power);
1021 Cvar_RegisterVariable(&r_hdr);
1022 Cvar_RegisterVariable(&r_hdr_scenebrightness);
1023 Cvar_RegisterVariable(&r_hdr_bloomintensity);
1024 Cvar_RegisterVariable(&r_hdr_glowintensity);
1025 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
1026 Cvar_RegisterVariable(&developer_texturelogging);
1027 Cvar_RegisterVariable(&gl_lightmaps);
1028 Cvar_RegisterVariable(&r_test);
1029 Cvar_RegisterVariable(&r_batchmode);
1030 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
1031 Cvar_SetValue("r_fullbrights", 0);
1032 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
1035 extern void R_Textures_Init(void);
1036 extern void GL_Draw_Init(void);
1037 extern void GL_Main_Init(void);
1038 extern void R_Shadow_Init(void);
1039 extern void R_Sky_Init(void);
1040 extern void GL_Surf_Init(void);
1041 extern void R_Light_Init(void);
1042 extern void R_Particles_Init(void);
1043 extern void R_Explosion_Init(void);
1044 extern void gl_backend_init(void);
1045 extern void Sbar_Init(void);
1046 extern void R_LightningBeams_Init(void);
1047 extern void Mod_RenderInit(void);
1049 void Render_Init(void)
1062 R_LightningBeams_Init();
1071 extern char *ENGINE_EXTENSIONS;
1074 VID_CheckExtensions();
1076 // LordHavoc: report supported extensions
1077 Con_DPrintf("\nengine extensions: %s\n", vm_sv_extensions );
1079 // clear to black (loading plaque will be seen over this)
1081 qglClearColor(0,0,0,1);CHECKGLERROR
1082 qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
1085 int R_CullBox(const vec3_t mins, const vec3_t maxs)
1089 for (i = 0;i < 4;i++)
1091 p = r_view.frustum + i;
1096 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1100 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1104 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1108 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1112 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1116 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1120 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1124 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1132 //==================================================================================
1134 static void R_UpdateEntityLighting(entity_render_t *ent)
1136 vec3_t tempdiffusenormal;
1137 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));
1138 VectorClear(ent->modellight_diffuse);
1139 VectorClear(ent->modellight_lightdir);
1140 if ((ent->flags & RENDER_LIGHT) && r_refdef.worldmodel && r_refdef.worldmodel->brush.LightPoint)
1141 r_refdef.worldmodel->brush.LightPoint(r_refdef.worldmodel, ent->origin, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
1143 VectorSet(ent->modellight_ambient, 1, 1, 1);
1144 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
1145 VectorNormalize(ent->modellight_lightdir);
1146 ent->modellight_ambient[0] *= ent->colormod[0] * r_refdef.lightmapintensity;
1147 ent->modellight_ambient[1] *= ent->colormod[1] * r_refdef.lightmapintensity;
1148 ent->modellight_ambient[2] *= ent->colormod[2] * r_refdef.lightmapintensity;
1149 ent->modellight_diffuse[0] *= ent->colormod[0] * r_refdef.lightmapintensity;
1150 ent->modellight_diffuse[1] *= ent->colormod[1] * r_refdef.lightmapintensity;
1151 ent->modellight_diffuse[2] *= ent->colormod[2] * r_refdef.lightmapintensity;
1154 static void R_View_UpdateEntityVisible (void)
1157 entity_render_t *ent;
1159 if (!r_drawentities.integer)
1162 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : (chase_active.integer ? 0 : RENDER_EXTERIORMODEL);
1163 if (r_refdef.worldmodel && r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs)
1165 // worldmodel can check visibility
1166 for (i = 0;i < r_refdef.numentities;i++)
1168 ent = r_refdef.entities[i];
1169 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));
1174 // no worldmodel or it can't check visibility
1175 for (i = 0;i < r_refdef.numentities;i++)
1177 ent = r_refdef.entities[i];
1178 r_viewcache.entityvisible[i] = !(ent->flags & renderimask) && !R_CullBox(ent->mins, ent->maxs) && (ent->effects & EF_NODEPTHTEST);
1183 // only used if skyrendermasked, and normally returns false
1184 int R_DrawBrushModelsSky (void)
1187 entity_render_t *ent;
1189 if (!r_drawentities.integer)
1193 for (i = 0;i < r_refdef.numentities;i++)
1195 if (!r_viewcache.entityvisible[i])
1197 ent = r_refdef.entities[i];
1198 if (!ent->model || !ent->model->DrawSky)
1200 ent->model->DrawSky(ent);
1206 void R_DrawNoModel(entity_render_t *ent);
1207 void R_DrawModels(void)
1210 entity_render_t *ent;
1212 if (!r_drawentities.integer)
1215 for (i = 0;i < r_refdef.numentities;i++)
1217 if (!r_viewcache.entityvisible[i])
1219 ent = r_refdef.entities[i];
1220 r_refdef.stats.entities++;
1221 if (ent->model && ent->model->Draw != NULL)
1222 ent->model->Draw(ent);
1228 static void R_View_SetFrustum(void)
1230 // break apart the view matrix into vectors for various purposes
1231 Matrix4x4_ToVectors(&r_view.matrix, r_view.forward, r_view.left, r_view.up, r_view.origin);
1232 VectorNegate(r_view.left, r_view.right);
1235 r_view.frustum[0].normal[0] = 0 - 1.0 / r_view.frustum_x;
1236 r_view.frustum[0].normal[1] = 0 - 0;
1237 r_view.frustum[0].normal[2] = -1 - 0;
1238 r_view.frustum[1].normal[0] = 0 + 1.0 / r_view.frustum_x;
1239 r_view.frustum[1].normal[1] = 0 + 0;
1240 r_view.frustum[1].normal[2] = -1 + 0;
1241 r_view.frustum[2].normal[0] = 0 - 0;
1242 r_view.frustum[2].normal[1] = 0 - 1.0 / r_view.frustum_y;
1243 r_view.frustum[2].normal[2] = -1 - 0;
1244 r_view.frustum[3].normal[0] = 0 + 0;
1245 r_view.frustum[3].normal[1] = 0 + 1.0 / r_view.frustum_y;
1246 r_view.frustum[3].normal[2] = -1 + 0;
1250 zNear = r_refdef.nearclip;
1251 nudge = 1.0 - 1.0 / (1<<23);
1252 r_view.frustum[4].normal[0] = 0 - 0;
1253 r_view.frustum[4].normal[1] = 0 - 0;
1254 r_view.frustum[4].normal[2] = -1 - -nudge;
1255 r_view.frustum[4].dist = 0 - -2 * zNear * nudge;
1256 r_view.frustum[5].normal[0] = 0 + 0;
1257 r_view.frustum[5].normal[1] = 0 + 0;
1258 r_view.frustum[5].normal[2] = -1 + -nudge;
1259 r_view.frustum[5].dist = 0 + -2 * zNear * nudge;
1265 r_view.frustum[0].normal[0] = m[3] - m[0];
1266 r_view.frustum[0].normal[1] = m[7] - m[4];
1267 r_view.frustum[0].normal[2] = m[11] - m[8];
1268 r_view.frustum[0].dist = m[15] - m[12];
1270 r_view.frustum[1].normal[0] = m[3] + m[0];
1271 r_view.frustum[1].normal[1] = m[7] + m[4];
1272 r_view.frustum[1].normal[2] = m[11] + m[8];
1273 r_view.frustum[1].dist = m[15] + m[12];
1275 r_view.frustum[2].normal[0] = m[3] - m[1];
1276 r_view.frustum[2].normal[1] = m[7] - m[5];
1277 r_view.frustum[2].normal[2] = m[11] - m[9];
1278 r_view.frustum[2].dist = m[15] - m[13];
1280 r_view.frustum[3].normal[0] = m[3] + m[1];
1281 r_view.frustum[3].normal[1] = m[7] + m[5];
1282 r_view.frustum[3].normal[2] = m[11] + m[9];
1283 r_view.frustum[3].dist = m[15] + m[13];
1285 r_view.frustum[4].normal[0] = m[3] - m[2];
1286 r_view.frustum[4].normal[1] = m[7] - m[6];
1287 r_view.frustum[4].normal[2] = m[11] - m[10];
1288 r_view.frustum[4].dist = m[15] - m[14];
1290 r_view.frustum[5].normal[0] = m[3] + m[2];
1291 r_view.frustum[5].normal[1] = m[7] + m[6];
1292 r_view.frustum[5].normal[2] = m[11] + m[10];
1293 r_view.frustum[5].dist = m[15] + m[14];
1298 VectorMAM(1, r_view.forward, 1.0 / -r_view.frustum_x, r_view.left, r_view.frustum[0].normal);
1299 VectorMAM(1, r_view.forward, 1.0 / r_view.frustum_x, r_view.left, r_view.frustum[1].normal);
1300 VectorMAM(1, r_view.forward, 1.0 / -r_view.frustum_y, r_view.up, r_view.frustum[2].normal);
1301 VectorMAM(1, r_view.forward, 1.0 / r_view.frustum_y, r_view.up, r_view.frustum[3].normal);
1302 VectorCopy(r_view.forward, r_view.frustum[4].normal);
1303 VectorNormalize(r_view.frustum[0].normal);
1304 VectorNormalize(r_view.frustum[1].normal);
1305 VectorNormalize(r_view.frustum[2].normal);
1306 VectorNormalize(r_view.frustum[3].normal);
1307 r_view.frustum[0].dist = DotProduct (r_view.origin, r_view.frustum[0].normal);
1308 r_view.frustum[1].dist = DotProduct (r_view.origin, r_view.frustum[1].normal);
1309 r_view.frustum[2].dist = DotProduct (r_view.origin, r_view.frustum[2].normal);
1310 r_view.frustum[3].dist = DotProduct (r_view.origin, r_view.frustum[3].normal);
1311 r_view.frustum[4].dist = DotProduct (r_view.origin, r_view.frustum[4].normal) + r_refdef.nearclip;
1312 PlaneClassify(&r_view.frustum[0]);
1313 PlaneClassify(&r_view.frustum[1]);
1314 PlaneClassify(&r_view.frustum[2]);
1315 PlaneClassify(&r_view.frustum[3]);
1316 PlaneClassify(&r_view.frustum[4]);
1318 // LordHavoc: note to all quake engine coders, Quake had a special case
1319 // for 90 degrees which assumed a square view (wrong), so I removed it,
1320 // Quake2 has it disabled as well.
1322 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
1323 //RotatePointAroundVector( r_view.frustum[0].normal, r_view.up, r_view.forward, -(90 - r_refdef.fov_x / 2));
1324 //r_view.frustum[0].dist = DotProduct (r_view.origin, frustum[0].normal);
1325 //PlaneClassify(&frustum[0]);
1327 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
1328 //RotatePointAroundVector( r_view.frustum[1].normal, r_view.up, r_view.forward, (90 - r_refdef.fov_x / 2));
1329 //r_view.frustum[1].dist = DotProduct (r_view.origin, frustum[1].normal);
1330 //PlaneClassify(&frustum[1]);
1332 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
1333 //RotatePointAroundVector( r_view.frustum[2].normal, r_view.left, r_view.forward, -(90 - r_refdef.fov_y / 2));
1334 //r_view.frustum[2].dist = DotProduct (r_view.origin, frustum[2].normal);
1335 //PlaneClassify(&frustum[2]);
1337 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
1338 //RotatePointAroundVector( r_view.frustum[3].normal, r_view.left, r_view.forward, (90 - r_refdef.fov_y / 2));
1339 //r_view.frustum[3].dist = DotProduct (r_view.origin, frustum[3].normal);
1340 //PlaneClassify(&frustum[3]);
1343 //VectorCopy(r_view.forward, r_view.frustum[4].normal);
1344 //r_view.frustum[4].dist = DotProduct (r_view.origin, frustum[4].normal) + r_nearclip.value;
1345 //PlaneClassify(&frustum[4]);
1348 void R_View_Update(void)
1350 R_View_SetFrustum();
1351 R_View_WorldVisibility();
1352 R_View_UpdateEntityVisible();
1355 void R_ResetViewRendering(void)
1357 if (gl_support_fragment_shader)
1359 qglUseProgramObjectARB(0);CHECKGLERROR
1362 // GL is weird because it's bottom to top, r_view.y is top to bottom
1363 qglViewport(r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
1364 GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
1365 GL_Scissor(r_view.x, r_view.y, r_view.width, r_view.height);
1366 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
1367 GL_ScissorTest(true);
1370 R_Mesh_Matrix(&identitymatrix);
1371 R_Mesh_ResetTextureState();
1374 void R_RenderScene(void);
1376 void R_Bloom_MakeTexture(qboolean darken)
1378 int screenwidth, screenheight;
1379 int screentexturewidth, screentextureheight;
1380 int bloomtexturewidth, bloomtextureheight;
1381 int bloomwidth, bloomheight, x, range;
1382 float xoffset, yoffset, r;
1384 float texcoord2f[3][8];
1386 // set bloomwidth and bloomheight to the bloom resolution that will be
1387 // used (often less than the screen resolution for faster rendering)
1388 bloomwidth = bound(1, r_bloom_resolution.integer, r_view.width);
1389 bloomheight = bound(1, bloomwidth * r_view.height / r_view.width, r_view.height);
1391 // set the (poorly named) screenwidth and screenheight variables to
1392 // a power of 2 at least as large as the screen, these will define the
1393 // size of the texture to allocate
1394 for (screenwidth = 1;screenwidth < vid.width;screenwidth *= 2);
1395 for (screenheight = 1;screenheight < vid.height;screenheight *= 2);
1397 r_refdef.stats.bloom++;
1399 // allocate textures as needed
1400 // TODO: reallocate these when size settings change
1401 if (!r_bloom_texture_screen)
1402 r_bloom_texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", screenwidth, screenheight, NULL, TEXTYPE_RGBA, TEXF_FORCENEAREST | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
1403 if (!r_bloom_texture_bloom)
1404 r_bloom_texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", screenwidth, screenheight, NULL, TEXTYPE_RGBA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
1406 screentexturewidth = R_TextureWidth(r_bloom_texture_screen);
1407 screentextureheight = R_TextureHeight(r_bloom_texture_screen);
1408 bloomtexturewidth = R_TextureWidth(r_bloom_texture_bloom);
1409 bloomtextureheight = R_TextureHeight(r_bloom_texture_bloom);
1411 // vertex coordinates for a quad that covers the screen exactly
1412 vertex3f[0] = 0;vertex3f[1] = 0;vertex3f[2] = 0;
1413 vertex3f[3] = 1;vertex3f[4] = 0;vertex3f[5] = 0;
1414 vertex3f[6] = 1;vertex3f[7] = 1;vertex3f[8] = 0;
1415 vertex3f[9] = 0;vertex3f[10] = 1;vertex3f[11] = 0;
1417 // set up a texcoord array for the full resolution screen image
1418 // (we have to keep this around to copy back during final render)
1419 texcoord2f[0][0] = 0;
1420 texcoord2f[0][1] = (float)r_view.height / (float)screentextureheight;
1421 texcoord2f[0][2] = (float)r_view.width / (float)screentexturewidth;
1422 texcoord2f[0][3] = (float)r_view.height / (float)screentextureheight;
1423 texcoord2f[0][4] = (float)r_view.width / (float)screentexturewidth;
1424 texcoord2f[0][5] = 0;
1425 texcoord2f[0][6] = 0;
1426 texcoord2f[0][7] = 0;
1428 // set up a texcoord array for the reduced resolution bloom image
1429 // (which will be additive blended over the screen image)
1430 texcoord2f[1][0] = 0;
1431 texcoord2f[1][1] = (float)bloomheight / (float)bloomtextureheight;
1432 texcoord2f[1][2] = (float)bloomwidth / (float)bloomtexturewidth;
1433 texcoord2f[1][3] = (float)bloomheight / (float)bloomtextureheight;
1434 texcoord2f[1][4] = (float)bloomwidth / (float)bloomtexturewidth;
1435 texcoord2f[1][5] = 0;
1436 texcoord2f[1][6] = 0;
1437 texcoord2f[1][7] = 0;
1439 R_ResetViewRendering();
1440 GL_DepthTest(false);
1441 R_Mesh_VertexPointer(vertex3f);
1442 R_Mesh_ColorPointer(NULL);
1444 R_Mesh_TexCoordPointer(0, 2, texcoord2f[0]);
1445 R_Mesh_TexBind(0, R_GetTexture(r_bloom_texture_screen));
1447 // copy view into the screen texture
1448 GL_ActiveTexture(0);
1450 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
1451 r_refdef.stats.bloom_copypixels += r_view.width * r_view.height;
1453 // now scale it down to the bloom texture size
1455 qglViewport(r_view.x, vid.height - (r_view.y + bloomheight), bloomwidth, bloomheight);CHECKGLERROR
1456 GL_BlendFunc(GL_ONE, GL_ZERO);
1457 GL_Color(1, 1, 1, 1);
1458 // TODO: optimize with multitexture or GLSL
1459 R_Mesh_Draw(0, 4, 2, polygonelements);
1460 r_refdef.stats.bloom_drawpixels += bloomwidth * bloomheight;
1464 // raise to a power of itself to darken it (this leaves the really
1465 // bright stuff bright, and everything else becomes very dark)
1466 // render multiple times with a multiply blendfunc to raise to a power
1467 GL_BlendFunc(GL_DST_COLOR, GL_ZERO);
1468 for (x = 1;x < r_bloom_power.integer;x++)
1470 R_Mesh_Draw(0, 4, 2, polygonelements);
1471 r_refdef.stats.bloom_drawpixels += bloomwidth * bloomheight;
1475 // we now have a darkened bloom image in the framebuffer
1476 // copy it into the bloom image texture for more processing
1477 R_Mesh_TexBind(0, R_GetTexture(r_bloom_texture_bloom));
1478 R_Mesh_TexCoordPointer(0, 2, texcoord2f[2]);
1479 GL_ActiveTexture(0);
1481 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view.x, vid.height - (r_view.y + bloomheight), bloomwidth, bloomheight);CHECKGLERROR
1482 r_refdef.stats.bloom_copypixels += bloomwidth * bloomheight;
1484 // blend on at multiple vertical offsets to achieve a vertical blur
1485 // TODO: do offset blends using GLSL
1486 range = r_bloom_blur.integer * bloomwidth / 320;
1487 GL_BlendFunc(GL_ONE, GL_ZERO);
1488 for (x = -range;x <= range;x++)
1490 xoffset = 0 / (float)bloomwidth * (float)bloomwidth / (float)screenwidth;
1491 yoffset = x / (float)bloomheight * (float)bloomheight / (float)screenheight;
1492 // compute a texcoord array with the specified x and y offset
1493 texcoord2f[2][0] = xoffset+0;
1494 texcoord2f[2][1] = yoffset+(float)bloomheight / (float)screenheight;
1495 texcoord2f[2][2] = xoffset+(float)bloomwidth / (float)screenwidth;
1496 texcoord2f[2][3] = yoffset+(float)bloomheight / (float)screenheight;
1497 texcoord2f[2][4] = xoffset+(float)bloomwidth / (float)screenwidth;
1498 texcoord2f[2][5] = yoffset+0;
1499 texcoord2f[2][6] = xoffset+0;
1500 texcoord2f[2][7] = yoffset+0;
1501 // this r value looks like a 'dot' particle, fading sharply to
1502 // black at the edges
1503 // (probably not realistic but looks good enough)
1504 r = r_bloom_intensity.value/(range*2+1)*(1 - x*x/(float)(range*range));
1507 GL_Color(r, r, r, 1);
1508 R_Mesh_Draw(0, 4, 2, polygonelements);
1509 r_refdef.stats.bloom_drawpixels += bloomwidth * bloomheight;
1510 GL_BlendFunc(GL_ONE, GL_ONE);
1513 // copy the vertically blurred bloom view to a texture
1514 GL_ActiveTexture(0);
1516 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view.x, vid.height - (r_view.y + bloomheight), bloomwidth, bloomheight);CHECKGLERROR
1517 r_refdef.stats.bloom_copypixels += bloomwidth * bloomheight;
1519 // blend the vertically blurred image at multiple offsets horizontally
1520 // to finish the blur effect
1521 // TODO: do offset blends using GLSL
1522 range = r_bloom_blur.integer * bloomwidth / 320;
1523 GL_BlendFunc(GL_ONE, GL_ZERO);
1524 for (x = -range;x <= range;x++)
1526 xoffset = x / (float)bloomwidth * (float)bloomwidth / (float)screenwidth;
1527 yoffset = 0 / (float)bloomheight * (float)bloomheight / (float)screenheight;
1528 // compute a texcoord array with the specified x and y offset
1529 texcoord2f[2][0] = xoffset+0;
1530 texcoord2f[2][1] = yoffset+(float)bloomheight / (float)screenheight;
1531 texcoord2f[2][2] = xoffset+(float)bloomwidth / (float)screenwidth;
1532 texcoord2f[2][3] = yoffset+(float)bloomheight / (float)screenheight;
1533 texcoord2f[2][4] = xoffset+(float)bloomwidth / (float)screenwidth;
1534 texcoord2f[2][5] = yoffset+0;
1535 texcoord2f[2][6] = xoffset+0;
1536 texcoord2f[2][7] = yoffset+0;
1537 // this r value looks like a 'dot' particle, fading sharply to
1538 // black at the edges
1539 // (probably not realistic but looks good enough)
1540 r = r_bloom_intensity.value/(range*2+1)*(1 - x*x/(float)(range*range));
1543 GL_Color(r, r, r, 1);
1544 R_Mesh_Draw(0, 4, 2, polygonelements);
1545 r_refdef.stats.bloom_drawpixels += bloomwidth * bloomheight;
1546 GL_BlendFunc(GL_ONE, GL_ONE);
1549 // copy the blurred bloom view to a texture
1550 GL_ActiveTexture(0);
1552 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view.x, vid.height - (r_view.y + bloomheight), bloomwidth, bloomheight);CHECKGLERROR
1553 r_refdef.stats.bloom_copypixels += bloomwidth * bloomheight;
1556 void R_HDR_RenderBloomTexture(void)
1558 int oldwidth, oldheight;
1560 oldwidth = r_view.width;
1561 oldheight = r_view.height;
1562 r_view.width = bound(1, r_bloom_resolution.integer, min(r_view.width, gl_max_texture_size));
1563 r_view.height = r_view.width * oldheight / oldwidth;
1565 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
1566 // FIXME: change global lightmapintensity and light intensity according to r_hdr_bloomintensity cvar
1567 // FIXME: change global lightmapintensity and light intensity according to r_hdr_scenebrightness cvar
1568 // TODO: add exposure compensation features
1570 r_view.colorscale = r_hdr_bloomintensity.value * r_hdr_scenebrightness.value;
1573 R_ResetViewRendering();
1575 R_Bloom_MakeTexture(false);
1578 if (r_timereport_active)
1579 R_TimeReport("clear");
1581 // restore the view settings
1582 r_view.width = oldwidth;
1583 r_view.height = oldheight;
1585 // go back to full view area
1586 R_ResetViewRendering();
1589 static void R_BlendView(void)
1591 int screenwidth, screenheight;
1592 int bloomwidth, bloomheight;
1597 float texcoord2f[3][8];
1599 // set the (poorly named) screenwidth and screenheight variables to
1600 // a power of 2 at least as large as the screen, these will define the
1601 // size of the texture to allocate
1602 for (screenwidth = 1;screenwidth < vid.width;screenwidth *= 2);
1603 for (screenheight = 1;screenheight < vid.height;screenheight *= 2);
1605 doblend = r_refdef.viewblend[3] >= 0.01f;
1606 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;
1607 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;
1609 if (!dobloom && !dohdr && !doblend)
1612 // vertex coordinates for a quad that covers the screen exactly
1613 vertex3f[0] = 0;vertex3f[1] = 0;vertex3f[2] = 0;
1614 vertex3f[3] = 1;vertex3f[4] = 0;vertex3f[5] = 0;
1615 vertex3f[6] = 1;vertex3f[7] = 1;vertex3f[8] = 0;
1616 vertex3f[9] = 0;vertex3f[10] = 1;vertex3f[11] = 0;
1618 // set bloomwidth and bloomheight to the bloom resolution that will be
1619 // used (often less than the screen resolution for faster rendering)
1620 bloomwidth = min(r_view.width, r_bloom_resolution.integer);
1621 bloomheight = min(r_view.height, bloomwidth * r_view.height / r_view.width);
1622 // set up a texcoord array for the full resolution screen image
1623 // (we have to keep this around to copy back during final render)
1624 texcoord2f[0][0] = 0;
1625 texcoord2f[0][1] = (float)r_view.height / (float)screenheight;
1626 texcoord2f[0][2] = (float)r_view.width / (float)screenwidth;
1627 texcoord2f[0][3] = (float)r_view.height / (float)screenheight;
1628 texcoord2f[0][4] = (float)r_view.width / (float)screenwidth;
1629 texcoord2f[0][5] = 0;
1630 texcoord2f[0][6] = 0;
1631 texcoord2f[0][7] = 0;
1632 // set up a texcoord array for the reduced resolution bloom image
1633 // (which will be additive blended over the screen image)
1634 texcoord2f[1][0] = 0;
1635 texcoord2f[1][1] = (float)bloomheight / (float)screenheight;
1636 texcoord2f[1][2] = (float)bloomwidth / (float)screenwidth;
1637 texcoord2f[1][3] = (float)bloomheight / (float)screenheight;
1638 texcoord2f[1][4] = (float)bloomwidth / (float)screenwidth;
1639 texcoord2f[1][5] = 0;
1640 texcoord2f[1][6] = 0;
1641 texcoord2f[1][7] = 0;
1645 // render high dynamic range bloom effect
1646 // the bloom texture was made earlier this render, so we just need to
1647 // blend it onto the screen...
1648 R_ResetViewRendering();
1649 GL_DepthTest(false);
1650 R_Mesh_VertexPointer(vertex3f);
1651 R_Mesh_ColorPointer(NULL);
1652 GL_Color(1, 1, 1, 1);
1653 GL_BlendFunc(GL_ONE, GL_ONE);
1654 R_Mesh_TexBind(0, R_GetTexture(r_bloom_texture_bloom));
1655 R_Mesh_TexCoordPointer(0, 2, texcoord2f[1]);
1656 R_Mesh_Draw(0, 4, 2, polygonelements);
1657 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
1661 // render simple bloom effect
1662 // make the bloom texture
1663 R_Bloom_MakeTexture(true);
1664 // put the original screen image back in place and blend the bloom
1666 R_ResetViewRendering();
1667 GL_DepthTest(false);
1668 R_Mesh_VertexPointer(vertex3f);
1669 R_Mesh_ColorPointer(NULL);
1670 GL_Color(1, 1, 1, 1);
1671 GL_BlendFunc(GL_ONE, GL_ZERO);
1672 // do both in one pass if possible
1673 R_Mesh_TexBind(0, R_GetTexture(r_bloom_texture_screen));
1674 R_Mesh_TexCoordPointer(0, 2, texcoord2f[0]);
1675 if (r_textureunits.integer >= 2 && gl_combine.integer)
1677 R_Mesh_TexCombine(1, GL_ADD, GL_ADD, 1, 1);
1678 R_Mesh_TexBind(1, R_GetTexture(r_bloom_texture_bloom));
1679 R_Mesh_TexCoordPointer(1, 2, texcoord2f[1]);
1683 R_Mesh_Draw(0, 4, 2, polygonelements);
1684 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
1685 // now blend on the bloom texture
1686 GL_BlendFunc(GL_ONE, GL_ONE);
1687 R_Mesh_TexBind(0, R_GetTexture(r_bloom_texture_bloom));
1688 R_Mesh_TexCoordPointer(0, 2, texcoord2f[1]);
1690 R_Mesh_Draw(0, 4, 2, polygonelements);
1691 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
1695 // apply a color tint to the whole view
1696 R_ResetViewRendering();
1697 GL_DepthTest(false);
1698 R_Mesh_VertexPointer(vertex3f);
1699 R_Mesh_ColorPointer(NULL);
1700 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1701 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
1702 R_Mesh_Draw(0, 4, 2, polygonelements);
1706 void R_RenderScene(void);
1708 matrix4x4_t r_waterscrollmatrix;
1710 void R_UpdateVariables(void)
1716 r_refdef.farclip = 4096;
1717 if (r_refdef.worldmodel)
1718 r_refdef.farclip += VectorDistance(r_refdef.worldmodel->normalmins, r_refdef.worldmodel->normalmaxs);
1719 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
1721 r_refdef.polygonfactor = 0;
1722 r_refdef.polygonoffset = 0;
1723 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_shadow_polygonfactor.value;
1724 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_shadow_polygonoffset.value;
1726 r_refdef.rtworld = r_shadow_realtime_world.integer;
1727 r_refdef.rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
1728 r_refdef.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer;
1729 r_refdef.rtdlightshadows = r_refdef.rtdlight && (r_refdef.rtworld ? r_shadow_realtime_world_dlightshadows.integer : r_shadow_realtime_dlight_shadows.integer) && gl_stencil;
1730 r_refdef.lightmapintensity = r_refdef.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
1731 if (r_showsurfaces.integer)
1733 r_refdef.rtworld = false;
1734 r_refdef.rtworldshadows = false;
1735 r_refdef.rtdlight = false;
1736 r_refdef.rtdlightshadows = false;
1737 r_refdef.lightmapintensity = 0;
1740 if (gamemode == GAME_NEHAHRA)
1742 if (gl_fogenable.integer)
1744 r_refdef.oldgl_fogenable = true;
1745 r_refdef.fog_density = gl_fogdensity.value;
1746 r_refdef.fog_red = gl_fogred.value;
1747 r_refdef.fog_green = gl_foggreen.value;
1748 r_refdef.fog_blue = gl_fogblue.value;
1750 else if (r_refdef.oldgl_fogenable)
1752 r_refdef.oldgl_fogenable = false;
1753 r_refdef.fog_density = 0;
1754 r_refdef.fog_red = 0;
1755 r_refdef.fog_green = 0;
1756 r_refdef.fog_blue = 0;
1759 if (r_refdef.fog_density)
1761 r_refdef.fogcolor[0] = bound(0.0f, r_refdef.fog_red , 1.0f);
1762 r_refdef.fogcolor[1] = bound(0.0f, r_refdef.fog_green, 1.0f);
1763 r_refdef.fogcolor[2] = bound(0.0f, r_refdef.fog_blue , 1.0f);
1765 if (r_refdef.fog_density)
1767 r_refdef.fogenabled = true;
1768 // this is the point where the fog reaches 0.9986 alpha, which we
1769 // consider a good enough cutoff point for the texture
1770 // (0.9986 * 256 == 255.6)
1771 r_refdef.fogrange = 400 / r_refdef.fog_density;
1772 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
1773 r_refdef.fogtabledistmultiplier = FOGTABLEWIDTH * r_refdef.fograngerecip;
1774 // fog color was already set
1777 r_refdef.fogenabled = false;
1779 // update some cached entity properties...
1780 for (i = 0;i < r_refdef.numentities;i++)
1782 entity_render_t *ent = r_refdef.entities[i];
1783 // some of the renderer still relies on origin...
1784 Matrix4x4_OriginFromMatrix(&ent->matrix, ent->origin);
1785 // some of the renderer still relies on scale...
1786 ent->scale = Matrix4x4_ScaleFromMatrix(&ent->matrix);
1787 R_UpdateEntityLighting(ent);
1796 void R_RenderView(void)
1798 if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
1799 return; //Host_Error ("R_RenderView: NULL worldmodel");
1802 if (r_timereport_active)
1803 R_TimeReport("setup");
1806 if (r_timereport_active)
1807 R_TimeReport("visibility");
1809 // GL is weird because it's bottom to top, r_view.y is top to bottom
1810 R_ResetViewRendering();
1813 if (r_timereport_active)
1814 R_TimeReport("clear");
1816 // this produces a bloom texture to be used in R_BlendView() later
1818 R_HDR_RenderBloomTexture();
1820 r_view.colorscale = r_hdr_scenebrightness.value;
1824 if (r_timereport_active)
1825 R_TimeReport("blendview");
1827 GL_Scissor(0, 0, vid.width, vid.height);
1828 GL_ScissorTest(false);
1833 void CSQC_R_ClearScreen (void)
1835 if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
1836 return; //Host_Error ("R_RenderView: NULL worldmodel");
1839 GL_ScissorTest(true);
1841 if (r_timereport_active)
1842 R_TimeReport("setup");
1845 if (r_timereport_active)
1846 R_TimeReport("visibility");
1848 R_ResetViewRendering();
1851 if (r_timereport_active)
1852 R_TimeReport("clear");
1857 void CSQC_R_RenderScene (void)
1859 R_ResetViewRendering();
1862 if (r_timereport_active)
1863 R_TimeReport("clear");
1865 // this produces a bloom texture to be used in R_BlendView() later
1867 R_HDR_RenderBloomTexture();
1869 r_view.colorscale = r_hdr_scenebrightness.value;
1873 if (r_timereport_active)
1874 R_TimeReport("blendview");
1876 GL_Scissor(0, 0, vid.width, vid.height);
1877 GL_ScissorTest(false);
1881 extern void R_DrawLightningBeams (void);
1882 extern void VM_AddPolygonsToMeshQueue (void);
1883 extern void R_DrawPortals (void);
1884 void R_RenderScene(void)
1886 // don't let sound skip if going slow
1887 if (r_refdef.extraupdate)
1891 if (gl_support_fragment_shader)
1893 qglUseProgramObjectARB(0);CHECKGLERROR
1895 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
1896 qglPolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR
1897 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
1899 R_ResetViewRendering();
1901 R_MeshQueue_BeginScene();
1903 if (r_refdef.rtworldshadows || r_refdef.rtdlightshadows)
1904 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_view.frustum_x, r_view.frustum_y, r_refdef.nearclip);
1906 GL_SetupView_Mode_Perspective(r_view.frustum_x, r_view.frustum_y, r_refdef.nearclip, r_refdef.farclip);
1908 GL_SetupView_Orientation_FromEntity(&r_view.matrix);
1910 R_Shadow_UpdateWorldLightSelection();
1914 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);
1916 if (cl.csqc_vidvars.drawworld)
1918 // don't let sound skip if going slow
1919 if (r_refdef.extraupdate)
1922 if (r_refdef.worldmodel && r_refdef.worldmodel->DrawSky)
1924 r_refdef.worldmodel->DrawSky(r_refdef.worldentity);
1925 if (r_timereport_active)
1926 R_TimeReport("worldsky");
1929 if (R_DrawBrushModelsSky() && r_timereport_active)
1930 R_TimeReport("bmodelsky");
1932 if (r_refdef.worldmodel && r_refdef.worldmodel->Draw)
1934 r_refdef.worldmodel->Draw(r_refdef.worldentity);
1935 if (r_timereport_active)
1936 R_TimeReport("world");
1940 // don't let sound skip if going slow
1941 if (r_refdef.extraupdate)
1945 if (r_timereport_active)
1946 R_TimeReport("models");
1948 // don't let sound skip if going slow
1949 if (r_refdef.extraupdate)
1952 R_ShadowVolumeLighting(false);
1953 if (r_timereport_active)
1954 R_TimeReport("rtlights");
1956 // don't let sound skip if going slow
1957 if (r_refdef.extraupdate)
1960 if (cl.csqc_vidvars.drawworld)
1962 R_DrawLightningBeams();
1963 if (r_timereport_active)
1964 R_TimeReport("lightning");
1967 if (r_timereport_active)
1968 R_TimeReport("particles");
1971 if (r_timereport_active)
1972 R_TimeReport("explosions");
1975 if (gl_support_fragment_shader)
1977 qglUseProgramObjectARB(0);CHECKGLERROR
1979 VM_AddPolygonsToMeshQueue();
1981 if (r_drawportals.integer)
1984 if (r_timereport_active)
1985 R_TimeReport("portals");
1988 if (gl_support_fragment_shader)
1990 qglUseProgramObjectARB(0);CHECKGLERROR
1992 R_MeshQueue_RenderTransparent();
1993 if (r_timereport_active)
1994 R_TimeReport("drawtrans");
1996 if (gl_support_fragment_shader)
1998 qglUseProgramObjectARB(0);CHECKGLERROR
2001 if (cl.csqc_vidvars.drawworld)
2004 if (r_timereport_active)
2005 R_TimeReport("coronas");
2008 // don't let sound skip if going slow
2009 if (r_refdef.extraupdate)
2013 if (gl_support_fragment_shader)
2015 qglUseProgramObjectARB(0);CHECKGLERROR
2017 qglPolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR
2018 qglDisable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
2022 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
2025 float *v, *c, f1, f2, diff[3], vertex3f[8*3], color4f[8*4];
2026 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2027 GL_DepthMask(false);
2029 R_Mesh_Matrix(&identitymatrix);
2031 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2];
2032 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
2033 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
2034 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
2035 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
2036 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
2037 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
2038 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
2039 R_FillColors(color, 8, cr, cg, cb, ca);
2040 if (r_refdef.fogenabled)
2042 for (i = 0, v = vertex, c = color;i < 8;i++, v += 4, c += 4)
2044 f2 = VERTEXFOGTABLE(VectorDistance(v, r_view.origin));
2046 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
2047 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
2048 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
2051 R_Mesh_VertexPointer(vertex3f);
2052 R_Mesh_ColorPointer(color);
2053 R_Mesh_ResetTextureState();
2058 int nomodelelements[24] =
2070 float nomodelvertex3f[6*3] =
2080 float nomodelcolor4f[6*4] =
2082 0.0f, 0.0f, 0.5f, 1.0f,
2083 0.0f, 0.0f, 0.5f, 1.0f,
2084 0.0f, 0.5f, 0.0f, 1.0f,
2085 0.0f, 0.5f, 0.0f, 1.0f,
2086 0.5f, 0.0f, 0.0f, 1.0f,
2087 0.5f, 0.0f, 0.0f, 1.0f
2090 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
2095 // this is only called once per entity so numsurfaces is always 1, and
2096 // surfacelist is always {0}, so this code does not handle batches
2097 R_Mesh_Matrix(&ent->matrix);
2099 if (ent->flags & EF_ADDITIVE)
2101 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2102 GL_DepthMask(false);
2104 else if (ent->alpha < 1)
2106 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2107 GL_DepthMask(false);
2111 GL_BlendFunc(GL_ONE, GL_ZERO);
2114 GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
2115 R_Mesh_VertexPointer(nomodelvertex3f);
2116 if (r_refdef.fogenabled)
2118 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
2119 R_Mesh_ColorPointer(color4f);
2120 f2 = VERTEXFOGTABLE(VectorDistance(ent->origin, r_view.origin));
2122 for (i = 0, c = color4f;i < 6;i++, c += 4)
2124 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
2125 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
2126 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
2130 else if (ent->alpha != 1)
2132 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
2133 R_Mesh_ColorPointer(color4f);
2134 for (i = 0, c = color4f;i < 6;i++, c += 4)
2138 R_Mesh_ColorPointer(nomodelcolor4f);
2139 R_Mesh_ResetTextureState();
2140 R_Mesh_Draw(0, 6, 8, nomodelelements);
2143 void R_DrawNoModel(entity_render_t *ent)
2145 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
2146 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_view.origin : ent->origin, R_DrawNoModel_TransparentCallback, ent, 0, r_shadow_rtlight);
2148 // R_DrawNoModelCallback(ent, 0);
2151 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
2153 vec3_t right1, right2, diff, normal;
2155 VectorSubtract (org2, org1, normal);
2157 // calculate 'right' vector for start
2158 VectorSubtract (r_view.origin, org1, diff);
2159 CrossProduct (normal, diff, right1);
2160 VectorNormalize (right1);
2162 // calculate 'right' vector for end
2163 VectorSubtract (r_view.origin, org2, diff);
2164 CrossProduct (normal, diff, right2);
2165 VectorNormalize (right2);
2167 vert[ 0] = org1[0] + width * right1[0];
2168 vert[ 1] = org1[1] + width * right1[1];
2169 vert[ 2] = org1[2] + width * right1[2];
2170 vert[ 3] = org1[0] - width * right1[0];
2171 vert[ 4] = org1[1] - width * right1[1];
2172 vert[ 5] = org1[2] - width * right1[2];
2173 vert[ 6] = org2[0] - width * right2[0];
2174 vert[ 7] = org2[1] - width * right2[1];
2175 vert[ 8] = org2[2] - width * right2[2];
2176 vert[ 9] = org2[0] + width * right2[0];
2177 vert[10] = org2[1] + width * right2[1];
2178 vert[11] = org2[2] + width * right2[2];
2181 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
2183 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)
2185 float fog = 0.0f, ifog;
2188 if (r_refdef.fogenabled)
2189 fog = VERTEXFOGTABLE(VectorDistance(origin, r_view.origin));
2192 R_Mesh_Matrix(&identitymatrix);
2193 GL_BlendFunc(blendfunc1, blendfunc2);
2194 GL_DepthMask(false);
2195 GL_DepthTest(!depthdisable);
2197 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
2198 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
2199 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
2200 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
2201 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
2202 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
2203 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
2204 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
2205 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
2206 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
2207 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
2208 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
2210 R_Mesh_VertexPointer(vertex3f);
2211 R_Mesh_ColorPointer(NULL);
2212 R_Mesh_ResetTextureState();
2213 R_Mesh_TexBind(0, R_GetTexture(texture));
2214 R_Mesh_TexCoordPointer(0, 2, spritetexcoord2f);
2215 // FIXME: fixed function path can't properly handle r_view.colorscale > 1
2216 GL_Color(cr * ifog * r_view.colorscale, cg * ifog * r_view.colorscale, cb * ifog * r_view.colorscale, ca);
2217 R_Mesh_Draw(0, 4, 2, polygonelements);
2219 if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
2221 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
2222 GL_BlendFunc(blendfunc1, GL_ONE);
2223 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);
2224 R_Mesh_Draw(0, 4, 2, polygonelements);
2228 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
2233 VectorSet(v, x, y, z);
2234 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
2235 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
2237 if (i == mesh->numvertices)
2239 if (mesh->numvertices < mesh->maxvertices)
2241 VectorCopy(v, vertex3f);
2242 mesh->numvertices++;
2244 return mesh->numvertices;
2250 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
2254 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
2255 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
2256 e = mesh->element3i + mesh->numtriangles * 3;
2257 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
2259 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
2260 if (mesh->numtriangles < mesh->maxtriangles)
2265 mesh->numtriangles++;
2267 element[1] = element[2];
2271 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
2275 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
2276 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
2277 e = mesh->element3i + mesh->numtriangles * 3;
2278 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
2280 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
2281 if (mesh->numtriangles < mesh->maxtriangles)
2286 mesh->numtriangles++;
2288 element[1] = element[2];
2292 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
2293 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
2295 int planenum, planenum2;
2298 mplane_t *plane, *plane2;
2300 double temppoints[2][256*3];
2301 // figure out how large a bounding box we need to properly compute this brush
2303 for (w = 0;w < numplanes;w++)
2304 maxdist = max(maxdist, planes[w].dist);
2305 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
2306 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
2307 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
2311 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->normal[3], maxdist);
2312 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
2314 if (planenum2 == planenum)
2316 PolygonD_Divide(tempnumpoints, temppoints[w], plane2->normal[0], plane2->normal[1], plane2->normal[2], plane2->dist, R_MESH_PLANE_DIST_EPSILON, 0, NULL, NULL, 256, temppoints[!w], &tempnumpoints, NULL);
2319 if (tempnumpoints < 3)
2321 // generate elements forming a triangle fan for this polygon
2322 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
2326 static void R_DrawCollisionBrush(const colbrushf_t *brush)
2329 R_Mesh_VertexPointer(brush->points->v);
2330 i = (int)(((size_t)brush) / sizeof(colbrushf_t));
2331 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);
2332 GL_LockArrays(0, brush->numpoints);
2333 R_Mesh_Draw(0, brush->numpoints, brush->numtriangles, brush->elements);
2334 GL_LockArrays(0, 0);
2337 static void R_DrawCollisionSurface(const entity_render_t *ent, const msurface_t *surface)
2340 if (!surface->num_collisiontriangles)
2342 R_Mesh_VertexPointer(surface->data_collisionvertex3f);
2343 i = (int)(((size_t)surface) / sizeof(msurface_t));
2344 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);
2345 GL_LockArrays(0, surface->num_collisionvertices);
2346 R_Mesh_Draw(0, surface->num_collisionvertices, surface->num_collisiontriangles, surface->data_collisionelement3i);
2347 GL_LockArrays(0, 0);
2350 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)
2352 texturelayer_t *layer;
2353 layer = t->currentlayers + t->currentnumlayers++;
2355 layer->depthmask = depthmask;
2356 layer->blendfunc1 = blendfunc1;
2357 layer->blendfunc2 = blendfunc2;
2358 layer->texture = texture;
2359 layer->texmatrix = *matrix;
2360 layer->color[0] = r * r_view.colorscale;
2361 layer->color[1] = g * r_view.colorscale;
2362 layer->color[2] = b * r_view.colorscale;
2363 layer->color[3] = a;
2366 void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
2368 // FIXME: identify models using a better check than ent->model->brush.shadowmesh
2369 //int lightmode = ((ent->effects & EF_FULLBRIGHT) || ent->model->brush.shadowmesh) ? 0 : 2;
2372 texture_t *texture = t;
2373 model_t *model = ent->model;
2374 int s = ent->skinnum;
2375 if ((unsigned int)s >= (unsigned int)model->numskins)
2377 if (model->skinscenes)
2379 if (model->skinscenes[s].framecount > 1)
2380 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
2382 s = model->skinscenes[s].firstframe;
2385 t = t + s * model->num_surfaces;
2388 // use an alternate animation if the entity's frame is not 0,
2389 // and only if the texture has an alternate animation
2390 if (ent->frame != 0 && t->anim_total[1])
2391 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.time * 5.0f) % t->anim_total[1]) : 0];
2393 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.time * 5.0f) % t->anim_total[0]) : 0];
2395 texture->currentframe = t;
2398 t->currentmaterialflags = t->basematerialflags;
2399 t->currentalpha = ent->alpha;
2400 if (t->basematerialflags & MATERIALFLAG_WATERALPHA)
2401 t->currentalpha *= r_wateralpha.value;
2402 if (!(ent->flags & RENDER_LIGHT))
2403 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
2404 if (ent->effects & EF_ADDITIVE)
2405 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_TRANSPARENT;
2406 else if (t->currentalpha < 1)
2407 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_TRANSPARENT;
2408 if (ent->effects & EF_NODEPTHTEST)
2409 t->currentmaterialflags |= MATERIALFLAG_NODEPTHTEST;
2410 if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
2411 t->currenttexmatrix = r_waterscrollmatrix;
2413 t->currenttexmatrix = identitymatrix;
2415 t->colormapping = VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f);
2416 t->basetexture = (!t->colormapping && t->skin.merged) ? t->skin.merged : t->skin.base;
2417 t->glosstexture = r_texture_white;
2418 t->specularpower = 8;
2419 t->specularscale = 0;
2420 if (r_shadow_gloss.integer > 0)
2424 if (r_shadow_glossintensity.value > 0)
2426 t->glosstexture = t->skin.gloss;
2427 t->specularscale = r_shadow_glossintensity.value;
2430 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
2431 t->specularscale = r_shadow_gloss2intensity.value;
2434 t->currentnumlayers = 0;
2435 if (!(t->currentmaterialflags & MATERIALFLAG_NODRAW))
2437 if (gl_lightmaps.integer)
2438 R_Texture_AddLayer(t, true, GL_ONE, GL_ZERO, TEXTURELAYERTYPE_LITTEXTURE, r_texture_white, &identitymatrix, 1, 1, 1, 1);
2439 else if (!(t->currentmaterialflags & MATERIALFLAG_SKY))
2441 int blendfunc1, blendfunc2, depthmask;
2442 if (t->currentmaterialflags & MATERIALFLAG_ADD)
2444 blendfunc1 = GL_SRC_ALPHA;
2445 blendfunc2 = GL_ONE;
2447 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
2449 blendfunc1 = GL_SRC_ALPHA;
2450 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
2452 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
2454 blendfunc1 = t->customblendfunc[0];
2455 blendfunc2 = t->customblendfunc[1];
2459 blendfunc1 = GL_ONE;
2460 blendfunc2 = GL_ZERO;
2462 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
2463 if (t->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL))
2465 rtexture_t *currentbasetexture;
2467 if (r_refdef.fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED))
2468 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
2469 currentbasetexture = (VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) < (1.0f / 1048576.0f) && t->skin.merged) ? t->skin.merged : t->skin.base;
2470 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2472 // fullbright is not affected by r_refdef.lightmapintensity
2473 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
2474 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->skin.pants)
2475 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);
2476 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->skin.shirt)
2477 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);
2483 // q3bsp has no lightmap updates, so the lightstylevalue that
2484 // would normally be baked into the lightmap must be
2485 // applied to the color
2486 if (ent->model->type == mod_brushq3)
2487 colorscale *= r_refdef.lightstylevalue[0] * (1.0f / 256.0f);
2488 colorscale *= r_refdef.lightmapintensity;
2489 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);
2490 if (r_ambient.value >= (1.0f/64.0f))
2491 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);
2492 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->skin.pants)
2494 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);
2495 if (r_ambient.value >= (1.0f/64.0f))
2496 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);
2498 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->skin.shirt)
2500 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);
2501 if (r_ambient.value >= (1.0f/64.0f))
2502 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);
2505 if (t->skin.glow != NULL)
2506 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);
2507 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
2509 // if this is opaque use alpha blend which will darken the earlier
2512 // if this is an alpha blended material, all the earlier passes
2513 // were darkened by fog already, so we only need to add the fog
2514 // color ontop through the fog mask texture
2516 // if this is an additive blended material, all the earlier passes
2517 // were darkened by fog already, and we should not add fog color
2518 // (because the background was not darkened, there is no fog color
2519 // that was lost behind it).
2520 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);
2527 void R_UpdateAllTextureInfo(entity_render_t *ent)
2531 for (i = 0;i < ent->model->num_textures;i++)
2532 R_UpdateTextureInfo(ent, ent->model->data_textures + i);
2535 int rsurface_array_size = 0;
2536 float *rsurface_array_modelvertex3f = NULL;
2537 float *rsurface_array_modelsvector3f = NULL;
2538 float *rsurface_array_modeltvector3f = NULL;
2539 float *rsurface_array_modelnormal3f = NULL;
2540 float *rsurface_array_deformedvertex3f = NULL;
2541 float *rsurface_array_deformedsvector3f = NULL;
2542 float *rsurface_array_deformedtvector3f = NULL;
2543 float *rsurface_array_deformednormal3f = NULL;
2544 float *rsurface_array_color4f = NULL;
2545 float *rsurface_array_texcoord3f = NULL;
2547 void R_Mesh_ResizeArrays(int newvertices)
2550 if (rsurface_array_size >= newvertices)
2552 if (rsurface_array_modelvertex3f)
2553 Mem_Free(rsurface_array_modelvertex3f);
2554 rsurface_array_size = (newvertices + 1023) & ~1023;
2555 base = (float *)Mem_Alloc(r_main_mempool, rsurface_array_size * sizeof(float[31]));
2556 rsurface_array_modelvertex3f = base + rsurface_array_size * 0;
2557 rsurface_array_modelsvector3f = base + rsurface_array_size * 3;
2558 rsurface_array_modeltvector3f = base + rsurface_array_size * 6;
2559 rsurface_array_modelnormal3f = base + rsurface_array_size * 9;
2560 rsurface_array_deformedvertex3f = base + rsurface_array_size * 12;
2561 rsurface_array_deformedsvector3f = base + rsurface_array_size * 15;
2562 rsurface_array_deformedtvector3f = base + rsurface_array_size * 18;
2563 rsurface_array_deformednormal3f = base + rsurface_array_size * 21;
2564 rsurface_array_texcoord3f = base + rsurface_array_size * 24;
2565 rsurface_array_color4f = base + rsurface_array_size * 27;
2568 float *rsurface_modelvertex3f;
2569 float *rsurface_modelsvector3f;
2570 float *rsurface_modeltvector3f;
2571 float *rsurface_modelnormal3f;
2572 float *rsurface_vertex3f;
2573 float *rsurface_svector3f;
2574 float *rsurface_tvector3f;
2575 float *rsurface_normal3f;
2576 float *rsurface_lightmapcolor4f;
2577 vec3_t rsurface_modelorg;
2578 qboolean rsurface_generatedvertex;
2579 const entity_render_t *rsurface_entity;
2580 const model_t *rsurface_model;
2581 texture_t *rsurface_texture;
2582 rtexture_t *rsurface_lightmaptexture;
2583 rsurfmode_t rsurface_mode;
2584 texture_t *rsurface_glsl_texture;
2585 qboolean rsurface_glsl_uselightmap;
2587 void RSurf_ActiveEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
2589 Matrix4x4_Transform(&ent->inversematrix, r_view.origin, rsurface_modelorg);
2590 rsurface_entity = ent;
2591 rsurface_model = ent->model;
2592 if (rsurface_array_size < rsurface_model->surfmesh.num_vertices)
2593 R_Mesh_ResizeArrays(rsurface_model->surfmesh.num_vertices);
2594 R_Mesh_Matrix(&ent->matrix);
2595 Matrix4x4_Transform(&ent->inversematrix, r_view.origin, rsurface_modelorg);
2596 if ((rsurface_entity->frameblend[0].lerp != 1 || rsurface_entity->frameblend[0].frame != 0) && rsurface_model->surfmesh.isanimated)
2600 rsurface_modelvertex3f = rsurface_array_modelvertex3f;
2601 rsurface_modelsvector3f = rsurface_array_modelsvector3f;
2602 rsurface_modeltvector3f = rsurface_array_modeltvector3f;
2603 rsurface_modelnormal3f = rsurface_array_modelnormal3f;
2604 Mod_Alias_GetMesh_Vertices(rsurface_model, rsurface_entity->frameblend, rsurface_array_modelvertex3f, rsurface_array_modelnormal3f, rsurface_array_modelsvector3f, rsurface_array_modeltvector3f);
2606 else if (wantnormals)
2608 rsurface_modelvertex3f = rsurface_array_modelvertex3f;
2609 rsurface_modelsvector3f = NULL;
2610 rsurface_modeltvector3f = NULL;
2611 rsurface_modelnormal3f = rsurface_array_modelnormal3f;
2612 Mod_Alias_GetMesh_Vertices(rsurface_model, rsurface_entity->frameblend, rsurface_array_modelvertex3f, rsurface_array_modelnormal3f, NULL, NULL);
2616 rsurface_modelvertex3f = rsurface_array_modelvertex3f;
2617 rsurface_modelsvector3f = NULL;
2618 rsurface_modeltvector3f = NULL;
2619 rsurface_modelnormal3f = NULL;
2620 Mod_Alias_GetMesh_Vertices(rsurface_model, rsurface_entity->frameblend, rsurface_array_modelvertex3f, NULL, NULL, NULL);
2622 rsurface_generatedvertex = true;
2626 rsurface_modelvertex3f = rsurface_model->surfmesh.data_vertex3f;
2627 rsurface_modelsvector3f = rsurface_model->surfmesh.data_svector3f;
2628 rsurface_modeltvector3f = rsurface_model->surfmesh.data_tvector3f;
2629 rsurface_modelnormal3f = rsurface_model->surfmesh.data_normal3f;
2630 rsurface_generatedvertex = false;
2632 rsurface_vertex3f = rsurface_modelvertex3f;
2633 rsurface_svector3f = rsurface_modelsvector3f;
2634 rsurface_tvector3f = rsurface_modeltvector3f;
2635 rsurface_normal3f = rsurface_modelnormal3f;
2636 rsurface_mode = RSURFMODE_NONE;
2637 rsurface_lightmaptexture = NULL;
2638 rsurface_texture = NULL;
2639 rsurface_glsl_texture = NULL;
2640 rsurface_glsl_uselightmap = false;
2643 void RSurf_CleanUp(void)
2646 if (rsurface_mode == RSURFMODE_GLSL)
2648 qglUseProgramObjectARB(0);CHECKGLERROR
2650 GL_AlphaTest(false);
2651 rsurface_mode = RSURFMODE_NONE;
2652 rsurface_lightmaptexture = NULL;
2653 rsurface_texture = NULL;
2654 rsurface_glsl_texture = NULL;
2655 rsurface_glsl_uselightmap = false;
2658 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, msurface_t **texturesurfacelist)
2660 if (rsurface_generatedvertex)
2662 if (rsurface_texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
2663 generatetangents = true;
2664 if (generatetangents)
2665 generatenormals = true;
2666 if (generatenormals && !rsurface_modelnormal3f)
2668 rsurface_normal3f = rsurface_modelnormal3f = rsurface_array_modelnormal3f;
2669 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);
2671 if (generatetangents && !rsurface_modelsvector3f)
2673 rsurface_svector3f = rsurface_modelsvector3f = rsurface_array_modelsvector3f;
2674 rsurface_tvector3f = rsurface_modeltvector3f = rsurface_array_modeltvector3f;
2675 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);
2678 if (rsurface_texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
2680 int texturesurfaceindex;
2681 float center[3], forward[3], right[3], up[3], v[4][3];
2682 matrix4x4_t matrix1, imatrix1;
2683 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_view.forward, forward);
2684 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_view.right, right);
2685 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_view.up, up);
2686 // make deformed versions of only the vertices used by the specified surfaces
2687 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2690 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2691 // a single autosprite surface can contain multiple sprites...
2692 for (j = 0;j < surface->num_vertices - 3;j += 4)
2694 VectorClear(center);
2695 for (i = 0;i < 4;i++)
2696 VectorAdd(center, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
2697 VectorScale(center, 0.25f, center);
2698 if (rsurface_texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE2)
2700 forward[0] = rsurface_modelorg[0] - center[0];
2701 forward[1] = rsurface_modelorg[1] - center[1];
2703 VectorNormalize(forward);
2704 right[0] = forward[1];
2705 right[1] = -forward[0];
2707 VectorSet(up, 0, 0, 1);
2709 // FIXME: calculate vectors from triangle edges instead of using texture vectors as an easy way out?
2710 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);
2711 Matrix4x4_Invert_Simple(&imatrix1, &matrix1);
2712 for (i = 0;i < 4;i++)
2713 Matrix4x4_Transform(&imatrix1, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, v[i]);
2714 for (i = 0;i < 4;i++)
2715 VectorMAMAMAM(1, center, v[i][0], forward, v[i][1], right, v[i][2], up, rsurface_array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
2717 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);
2718 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);
2720 rsurface_vertex3f = rsurface_array_deformedvertex3f;
2721 rsurface_svector3f = rsurface_array_deformedsvector3f;
2722 rsurface_tvector3f = rsurface_array_deformedtvector3f;
2723 rsurface_normal3f = rsurface_array_deformednormal3f;
2725 R_Mesh_VertexPointer(rsurface_vertex3f);
2728 void RSurf_DrawBatch_Simple(int texturenumsurfaces, msurface_t **texturesurfacelist)
2730 int texturesurfaceindex;
2731 const msurface_t *surface = texturesurfacelist[0];
2732 int firstvertex = surface->num_firstvertex;
2733 int endvertex = surface->num_firstvertex + surface->num_vertices;
2734 if (texturenumsurfaces == 1)
2736 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2737 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
2739 else if (r_batchmode.integer == 2)
2741 #define MAXBATCHTRIANGLES 4096
2742 int batchtriangles = 0;
2743 int batchelements[MAXBATCHTRIANGLES*3];
2744 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2746 surface = texturesurfacelist[texturesurfaceindex];
2747 if (surface->num_triangles >= 256 || (batchtriangles == 0 && texturesurfaceindex + 1 >= texturenumsurfaces))
2749 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
2752 if (batchtriangles + surface->num_triangles > MAXBATCHTRIANGLES)
2754 R_Mesh_Draw(firstvertex, endvertex - firstvertex, batchtriangles, batchelements);
2756 firstvertex = surface->num_firstvertex;
2757 endvertex = surface->num_firstvertex + surface->num_vertices;
2761 firstvertex = min(firstvertex, surface->num_firstvertex);
2762 endvertex = max(endvertex, surface->num_firstvertex + surface->num_vertices);
2764 memcpy(batchelements + batchtriangles * 3, rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
2765 batchtriangles += surface->num_triangles;
2768 R_Mesh_Draw(firstvertex, endvertex - firstvertex, batchtriangles, batchelements);
2770 else if (r_batchmode.integer == 1)
2772 int firsttriangle = 0;
2773 int endtriangle = -1;
2774 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2776 surface = texturesurfacelist[texturesurfaceindex];
2777 if (surface->num_firsttriangle != endtriangle)
2779 if (endtriangle > firsttriangle)
2781 GL_LockArrays(firstvertex, endvertex - firstvertex);
2782 R_Mesh_Draw(firstvertex, endvertex - firstvertex, endtriangle - firsttriangle, (rsurface_model->surfmesh.data_element3i + 3 * firsttriangle));
2784 firstvertex = surface->num_firstvertex;
2785 endvertex = surface->num_firstvertex + surface->num_vertices;
2786 firsttriangle = surface->num_firsttriangle;
2790 firstvertex = min(firstvertex, surface->num_firstvertex);
2791 endvertex = max(endvertex, surface->num_firstvertex + surface->num_vertices);
2793 endtriangle = surface->num_firsttriangle + surface->num_triangles;
2795 if (endtriangle > firsttriangle)
2797 GL_LockArrays(firstvertex, endvertex - firstvertex);
2798 R_Mesh_Draw(firstvertex, endvertex - firstvertex, endtriangle - firsttriangle, (rsurface_model->surfmesh.data_element3i + 3 * firsttriangle));
2803 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2805 surface = texturesurfacelist[texturesurfaceindex];
2806 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2807 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
2812 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
2814 int texturesurfaceindex;
2815 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2817 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2818 int k = (int)(((size_t)surface) / sizeof(msurface_t));
2819 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);
2820 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2821 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
2825 static void RSurf_DrawBatch_Lightmap(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, int lightmode, qboolean applycolor, qboolean applyfog)
2827 int texturesurfaceindex;
2835 vec3_t ambientcolor;
2836 vec3_t diffusecolor;
2838 VectorCopy(rsurface_entity->modellight_lightdir, lightdir);
2839 ambientcolor[0] = rsurface_entity->modellight_ambient[0] * r * 0.5f;
2840 ambientcolor[1] = rsurface_entity->modellight_ambient[1] * g * 0.5f;
2841 ambientcolor[2] = rsurface_entity->modellight_ambient[2] * b * 0.5f;
2842 diffusecolor[0] = rsurface_entity->modellight_diffuse[0] * r * 0.5f;
2843 diffusecolor[1] = rsurface_entity->modellight_diffuse[1] * g * 0.5f;
2844 diffusecolor[2] = rsurface_entity->modellight_diffuse[2] * b * 0.5f;
2845 if (VectorLength2(diffusecolor) > 0)
2847 // generate color arrays for the surfaces in this list
2848 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2850 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2851 int numverts = surface->num_vertices;
2852 v = rsurface_vertex3f + 3 * surface->num_firstvertex;
2853 c2 = rsurface_normal3f + 3 * surface->num_firstvertex;
2854 c = rsurface_array_color4f + 4 * surface->num_firstvertex;
2855 // q3-style directional shading
2856 for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
2858 if ((f = DotProduct(c2, lightdir)) > 0)
2859 VectorMA(ambientcolor, f, diffusecolor, c);
2861 VectorCopy(ambientcolor, c);
2870 rsurface_lightmapcolor4f = rsurface_array_color4f;
2874 r = ambientcolor[0];
2875 g = ambientcolor[1];
2876 b = ambientcolor[2];
2877 rsurface_lightmapcolor4f = NULL;
2880 else if (lightmode >= 1 || !rsurface_lightmaptexture)
2882 if (texturesurfacelist[0]->lightmapinfo && texturesurfacelist[0]->lightmapinfo->stainsamples)
2884 // generate color arrays for the surfaces in this list
2885 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2887 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2888 for (i = 0, c = rsurface_array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
2890 if (surface->lightmapinfo->samples)
2892 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface_model->surfmesh.data_lightmapoffsets + surface->num_firstvertex)[i];
2893 float scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
2894 VectorScale(lm, scale, c);
2895 if (surface->lightmapinfo->styles[1] != 255)
2897 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
2899 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
2900 VectorMA(c, scale, lm, c);
2901 if (surface->lightmapinfo->styles[2] != 255)
2904 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
2905 VectorMA(c, scale, lm, c);
2906 if (surface->lightmapinfo->styles[3] != 255)
2909 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
2910 VectorMA(c, scale, lm, c);
2920 rsurface_lightmapcolor4f = rsurface_array_color4f;
2923 rsurface_lightmapcolor4f = rsurface_model->surfmesh.data_lightmapcolor4f;
2928 rsurface_lightmapcolor4f = NULL;
2932 if (rsurface_lightmapcolor4f)
2934 // generate color arrays for the surfaces in this list
2935 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2937 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2938 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)
2940 f = 1 - VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
2950 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2952 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2953 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)
2955 f = 1 - VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
2963 rsurface_lightmapcolor4f = rsurface_array_color4f;
2965 if (applycolor && rsurface_lightmapcolor4f)
2967 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2969 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2970 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)
2978 rsurface_lightmapcolor4f = rsurface_array_color4f;
2980 R_Mesh_ColorPointer(rsurface_lightmapcolor4f);
2981 GL_Color(r, g, b, a);
2982 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
2985 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
2987 if (rsurface_mode != RSURFMODE_SHOWSURFACES)
2989 rsurface_mode = RSURFMODE_SHOWSURFACES;
2991 GL_BlendFunc(GL_ONE, GL_ZERO);
2992 R_Mesh_ColorPointer(NULL);
2993 R_Mesh_ResetTextureState();
2995 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
2996 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
2999 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, msurface_t **texturesurfacelist)
3001 // transparent sky would be ridiculous
3002 if ((rsurface_texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
3004 if (rsurface_mode != RSURFMODE_SKY)
3006 if (rsurface_mode == RSURFMODE_GLSL)
3008 qglUseProgramObjectARB(0);CHECKGLERROR
3010 rsurface_mode = RSURFMODE_SKY;
3014 skyrendernow = false;
3016 // restore entity matrix
3017 R_Mesh_Matrix(&rsurface_entity->matrix);
3020 // LordHavoc: HalfLife maps have freaky skypolys so don't use
3021 // skymasking on them, and Quake3 never did sky masking (unlike
3022 // software Quake and software Quake2), so disable the sky masking
3023 // in Quake3 maps as it causes problems with q3map2 sky tricks,
3024 // and skymasking also looks very bad when noclipping outside the
3025 // level, so don't use it then either.
3026 if (rsurface_model->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_viewcache.world_novis)
3028 GL_Color(r_refdef.fogcolor[0] * r_view.colorscale, r_refdef.fogcolor[1] * r_view.colorscale, r_refdef.fogcolor[2] * r_view.colorscale, 1);
3029 R_Mesh_ColorPointer(NULL);
3030 R_Mesh_ResetTextureState();
3031 if (skyrendermasked)
3033 // depth-only (masking)
3034 GL_ColorMask(0,0,0,0);
3035 // just to make sure that braindead drivers don't draw
3036 // anything despite that colormask...
3037 GL_BlendFunc(GL_ZERO, GL_ONE);
3042 GL_BlendFunc(GL_ONE, GL_ZERO);
3044 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
3045 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3046 if (skyrendermasked)
3047 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
3051 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, msurface_t **texturesurfacelist)
3054 // FIXME: identify models using a better check than rsurface_model->brush.shadowmesh
3055 lightmode = ((rsurface_entity->effects & EF_FULLBRIGHT) || rsurface_model->brush.shadowmesh) ? 0 : 2;
3056 if (rsurface_mode != RSURFMODE_GLSL)
3058 rsurface_mode = RSURFMODE_GLSL;
3059 rsurface_glsl_texture = NULL;
3060 rsurface_glsl_uselightmap = false;
3061 R_Mesh_ResetTextureState();
3063 if (rsurface_glsl_texture != rsurface_texture || rsurface_glsl_uselightmap != (rsurface_lightmaptexture != NULL))
3065 rsurface_glsl_texture = rsurface_texture;
3066 rsurface_glsl_uselightmap = rsurface_lightmaptexture != NULL;
3067 GL_BlendFunc(rsurface_texture->currentlayers[0].blendfunc1, rsurface_texture->currentlayers[0].blendfunc2);
3068 GL_DepthMask(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_BLENDED));
3069 GL_Color(rsurface_entity->colormod[0], rsurface_entity->colormod[1], rsurface_entity->colormod[2], rsurface_texture->currentalpha);
3070 R_SetupSurfaceShader(vec3_origin, lightmode == 2);
3071 //permutation_deluxemapping = permutation_lightmapping = R_SetupSurfaceShader(vec3_origin, lightmode == 2, false);
3072 //if (r_glsl_deluxemapping.integer)
3073 // permutation_deluxemapping = R_SetupSurfaceShader(vec3_origin, lightmode == 2, true);
3074 R_Mesh_TexCoordPointer(0, 2, rsurface_model->surfmesh.data_texcoordtexture2f);
3075 R_Mesh_TexCoordPointer(4, 2, rsurface_model->surfmesh.data_texcoordlightmap2f);
3076 GL_AlphaTest((rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
3078 if (!r_glsl_permutation)
3080 RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
3081 R_Mesh_TexCoordPointer(1, 3, rsurface_svector3f);
3082 R_Mesh_TexCoordPointer(2, 3, rsurface_tvector3f);
3083 R_Mesh_TexCoordPointer(3, 3, rsurface_normal3f);
3084 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
3086 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
3087 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
3088 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
3089 R_Mesh_ColorPointer(NULL);
3091 else if (rsurface_lightmaptexture)
3093 R_Mesh_TexBind(7, R_GetTexture(rsurface_lightmaptexture));
3094 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
3095 R_Mesh_TexBind(8, R_GetTexture(texturesurfacelist[0]->deluxemaptexture));
3096 R_Mesh_ColorPointer(NULL);
3100 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
3101 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
3102 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
3103 R_Mesh_ColorPointer(rsurface_model->surfmesh.data_lightmapcolor4f);
3105 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3108 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, msurface_t **texturesurfacelist)
3110 // OpenGL 1.3 path - anything not completely ancient
3111 int texturesurfaceindex;
3113 qboolean applycolor;
3117 const texturelayer_t *layer;
3119 // FIXME: identify models using a better check than rsurface_model->brush.shadowmesh
3120 lightmode = ((rsurface_entity->effects & EF_FULLBRIGHT) || rsurface_model->brush.shadowmesh) ? 0 : 2;
3121 if (rsurface_mode != RSURFMODE_MULTIPASS)
3122 rsurface_mode = RSURFMODE_MULTIPASS;
3123 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
3124 for (layerindex = 0, layer = rsurface_texture->currentlayers;layerindex < rsurface_texture->currentnumlayers;layerindex++, layer++)
3127 int layertexrgbscale;
3128 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
3130 if (layerindex == 0)
3134 GL_AlphaTest(false);
3135 qglDepthFunc(GL_EQUAL);CHECKGLERROR
3138 GL_DepthMask(layer->depthmask);
3139 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
3140 if ((layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2) && (gl_combine.integer || layer->depthmask))
3142 layertexrgbscale = 4;
3143 VectorScale(layer->color, 0.25f, layercolor);
3145 else if ((layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1) && (gl_combine.integer || layer->depthmask))
3147 layertexrgbscale = 2;
3148 VectorScale(layer->color, 0.5f, layercolor);
3152 layertexrgbscale = 1;
3153 VectorScale(layer->color, 1.0f, layercolor);
3155 layercolor[3] = layer->color[3];
3156 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
3157 R_Mesh_ColorPointer(NULL);
3158 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
3159 switch (layer->type)
3161 case TEXTURELAYERTYPE_LITTEXTURE:
3162 memset(&m, 0, sizeof(m));
3163 if (lightmode >= 1 || !rsurface_lightmaptexture)
3164 m.tex[0] = R_GetTexture(r_texture_white);
3166 m.tex[0] = R_GetTexture(rsurface_lightmaptexture);
3167 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordlightmap2f;
3168 m.tex[1] = R_GetTexture(layer->texture);
3169 m.texmatrix[1] = layer->texmatrix;
3170 m.texrgbscale[1] = layertexrgbscale;
3171 m.pointer_texcoord[1] = rsurface_model->surfmesh.data_texcoordtexture2f;
3172 R_Mesh_TextureState(&m);
3173 RSurf_DrawBatch_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], lightmode, applycolor, applyfog);
3175 case TEXTURELAYERTYPE_TEXTURE:
3176 memset(&m, 0, sizeof(m));
3177 m.tex[0] = R_GetTexture(layer->texture);
3178 m.texmatrix[0] = layer->texmatrix;
3179 m.texrgbscale[0] = layertexrgbscale;
3180 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3181 R_Mesh_TextureState(&m);
3182 RSurf_DrawBatch_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, applyfog);
3184 case TEXTURELAYERTYPE_FOG:
3185 memset(&m, 0, sizeof(m));
3186 m.texrgbscale[0] = layertexrgbscale;
3189 m.tex[0] = R_GetTexture(layer->texture);
3190 m.texmatrix[0] = layer->texmatrix;
3191 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3193 R_Mesh_TextureState(&m);
3194 // generate a color array for the fog pass
3195 R_Mesh_ColorPointer(rsurface_array_color4f);
3196 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3200 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3201 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)
3203 f = VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
3204 c[0] = layercolor[0];
3205 c[1] = layercolor[1];
3206 c[2] = layercolor[2];
3207 c[3] = f * layercolor[3];
3210 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3213 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
3215 GL_LockArrays(0, 0);
3218 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
3220 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3221 GL_AlphaTest(false);
3225 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, msurface_t **texturesurfacelist)
3227 // OpenGL 1.1 - crusty old voodoo path
3228 int texturesurfaceindex;
3233 const texturelayer_t *layer;
3235 // FIXME: identify models using a better check than rsurface_model->brush.shadowmesh
3236 lightmode = ((rsurface_entity->effects & EF_FULLBRIGHT) || rsurface_model->brush.shadowmesh) ? 0 : 2;
3237 if (rsurface_mode != RSURFMODE_MULTIPASS)
3238 rsurface_mode = RSURFMODE_MULTIPASS;
3239 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
3240 for (layerindex = 0, layer = rsurface_texture->currentlayers;layerindex < rsurface_texture->currentnumlayers;layerindex++, layer++)
3242 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
3244 if (layerindex == 0)
3248 GL_AlphaTest(false);
3249 qglDepthFunc(GL_EQUAL);CHECKGLERROR
3252 GL_DepthMask(layer->depthmask);
3253 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
3254 R_Mesh_ColorPointer(NULL);
3255 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
3256 switch (layer->type)
3258 case TEXTURELAYERTYPE_LITTEXTURE:
3259 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
3261 // two-pass lit texture with 2x rgbscale
3262 // first the lightmap pass
3263 memset(&m, 0, sizeof(m));
3264 if (lightmode >= 1 || !rsurface_lightmaptexture)
3265 m.tex[0] = R_GetTexture(r_texture_white);
3267 m.tex[0] = R_GetTexture(rsurface_lightmaptexture);
3268 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordlightmap2f;
3269 R_Mesh_TextureState(&m);
3270 RSurf_DrawBatch_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, lightmode, false, false);
3271 GL_LockArrays(0, 0);
3272 // then apply the texture to it
3273 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
3274 memset(&m, 0, sizeof(m));
3275 m.tex[0] = R_GetTexture(layer->texture);
3276 m.texmatrix[0] = layer->texmatrix;
3277 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3278 R_Mesh_TextureState(&m);
3279 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);
3283 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
3284 memset(&m, 0, sizeof(m));
3285 m.tex[0] = R_GetTexture(layer->texture);
3286 m.texmatrix[0] = layer->texmatrix;
3287 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3288 R_Mesh_TextureState(&m);
3289 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);
3292 case TEXTURELAYERTYPE_TEXTURE:
3293 // singletexture unlit texture with transparency support
3294 memset(&m, 0, sizeof(m));
3295 m.tex[0] = R_GetTexture(layer->texture);
3296 m.texmatrix[0] = layer->texmatrix;
3297 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3298 R_Mesh_TextureState(&m);
3299 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);
3301 case TEXTURELAYERTYPE_FOG:
3302 // singletexture fogging
3303 R_Mesh_ColorPointer(rsurface_array_color4f);
3306 memset(&m, 0, sizeof(m));
3307 m.tex[0] = R_GetTexture(layer->texture);
3308 m.texmatrix[0] = layer->texmatrix;
3309 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3310 R_Mesh_TextureState(&m);
3313 R_Mesh_ResetTextureState();
3314 // generate a color array for the fog pass
3315 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3319 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3320 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)
3322 f = VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
3323 c[0] = layer->color[0];
3324 c[1] = layer->color[1];
3325 c[2] = layer->color[2];
3326 c[3] = f * layer->color[3];
3329 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3332 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
3334 GL_LockArrays(0, 0);
3337 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
3339 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3340 GL_AlphaTest(false);
3344 static void R_DrawTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist)
3346 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_NODRAW)
3348 r_shadow_rtlight = NULL;
3349 r_refdef.stats.entities_surfaces += texturenumsurfaces;
3351 GL_DepthTest(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
3352 if ((rsurface_texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (rsurface_entity->flags & RENDER_NOCULLFACE))
3354 qglDisable(GL_CULL_FACE);CHECKGLERROR
3356 if (r_showsurfaces.integer)
3357 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
3358 else if (rsurface_texture->currentmaterialflags & MATERIALFLAG_SKY)
3359 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
3360 else if (rsurface_texture->currentnumlayers)
3362 if (r_glsl.integer && gl_support_fragment_shader)
3363 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist);
3364 else if (gl_combine.integer && r_textureunits.integer >= 2)
3365 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist);
3367 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist);
3370 GL_LockArrays(0, 0);
3371 if ((rsurface_texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (rsurface_entity->flags & RENDER_NOCULLFACE))
3373 qglEnable(GL_CULL_FACE);CHECKGLERROR
3377 #define BATCHSIZE 256
3378 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
3380 int surfacelistindex;
3383 msurface_t *texturesurfacelist[BATCHSIZE];
3384 // if the model is static it doesn't matter what value we give for
3385 // wantnormals and wanttangents, so this logic uses only rules applicable
3386 // to a model, knowing that they are meaningless otherwise
3387 if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
3388 RSurf_ActiveEntity(ent, false, false);
3390 RSurf_ActiveEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
3393 for (surfacelistindex = 0;surfacelistindex < numsurfaces;surfacelistindex++)
3395 msurface_t *surface = ent->model->data_surfaces + surfacelist[surfacelistindex];
3397 if (t != surface->texture || rsurface_lightmaptexture != surface->lightmaptexture)
3400 R_DrawTextureSurfaceList(batchcount, texturesurfacelist);
3402 t = surface->texture;
3403 rsurface_lightmaptexture = surface->lightmaptexture;
3404 R_UpdateTextureInfo(ent, t);
3405 rsurface_texture = t->currentframe;
3407 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_SKY)
3408 continue; // transparent sky is too difficult
3410 texturesurfacelist[batchcount++] = surface;
3413 R_DrawTextureSurfaceList(batchcount, texturesurfacelist);
3417 void R_QueueTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist)
3419 int texturesurfaceindex;
3420 vec3_t tempcenter, center;
3421 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_BLENDED)
3423 // drawing sky transparently would be too difficult
3424 if (!(rsurface_texture->currentmaterialflags & MATERIALFLAG_SKY))
3426 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3428 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3429 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
3430 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
3431 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
3432 Matrix4x4_Transform(&rsurface_entity->matrix, tempcenter, center);
3433 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);
3438 R_DrawTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
3441 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
3442 void R_DrawSurfaces(entity_render_t *ent, qboolean skysurfaces)
3444 int i, j, f, flagsmask;
3445 int counttriangles = 0;
3447 model_t *model = ent->model;
3448 const int maxsurfacelist = 1024;
3449 int numsurfacelist = 0;
3450 msurface_t *surfacelist[1024];
3454 // if the model is static it doesn't matter what value we give for
3455 // wantnormals and wanttangents, so this logic uses only rules applicable
3456 // to a model, knowing that they are meaningless otherwise
3457 if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
3458 RSurf_ActiveEntity(ent, false, false);
3460 RSurf_ActiveEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
3462 // update light styles
3463 if (!skysurfaces && model->brushq1.light_styleupdatechains)
3465 msurface_t *surface, **surfacechain;
3466 for (i = 0;i < model->brushq1.light_styles;i++)
3468 if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
3470 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
3471 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
3472 for (;(surface = *surfacechain);surfacechain++)
3473 surface->cached_dlight = true;
3478 R_UpdateAllTextureInfo(ent);
3479 flagsmask = skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL);
3482 rsurface_lightmaptexture = NULL;
3483 rsurface_texture = NULL;
3485 if (ent == r_refdef.worldentity)
3487 msurface_t *surface;
3488 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
3490 if (!r_viewcache.world_surfacevisible[j])
3492 if (t != surface->texture || rsurface_lightmaptexture != surface->lightmaptexture)
3496 R_QueueTextureSurfaceList(numsurfacelist, surfacelist);
3499 t = surface->texture;
3500 rsurface_lightmaptexture = surface->lightmaptexture;
3501 rsurface_texture = t->currentframe;
3502 f = rsurface_texture->currentmaterialflags & flagsmask;
3504 if (f && surface->num_triangles)
3506 // if lightmap parameters changed, rebuild lightmap texture
3507 if (surface->cached_dlight)
3508 R_BuildLightMap(ent, surface);
3509 // add face to draw list
3510 surfacelist[numsurfacelist++] = surface;
3511 counttriangles += surface->num_triangles;
3512 if (numsurfacelist >= maxsurfacelist)
3514 R_QueueTextureSurfaceList(numsurfacelist, surfacelist);
3522 msurface_t *surface;
3523 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
3525 if (t != surface->texture || rsurface_lightmaptexture != surface->lightmaptexture)
3529 R_QueueTextureSurfaceList(numsurfacelist, surfacelist);
3532 t = surface->texture;
3533 rsurface_lightmaptexture = surface->lightmaptexture;
3534 rsurface_texture = t->currentframe;
3535 f = rsurface_texture->currentmaterialflags & flagsmask;
3537 if (f && surface->num_triangles)
3539 // if lightmap parameters changed, rebuild lightmap texture
3540 if (surface->cached_dlight)
3541 R_BuildLightMap(ent, surface);
3542 // add face to draw list
3543 surfacelist[numsurfacelist++] = surface;
3544 counttriangles += surface->num_triangles;
3545 if (numsurfacelist >= maxsurfacelist)
3547 R_QueueTextureSurfaceList(numsurfacelist, surfacelist);
3554 R_QueueTextureSurfaceList(numsurfacelist, surfacelist);
3555 r_refdef.stats.entities_triangles += counttriangles;
3558 if (r_showcollisionbrushes.integer && model->brush.num_brushes && !skysurfaces)
3561 const msurface_t *surface;
3564 R_Mesh_Matrix(&ent->matrix);
3565 R_Mesh_ColorPointer(NULL);
3566 R_Mesh_ResetTextureState();
3567 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
3568 GL_DepthMask(false);
3569 GL_DepthTest(!r_showdisabledepthtest.integer);
3570 qglPolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);CHECKGLERROR
3571 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
3572 if (brush->colbrushf && brush->colbrushf->numtriangles)
3573 R_DrawCollisionBrush(brush->colbrushf);
3574 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
3575 if (surface->num_collisiontriangles)
3576 R_DrawCollisionSurface(ent, surface);
3577 qglPolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR
3580 if (r_showtris.integer || r_shownormals.integer)
3583 msurface_t *surface;
3584 const int *elements;
3589 if (r_showdisabledepthtest.integer)
3591 qglDepthFunc(GL_ALWAYS);CHECKGLERROR
3593 GL_BlendFunc(GL_ONE, GL_ZERO);
3594 R_Mesh_ColorPointer(NULL);
3595 R_Mesh_ResetTextureState();
3596 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
3598 if (ent == r_refdef.worldentity && !r_viewcache.world_surfacevisible[j])
3600 rsurface_texture = surface->texture->currentframe;
3601 if ((rsurface_texture->currentmaterialflags & flagsmask) && surface->num_triangles)
3603 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
3604 if (r_showtris.integer)
3606 if (!rsurface_texture->currentlayers->depthmask)
3607 GL_Color(r_showtris.value * r_view.colorscale, 0, 0, 1);
3608 else if (ent == r_refdef.worldentity)
3609 GL_Color(r_showtris.value * r_view.colorscale, r_showtris.value * r_view.colorscale, r_showtris.value * r_view.colorscale, 1);
3611 GL_Color(0, r_showtris.value * r_view.colorscale, 0, 1);
3612 elements = (ent->model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
3615 for (k = 0;k < surface->num_triangles;k++, elements += 3)
3617 qglArrayElement(elements[0]);qglArrayElement(elements[1]);
3618 qglArrayElement(elements[1]);qglArrayElement(elements[2]);
3619 qglArrayElement(elements[2]);qglArrayElement(elements[0]);
3624 if (r_shownormals.integer)
3626 GL_Color(r_shownormals.value * r_view.colorscale, 0, 0, 1);
3628 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
3630 VectorCopy(rsurface_vertex3f + l * 3, v);
3631 qglVertex3f(v[0], v[1], v[2]);
3632 VectorMA(v, 8, rsurface_svector3f + l * 3, v);
3633 qglVertex3f(v[0], v[1], v[2]);
3637 GL_Color(0, 0, r_shownormals.value * r_view.colorscale, 1);
3639 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
3641 VectorCopy(rsurface_vertex3f + l * 3, v);
3642 qglVertex3f(v[0], v[1], v[2]);
3643 VectorMA(v, 8, rsurface_tvector3f + l * 3, v);
3644 qglVertex3f(v[0], v[1], v[2]);
3648 GL_Color(0, r_shownormals.value * r_view.colorscale, 0, 1);
3650 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
3652 VectorCopy(rsurface_vertex3f + l * 3, v);
3653 qglVertex3f(v[0], v[1], v[2]);
3654 VectorMA(v, 8, rsurface_normal3f + l * 3, v);
3655 qglVertex3f(v[0], v[1], v[2]);
3662 rsurface_texture = NULL;
3663 if (r_showdisabledepthtest.integer)
3665 qglDepthFunc(GL_LEQUAL);CHECKGLERROR