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 strcpy(entname + l, ".ent");
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_AddVertex3f(rmesh_t *mesh, const float *v)
2232 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
2233 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
2235 if (i == mesh->numvertices)
2237 if (mesh->numvertices < mesh->maxvertices)
2239 VectorCopy(v, vertex3f);
2240 mesh->numvertices++;
2242 return mesh->numvertices;
2248 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
2252 element[0] = R_Mesh_AddVertex3f(mesh, vertex3f);vertex3f += 3;
2253 element[1] = R_Mesh_AddVertex3f(mesh, vertex3f);vertex3f += 3;
2254 e = mesh->element3i + mesh->numtriangles * 3;
2255 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
2257 element[2] = R_Mesh_AddVertex3f(mesh, vertex3f);
2258 if (mesh->numtriangles < mesh->maxtriangles)
2263 mesh->numtriangles++;
2265 element[1] = element[2];
2269 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
2271 int planenum, planenum2;
2274 mplane_t *plane, *plane2;
2275 float temppoints[2][256*3];
2276 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
2280 PolygonF_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->normal[3], 1024.0*1024.0*1024.0);
2281 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
2283 if (planenum2 == planenum)
2285 PolygonF_Divide(tempnumpoints, temppoints[w], plane2->normal[0], plane2->normal[1], plane2->normal[2], plane2->dist, 1.0/32.0, 0, NULL, NULL, 256, temppoints[!w], &tempnumpoints, NULL);
2288 if (tempnumpoints < 3)
2290 // generate elements forming a triangle fan for this polygon
2291 R_Mesh_AddPolygon3f(mesh, tempnumpoints, temppoints[w]);
2295 static void R_DrawCollisionBrush(const colbrushf_t *brush)
2298 R_Mesh_VertexPointer(brush->points->v);
2299 i = (int)(((size_t)brush) / sizeof(colbrushf_t));
2300 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);
2301 GL_LockArrays(0, brush->numpoints);
2302 R_Mesh_Draw(0, brush->numpoints, brush->numtriangles, brush->elements);
2303 GL_LockArrays(0, 0);
2306 static void R_DrawCollisionSurface(const entity_render_t *ent, const msurface_t *surface)
2309 if (!surface->num_collisiontriangles)
2311 R_Mesh_VertexPointer(surface->data_collisionvertex3f);
2312 i = (int)(((size_t)surface) / sizeof(msurface_t));
2313 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);
2314 GL_LockArrays(0, surface->num_collisionvertices);
2315 R_Mesh_Draw(0, surface->num_collisionvertices, surface->num_collisiontriangles, surface->data_collisionelement3i);
2316 GL_LockArrays(0, 0);
2319 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)
2321 texturelayer_t *layer;
2322 layer = t->currentlayers + t->currentnumlayers++;
2324 layer->depthmask = depthmask;
2325 layer->blendfunc1 = blendfunc1;
2326 layer->blendfunc2 = blendfunc2;
2327 layer->texture = texture;
2328 layer->texmatrix = *matrix;
2329 layer->color[0] = r * r_view.colorscale;
2330 layer->color[1] = g * r_view.colorscale;
2331 layer->color[2] = b * r_view.colorscale;
2332 layer->color[3] = a;
2335 void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
2337 // FIXME: identify models using a better check than ent->model->brush.shadowmesh
2338 //int lightmode = ((ent->effects & EF_FULLBRIGHT) || ent->model->brush.shadowmesh) ? 0 : 2;
2341 texture_t *texture = t;
2342 model_t *model = ent->model;
2343 int s = ent->skinnum;
2344 if ((unsigned int)s >= (unsigned int)model->numskins)
2346 if (model->skinscenes)
2348 if (model->skinscenes[s].framecount > 1)
2349 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
2351 s = model->skinscenes[s].firstframe;
2354 t = t + s * model->num_surfaces;
2357 // use an alternate animation if the entity's frame is not 0,
2358 // and only if the texture has an alternate animation
2359 if (ent->frame != 0 && t->anim_total[1])
2360 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.time * 5.0f) % t->anim_total[1]) : 0];
2362 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.time * 5.0f) % t->anim_total[0]) : 0];
2364 texture->currentframe = t;
2367 t->currentmaterialflags = t->basematerialflags;
2368 t->currentalpha = ent->alpha;
2369 if (t->basematerialflags & MATERIALFLAG_WATERALPHA)
2370 t->currentalpha *= r_wateralpha.value;
2371 if (!(ent->flags & RENDER_LIGHT))
2372 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
2373 if (ent->effects & EF_ADDITIVE)
2374 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_TRANSPARENT;
2375 else if (t->currentalpha < 1)
2376 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_TRANSPARENT;
2377 if (ent->effects & EF_NODEPTHTEST)
2378 t->currentmaterialflags |= MATERIALFLAG_NODEPTHTEST;
2379 if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
2380 t->currenttexmatrix = r_waterscrollmatrix;
2382 t->currenttexmatrix = identitymatrix;
2384 t->colormapping = VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f);
2385 t->basetexture = (!t->colormapping && t->skin.merged) ? t->skin.merged : t->skin.base;
2386 t->glosstexture = r_texture_white;
2387 t->specularpower = 8;
2388 t->specularscale = 0;
2389 if (r_shadow_gloss.integer > 0)
2393 if (r_shadow_glossintensity.value > 0)
2395 t->glosstexture = t->skin.gloss;
2396 t->specularscale = r_shadow_glossintensity.value;
2399 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
2400 t->specularscale = r_shadow_gloss2intensity.value;
2403 t->currentnumlayers = 0;
2404 if (!(t->currentmaterialflags & MATERIALFLAG_NODRAW))
2406 if (gl_lightmaps.integer)
2407 R_Texture_AddLayer(t, true, GL_ONE, GL_ZERO, TEXTURELAYERTYPE_LITTEXTURE, r_texture_white, &identitymatrix, 1, 1, 1, 1);
2408 else if (!(t->currentmaterialflags & MATERIALFLAG_SKY))
2410 int blendfunc1, blendfunc2, depthmask;
2411 if (t->currentmaterialflags & MATERIALFLAG_ADD)
2413 blendfunc1 = GL_SRC_ALPHA;
2414 blendfunc2 = GL_ONE;
2416 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
2418 blendfunc1 = GL_SRC_ALPHA;
2419 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
2421 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
2423 blendfunc1 = t->customblendfunc[0];
2424 blendfunc2 = t->customblendfunc[1];
2428 blendfunc1 = GL_ONE;
2429 blendfunc2 = GL_ZERO;
2431 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
2432 if (t->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL))
2434 rtexture_t *currentbasetexture;
2436 if (r_refdef.fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED))
2437 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
2438 currentbasetexture = (VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) < (1.0f / 1048576.0f) && t->skin.merged) ? t->skin.merged : t->skin.base;
2439 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2441 // fullbright is not affected by r_refdef.lightmapintensity
2442 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
2443 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->skin.pants)
2444 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);
2445 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->skin.shirt)
2446 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);
2452 // q3bsp has no lightmap updates, so the lightstylevalue that
2453 // would normally be baked into the lightmap must be
2454 // applied to the color
2455 if (ent->model->type == mod_brushq3)
2456 colorscale *= r_refdef.lightstylevalue[0] * (1.0f / 256.0f);
2457 colorscale *= r_refdef.lightmapintensity;
2458 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);
2459 if (r_ambient.value >= (1.0f/64.0f))
2460 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);
2461 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->skin.pants)
2463 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);
2464 if (r_ambient.value >= (1.0f/64.0f))
2465 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);
2467 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->skin.shirt)
2469 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);
2470 if (r_ambient.value >= (1.0f/64.0f))
2471 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);
2474 if (t->skin.glow != NULL)
2475 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);
2476 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
2478 // if this is opaque use alpha blend which will darken the earlier
2481 // if this is an alpha blended material, all the earlier passes
2482 // were darkened by fog already, so we only need to add the fog
2483 // color ontop through the fog mask texture
2485 // if this is an additive blended material, all the earlier passes
2486 // were darkened by fog already, and we should not add fog color
2487 // (because the background was not darkened, there is no fog color
2488 // that was lost behind it).
2489 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);
2496 void R_UpdateAllTextureInfo(entity_render_t *ent)
2500 for (i = 0;i < ent->model->num_textures;i++)
2501 R_UpdateTextureInfo(ent, ent->model->data_textures + i);
2504 int rsurface_array_size = 0;
2505 float *rsurface_array_modelvertex3f = NULL;
2506 float *rsurface_array_modelsvector3f = NULL;
2507 float *rsurface_array_modeltvector3f = NULL;
2508 float *rsurface_array_modelnormal3f = NULL;
2509 float *rsurface_array_deformedvertex3f = NULL;
2510 float *rsurface_array_deformedsvector3f = NULL;
2511 float *rsurface_array_deformedtvector3f = NULL;
2512 float *rsurface_array_deformednormal3f = NULL;
2513 float *rsurface_array_color4f = NULL;
2514 float *rsurface_array_texcoord3f = NULL;
2516 void R_Mesh_ResizeArrays(int newvertices)
2519 if (rsurface_array_size >= newvertices)
2521 if (rsurface_array_modelvertex3f)
2522 Mem_Free(rsurface_array_modelvertex3f);
2523 rsurface_array_size = (newvertices + 1023) & ~1023;
2524 base = (float *)Mem_Alloc(r_main_mempool, rsurface_array_size * sizeof(float[31]));
2525 rsurface_array_modelvertex3f = base + rsurface_array_size * 0;
2526 rsurface_array_modelsvector3f = base + rsurface_array_size * 3;
2527 rsurface_array_modeltvector3f = base + rsurface_array_size * 6;
2528 rsurface_array_modelnormal3f = base + rsurface_array_size * 9;
2529 rsurface_array_deformedvertex3f = base + rsurface_array_size * 12;
2530 rsurface_array_deformedsvector3f = base + rsurface_array_size * 15;
2531 rsurface_array_deformedtvector3f = base + rsurface_array_size * 18;
2532 rsurface_array_deformednormal3f = base + rsurface_array_size * 21;
2533 rsurface_array_texcoord3f = base + rsurface_array_size * 24;
2534 rsurface_array_color4f = base + rsurface_array_size * 27;
2537 float *rsurface_modelvertex3f;
2538 float *rsurface_modelsvector3f;
2539 float *rsurface_modeltvector3f;
2540 float *rsurface_modelnormal3f;
2541 float *rsurface_vertex3f;
2542 float *rsurface_svector3f;
2543 float *rsurface_tvector3f;
2544 float *rsurface_normal3f;
2545 float *rsurface_lightmapcolor4f;
2546 vec3_t rsurface_modelorg;
2547 qboolean rsurface_generatedvertex;
2548 const entity_render_t *rsurface_entity;
2549 const model_t *rsurface_model;
2550 texture_t *rsurface_texture;
2551 rtexture_t *rsurface_lightmaptexture;
2552 rsurfmode_t rsurface_mode;
2553 texture_t *rsurface_glsl_texture;
2554 qboolean rsurface_glsl_uselightmap;
2556 void RSurf_ActiveEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
2558 Matrix4x4_Transform(&ent->inversematrix, r_view.origin, rsurface_modelorg);
2559 rsurface_entity = ent;
2560 rsurface_model = ent->model;
2561 if (rsurface_array_size < rsurface_model->surfmesh.num_vertices)
2562 R_Mesh_ResizeArrays(rsurface_model->surfmesh.num_vertices);
2563 R_Mesh_Matrix(&ent->matrix);
2564 Matrix4x4_Transform(&ent->inversematrix, r_view.origin, rsurface_modelorg);
2565 if ((rsurface_entity->frameblend[0].lerp != 1 || rsurface_entity->frameblend[0].frame != 0) && rsurface_model->surfmesh.isanimated)
2569 rsurface_modelvertex3f = rsurface_array_modelvertex3f;
2570 rsurface_modelsvector3f = rsurface_array_modelsvector3f;
2571 rsurface_modeltvector3f = rsurface_array_modeltvector3f;
2572 rsurface_modelnormal3f = rsurface_array_modelnormal3f;
2573 Mod_Alias_GetMesh_Vertices(rsurface_model, rsurface_entity->frameblend, rsurface_array_modelvertex3f, rsurface_array_modelnormal3f, rsurface_array_modelsvector3f, rsurface_array_modeltvector3f);
2575 else if (wantnormals)
2577 rsurface_modelvertex3f = rsurface_array_modelvertex3f;
2578 rsurface_modelsvector3f = NULL;
2579 rsurface_modeltvector3f = NULL;
2580 rsurface_modelnormal3f = rsurface_array_modelnormal3f;
2581 Mod_Alias_GetMesh_Vertices(rsurface_model, rsurface_entity->frameblend, rsurface_array_modelvertex3f, rsurface_array_modelnormal3f, NULL, NULL);
2585 rsurface_modelvertex3f = rsurface_array_modelvertex3f;
2586 rsurface_modelsvector3f = NULL;
2587 rsurface_modeltvector3f = NULL;
2588 rsurface_modelnormal3f = NULL;
2589 Mod_Alias_GetMesh_Vertices(rsurface_model, rsurface_entity->frameblend, rsurface_array_modelvertex3f, NULL, NULL, NULL);
2591 rsurface_generatedvertex = true;
2595 rsurface_modelvertex3f = rsurface_model->surfmesh.data_vertex3f;
2596 rsurface_modelsvector3f = rsurface_model->surfmesh.data_svector3f;
2597 rsurface_modeltvector3f = rsurface_model->surfmesh.data_tvector3f;
2598 rsurface_modelnormal3f = rsurface_model->surfmesh.data_normal3f;
2599 rsurface_generatedvertex = false;
2601 rsurface_vertex3f = rsurface_modelvertex3f;
2602 rsurface_svector3f = rsurface_modelsvector3f;
2603 rsurface_tvector3f = rsurface_modeltvector3f;
2604 rsurface_normal3f = rsurface_modelnormal3f;
2605 rsurface_mode = RSURFMODE_NONE;
2606 rsurface_lightmaptexture = NULL;
2607 rsurface_texture = NULL;
2608 rsurface_glsl_texture = NULL;
2609 rsurface_glsl_uselightmap = false;
2612 void RSurf_CleanUp(void)
2615 if (rsurface_mode == RSURFMODE_GLSL)
2617 qglUseProgramObjectARB(0);CHECKGLERROR
2619 GL_AlphaTest(false);
2620 rsurface_mode = RSURFMODE_NONE;
2621 rsurface_lightmaptexture = NULL;
2622 rsurface_texture = NULL;
2623 rsurface_glsl_texture = NULL;
2624 rsurface_glsl_uselightmap = false;
2627 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, msurface_t **texturesurfacelist)
2629 if (rsurface_generatedvertex)
2631 if (rsurface_texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
2632 generatetangents = true;
2633 if (generatetangents)
2634 generatenormals = true;
2635 if (generatenormals && !rsurface_modelnormal3f)
2637 rsurface_normal3f = rsurface_modelnormal3f = rsurface_array_modelnormal3f;
2638 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);
2640 if (generatetangents && !rsurface_modelsvector3f)
2642 rsurface_svector3f = rsurface_modelsvector3f = rsurface_array_modelsvector3f;
2643 rsurface_tvector3f = rsurface_modeltvector3f = rsurface_array_modeltvector3f;
2644 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);
2647 if (rsurface_texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
2649 int texturesurfaceindex;
2650 float center[3], forward[3], right[3], up[3], v[4][3];
2651 matrix4x4_t matrix1, imatrix1;
2652 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_view.forward, forward);
2653 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_view.right, right);
2654 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_view.up, up);
2655 // make deformed versions of only the vertices used by the specified surfaces
2656 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2659 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2660 // a single autosprite surface can contain multiple sprites...
2661 for (j = 0;j < surface->num_vertices - 3;j += 4)
2663 VectorClear(center);
2664 for (i = 0;i < 4;i++)
2665 VectorAdd(center, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
2666 VectorScale(center, 0.25f, center);
2667 if (rsurface_texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE2)
2669 forward[0] = rsurface_modelorg[0] - center[0];
2670 forward[1] = rsurface_modelorg[1] - center[1];
2672 VectorNormalize(forward);
2673 right[0] = forward[1];
2674 right[1] = -forward[0];
2676 VectorSet(up, 0, 0, 1);
2678 // FIXME: calculate vectors from triangle edges instead of using texture vectors as an easy way out?
2679 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);
2680 Matrix4x4_Invert_Simple(&imatrix1, &matrix1);
2681 for (i = 0;i < 4;i++)
2682 Matrix4x4_Transform(&imatrix1, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, v[i]);
2683 for (i = 0;i < 4;i++)
2684 VectorMAMAMAM(1, center, v[i][0], forward, v[i][1], right, v[i][2], up, rsurface_array_modelvertex3f + (surface->num_firstvertex+i+j) * 3);
2686 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);
2687 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);
2689 rsurface_vertex3f = rsurface_array_deformedvertex3f;
2690 rsurface_svector3f = rsurface_array_deformedsvector3f;
2691 rsurface_tvector3f = rsurface_array_deformedtvector3f;
2692 rsurface_normal3f = rsurface_array_deformednormal3f;
2694 R_Mesh_VertexPointer(rsurface_vertex3f);
2697 void RSurf_DrawBatch_Simple(int texturenumsurfaces, msurface_t **texturesurfacelist)
2699 int texturesurfaceindex;
2700 const msurface_t *surface = texturesurfacelist[0];
2701 int firstvertex = surface->num_firstvertex;
2702 int endvertex = surface->num_firstvertex + surface->num_vertices;
2703 if (texturenumsurfaces == 1)
2705 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2706 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
2708 else if (r_batchmode.integer == 2)
2710 #define MAXBATCHTRIANGLES 4096
2711 int batchtriangles = 0;
2712 int batchelements[MAXBATCHTRIANGLES*3];
2713 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2715 surface = texturesurfacelist[texturesurfaceindex];
2716 if (surface->num_triangles >= 256 || (batchtriangles == 0 && texturesurfaceindex + 1 >= texturenumsurfaces))
2718 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
2721 if (batchtriangles + surface->num_triangles > MAXBATCHTRIANGLES)
2723 R_Mesh_Draw(firstvertex, endvertex - firstvertex, batchtriangles, batchelements);
2725 firstvertex = surface->num_firstvertex;
2726 endvertex = surface->num_firstvertex + surface->num_vertices;
2730 firstvertex = min(firstvertex, surface->num_firstvertex);
2731 endvertex = max(endvertex, surface->num_firstvertex + surface->num_vertices);
2733 memcpy(batchelements + batchtriangles * 3, rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
2734 batchtriangles += surface->num_triangles;
2737 R_Mesh_Draw(firstvertex, endvertex - firstvertex, batchtriangles, batchelements);
2739 else if (r_batchmode.integer == 1)
2741 int firsttriangle = 0;
2742 int endtriangle = -1;
2743 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2745 surface = texturesurfacelist[texturesurfaceindex];
2746 if (surface->num_firsttriangle != endtriangle)
2748 if (endtriangle > firsttriangle)
2750 GL_LockArrays(firstvertex, endvertex - firstvertex);
2751 R_Mesh_Draw(firstvertex, endvertex - firstvertex, endtriangle - firsttriangle, (rsurface_model->surfmesh.data_element3i + 3 * firsttriangle));
2753 firstvertex = surface->num_firstvertex;
2754 endvertex = surface->num_firstvertex + surface->num_vertices;
2755 firsttriangle = surface->num_firsttriangle;
2759 firstvertex = min(firstvertex, surface->num_firstvertex);
2760 endvertex = max(endvertex, surface->num_firstvertex + surface->num_vertices);
2762 endtriangle = surface->num_firsttriangle + surface->num_triangles;
2764 if (endtriangle > firsttriangle)
2766 GL_LockArrays(firstvertex, endvertex - firstvertex);
2767 R_Mesh_Draw(firstvertex, endvertex - firstvertex, endtriangle - firsttriangle, (rsurface_model->surfmesh.data_element3i + 3 * firsttriangle));
2772 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2774 surface = texturesurfacelist[texturesurfaceindex];
2775 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2776 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
2781 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
2783 int texturesurfaceindex;
2784 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2786 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2787 int k = (int)(((size_t)surface) / sizeof(msurface_t));
2788 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);
2789 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2790 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
2794 static void RSurf_DrawBatch_Lightmap(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, int lightmode, qboolean applycolor, qboolean applyfog)
2796 int texturesurfaceindex;
2804 vec3_t ambientcolor;
2805 vec3_t diffusecolor;
2807 VectorCopy(rsurface_entity->modellight_lightdir, lightdir);
2808 ambientcolor[0] = rsurface_entity->modellight_ambient[0] * r * 0.5f;
2809 ambientcolor[1] = rsurface_entity->modellight_ambient[1] * g * 0.5f;
2810 ambientcolor[2] = rsurface_entity->modellight_ambient[2] * b * 0.5f;
2811 diffusecolor[0] = rsurface_entity->modellight_diffuse[0] * r * 0.5f;
2812 diffusecolor[1] = rsurface_entity->modellight_diffuse[1] * g * 0.5f;
2813 diffusecolor[2] = rsurface_entity->modellight_diffuse[2] * b * 0.5f;
2814 if (VectorLength2(diffusecolor) > 0)
2816 // generate color arrays for the surfaces in this list
2817 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2819 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2820 int numverts = surface->num_vertices;
2821 v = rsurface_vertex3f + 3 * surface->num_firstvertex;
2822 c2 = rsurface_normal3f + 3 * surface->num_firstvertex;
2823 c = rsurface_array_color4f + 4 * surface->num_firstvertex;
2824 // q3-style directional shading
2825 for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
2827 if ((f = DotProduct(c2, lightdir)) > 0)
2828 VectorMA(ambientcolor, f, diffusecolor, c);
2830 VectorCopy(ambientcolor, c);
2839 rsurface_lightmapcolor4f = rsurface_array_color4f;
2843 r = ambientcolor[0];
2844 g = ambientcolor[1];
2845 b = ambientcolor[2];
2846 rsurface_lightmapcolor4f = NULL;
2849 else if (lightmode >= 1 || !rsurface_lightmaptexture)
2851 if (texturesurfacelist[0]->lightmapinfo && texturesurfacelist[0]->lightmapinfo->stainsamples)
2853 // generate color arrays for the surfaces in this list
2854 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2856 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2857 for (i = 0, c = rsurface_array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
2859 if (surface->lightmapinfo->samples)
2861 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface_model->surfmesh.data_lightmapoffsets + surface->num_firstvertex)[i];
2862 float scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
2863 VectorScale(lm, scale, c);
2864 if (surface->lightmapinfo->styles[1] != 255)
2866 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
2868 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
2869 VectorMA(c, scale, lm, c);
2870 if (surface->lightmapinfo->styles[2] != 255)
2873 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
2874 VectorMA(c, scale, lm, c);
2875 if (surface->lightmapinfo->styles[3] != 255)
2878 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
2879 VectorMA(c, scale, lm, c);
2889 rsurface_lightmapcolor4f = rsurface_array_color4f;
2892 rsurface_lightmapcolor4f = rsurface_model->surfmesh.data_lightmapcolor4f;
2897 rsurface_lightmapcolor4f = NULL;
2901 if (rsurface_lightmapcolor4f)
2903 // generate color arrays for the surfaces in this list
2904 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2906 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2907 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)
2909 f = 1 - VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
2919 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2921 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2922 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)
2924 f = 1 - VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
2932 rsurface_lightmapcolor4f = rsurface_array_color4f;
2934 if (applycolor && rsurface_lightmapcolor4f)
2936 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2938 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2939 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)
2947 rsurface_lightmapcolor4f = rsurface_array_color4f;
2949 R_Mesh_ColorPointer(rsurface_lightmapcolor4f);
2950 GL_Color(r, g, b, a);
2951 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
2954 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
2956 if (rsurface_mode != RSURFMODE_SHOWSURFACES)
2958 rsurface_mode = RSURFMODE_SHOWSURFACES;
2960 GL_BlendFunc(GL_ONE, GL_ZERO);
2961 R_Mesh_ColorPointer(NULL);
2962 R_Mesh_ResetTextureState();
2964 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
2965 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
2968 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, msurface_t **texturesurfacelist)
2970 // transparent sky would be ridiculous
2971 if ((rsurface_texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
2973 if (rsurface_mode != RSURFMODE_SKY)
2975 if (rsurface_mode == RSURFMODE_GLSL)
2977 qglUseProgramObjectARB(0);CHECKGLERROR
2979 rsurface_mode = RSURFMODE_SKY;
2983 skyrendernow = false;
2985 // restore entity matrix
2986 R_Mesh_Matrix(&rsurface_entity->matrix);
2989 // LordHavoc: HalfLife maps have freaky skypolys so don't use
2990 // skymasking on them, and Quake3 never did sky masking (unlike
2991 // software Quake and software Quake2), so disable the sky masking
2992 // in Quake3 maps as it causes problems with q3map2 sky tricks,
2993 // and skymasking also looks very bad when noclipping outside the
2994 // level, so don't use it then either.
2995 if (rsurface_model->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_viewcache.world_novis)
2997 GL_Color(r_refdef.fogcolor[0] * r_view.colorscale, r_refdef.fogcolor[1] * r_view.colorscale, r_refdef.fogcolor[2] * r_view.colorscale, 1);
2998 R_Mesh_ColorPointer(NULL);
2999 R_Mesh_ResetTextureState();
3000 if (skyrendermasked)
3002 // depth-only (masking)
3003 GL_ColorMask(0,0,0,0);
3004 // just to make sure that braindead drivers don't draw
3005 // anything despite that colormask...
3006 GL_BlendFunc(GL_ZERO, GL_ONE);
3011 GL_BlendFunc(GL_ONE, GL_ZERO);
3013 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
3014 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3015 if (skyrendermasked)
3016 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
3020 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, msurface_t **texturesurfacelist)
3023 // FIXME: identify models using a better check than rsurface_model->brush.shadowmesh
3024 lightmode = ((rsurface_entity->effects & EF_FULLBRIGHT) || rsurface_model->brush.shadowmesh) ? 0 : 2;
3025 if (rsurface_mode != RSURFMODE_GLSL)
3027 rsurface_mode = RSURFMODE_GLSL;
3028 rsurface_glsl_texture = NULL;
3029 rsurface_glsl_uselightmap = false;
3030 R_Mesh_ResetTextureState();
3032 if (rsurface_glsl_texture != rsurface_texture || rsurface_glsl_uselightmap != (rsurface_lightmaptexture != NULL))
3034 rsurface_glsl_texture = rsurface_texture;
3035 rsurface_glsl_uselightmap = rsurface_lightmaptexture != NULL;
3036 GL_BlendFunc(rsurface_texture->currentlayers[0].blendfunc1, rsurface_texture->currentlayers[0].blendfunc2);
3037 GL_DepthMask(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_BLENDED));
3038 GL_Color(rsurface_entity->colormod[0], rsurface_entity->colormod[1], rsurface_entity->colormod[2], rsurface_texture->currentalpha);
3039 R_SetupSurfaceShader(vec3_origin, lightmode == 2);
3040 //permutation_deluxemapping = permutation_lightmapping = R_SetupSurfaceShader(vec3_origin, lightmode == 2, false);
3041 //if (r_glsl_deluxemapping.integer)
3042 // permutation_deluxemapping = R_SetupSurfaceShader(vec3_origin, lightmode == 2, true);
3043 R_Mesh_TexCoordPointer(0, 2, rsurface_model->surfmesh.data_texcoordtexture2f);
3044 R_Mesh_TexCoordPointer(4, 2, rsurface_model->surfmesh.data_texcoordlightmap2f);
3045 GL_AlphaTest((rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
3047 if (!r_glsl_permutation)
3049 RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
3050 R_Mesh_TexCoordPointer(1, 3, rsurface_svector3f);
3051 R_Mesh_TexCoordPointer(2, 3, rsurface_tvector3f);
3052 R_Mesh_TexCoordPointer(3, 3, rsurface_normal3f);
3053 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
3055 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
3056 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
3057 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
3058 R_Mesh_ColorPointer(NULL);
3060 else if (rsurface_lightmaptexture)
3062 R_Mesh_TexBind(7, R_GetTexture(rsurface_lightmaptexture));
3063 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
3064 R_Mesh_TexBind(8, R_GetTexture(texturesurfacelist[0]->deluxemaptexture));
3065 R_Mesh_ColorPointer(NULL);
3069 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
3070 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
3071 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
3072 R_Mesh_ColorPointer(rsurface_model->surfmesh.data_lightmapcolor4f);
3074 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3077 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, msurface_t **texturesurfacelist)
3079 // OpenGL 1.3 path - anything not completely ancient
3080 int texturesurfaceindex;
3082 qboolean applycolor;
3086 const texturelayer_t *layer;
3088 // FIXME: identify models using a better check than rsurface_model->brush.shadowmesh
3089 lightmode = ((rsurface_entity->effects & EF_FULLBRIGHT) || rsurface_model->brush.shadowmesh) ? 0 : 2;
3090 if (rsurface_mode != RSURFMODE_MULTIPASS)
3091 rsurface_mode = RSURFMODE_MULTIPASS;
3092 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
3093 for (layerindex = 0, layer = rsurface_texture->currentlayers;layerindex < rsurface_texture->currentnumlayers;layerindex++, layer++)
3096 int layertexrgbscale;
3097 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
3099 if (layerindex == 0)
3103 GL_AlphaTest(false);
3104 qglDepthFunc(GL_EQUAL);CHECKGLERROR
3107 GL_DepthMask(layer->depthmask);
3108 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
3109 if ((layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2) && (gl_combine.integer || layer->depthmask))
3111 layertexrgbscale = 4;
3112 VectorScale(layer->color, 0.25f, layercolor);
3114 else if ((layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1) && (gl_combine.integer || layer->depthmask))
3116 layertexrgbscale = 2;
3117 VectorScale(layer->color, 0.5f, layercolor);
3121 layertexrgbscale = 1;
3122 VectorScale(layer->color, 1.0f, layercolor);
3124 layercolor[3] = layer->color[3];
3125 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
3126 R_Mesh_ColorPointer(NULL);
3127 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
3128 switch (layer->type)
3130 case TEXTURELAYERTYPE_LITTEXTURE:
3131 memset(&m, 0, sizeof(m));
3132 if (lightmode >= 1 || !rsurface_lightmaptexture)
3133 m.tex[0] = R_GetTexture(r_texture_white);
3135 m.tex[0] = R_GetTexture(rsurface_lightmaptexture);
3136 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordlightmap2f;
3137 m.tex[1] = R_GetTexture(layer->texture);
3138 m.texmatrix[1] = layer->texmatrix;
3139 m.texrgbscale[1] = layertexrgbscale;
3140 m.pointer_texcoord[1] = rsurface_model->surfmesh.data_texcoordtexture2f;
3141 R_Mesh_TextureState(&m);
3142 RSurf_DrawBatch_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], lightmode, applycolor, applyfog);
3144 case TEXTURELAYERTYPE_TEXTURE:
3145 memset(&m, 0, sizeof(m));
3146 m.tex[0] = R_GetTexture(layer->texture);
3147 m.texmatrix[0] = layer->texmatrix;
3148 m.texrgbscale[0] = layertexrgbscale;
3149 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3150 R_Mesh_TextureState(&m);
3151 RSurf_DrawBatch_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, applyfog);
3153 case TEXTURELAYERTYPE_FOG:
3154 memset(&m, 0, sizeof(m));
3155 m.texrgbscale[0] = layertexrgbscale;
3158 m.tex[0] = R_GetTexture(layer->texture);
3159 m.texmatrix[0] = layer->texmatrix;
3160 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3162 R_Mesh_TextureState(&m);
3163 // generate a color array for the fog pass
3164 R_Mesh_ColorPointer(rsurface_array_color4f);
3165 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3169 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3170 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)
3172 f = VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
3173 c[0] = layercolor[0];
3174 c[1] = layercolor[1];
3175 c[2] = layercolor[2];
3176 c[3] = f * layercolor[3];
3179 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3182 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
3184 GL_LockArrays(0, 0);
3187 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
3189 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3190 GL_AlphaTest(false);
3194 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, msurface_t **texturesurfacelist)
3196 // OpenGL 1.1 - crusty old voodoo path
3197 int texturesurfaceindex;
3202 const texturelayer_t *layer;
3204 // FIXME: identify models using a better check than rsurface_model->brush.shadowmesh
3205 lightmode = ((rsurface_entity->effects & EF_FULLBRIGHT) || rsurface_model->brush.shadowmesh) ? 0 : 2;
3206 if (rsurface_mode != RSURFMODE_MULTIPASS)
3207 rsurface_mode = RSURFMODE_MULTIPASS;
3208 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
3209 for (layerindex = 0, layer = rsurface_texture->currentlayers;layerindex < rsurface_texture->currentnumlayers;layerindex++, layer++)
3211 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
3213 if (layerindex == 0)
3217 GL_AlphaTest(false);
3218 qglDepthFunc(GL_EQUAL);CHECKGLERROR
3221 GL_DepthMask(layer->depthmask);
3222 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
3223 R_Mesh_ColorPointer(NULL);
3224 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
3225 switch (layer->type)
3227 case TEXTURELAYERTYPE_LITTEXTURE:
3228 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
3230 // two-pass lit texture with 2x rgbscale
3231 // first the lightmap pass
3232 memset(&m, 0, sizeof(m));
3233 if (lightmode >= 1 || !rsurface_lightmaptexture)
3234 m.tex[0] = R_GetTexture(r_texture_white);
3236 m.tex[0] = R_GetTexture(rsurface_lightmaptexture);
3237 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordlightmap2f;
3238 R_Mesh_TextureState(&m);
3239 RSurf_DrawBatch_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, lightmode, false, false);
3240 GL_LockArrays(0, 0);
3241 // then apply the texture to it
3242 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
3243 memset(&m, 0, sizeof(m));
3244 m.tex[0] = R_GetTexture(layer->texture);
3245 m.texmatrix[0] = layer->texmatrix;
3246 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3247 R_Mesh_TextureState(&m);
3248 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);
3252 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
3253 memset(&m, 0, sizeof(m));
3254 m.tex[0] = R_GetTexture(layer->texture);
3255 m.texmatrix[0] = layer->texmatrix;
3256 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3257 R_Mesh_TextureState(&m);
3258 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);
3261 case TEXTURELAYERTYPE_TEXTURE:
3262 // singletexture unlit texture with transparency support
3263 memset(&m, 0, sizeof(m));
3264 m.tex[0] = R_GetTexture(layer->texture);
3265 m.texmatrix[0] = layer->texmatrix;
3266 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3267 R_Mesh_TextureState(&m);
3268 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);
3270 case TEXTURELAYERTYPE_FOG:
3271 // singletexture fogging
3272 R_Mesh_ColorPointer(rsurface_array_color4f);
3275 memset(&m, 0, sizeof(m));
3276 m.tex[0] = R_GetTexture(layer->texture);
3277 m.texmatrix[0] = layer->texmatrix;
3278 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3279 R_Mesh_TextureState(&m);
3282 R_Mesh_ResetTextureState();
3283 // generate a color array for the fog pass
3284 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3288 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3289 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)
3291 f = VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
3292 c[0] = layer->color[0];
3293 c[1] = layer->color[1];
3294 c[2] = layer->color[2];
3295 c[3] = f * layer->color[3];
3298 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3301 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
3303 GL_LockArrays(0, 0);
3306 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
3308 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3309 GL_AlphaTest(false);
3313 static void R_DrawTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist)
3315 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_NODRAW)
3317 r_shadow_rtlight = NULL;
3318 r_refdef.stats.entities_surfaces += texturenumsurfaces;
3320 GL_DepthTest(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
3321 if ((rsurface_texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (rsurface_entity->flags & RENDER_NOCULLFACE))
3323 qglDisable(GL_CULL_FACE);CHECKGLERROR
3325 if (r_showsurfaces.integer)
3326 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
3327 else if (rsurface_texture->currentmaterialflags & MATERIALFLAG_SKY)
3328 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
3329 else if (rsurface_texture->currentnumlayers)
3331 if (r_glsl.integer && gl_support_fragment_shader)
3332 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist);
3333 else if (gl_combine.integer && r_textureunits.integer >= 2)
3334 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist);
3336 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist);
3339 GL_LockArrays(0, 0);
3340 if ((rsurface_texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (rsurface_entity->flags & RENDER_NOCULLFACE))
3342 qglEnable(GL_CULL_FACE);CHECKGLERROR
3346 #define BATCHSIZE 256
3347 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
3349 int surfacelistindex;
3352 msurface_t *texturesurfacelist[BATCHSIZE];
3353 // if the model is static it doesn't matter what value we give for
3354 // wantnormals and wanttangents, so this logic uses only rules applicable
3355 // to a model, knowing that they are meaningless otherwise
3356 if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
3357 RSurf_ActiveEntity(ent, false, false);
3359 RSurf_ActiveEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
3362 for (surfacelistindex = 0;surfacelistindex < numsurfaces;surfacelistindex++)
3364 msurface_t *surface = ent->model->data_surfaces + surfacelist[surfacelistindex];
3366 if (t != surface->texture || rsurface_lightmaptexture != surface->lightmaptexture)
3369 R_DrawTextureSurfaceList(batchcount, texturesurfacelist);
3371 t = surface->texture;
3372 rsurface_lightmaptexture = surface->lightmaptexture;
3373 R_UpdateTextureInfo(ent, t);
3374 rsurface_texture = t->currentframe;
3376 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_SKY)
3377 continue; // transparent sky is too difficult
3379 texturesurfacelist[batchcount++] = surface;
3382 R_DrawTextureSurfaceList(batchcount, texturesurfacelist);
3386 void R_QueueTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist)
3388 int texturesurfaceindex;
3389 vec3_t tempcenter, center;
3390 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_BLENDED)
3392 // drawing sky transparently would be too difficult
3393 if (!(rsurface_texture->currentmaterialflags & MATERIALFLAG_SKY))
3395 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3397 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3398 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
3399 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
3400 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
3401 Matrix4x4_Transform(&rsurface_entity->matrix, tempcenter, center);
3402 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);
3407 R_DrawTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
3410 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
3411 void R_DrawSurfaces(entity_render_t *ent, qboolean skysurfaces)
3413 int i, j, f, flagsmask;
3414 int counttriangles = 0;
3416 model_t *model = ent->model;
3417 const int maxsurfacelist = 1024;
3418 int numsurfacelist = 0;
3419 msurface_t *surfacelist[1024];
3423 // if the model is static it doesn't matter what value we give for
3424 // wantnormals and wanttangents, so this logic uses only rules applicable
3425 // to a model, knowing that they are meaningless otherwise
3426 if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
3427 RSurf_ActiveEntity(ent, false, false);
3429 RSurf_ActiveEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
3431 // update light styles
3432 if (!skysurfaces && model->brushq1.light_styleupdatechains)
3434 msurface_t *surface, **surfacechain;
3435 for (i = 0;i < model->brushq1.light_styles;i++)
3437 if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
3439 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
3440 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
3441 for (;(surface = *surfacechain);surfacechain++)
3442 surface->cached_dlight = true;
3447 R_UpdateAllTextureInfo(ent);
3448 flagsmask = skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL);
3451 rsurface_lightmaptexture = NULL;
3452 rsurface_texture = NULL;
3454 if (ent == r_refdef.worldentity)
3456 msurface_t *surface;
3457 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
3459 if (!r_viewcache.world_surfacevisible[j])
3461 if (t != surface->texture || rsurface_lightmaptexture != surface->lightmaptexture)
3465 R_QueueTextureSurfaceList(numsurfacelist, surfacelist);
3468 t = surface->texture;
3469 rsurface_lightmaptexture = surface->lightmaptexture;
3470 rsurface_texture = t->currentframe;
3471 f = rsurface_texture->currentmaterialflags & flagsmask;
3473 if (f && surface->num_triangles)
3475 // if lightmap parameters changed, rebuild lightmap texture
3476 if (surface->cached_dlight)
3477 R_BuildLightMap(ent, surface);
3478 // add face to draw list
3479 surfacelist[numsurfacelist++] = surface;
3480 counttriangles += surface->num_triangles;
3481 if (numsurfacelist >= maxsurfacelist)
3483 R_QueueTextureSurfaceList(numsurfacelist, surfacelist);
3491 msurface_t *surface;
3492 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
3494 if (t != surface->texture || rsurface_lightmaptexture != surface->lightmaptexture)
3498 R_QueueTextureSurfaceList(numsurfacelist, surfacelist);
3501 t = surface->texture;
3502 rsurface_lightmaptexture = surface->lightmaptexture;
3503 rsurface_texture = t->currentframe;
3504 f = rsurface_texture->currentmaterialflags & flagsmask;
3506 if (f && surface->num_triangles)
3508 // if lightmap parameters changed, rebuild lightmap texture
3509 if (surface->cached_dlight)
3510 R_BuildLightMap(ent, surface);
3511 // add face to draw list
3512 surfacelist[numsurfacelist++] = surface;
3513 counttriangles += surface->num_triangles;
3514 if (numsurfacelist >= maxsurfacelist)
3516 R_QueueTextureSurfaceList(numsurfacelist, surfacelist);
3523 R_QueueTextureSurfaceList(numsurfacelist, surfacelist);
3524 r_refdef.stats.entities_triangles += counttriangles;
3527 if (r_showcollisionbrushes.integer && model->brush.num_brushes && !skysurfaces)
3530 const msurface_t *surface;
3533 R_Mesh_Matrix(&ent->matrix);
3534 R_Mesh_ColorPointer(NULL);
3535 R_Mesh_ResetTextureState();
3536 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
3537 GL_DepthMask(false);
3538 GL_DepthTest(!r_showdisabledepthtest.integer);
3539 qglPolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);CHECKGLERROR
3540 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
3541 if (brush->colbrushf && brush->colbrushf->numtriangles)
3542 R_DrawCollisionBrush(brush->colbrushf);
3543 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
3544 if (surface->num_collisiontriangles)
3545 R_DrawCollisionSurface(ent, surface);
3546 qglPolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR
3549 if (r_showtris.integer || r_shownormals.integer)
3552 msurface_t *surface;
3553 const int *elements;
3558 if (r_showdisabledepthtest.integer)
3560 qglDepthFunc(GL_ALWAYS);CHECKGLERROR
3562 GL_BlendFunc(GL_ONE, GL_ZERO);
3563 R_Mesh_ColorPointer(NULL);
3564 R_Mesh_ResetTextureState();
3565 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
3567 if (ent == r_refdef.worldentity && !r_viewcache.world_surfacevisible[j])
3569 rsurface_texture = surface->texture->currentframe;
3570 if ((rsurface_texture->currentmaterialflags & flagsmask) && surface->num_triangles)
3572 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
3573 if (r_showtris.integer)
3575 if (!rsurface_texture->currentlayers->depthmask)
3576 GL_Color(r_showtris.value * r_view.colorscale, 0, 0, 1);
3577 else if (ent == r_refdef.worldentity)
3578 GL_Color(r_showtris.value * r_view.colorscale, r_showtris.value * r_view.colorscale, r_showtris.value * r_view.colorscale, 1);
3580 GL_Color(0, r_showtris.value * r_view.colorscale, 0, 1);
3581 elements = (ent->model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
3584 for (k = 0;k < surface->num_triangles;k++, elements += 3)
3586 qglArrayElement(elements[0]);qglArrayElement(elements[1]);
3587 qglArrayElement(elements[1]);qglArrayElement(elements[2]);
3588 qglArrayElement(elements[2]);qglArrayElement(elements[0]);
3593 if (r_shownormals.integer)
3595 GL_Color(r_shownormals.value * r_view.colorscale, 0, 0, 1);
3597 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
3599 VectorCopy(rsurface_vertex3f + l * 3, v);
3600 qglVertex3f(v[0], v[1], v[2]);
3601 VectorMA(v, 8, rsurface_svector3f + l * 3, v);
3602 qglVertex3f(v[0], v[1], v[2]);
3606 GL_Color(0, 0, r_shownormals.value * r_view.colorscale, 1);
3608 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
3610 VectorCopy(rsurface_vertex3f + l * 3, v);
3611 qglVertex3f(v[0], v[1], v[2]);
3612 VectorMA(v, 8, rsurface_tvector3f + l * 3, v);
3613 qglVertex3f(v[0], v[1], v[2]);
3617 GL_Color(0, r_shownormals.value * r_view.colorscale, 0, 1);
3619 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
3621 VectorCopy(rsurface_vertex3f + l * 3, v);
3622 qglVertex3f(v[0], v[1], v[2]);
3623 VectorMA(v, 8, rsurface_normal3f + l * 3, v);
3624 qglVertex3f(v[0], v[1], v[2]);
3631 rsurface_texture = NULL;
3632 if (r_showdisabledepthtest.integer)
3634 qglDepthFunc(GL_LEQUAL);CHECKGLERROR