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_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this)"};
55 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
56 cvar_t r_q1bsp_skymasking = {0, "r_qb1sp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
58 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
59 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
60 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
61 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
62 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
63 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
64 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
66 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)"};
68 cvar_t r_glsl = {0, "r_glsl", "1", "enables use of OpenGL 2.0 pixel shaders for lighting"};
69 cvar_t r_glsl_offsetmapping = {0, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
70 cvar_t r_glsl_offsetmapping_reliefmapping = {0, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
71 cvar_t r_glsl_offsetmapping_scale = {0, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
72 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)"};
74 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1", "enables animation smoothing on sprites (requires r_lerpmodels 1)"};
75 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
76 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
78 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
79 cvar_t r_bloom_intensity = {CVAR_SAVE, "r_bloom_intensity", "1.5", "how bright the glow is"};
80 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
81 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
82 cvar_t r_bloom_power = {CVAR_SAVE, "r_bloom_power", "2", "how much to darken the image before blurring to make the bloom effect"};
84 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
85 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
86 cvar_t r_hdr_bloomintensity = {CVAR_SAVE, "r_hdr_bloomintensity", "0.5", "amount of bloom"};
87 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
89 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"};
91 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"};
93 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
95 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
96 cvar_t r_batchmode = {0, "r_batchmode", "1", "selects method of rendering multiple surfaces with one driver call (values are 0, 1, 2, etc...)"};
98 rtexture_t *r_bloom_texture_screen;
99 rtexture_t *r_bloom_texture_bloom;
100 rtexture_t *r_texture_blanknormalmap;
101 rtexture_t *r_texture_white;
102 rtexture_t *r_texture_black;
103 rtexture_t *r_texture_notexture;
104 rtexture_t *r_texture_whitecube;
105 rtexture_t *r_texture_normalizationcube;
106 rtexture_t *r_texture_fogattenuation;
107 //rtexture_t *r_texture_fogintensity;
109 // information about each possible shader permutation
110 r_glsl_permutation_t r_glsl_permutations[SHADERPERMUTATION_COUNT];
111 // currently selected permutation
112 r_glsl_permutation_t *r_glsl_permutation;
114 // temporary variable used by a macro
117 extern void R_DrawModelShadows(void);
119 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
122 for (i = 0;i < verts;i++)
133 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
136 for (i = 0;i < verts;i++)
146 // FIXME: move this to client?
149 if (gamemode == GAME_NEHAHRA)
151 Cvar_Set("gl_fogenable", "0");
152 Cvar_Set("gl_fogdensity", "0.2");
153 Cvar_Set("gl_fogred", "0.3");
154 Cvar_Set("gl_foggreen", "0.3");
155 Cvar_Set("gl_fogblue", "0.3");
157 r_refdef.fog_density = r_refdef.fog_red = r_refdef.fog_green = r_refdef.fog_blue = 0.0f;
160 // FIXME: move this to client?
161 void FOG_registercvars(void)
166 if (gamemode == GAME_NEHAHRA)
168 Cvar_RegisterVariable (&gl_fogenable);
169 Cvar_RegisterVariable (&gl_fogdensity);
170 Cvar_RegisterVariable (&gl_fogred);
171 Cvar_RegisterVariable (&gl_foggreen);
172 Cvar_RegisterVariable (&gl_fogblue);
173 Cvar_RegisterVariable (&gl_fogstart);
174 Cvar_RegisterVariable (&gl_fogend);
177 r = (-1.0/256.0) * (FOGTABLEWIDTH * FOGTABLEWIDTH);
178 for (x = 0;x < FOGTABLEWIDTH;x++)
180 alpha = exp(r / ((double)x*(double)x));
181 if (x == FOGTABLEWIDTH - 1)
183 r_refdef.fogtable[x] = bound(0, alpha, 1);
187 static void R_BuildBlankTextures(void)
189 unsigned char data[4];
190 data[0] = 128; // normal X
191 data[1] = 128; // normal Y
192 data[2] = 255; // normal Z
193 data[3] = 128; // height
194 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
199 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
204 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
207 static void R_BuildNoTexture(void)
210 unsigned char pix[16][16][4];
211 // this makes a light grey/dark grey checkerboard texture
212 for (y = 0;y < 16;y++)
214 for (x = 0;x < 16;x++)
216 if ((y < 8) ^ (x < 8))
232 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_RGBA, TEXF_MIPMAP, NULL);
235 static void R_BuildWhiteCube(void)
237 unsigned char data[6*1*1*4];
238 data[ 0] = 255;data[ 1] = 255;data[ 2] = 255;data[ 3] = 255;
239 data[ 4] = 255;data[ 5] = 255;data[ 6] = 255;data[ 7] = 255;
240 data[ 8] = 255;data[ 9] = 255;data[10] = 255;data[11] = 255;
241 data[12] = 255;data[13] = 255;data[14] = 255;data[15] = 255;
242 data[16] = 255;data[17] = 255;data[18] = 255;data[19] = 255;
243 data[20] = 255;data[21] = 255;data[22] = 255;data[23] = 255;
244 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
247 static void R_BuildNormalizationCube(void)
251 vec_t s, t, intensity;
253 unsigned char data[6][NORMSIZE][NORMSIZE][4];
254 for (side = 0;side < 6;side++)
256 for (y = 0;y < NORMSIZE;y++)
258 for (x = 0;x < NORMSIZE;x++)
260 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
261 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
296 intensity = 127.0f / sqrt(DotProduct(v, v));
297 data[side][y][x][0] = (unsigned char)(128.0f + intensity * v[0]);
298 data[side][y][x][1] = (unsigned char)(128.0f + intensity * v[1]);
299 data[side][y][x][2] = (unsigned char)(128.0f + intensity * v[2]);
300 data[side][y][x][3] = 255;
304 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, &data[0][0][0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
307 static void R_BuildFogTexture(void)
312 unsigned char data1[FOGWIDTH][4];
313 //unsigned char data2[FOGWIDTH][4];
314 r = (-1.0/256.0) * (FOGWIDTH * FOGWIDTH);
315 for (x = 0;x < FOGWIDTH;x++)
317 alpha = exp(r / ((double)x*(double)x));
318 if (x == FOGWIDTH - 1)
320 b = (int)(256.0 * alpha);
321 b = bound(0, b, 255);
322 data1[x][0] = 255 - b;
323 data1[x][1] = 255 - b;
324 data1[x][2] = 255 - b;
331 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
332 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
335 static const char *builtinshaderstring =
336 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
337 "// written by Forest 'LordHavoc' Hale\n"
339 "// common definitions between vertex shader and fragment shader:\n"
341 "#ifdef __GLSL_CG_DATA_TYPES\n"
342 "#define myhalf half\n"
343 "#define myhvec2 hvec2\n"
344 "#define myhvec3 hvec3\n"
345 "#define myhvec4 hvec4\n"
347 "#define myhalf float\n"
348 "#define myhvec2 vec2\n"
349 "#define myhvec3 vec3\n"
350 "#define myhvec4 vec4\n"
353 "varying vec2 TexCoord;\n"
354 "varying vec2 TexCoordLightmap;\n"
356 "varying vec3 CubeVector;\n"
357 "varying vec3 LightVector;\n"
358 "varying vec3 EyeVector;\n"
360 "varying vec3 EyeVectorModelSpace;\n"
363 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
364 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
365 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
370 "// vertex shader specific:\n"
371 "#ifdef VERTEX_SHADER\n"
373 "uniform vec3 LightPosition;\n"
374 "uniform vec3 EyePosition;\n"
375 "uniform vec3 LightDir;\n"
377 "// TODO: get rid of tangentt (texcoord2) and use a crossproduct to regenerate it from tangents (texcoord1) and normal (texcoord3)\n"
381 " gl_FrontColor = gl_Color;\n"
382 " // copy the surface texcoord\n"
383 " TexCoord = vec2(gl_TextureMatrix[0] * gl_MultiTexCoord0);\n"
384 "#if !defined(MODE_LIGHTSOURCE) && !defined(MODE_LIGHTDIRECTION)\n"
385 " TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
388 "#ifdef MODE_LIGHTSOURCE\n"
389 " // transform vertex position into light attenuation/cubemap space\n"
390 " // (-1 to +1 across the light box)\n"
391 " CubeVector = vec3(gl_TextureMatrix[3] * gl_Vertex);\n"
393 " // transform unnormalized light direction into tangent space\n"
394 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
395 " // normalize it per pixel)\n"
396 " vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
397 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
398 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
399 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
402 "#ifdef MODE_LIGHTDIRECTION\n"
403 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
404 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
405 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
408 " // transform unnormalized eye direction into tangent space\n"
410 " vec3 EyeVectorModelSpace;\n"
412 " EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
413 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
414 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
415 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
417 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
418 " VectorS = gl_MultiTexCoord1.xyz;\n"
419 " VectorT = gl_MultiTexCoord2.xyz;\n"
420 " VectorR = gl_MultiTexCoord3.xyz;\n"
423 " // transform vertex to camera space, using ftransform to match non-VS\n"
425 " gl_Position = ftransform();\n"
428 "#endif // VERTEX_SHADER\n"
433 "// fragment shader specific:\n"
434 "#ifdef FRAGMENT_SHADER\n"
436 "uniform sampler2D Texture_Normal;\n"
437 "uniform sampler2D Texture_Color;\n"
438 "uniform sampler2D Texture_Gloss;\n"
439 "uniform samplerCube Texture_Cube;\n"
440 "uniform sampler2D Texture_FogMask;\n"
441 "uniform sampler2D Texture_Pants;\n"
442 "uniform sampler2D Texture_Shirt;\n"
443 "uniform sampler2D Texture_Lightmap;\n"
444 "uniform sampler2D Texture_Deluxemap;\n"
445 "uniform sampler2D Texture_Glow;\n"
447 "uniform myhvec3 LightColor;\n"
448 "uniform myhvec3 AmbientColor;\n"
449 "uniform myhvec3 DiffuseColor;\n"
450 "uniform myhvec3 SpecularColor;\n"
451 "uniform myhvec3 Color_Pants;\n"
452 "uniform myhvec3 Color_Shirt;\n"
453 "uniform myhvec3 FogColor;\n"
455 "uniform myhalf GlowScale;\n"
456 "uniform myhalf SceneBrightness;\n"
458 "uniform float OffsetMapping_Scale;\n"
459 "uniform float OffsetMapping_Bias;\n"
460 "uniform float FogRangeRecip;\n"
462 "uniform myhalf AmbientScale;\n"
463 "uniform myhalf DiffuseScale;\n"
464 "uniform myhalf SpecularScale;\n"
465 "uniform myhalf SpecularPower;\n"
469 " // apply offsetmapping\n"
470 "#ifdef USEOFFSETMAPPING\n"
471 " vec2 TexCoordOffset = TexCoord;\n"
472 "#define TexCoord TexCoordOffset\n"
474 " vec3 eyedir = vec3(normalize(EyeVector));\n"
475 " float depthbias = 1.0 - eyedir.z; // should this be a -?\n"
476 " depthbias = 1.0 - depthbias * depthbias;\n"
478 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
479 " // 14 sample relief mapping: linear search and then binary search\n"
480 " //vec3 OffsetVector = vec3(EyeVector.xy * (1.0 / EyeVector.z) * depthbias * OffsetMapping_Scale * vec2(-0.1, 0.1), -0.1);\n"
481 " //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-0.1, 0.1), -0.1);\n"
482 " vec3 OffsetVector = vec3(eyedir.xy * OffsetMapping_Scale * vec2(-0.1, 0.1), -0.1);\n"
483 " vec3 RT = vec3(TexCoord - OffsetVector.xy * 10.0, 1.0) + 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;\n"
489 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
490 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
491 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) 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 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;OffsetVector *= 0.5;RT -= OffsetVector;\n"
495 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;OffsetVector *= 0.5;RT -= OffsetVector;\n"
496 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;OffsetVector *= 0.5;RT -= OffsetVector;\n"
497 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;OffsetVector *= 0.5;RT -= OffsetVector;\n"
498 " TexCoord = RT.xy;\n"
500 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
501 " //vec2 OffsetVector = vec2(EyeVector.xy * (1.0 / EyeVector.z) * depthbias) * OffsetMapping_Scale * vec2(-0.333, 0.333);\n"
502 " //vec2 OffsetVector = vec2(normalize(EyeVector.xy)) * OffsetMapping_Scale * vec2(-0.333, 0.333);\n"
503 " vec2 OffsetVector = vec2(eyedir.xy) * OffsetMapping_Scale * vec2(-0.333, 0.333);\n"
504 " //TexCoord += OffsetVector * 3.0;\n"
505 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
506 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
507 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
509 " // 10 sample offset mapping\n"
510 " //vec2 OffsetVector = vec2(EyeVector.xy * (1.0 / EyeVector.z) * depthbias) * OffsetMapping_Scale * vec2(-0.333, 0.333);\n"
511 " //vec2 OffsetVector = vec2(normalize(EyeVector.xy)) * OffsetMapping_Scale * vec2(-0.333, 0.333);\n"
512 " vec2 OffsetVector = vec2(eyedir.xy) * OffsetMapping_Scale * vec2(-0.1, 0.1);\n"
513 " //TexCoord += OffsetVector * 3.0;\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"
520 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
521 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
522 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
523 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
525 " // parallax mapping as described in the paper\n"
526 " // 'Parallax Mapping with Offset Limiting: A Per-Pixel Approximation of Uneven Surfaces' by Terry Welsh\n"
527 " // The paper provides code in the ARB fragment program assembly language\n"
528 " // I translated it to GLSL but may have done something wrong - SavageX\n"
529 " // LordHavoc: removed bias and simplified to one line\n"
530 " // LordHavoc: this is just a single sample offsetmapping...\n"
531 " TexCoordOffset += vec2(eyedir.x, -1.0 * eyedir.y) * OffsetMapping_Scale * texture2D(Texture_Normal, TexCoord).a;\n"
533 " // parallax mapping as described in the paper\n"
534 " // 'Parallax Mapping with Offset Limiting: A Per-Pixel Approximation of Uneven Surfaces' by Terry Welsh\n"
535 " // The paper provides code in the ARB fragment program assembly language\n"
536 " // I translated it to GLSL but may have done something wrong - SavageX\n"
537 " float height = texture2D(Texture_Normal, TexCoord).a;\n"
538 " height = (height - 0.5) * OffsetMapping_Scale; // bias and scale\n"
539 " TexCoordOffset += height * vec2(eyedir.x, -1.0 * eyedir.y);\n"
543 " // combine the diffuse textures (base, pants, shirt)\n"
544 " myhvec4 color = myhvec4(texture2D(Texture_Color, TexCoord));\n"
545 "#ifdef USECOLORMAPPING\n"
546 " color.rgb += myhvec3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhvec3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
552 "#ifdef MODE_LIGHTSOURCE\n"
555 " // get the surface normal and light normal\n"
556 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
557 " myhvec3 diffusenormal = myhvec3(normalize(LightVector));\n"
559 " // calculate directional shading\n"
560 " color.rgb *= AmbientScale + DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
561 "#ifdef USESPECULAR\n"
562 " myhvec3 specularnormal = normalize(diffusenormal + myhvec3(normalize(EyeVector)));\n"
563 " color.rgb += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
566 "#ifdef USECUBEFILTER\n"
567 " // apply light cubemap filter\n"
568 " //color.rgb *= normalize(CubeVector) * 0.5 + 0.5;//vec3(textureCube(Texture_Cube, CubeVector));\n"
569 " color.rgb *= myhvec3(textureCube(Texture_Cube, CubeVector));\n"
572 " // apply light color\n"
573 " color.rgb *= LightColor;\n"
575 " // apply attenuation\n"
577 " // the attenuation is (1-(x*x+y*y+z*z)) which gives a large bright\n"
578 " // center and sharp falloff at the edge, this is about the most efficient\n"
579 " // we can get away with as far as providing illumination.\n"
581 " // pow(1-(x*x+y*y+z*z), 4) is far more realistic but needs large lights to\n"
582 " // provide significant illumination, large = slow = pain.\n"
583 " color.rgb *= myhalf(max(1.0 - dot(CubeVector, CubeVector), 0.0));\n"
588 "#elif defined(MODE_LIGHTDIRECTION)\n"
589 " // directional model lighting\n"
591 " // get the surface normal and light normal\n"
592 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
593 " myhvec3 diffusenormal = myhvec3(normalize(LightVector));\n"
595 " // calculate directional shading\n"
596 " color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
597 "#ifdef USESPECULAR\n"
598 " myhvec3 specularnormal = normalize(diffusenormal + myhvec3(normalize(EyeVector)));\n"
599 " color.rgb += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
605 "#elif defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
606 " // deluxemap lightmapping using light vectors in modelspace (evil q3map2)\n"
608 " // get the surface normal and light normal\n"
609 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
611 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
612 " myhvec3 diffusenormal_modelspace = myhvec3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - myhvec3(0.5);\n"
613 " myhvec3 diffusenormal = normalize(myhvec3(dot(diffusenormal_modelspace, myhvec3(VectorS)), dot(diffusenormal_modelspace, myhvec3(VectorT)), dot(diffusenormal_modelspace, myhvec3(VectorR))));\n"
615 " myhvec3 diffusenormal = normalize(myhvec3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - myhvec3(0.5));\n"
617 " // calculate directional shading\n"
618 " myhvec3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0)));\n"
619 "#ifdef USESPECULAR\n"
620 " myhvec3 specularnormal = myhvec3(normalize(diffusenormal + myhvec3(normalize(EyeVector))));\n"
621 " tempcolor += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
624 " // apply lightmap color\n"
625 " color.rgb = tempcolor * myhvec3(texture2D(Texture_Lightmap, TexCoordLightmap)) + color.rgb * AmbientScale;\n"
628 "#else // MODE none (lightmap)\n"
629 " // apply lightmap color\n"
630 " color.rgb *= myhvec3(texture2D(Texture_Lightmap, TexCoordLightmap)) * DiffuseScale + myhvec3(AmbientScale);\n"
633 " color *= myhvec4(gl_Color);\n"
636 " color.rgb += myhvec3(texture2D(Texture_Glow, TexCoord)) * GlowScale;\n"
641 " myhalf fog = myhalf(texture2D(Texture_FogMask, myhvec2(length(EyeVectorModelSpace)*FogRangeRecip, 0.0)).x);\n"
642 " color.rgb = color.rgb * fog + FogColor * (1.0 - fog);\n"
645 " color.rgb *= SceneBrightness;\n"
647 " gl_FragColor = vec4(color);\n"
650 "#endif // FRAGMENT_SHADER\n"
653 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
654 const char *permutationinfo[][2] =
656 {"#define MODE_LIGHTSOURCE\n", " lightsource"},
657 {"#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
658 {"#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
659 {"#define MODE_LIGHTDIRECTION\n", " lightdirection"},
660 {"#define USEGLOW\n", " glow"},
661 {"#define USEFOG\n", " fog"},
662 {"#define USECOLORMAPPING\n", " colormapping"},
663 {"#define USESPECULAR\n", " specular"},
664 {"#define USECUBEFILTER\n", " cubefilter"},
665 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
666 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
670 void R_GLSL_CompilePermutation(int permutation)
673 r_glsl_permutation_t *p = r_glsl_permutations + permutation;
674 int vertstrings_count;
675 int fragstrings_count;
677 const char *vertstrings_list[SHADERPERMUTATION_COUNT+1];
678 const char *fragstrings_list[SHADERPERMUTATION_COUNT+1];
679 char permutationname[256];
683 vertstrings_list[0] = "#define VERTEX_SHADER\n";
684 fragstrings_list[0] = "#define FRAGMENT_SHADER\n";
685 vertstrings_count = 1;
686 fragstrings_count = 1;
687 permutationname[0] = 0;
688 for (i = 0;permutationinfo[i][0];i++)
690 if (permutation & (1<<i))
692 vertstrings_list[vertstrings_count++] = permutationinfo[i][0];
693 fragstrings_list[fragstrings_count++] = permutationinfo[i][0];
694 strlcat(permutationname, permutationinfo[i][1], sizeof(permutationname));
698 // keep line numbers correct
699 vertstrings_list[vertstrings_count++] = "\n";
700 fragstrings_list[fragstrings_count++] = "\n";
703 shaderstring = (char *)FS_LoadFile("glsl/default.glsl", r_main_mempool, false, NULL);
706 Con_DPrintf("GLSL shader text loaded from disk\n");
707 vertstrings_list[vertstrings_count++] = shaderstring;
708 fragstrings_list[fragstrings_count++] = shaderstring;
712 vertstrings_list[vertstrings_count++] = builtinshaderstring;
713 fragstrings_list[fragstrings_count++] = builtinshaderstring;
715 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, fragstrings_count, fragstrings_list);
719 qglUseProgramObjectARB(p->program);CHECKGLERROR
720 p->loc_Texture_Normal = qglGetUniformLocationARB(p->program, "Texture_Normal");
721 p->loc_Texture_Color = qglGetUniformLocationARB(p->program, "Texture_Color");
722 p->loc_Texture_Gloss = qglGetUniformLocationARB(p->program, "Texture_Gloss");
723 p->loc_Texture_Cube = qglGetUniformLocationARB(p->program, "Texture_Cube");
724 p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
725 p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
726 p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
727 p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
728 p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
729 p->loc_Texture_Glow = qglGetUniformLocationARB(p->program, "Texture_Glow");
730 p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
731 p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
732 p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
733 p->loc_LightColor = qglGetUniformLocationARB(p->program, "LightColor");
734 p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants");
735 p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt");
736 p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip");
737 p->loc_AmbientScale = qglGetUniformLocationARB(p->program, "AmbientScale");
738 p->loc_DiffuseScale = qglGetUniformLocationARB(p->program, "DiffuseScale");
739 p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
740 p->loc_SpecularScale = qglGetUniformLocationARB(p->program, "SpecularScale");
741 p->loc_GlowScale = qglGetUniformLocationARB(p->program, "GlowScale");
742 p->loc_SceneBrightness = qglGetUniformLocationARB(p->program, "SceneBrightness");
743 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
744 p->loc_AmbientColor = qglGetUniformLocationARB(p->program, "AmbientColor");
745 p->loc_DiffuseColor = qglGetUniformLocationARB(p->program, "DiffuseColor");
746 p->loc_SpecularColor = qglGetUniformLocationARB(p->program, "SpecularColor");
747 p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
748 if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal, 0);
749 if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color, 1);
750 if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss, 2);
751 if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube, 3);
752 if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask, 4);
753 if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants, 5);
754 if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt, 6);
755 if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap, 7);
756 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap, 8);
757 if (p->loc_Texture_Glow >= 0) qglUniform1iARB(p->loc_Texture_Glow, 9);
759 qglUseProgramObjectARB(0);CHECKGLERROR
762 Con_Printf("permutation%s failed for shader %s, some features may not work properly!\n", permutationname, "glsl/default.glsl");
764 Mem_Free(shaderstring);
767 void R_GLSL_Restart_f(void)
770 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
771 if (r_glsl_permutations[i].program)
772 GL_Backend_FreeProgram(r_glsl_permutations[i].program);
773 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
776 int R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting)
778 // select a permutation of the lighting shader appropriate to this
779 // combination of texture, entity, light source, and fogging, only use the
780 // minimum features necessary to avoid wasting rendering time in the
781 // fragment shader on features that are not being used
783 float specularscale = rsurface_texture->specularscale;
784 r_glsl_permutation = NULL;
785 if (r_shadow_rtlight)
787 permutation |= SHADERPERMUTATION_MODE_LIGHTSOURCE;
788 specularscale *= r_shadow_rtlight->specularscale;
789 if (r_shadow_rtlight->currentcubemap != r_texture_whitecube)
790 permutation |= SHADERPERMUTATION_CUBEFILTER;
794 if (!(rsurface_texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
797 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTION;
798 else if (r_glsl_deluxemapping.integer >= 1 && rsurface_lightmaptexture)
800 if (r_refdef.worldmodel && r_refdef.worldmodel->brushq3.deluxemapping)
802 if (r_refdef.worldmodel->brushq3.deluxemapping_modelspace)
803 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_MODELSPACE;
805 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
807 else if (r_glsl_deluxemapping.integer >= 2) // fake mode
808 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
811 if (rsurface_texture->currentskinframe->glow)
812 permutation |= SHADERPERMUTATION_GLOW;
814 if (specularscale > 0)
815 permutation |= SHADERPERMUTATION_SPECULAR;
816 if (r_refdef.fogenabled)
817 permutation |= SHADERPERMUTATION_FOG;
818 if (rsurface_texture->colormapping)
819 permutation |= SHADERPERMUTATION_COLORMAPPING;
820 if (r_glsl_offsetmapping.integer)
822 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
823 if (r_glsl_offsetmapping_reliefmapping.integer)
824 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
826 if (!r_glsl_permutations[permutation].program)
828 if (!r_glsl_permutations[permutation].compiled)
829 R_GLSL_CompilePermutation(permutation);
830 if (!r_glsl_permutations[permutation].program)
832 // remove features until we find a valid permutation
834 for (i = SHADERPERMUTATION_COUNT-1;;i>>=1)
836 // reduce i more quickly whenever it would not remove any bits
840 if (!r_glsl_permutations[permutation].compiled)
841 R_GLSL_CompilePermutation(permutation);
842 if (r_glsl_permutations[permutation].program)
845 return 0; // utterly failed
849 r_glsl_permutation = r_glsl_permutations + permutation;
851 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
852 R_Mesh_TexMatrix(0, &rsurface_texture->currenttexmatrix);
853 if (permutation & SHADERPERMUTATION_MODE_LIGHTSOURCE)
855 if (r_glsl_permutation->loc_Texture_Cube >= 0 && r_shadow_rtlight) R_Mesh_TexBindCubeMap(3, R_GetTexture(r_shadow_rtlight->currentcubemap));
856 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]);
857 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
858 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_shadow_rtlight->ambientscale);
859 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_shadow_rtlight->diffusescale);
860 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, specularscale);
862 else if (permutation & SHADERPERMUTATION_MODE_LIGHTDIRECTION)
864 if (r_glsl_permutation->loc_AmbientColor >= 0)
865 qglUniform3fARB(r_glsl_permutation->loc_AmbientColor, rsurface_entity->modellight_ambient[0], rsurface_entity->modellight_ambient[1], rsurface_entity->modellight_ambient[2]);
866 if (r_glsl_permutation->loc_DiffuseColor >= 0)
867 qglUniform3fARB(r_glsl_permutation->loc_DiffuseColor, rsurface_entity->modellight_diffuse[0], rsurface_entity->modellight_diffuse[1], rsurface_entity->modellight_diffuse[2]);
868 if (r_glsl_permutation->loc_SpecularColor >= 0)
869 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);
870 if (r_glsl_permutation->loc_LightDir >= 0)
871 qglUniform3fARB(r_glsl_permutation->loc_LightDir, rsurface_entity->modellight_lightdir[0], rsurface_entity->modellight_lightdir[1], rsurface_entity->modellight_lightdir[2]);
875 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_ambient.value * 2.0f / 128.0f);
876 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_refdef.lightmapintensity * 2.0f);
877 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, r_refdef.lightmapintensity * specularscale * 2.0f);
879 if (r_glsl_permutation->loc_Texture_Normal >= 0) R_Mesh_TexBind(0, R_GetTexture(rsurface_texture->currentskinframe->nmap));
880 if (r_glsl_permutation->loc_Texture_Color >= 0) R_Mesh_TexBind(1, R_GetTexture(rsurface_texture->basetexture));
881 if (r_glsl_permutation->loc_Texture_Gloss >= 0) R_Mesh_TexBind(2, R_GetTexture(rsurface_texture->glosstexture));
882 //if (r_glsl_permutation->loc_Texture_Cube >= 0 && permutation & SHADERPERMUTATION_MODE_LIGHTSOURCE) R_Mesh_TexBindCubeMap(3, R_GetTexture(r_shadow_rtlight->currentcubemap));
883 if (r_glsl_permutation->loc_Texture_FogMask >= 0) R_Mesh_TexBind(4, R_GetTexture(r_texture_fogattenuation));
884 if (r_glsl_permutation->loc_Texture_Pants >= 0) R_Mesh_TexBind(5, R_GetTexture(rsurface_texture->currentskinframe->pants));
885 if (r_glsl_permutation->loc_Texture_Shirt >= 0) R_Mesh_TexBind(6, R_GetTexture(rsurface_texture->currentskinframe->shirt));
886 //if (r_glsl_permutation->loc_Texture_Lightmap >= 0) R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
887 //if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
888 if (r_glsl_permutation->loc_Texture_Glow >= 0) R_Mesh_TexBind(9, R_GetTexture(rsurface_texture->currentskinframe->glow));
889 if (r_glsl_permutation->loc_GlowScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_GlowScale, r_hdr_glowintensity.value);
890 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_view.colorscale);
891 if (r_glsl_permutation->loc_FogColor >= 0)
893 // additive passes are only darkened by fog, not tinted
894 if (r_shadow_rtlight || (rsurface_texture->currentmaterialflags & MATERIALFLAG_ADD))
895 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
897 qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
899 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface_modelorg[0], rsurface_modelorg[1], rsurface_modelorg[2]);
900 if (r_glsl_permutation->loc_Color_Pants >= 0)
902 if (rsurface_texture->currentskinframe->pants)
903 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface_entity->colormap_pantscolor[0], rsurface_entity->colormap_pantscolor[1], rsurface_entity->colormap_pantscolor[2]);
905 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
907 if (r_glsl_permutation->loc_Color_Shirt >= 0)
909 if (rsurface_texture->currentskinframe->shirt)
910 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface_entity->colormap_shirtcolor[0], rsurface_entity->colormap_shirtcolor[1], rsurface_entity->colormap_shirtcolor[2]);
912 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
914 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, r_refdef.fograngerecip);
915 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface_texture->specularpower);
916 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
921 void R_SwitchSurfaceShader(int permutation)
923 if (r_glsl_permutation != r_glsl_permutations + permutation)
925 r_glsl_permutation = r_glsl_permutations + permutation;
927 qglUseProgramObjectARB(r_glsl_permutation->program);
932 void gl_main_start(void)
934 r_main_texturepool = R_AllocTexturePool();
935 r_bloom_texture_screen = NULL;
936 r_bloom_texture_bloom = NULL;
937 R_BuildBlankTextures();
939 if (gl_texturecubemap)
942 R_BuildNormalizationCube();
945 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
948 void gl_main_shutdown(void)
950 R_FreeTexturePool(&r_main_texturepool);
951 r_bloom_texture_screen = NULL;
952 r_bloom_texture_bloom = NULL;
953 r_texture_blanknormalmap = NULL;
954 r_texture_white = NULL;
955 r_texture_black = NULL;
956 r_texture_whitecube = NULL;
957 r_texture_normalizationcube = NULL;
961 extern void CL_ParseEntityLump(char *entitystring);
962 void gl_main_newmap(void)
964 // FIXME: move this code to client
966 char *entities, entname[MAX_QPATH];
969 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
970 l = (int)strlen(entname) - 4;
971 if (l >= 0 && !strcmp(entname + l, ".bsp"))
973 memcpy(entname + l, ".ent", 5);
974 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
976 CL_ParseEntityLump(entities);
981 if (cl.worldmodel->brush.entities)
982 CL_ParseEntityLump(cl.worldmodel->brush.entities);
986 void GL_Main_Init(void)
988 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
990 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed\n");
991 FOG_registercvars(); // FIXME: move this fog stuff to client?
992 Cvar_RegisterVariable(&r_nearclip);
993 Cvar_RegisterVariable(&r_showsurfaces);
994 Cvar_RegisterVariable(&r_showtris);
995 Cvar_RegisterVariable(&r_shownormals);
996 Cvar_RegisterVariable(&r_showlighting);
997 Cvar_RegisterVariable(&r_showshadowvolumes);
998 Cvar_RegisterVariable(&r_showcollisionbrushes);
999 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
1000 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
1001 Cvar_RegisterVariable(&r_showdisabledepthtest);
1002 Cvar_RegisterVariable(&r_drawportals);
1003 Cvar_RegisterVariable(&r_drawentities);
1004 Cvar_RegisterVariable(&r_drawviewmodel);
1005 Cvar_RegisterVariable(&r_speeds);
1006 Cvar_RegisterVariable(&r_fullbrights);
1007 Cvar_RegisterVariable(&r_wateralpha);
1008 Cvar_RegisterVariable(&r_dynamic);
1009 Cvar_RegisterVariable(&r_fullbright);
1010 Cvar_RegisterVariable(&r_shadows);
1011 Cvar_RegisterVariable(&r_shadows_throwdistance);
1012 Cvar_RegisterVariable(&r_q1bsp_skymasking);
1013 Cvar_RegisterVariable(&r_textureunits);
1014 Cvar_RegisterVariable(&r_glsl);
1015 Cvar_RegisterVariable(&r_glsl_offsetmapping);
1016 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
1017 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
1018 Cvar_RegisterVariable(&r_glsl_deluxemapping);
1019 Cvar_RegisterVariable(&r_lerpsprites);
1020 Cvar_RegisterVariable(&r_lerpmodels);
1021 Cvar_RegisterVariable(&r_waterscroll);
1022 Cvar_RegisterVariable(&r_bloom);
1023 Cvar_RegisterVariable(&r_bloom_intensity);
1024 Cvar_RegisterVariable(&r_bloom_blur);
1025 Cvar_RegisterVariable(&r_bloom_resolution);
1026 Cvar_RegisterVariable(&r_bloom_power);
1027 Cvar_RegisterVariable(&r_hdr);
1028 Cvar_RegisterVariable(&r_hdr_scenebrightness);
1029 Cvar_RegisterVariable(&r_hdr_bloomintensity);
1030 Cvar_RegisterVariable(&r_hdr_glowintensity);
1031 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
1032 Cvar_RegisterVariable(&developer_texturelogging);
1033 Cvar_RegisterVariable(&gl_lightmaps);
1034 Cvar_RegisterVariable(&r_test);
1035 Cvar_RegisterVariable(&r_batchmode);
1036 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
1037 Cvar_SetValue("r_fullbrights", 0);
1038 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
1041 extern void R_Textures_Init(void);
1042 extern void GL_Draw_Init(void);
1043 extern void GL_Main_Init(void);
1044 extern void R_Shadow_Init(void);
1045 extern void R_Sky_Init(void);
1046 extern void GL_Surf_Init(void);
1047 extern void R_Light_Init(void);
1048 extern void R_Particles_Init(void);
1049 extern void R_Explosion_Init(void);
1050 extern void gl_backend_init(void);
1051 extern void Sbar_Init(void);
1052 extern void R_LightningBeams_Init(void);
1053 extern void Mod_RenderInit(void);
1055 void Render_Init(void)
1068 R_LightningBeams_Init();
1077 extern char *ENGINE_EXTENSIONS;
1080 VID_CheckExtensions();
1082 // LordHavoc: report supported extensions
1083 Con_DPrintf("\nengine extensions: %s\n", vm_sv_extensions );
1085 // clear to black (loading plaque will be seen over this)
1087 qglClearColor(0,0,0,1);CHECKGLERROR
1088 qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
1091 int R_CullBox(const vec3_t mins, const vec3_t maxs)
1095 for (i = 0;i < 4;i++)
1097 p = r_view.frustum + i;
1102 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1106 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1110 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1114 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1118 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1122 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1126 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1130 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1138 //==================================================================================
1140 static void R_UpdateEntityLighting(entity_render_t *ent)
1142 vec3_t tempdiffusenormal;
1144 // fetch the lighting from the worldmodel data
1145 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));
1146 VectorClear(ent->modellight_diffuse);
1147 VectorClear(tempdiffusenormal);
1148 if ((ent->flags & RENDER_LIGHT) && r_refdef.worldmodel && r_refdef.worldmodel->brush.LightPoint)
1151 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
1152 r_refdef.worldmodel->brush.LightPoint(r_refdef.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
1155 VectorSet(ent->modellight_ambient, 1, 1, 1);
1157 // move the light direction into modelspace coordinates for lighting code
1158 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
1159 VectorNormalize(ent->modellight_lightdir);
1161 // scale ambient and directional light contributions according to rendering variables
1162 ent->modellight_ambient[0] *= ent->colormod[0] * r_refdef.lightmapintensity;
1163 ent->modellight_ambient[1] *= ent->colormod[1] * r_refdef.lightmapintensity;
1164 ent->modellight_ambient[2] *= ent->colormod[2] * r_refdef.lightmapintensity;
1165 ent->modellight_diffuse[0] *= ent->colormod[0] * r_refdef.lightmapintensity;
1166 ent->modellight_diffuse[1] *= ent->colormod[1] * r_refdef.lightmapintensity;
1167 ent->modellight_diffuse[2] *= ent->colormod[2] * r_refdef.lightmapintensity;
1170 static void R_View_UpdateEntityVisible (void)
1173 entity_render_t *ent;
1175 if (!r_drawentities.integer)
1178 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : (chase_active.integer ? 0 : RENDER_EXTERIORMODEL);
1179 if (r_refdef.worldmodel && r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs)
1181 // worldmodel can check visibility
1182 for (i = 0;i < r_refdef.numentities;i++)
1184 ent = r_refdef.entities[i];
1185 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));
1190 // no worldmodel or it can't check visibility
1191 for (i = 0;i < r_refdef.numentities;i++)
1193 ent = r_refdef.entities[i];
1194 r_viewcache.entityvisible[i] = !(ent->flags & renderimask) && !R_CullBox(ent->mins, ent->maxs);
1198 // update entity lighting (even on hidden entities for r_shadows)
1199 for (i = 0;i < r_refdef.numentities;i++)
1200 R_UpdateEntityLighting(r_refdef.entities[i]);
1203 // only used if skyrendermasked, and normally returns false
1204 int R_DrawBrushModelsSky (void)
1207 entity_render_t *ent;
1209 if (!r_drawentities.integer)
1213 for (i = 0;i < r_refdef.numentities;i++)
1215 if (!r_viewcache.entityvisible[i])
1217 ent = r_refdef.entities[i];
1218 if (!ent->model || !ent->model->DrawSky)
1220 ent->model->DrawSky(ent);
1226 void R_DrawNoModel(entity_render_t *ent);
1227 void R_DrawModels(void)
1230 entity_render_t *ent;
1232 if (!r_drawentities.integer)
1235 for (i = 0;i < r_refdef.numentities;i++)
1237 if (!r_viewcache.entityvisible[i])
1239 ent = r_refdef.entities[i];
1240 r_refdef.stats.entities++;
1241 if (ent->model && ent->model->Draw != NULL)
1242 ent->model->Draw(ent);
1248 static void R_View_SetFrustum(void)
1250 // break apart the view matrix into vectors for various purposes
1251 Matrix4x4_ToVectors(&r_view.matrix, r_view.forward, r_view.left, r_view.up, r_view.origin);
1252 VectorNegate(r_view.left, r_view.right);
1255 r_view.frustum[0].normal[0] = 0 - 1.0 / r_view.frustum_x;
1256 r_view.frustum[0].normal[1] = 0 - 0;
1257 r_view.frustum[0].normal[2] = -1 - 0;
1258 r_view.frustum[1].normal[0] = 0 + 1.0 / r_view.frustum_x;
1259 r_view.frustum[1].normal[1] = 0 + 0;
1260 r_view.frustum[1].normal[2] = -1 + 0;
1261 r_view.frustum[2].normal[0] = 0 - 0;
1262 r_view.frustum[2].normal[1] = 0 - 1.0 / r_view.frustum_y;
1263 r_view.frustum[2].normal[2] = -1 - 0;
1264 r_view.frustum[3].normal[0] = 0 + 0;
1265 r_view.frustum[3].normal[1] = 0 + 1.0 / r_view.frustum_y;
1266 r_view.frustum[3].normal[2] = -1 + 0;
1270 zNear = r_refdef.nearclip;
1271 nudge = 1.0 - 1.0 / (1<<23);
1272 r_view.frustum[4].normal[0] = 0 - 0;
1273 r_view.frustum[4].normal[1] = 0 - 0;
1274 r_view.frustum[4].normal[2] = -1 - -nudge;
1275 r_view.frustum[4].dist = 0 - -2 * zNear * nudge;
1276 r_view.frustum[5].normal[0] = 0 + 0;
1277 r_view.frustum[5].normal[1] = 0 + 0;
1278 r_view.frustum[5].normal[2] = -1 + -nudge;
1279 r_view.frustum[5].dist = 0 + -2 * zNear * nudge;
1285 r_view.frustum[0].normal[0] = m[3] - m[0];
1286 r_view.frustum[0].normal[1] = m[7] - m[4];
1287 r_view.frustum[0].normal[2] = m[11] - m[8];
1288 r_view.frustum[0].dist = m[15] - m[12];
1290 r_view.frustum[1].normal[0] = m[3] + m[0];
1291 r_view.frustum[1].normal[1] = m[7] + m[4];
1292 r_view.frustum[1].normal[2] = m[11] + m[8];
1293 r_view.frustum[1].dist = m[15] + m[12];
1295 r_view.frustum[2].normal[0] = m[3] - m[1];
1296 r_view.frustum[2].normal[1] = m[7] - m[5];
1297 r_view.frustum[2].normal[2] = m[11] - m[9];
1298 r_view.frustum[2].dist = m[15] - m[13];
1300 r_view.frustum[3].normal[0] = m[3] + m[1];
1301 r_view.frustum[3].normal[1] = m[7] + m[5];
1302 r_view.frustum[3].normal[2] = m[11] + m[9];
1303 r_view.frustum[3].dist = m[15] + m[13];
1305 r_view.frustum[4].normal[0] = m[3] - m[2];
1306 r_view.frustum[4].normal[1] = m[7] - m[6];
1307 r_view.frustum[4].normal[2] = m[11] - m[10];
1308 r_view.frustum[4].dist = m[15] - m[14];
1310 r_view.frustum[5].normal[0] = m[3] + m[2];
1311 r_view.frustum[5].normal[1] = m[7] + m[6];
1312 r_view.frustum[5].normal[2] = m[11] + m[10];
1313 r_view.frustum[5].dist = m[15] + m[14];
1318 VectorMAM(1, r_view.forward, 1.0 / -r_view.frustum_x, r_view.left, r_view.frustum[0].normal);
1319 VectorMAM(1, r_view.forward, 1.0 / r_view.frustum_x, r_view.left, r_view.frustum[1].normal);
1320 VectorMAM(1, r_view.forward, 1.0 / -r_view.frustum_y, r_view.up, r_view.frustum[2].normal);
1321 VectorMAM(1, r_view.forward, 1.0 / r_view.frustum_y, r_view.up, r_view.frustum[3].normal);
1322 VectorCopy(r_view.forward, r_view.frustum[4].normal);
1323 VectorNormalize(r_view.frustum[0].normal);
1324 VectorNormalize(r_view.frustum[1].normal);
1325 VectorNormalize(r_view.frustum[2].normal);
1326 VectorNormalize(r_view.frustum[3].normal);
1327 r_view.frustum[0].dist = DotProduct (r_view.origin, r_view.frustum[0].normal);
1328 r_view.frustum[1].dist = DotProduct (r_view.origin, r_view.frustum[1].normal);
1329 r_view.frustum[2].dist = DotProduct (r_view.origin, r_view.frustum[2].normal);
1330 r_view.frustum[3].dist = DotProduct (r_view.origin, r_view.frustum[3].normal);
1331 r_view.frustum[4].dist = DotProduct (r_view.origin, r_view.frustum[4].normal) + r_refdef.nearclip;
1332 PlaneClassify(&r_view.frustum[0]);
1333 PlaneClassify(&r_view.frustum[1]);
1334 PlaneClassify(&r_view.frustum[2]);
1335 PlaneClassify(&r_view.frustum[3]);
1336 PlaneClassify(&r_view.frustum[4]);
1338 // LordHavoc: note to all quake engine coders, Quake had a special case
1339 // for 90 degrees which assumed a square view (wrong), so I removed it,
1340 // Quake2 has it disabled as well.
1342 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
1343 //RotatePointAroundVector( r_view.frustum[0].normal, r_view.up, r_view.forward, -(90 - r_refdef.fov_x / 2));
1344 //r_view.frustum[0].dist = DotProduct (r_view.origin, frustum[0].normal);
1345 //PlaneClassify(&frustum[0]);
1347 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
1348 //RotatePointAroundVector( r_view.frustum[1].normal, r_view.up, r_view.forward, (90 - r_refdef.fov_x / 2));
1349 //r_view.frustum[1].dist = DotProduct (r_view.origin, frustum[1].normal);
1350 //PlaneClassify(&frustum[1]);
1352 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
1353 //RotatePointAroundVector( r_view.frustum[2].normal, r_view.left, r_view.forward, -(90 - r_refdef.fov_y / 2));
1354 //r_view.frustum[2].dist = DotProduct (r_view.origin, frustum[2].normal);
1355 //PlaneClassify(&frustum[2]);
1357 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
1358 //RotatePointAroundVector( r_view.frustum[3].normal, r_view.left, r_view.forward, (90 - r_refdef.fov_y / 2));
1359 //r_view.frustum[3].dist = DotProduct (r_view.origin, frustum[3].normal);
1360 //PlaneClassify(&frustum[3]);
1363 //VectorCopy(r_view.forward, r_view.frustum[4].normal);
1364 //r_view.frustum[4].dist = DotProduct (r_view.origin, frustum[4].normal) + r_nearclip.value;
1365 //PlaneClassify(&frustum[4]);
1368 void R_View_Update(void)
1370 R_View_SetFrustum();
1371 R_View_WorldVisibility();
1372 R_View_UpdateEntityVisible();
1375 void R_ResetViewRendering(void)
1377 if (gl_support_fragment_shader)
1379 qglUseProgramObjectARB(0);CHECKGLERROR
1382 // GL is weird because it's bottom to top, r_view.y is top to bottom
1383 qglViewport(r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
1384 GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
1385 GL_Scissor(r_view.x, r_view.y, r_view.width, r_view.height);
1386 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
1387 GL_ScissorTest(true);
1390 R_Mesh_Matrix(&identitymatrix);
1391 R_Mesh_ResetTextureState();
1394 void R_SetupView(const matrix4x4_t *matrix)
1396 if (r_refdef.rtworldshadows || r_refdef.rtdlightshadows)
1397 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_view.frustum_x, r_view.frustum_y, r_refdef.nearclip);
1399 GL_SetupView_Mode_Perspective(r_view.frustum_x, r_view.frustum_y, r_refdef.nearclip, r_refdef.farclip);
1401 GL_SetupView_Orientation_FromEntity(matrix);
1404 void R_RenderScene(void);
1406 void R_Bloom_MakeTexture(qboolean darken)
1408 int screenwidth, screenheight;
1409 int screentexturewidth, screentextureheight;
1410 int bloomtexturewidth, bloomtextureheight;
1411 int bloomwidth, bloomheight, x, range;
1412 float xoffset, yoffset, r;
1414 float texcoord2f[3][8];
1416 // set bloomwidth and bloomheight to the bloom resolution that will be
1417 // used (often less than the screen resolution for faster rendering)
1418 bloomwidth = bound(1, r_bloom_resolution.integer, r_view.width);
1419 bloomheight = bound(1, bloomwidth * r_view.height / r_view.width, r_view.height);
1421 // set the (poorly named) screenwidth and screenheight variables to
1422 // a power of 2 at least as large as the screen, these will define the
1423 // size of the texture to allocate
1424 for (screenwidth = 1;screenwidth < vid.width;screenwidth *= 2);
1425 for (screenheight = 1;screenheight < vid.height;screenheight *= 2);
1427 r_refdef.stats.bloom++;
1429 // allocate textures as needed
1430 // TODO: reallocate these when size settings change
1431 if (!r_bloom_texture_screen)
1432 r_bloom_texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", screenwidth, screenheight, NULL, TEXTYPE_RGBA, TEXF_FORCENEAREST | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
1433 if (!r_bloom_texture_bloom)
1434 r_bloom_texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", screenwidth, screenheight, NULL, TEXTYPE_RGBA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
1436 screentexturewidth = R_TextureWidth(r_bloom_texture_screen);
1437 screentextureheight = R_TextureHeight(r_bloom_texture_screen);
1438 bloomtexturewidth = R_TextureWidth(r_bloom_texture_bloom);
1439 bloomtextureheight = R_TextureHeight(r_bloom_texture_bloom);
1441 // vertex coordinates for a quad that covers the screen exactly
1442 vertex3f[0] = 0;vertex3f[1] = 0;vertex3f[2] = 0;
1443 vertex3f[3] = 1;vertex3f[4] = 0;vertex3f[5] = 0;
1444 vertex3f[6] = 1;vertex3f[7] = 1;vertex3f[8] = 0;
1445 vertex3f[9] = 0;vertex3f[10] = 1;vertex3f[11] = 0;
1447 // set up a texcoord array for the full resolution screen image
1448 // (we have to keep this around to copy back during final render)
1449 texcoord2f[0][0] = 0;
1450 texcoord2f[0][1] = (float)r_view.height / (float)screentextureheight;
1451 texcoord2f[0][2] = (float)r_view.width / (float)screentexturewidth;
1452 texcoord2f[0][3] = (float)r_view.height / (float)screentextureheight;
1453 texcoord2f[0][4] = (float)r_view.width / (float)screentexturewidth;
1454 texcoord2f[0][5] = 0;
1455 texcoord2f[0][6] = 0;
1456 texcoord2f[0][7] = 0;
1458 // set up a texcoord array for the reduced resolution bloom image
1459 // (which will be additive blended over the screen image)
1460 texcoord2f[1][0] = 0;
1461 texcoord2f[1][1] = (float)bloomheight / (float)bloomtextureheight;
1462 texcoord2f[1][2] = (float)bloomwidth / (float)bloomtexturewidth;
1463 texcoord2f[1][3] = (float)bloomheight / (float)bloomtextureheight;
1464 texcoord2f[1][4] = (float)bloomwidth / (float)bloomtexturewidth;
1465 texcoord2f[1][5] = 0;
1466 texcoord2f[1][6] = 0;
1467 texcoord2f[1][7] = 0;
1469 R_ResetViewRendering();
1470 GL_DepthTest(false);
1471 R_Mesh_VertexPointer(vertex3f);
1472 R_Mesh_ColorPointer(NULL);
1474 R_Mesh_TexCoordPointer(0, 2, texcoord2f[0]);
1475 R_Mesh_TexBind(0, R_GetTexture(r_bloom_texture_screen));
1477 // copy view into the screen texture
1478 GL_ActiveTexture(0);
1480 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
1481 r_refdef.stats.bloom_copypixels += r_view.width * r_view.height;
1483 // now scale it down to the bloom texture size
1485 qglViewport(r_view.x, vid.height - (r_view.y + bloomheight), bloomwidth, bloomheight);CHECKGLERROR
1486 GL_BlendFunc(GL_ONE, GL_ZERO);
1487 GL_Color(1, 1, 1, 1);
1488 // TODO: optimize with multitexture or GLSL
1489 R_Mesh_Draw(0, 4, 2, polygonelements);
1490 r_refdef.stats.bloom_drawpixels += bloomwidth * bloomheight;
1494 // raise to a power of itself to darken it (this leaves the really
1495 // bright stuff bright, and everything else becomes very dark)
1496 // render multiple times with a multiply blendfunc to raise to a power
1497 GL_BlendFunc(GL_DST_COLOR, GL_ZERO);
1498 for (x = 1;x < r_bloom_power.integer;x++)
1500 R_Mesh_Draw(0, 4, 2, polygonelements);
1501 r_refdef.stats.bloom_drawpixels += bloomwidth * bloomheight;
1505 // we now have a darkened bloom image in the framebuffer
1506 // copy it into the bloom image texture for more processing
1507 R_Mesh_TexBind(0, R_GetTexture(r_bloom_texture_bloom));
1508 R_Mesh_TexCoordPointer(0, 2, texcoord2f[2]);
1509 GL_ActiveTexture(0);
1511 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view.x, vid.height - (r_view.y + bloomheight), bloomwidth, bloomheight);CHECKGLERROR
1512 r_refdef.stats.bloom_copypixels += bloomwidth * bloomheight;
1514 // blend on at multiple vertical offsets to achieve a vertical blur
1515 // TODO: do offset blends using GLSL
1516 range = r_bloom_blur.integer * bloomwidth / 320;
1517 GL_BlendFunc(GL_ONE, GL_ZERO);
1518 for (x = -range;x <= range;x++)
1520 xoffset = 0 / (float)bloomwidth * (float)bloomwidth / (float)screenwidth;
1521 yoffset = x / (float)bloomheight * (float)bloomheight / (float)screenheight;
1522 // compute a texcoord array with the specified x and y offset
1523 texcoord2f[2][0] = xoffset+0;
1524 texcoord2f[2][1] = yoffset+(float)bloomheight / (float)screenheight;
1525 texcoord2f[2][2] = xoffset+(float)bloomwidth / (float)screenwidth;
1526 texcoord2f[2][3] = yoffset+(float)bloomheight / (float)screenheight;
1527 texcoord2f[2][4] = xoffset+(float)bloomwidth / (float)screenwidth;
1528 texcoord2f[2][5] = yoffset+0;
1529 texcoord2f[2][6] = xoffset+0;
1530 texcoord2f[2][7] = yoffset+0;
1531 // this r value looks like a 'dot' particle, fading sharply to
1532 // black at the edges
1533 // (probably not realistic but looks good enough)
1534 r = r_bloom_intensity.value/(range*2+1)*(1 - x*x/(float)(range*range));
1537 GL_Color(r, r, r, 1);
1538 R_Mesh_Draw(0, 4, 2, polygonelements);
1539 r_refdef.stats.bloom_drawpixels += bloomwidth * bloomheight;
1540 GL_BlendFunc(GL_ONE, GL_ONE);
1543 // copy the vertically blurred bloom view to a texture
1544 GL_ActiveTexture(0);
1546 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view.x, vid.height - (r_view.y + bloomheight), bloomwidth, bloomheight);CHECKGLERROR
1547 r_refdef.stats.bloom_copypixels += bloomwidth * bloomheight;
1549 // blend the vertically blurred image at multiple offsets horizontally
1550 // to finish the blur effect
1551 // TODO: do offset blends using GLSL
1552 range = r_bloom_blur.integer * bloomwidth / 320;
1553 GL_BlendFunc(GL_ONE, GL_ZERO);
1554 for (x = -range;x <= range;x++)
1556 xoffset = x / (float)bloomwidth * (float)bloomwidth / (float)screenwidth;
1557 yoffset = 0 / (float)bloomheight * (float)bloomheight / (float)screenheight;
1558 // compute a texcoord array with the specified x and y offset
1559 texcoord2f[2][0] = xoffset+0;
1560 texcoord2f[2][1] = yoffset+(float)bloomheight / (float)screenheight;
1561 texcoord2f[2][2] = xoffset+(float)bloomwidth / (float)screenwidth;
1562 texcoord2f[2][3] = yoffset+(float)bloomheight / (float)screenheight;
1563 texcoord2f[2][4] = xoffset+(float)bloomwidth / (float)screenwidth;
1564 texcoord2f[2][5] = yoffset+0;
1565 texcoord2f[2][6] = xoffset+0;
1566 texcoord2f[2][7] = yoffset+0;
1567 // this r value looks like a 'dot' particle, fading sharply to
1568 // black at the edges
1569 // (probably not realistic but looks good enough)
1570 r = r_bloom_intensity.value/(range*2+1)*(1 - x*x/(float)(range*range));
1573 GL_Color(r, r, r, 1);
1574 R_Mesh_Draw(0, 4, 2, polygonelements);
1575 r_refdef.stats.bloom_drawpixels += bloomwidth * bloomheight;
1576 GL_BlendFunc(GL_ONE, GL_ONE);
1579 // copy the blurred bloom view to a texture
1580 GL_ActiveTexture(0);
1582 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view.x, vid.height - (r_view.y + bloomheight), bloomwidth, bloomheight);CHECKGLERROR
1583 r_refdef.stats.bloom_copypixels += bloomwidth * bloomheight;
1586 void R_HDR_RenderBloomTexture(void)
1588 int oldwidth, oldheight;
1590 oldwidth = r_view.width;
1591 oldheight = r_view.height;
1592 r_view.width = bound(1, r_bloom_resolution.integer, min(r_view.width, gl_max_texture_size));
1593 r_view.height = r_view.width * oldheight / oldwidth;
1595 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
1596 // FIXME: change global lightmapintensity and light intensity according to r_hdr_bloomintensity cvar
1597 // FIXME: change global lightmapintensity and light intensity according to r_hdr_scenebrightness cvar
1598 // TODO: add exposure compensation features
1600 r_view.colorscale = r_hdr_bloomintensity.value * r_hdr_scenebrightness.value;
1603 R_ResetViewRendering();
1605 R_Bloom_MakeTexture(false);
1608 if (r_timereport_active)
1609 R_TimeReport("clear");
1611 // restore the view settings
1612 r_view.width = oldwidth;
1613 r_view.height = oldheight;
1615 // go back to full view area
1616 R_ResetViewRendering();
1619 static void R_BlendView(void)
1621 int screenwidth, screenheight;
1622 int bloomwidth, bloomheight;
1627 float texcoord2f[3][8];
1629 // set the (poorly named) screenwidth and screenheight variables to
1630 // a power of 2 at least as large as the screen, these will define the
1631 // size of the texture to allocate
1632 for (screenwidth = 1;screenwidth < vid.width;screenwidth *= 2);
1633 for (screenheight = 1;screenheight < vid.height;screenheight *= 2);
1635 doblend = r_refdef.viewblend[3] >= 0.01f;
1636 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;
1637 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;
1639 if (!dobloom && !dohdr && !doblend)
1642 // vertex coordinates for a quad that covers the screen exactly
1643 vertex3f[0] = 0;vertex3f[1] = 0;vertex3f[2] = 0;
1644 vertex3f[3] = 1;vertex3f[4] = 0;vertex3f[5] = 0;
1645 vertex3f[6] = 1;vertex3f[7] = 1;vertex3f[8] = 0;
1646 vertex3f[9] = 0;vertex3f[10] = 1;vertex3f[11] = 0;
1648 // set bloomwidth and bloomheight to the bloom resolution that will be
1649 // used (often less than the screen resolution for faster rendering)
1650 bloomwidth = min(r_view.width, r_bloom_resolution.integer);
1651 bloomheight = min(r_view.height, bloomwidth * r_view.height / r_view.width);
1652 // set up a texcoord array for the full resolution screen image
1653 // (we have to keep this around to copy back during final render)
1654 texcoord2f[0][0] = 0;
1655 texcoord2f[0][1] = (float)r_view.height / (float)screenheight;
1656 texcoord2f[0][2] = (float)r_view.width / (float)screenwidth;
1657 texcoord2f[0][3] = (float)r_view.height / (float)screenheight;
1658 texcoord2f[0][4] = (float)r_view.width / (float)screenwidth;
1659 texcoord2f[0][5] = 0;
1660 texcoord2f[0][6] = 0;
1661 texcoord2f[0][7] = 0;
1662 // set up a texcoord array for the reduced resolution bloom image
1663 // (which will be additive blended over the screen image)
1664 texcoord2f[1][0] = 0;
1665 texcoord2f[1][1] = (float)bloomheight / (float)screenheight;
1666 texcoord2f[1][2] = (float)bloomwidth / (float)screenwidth;
1667 texcoord2f[1][3] = (float)bloomheight / (float)screenheight;
1668 texcoord2f[1][4] = (float)bloomwidth / (float)screenwidth;
1669 texcoord2f[1][5] = 0;
1670 texcoord2f[1][6] = 0;
1671 texcoord2f[1][7] = 0;
1675 // render high dynamic range bloom effect
1676 // the bloom texture was made earlier this render, so we just need to
1677 // blend it onto the screen...
1678 R_ResetViewRendering();
1679 GL_DepthTest(false);
1680 R_Mesh_VertexPointer(vertex3f);
1681 R_Mesh_ColorPointer(NULL);
1682 GL_Color(1, 1, 1, 1);
1683 GL_BlendFunc(GL_ONE, GL_ONE);
1684 R_Mesh_TexBind(0, R_GetTexture(r_bloom_texture_bloom));
1685 R_Mesh_TexCoordPointer(0, 2, texcoord2f[1]);
1686 R_Mesh_Draw(0, 4, 2, polygonelements);
1687 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
1691 // render simple bloom effect
1692 // make the bloom texture
1693 R_Bloom_MakeTexture(true);
1694 // put the original screen image back in place and blend the bloom
1696 R_ResetViewRendering();
1697 GL_DepthTest(false);
1698 R_Mesh_VertexPointer(vertex3f);
1699 R_Mesh_ColorPointer(NULL);
1700 GL_Color(1, 1, 1, 1);
1701 GL_BlendFunc(GL_ONE, GL_ZERO);
1702 // do both in one pass if possible
1703 R_Mesh_TexBind(0, R_GetTexture(r_bloom_texture_screen));
1704 R_Mesh_TexCoordPointer(0, 2, texcoord2f[0]);
1705 if (r_textureunits.integer >= 2 && gl_combine.integer)
1707 R_Mesh_TexCombine(1, GL_ADD, GL_ADD, 1, 1);
1708 R_Mesh_TexBind(1, R_GetTexture(r_bloom_texture_bloom));
1709 R_Mesh_TexCoordPointer(1, 2, texcoord2f[1]);
1713 R_Mesh_Draw(0, 4, 2, polygonelements);
1714 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
1715 // now blend on the bloom texture
1716 GL_BlendFunc(GL_ONE, GL_ONE);
1717 R_Mesh_TexBind(0, R_GetTexture(r_bloom_texture_bloom));
1718 R_Mesh_TexCoordPointer(0, 2, texcoord2f[1]);
1720 R_Mesh_Draw(0, 4, 2, polygonelements);
1721 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
1725 // apply a color tint to the whole view
1726 R_ResetViewRendering();
1727 GL_DepthTest(false);
1728 R_Mesh_VertexPointer(vertex3f);
1729 R_Mesh_ColorPointer(NULL);
1730 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1731 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
1732 R_Mesh_Draw(0, 4, 2, polygonelements);
1736 void R_RenderScene(void);
1738 matrix4x4_t r_waterscrollmatrix;
1740 void R_UpdateVariables(void)
1744 r_refdef.farclip = 4096;
1745 if (r_refdef.worldmodel)
1746 r_refdef.farclip += VectorDistance(r_refdef.worldmodel->normalmins, r_refdef.worldmodel->normalmaxs);
1747 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
1749 r_refdef.polygonfactor = 0;
1750 r_refdef.polygonoffset = 0;
1751 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_shadow_polygonfactor.value;
1752 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_shadow_polygonoffset.value;
1754 r_refdef.rtworld = r_shadow_realtime_world.integer;
1755 r_refdef.rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
1756 r_refdef.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer;
1757 r_refdef.rtdlightshadows = r_refdef.rtdlight && (r_refdef.rtworld ? r_shadow_realtime_world_dlightshadows.integer : r_shadow_realtime_dlight_shadows.integer) && gl_stencil;
1758 r_refdef.lightmapintensity = r_refdef.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
1759 if (r_showsurfaces.integer)
1761 r_refdef.rtworld = false;
1762 r_refdef.rtworldshadows = false;
1763 r_refdef.rtdlight = false;
1764 r_refdef.rtdlightshadows = false;
1765 r_refdef.lightmapintensity = 0;
1768 if (gamemode == GAME_NEHAHRA)
1770 if (gl_fogenable.integer)
1772 r_refdef.oldgl_fogenable = true;
1773 r_refdef.fog_density = gl_fogdensity.value;
1774 r_refdef.fog_red = gl_fogred.value;
1775 r_refdef.fog_green = gl_foggreen.value;
1776 r_refdef.fog_blue = gl_fogblue.value;
1778 else if (r_refdef.oldgl_fogenable)
1780 r_refdef.oldgl_fogenable = false;
1781 r_refdef.fog_density = 0;
1782 r_refdef.fog_red = 0;
1783 r_refdef.fog_green = 0;
1784 r_refdef.fog_blue = 0;
1787 if (r_refdef.fog_density)
1789 r_refdef.fogcolor[0] = bound(0.0f, r_refdef.fog_red , 1.0f);
1790 r_refdef.fogcolor[1] = bound(0.0f, r_refdef.fog_green, 1.0f);
1791 r_refdef.fogcolor[2] = bound(0.0f, r_refdef.fog_blue , 1.0f);
1793 if (r_refdef.fog_density)
1795 r_refdef.fogenabled = true;
1796 // this is the point where the fog reaches 0.9986 alpha, which we
1797 // consider a good enough cutoff point for the texture
1798 // (0.9986 * 256 == 255.6)
1799 r_refdef.fogrange = 400 / r_refdef.fog_density;
1800 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
1801 r_refdef.fogtabledistmultiplier = FOGTABLEWIDTH * r_refdef.fograngerecip;
1802 // fog color was already set
1805 r_refdef.fogenabled = false;
1813 void R_RenderView(void)
1815 if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
1816 return; //Host_Error ("R_RenderView: NULL worldmodel");
1819 GL_ScissorTest(true);
1821 if (r_timereport_active)
1822 R_TimeReport("setup");
1825 if (r_timereport_active)
1826 R_TimeReport("visibility");
1828 R_ResetViewRendering();
1831 if (r_timereport_active)
1832 R_TimeReport("clear");
1834 // this produces a bloom texture to be used in R_BlendView() later
1836 R_HDR_RenderBloomTexture();
1838 r_view.colorscale = r_hdr_scenebrightness.value;
1842 if (r_timereport_active)
1843 R_TimeReport("blendview");
1845 GL_Scissor(0, 0, vid.width, vid.height);
1846 GL_ScissorTest(false);
1850 extern void R_DrawLightningBeams (void);
1851 extern void VM_AddPolygonsToMeshQueue (void);
1852 extern void R_DrawPortals (void);
1853 void R_RenderScene(void)
1857 // don't let sound skip if going slow
1858 if (r_refdef.extraupdate)
1862 if (gl_support_fragment_shader)
1864 qglUseProgramObjectARB(0);CHECKGLERROR
1866 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
1867 qglPolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR
1868 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
1870 R_ResetViewRendering();
1871 R_SetupView(&r_view.matrix);
1873 R_MeshQueue_BeginScene();
1875 R_Shadow_UpdateWorldLightSelection();
1879 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);
1881 if (cl.csqc_vidvars.drawworld)
1883 // don't let sound skip if going slow
1884 if (r_refdef.extraupdate)
1887 if (r_refdef.worldmodel && r_refdef.worldmodel->DrawSky)
1889 r_refdef.worldmodel->DrawSky(r_refdef.worldentity);
1890 if (r_timereport_active)
1891 R_TimeReport("worldsky");
1894 if (R_DrawBrushModelsSky() && r_timereport_active)
1895 R_TimeReport("bmodelsky");
1897 if (r_refdef.worldmodel && r_refdef.worldmodel->Draw)
1899 r_refdef.worldmodel->Draw(r_refdef.worldentity);
1900 if (r_timereport_active)
1901 R_TimeReport("world");
1905 // don't let sound skip if going slow
1906 if (r_refdef.extraupdate)
1910 if (r_timereport_active)
1911 R_TimeReport("models");
1913 // don't let sound skip if going slow
1914 if (r_refdef.extraupdate)
1917 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
1919 R_DrawModelShadows();
1921 // don't let sound skip if going slow
1922 if (r_refdef.extraupdate)
1926 R_ShadowVolumeLighting(false);
1927 if (r_timereport_active)
1928 R_TimeReport("rtlights");
1930 // don't let sound skip if going slow
1931 if (r_refdef.extraupdate)
1934 if (cl.csqc_vidvars.drawworld)
1936 R_DrawLightningBeams();
1937 if (r_timereport_active)
1938 R_TimeReport("lightning");
1941 if (r_timereport_active)
1942 R_TimeReport("particles");
1945 if (r_timereport_active)
1946 R_TimeReport("explosions");
1949 if (gl_support_fragment_shader)
1951 qglUseProgramObjectARB(0);CHECKGLERROR
1953 VM_AddPolygonsToMeshQueue();
1955 if (r_drawportals.integer)
1958 if (r_timereport_active)
1959 R_TimeReport("portals");
1962 if (gl_support_fragment_shader)
1964 qglUseProgramObjectARB(0);CHECKGLERROR
1966 R_MeshQueue_RenderTransparent();
1967 if (r_timereport_active)
1968 R_TimeReport("drawtrans");
1970 if (gl_support_fragment_shader)
1972 qglUseProgramObjectARB(0);CHECKGLERROR
1975 if (cl.csqc_vidvars.drawworld)
1978 if (r_timereport_active)
1979 R_TimeReport("coronas");
1982 // don't let sound skip if going slow
1983 if (r_refdef.extraupdate)
1987 if (gl_support_fragment_shader)
1989 qglUseProgramObjectARB(0);CHECKGLERROR
1991 qglPolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR
1992 qglDisable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
1996 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
1999 float *v, *c, f1, f2, diff[3], vertex3f[8*3], color4f[8*4];
2000 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2001 GL_DepthMask(false);
2003 R_Mesh_Matrix(&identitymatrix);
2005 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2];
2006 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
2007 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
2008 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
2009 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
2010 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
2011 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
2012 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
2013 R_FillColors(color, 8, cr, cg, cb, ca);
2014 if (r_refdef.fogenabled)
2016 for (i = 0, v = vertex, c = color;i < 8;i++, v += 4, c += 4)
2018 f2 = VERTEXFOGTABLE(VectorDistance(v, r_view.origin));
2020 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
2021 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
2022 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
2025 R_Mesh_VertexPointer(vertex3f);
2026 R_Mesh_ColorPointer(color);
2027 R_Mesh_ResetTextureState();
2032 int nomodelelements[24] =
2044 float nomodelvertex3f[6*3] =
2054 float nomodelcolor4f[6*4] =
2056 0.0f, 0.0f, 0.5f, 1.0f,
2057 0.0f, 0.0f, 0.5f, 1.0f,
2058 0.0f, 0.5f, 0.0f, 1.0f,
2059 0.0f, 0.5f, 0.0f, 1.0f,
2060 0.5f, 0.0f, 0.0f, 1.0f,
2061 0.5f, 0.0f, 0.0f, 1.0f
2064 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
2069 // this is only called once per entity so numsurfaces is always 1, and
2070 // surfacelist is always {0}, so this code does not handle batches
2071 R_Mesh_Matrix(&ent->matrix);
2073 if (ent->flags & EF_ADDITIVE)
2075 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2076 GL_DepthMask(false);
2078 else if (ent->alpha < 1)
2080 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2081 GL_DepthMask(false);
2085 GL_BlendFunc(GL_ONE, GL_ZERO);
2088 GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
2089 R_Mesh_VertexPointer(nomodelvertex3f);
2090 if (r_refdef.fogenabled)
2093 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
2094 R_Mesh_ColorPointer(color4f);
2095 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
2096 f2 = VERTEXFOGTABLE(VectorDistance(org, r_view.origin));
2098 for (i = 0, c = color4f;i < 6;i++, c += 4)
2100 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
2101 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
2102 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
2106 else if (ent->alpha != 1)
2108 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
2109 R_Mesh_ColorPointer(color4f);
2110 for (i = 0, c = color4f;i < 6;i++, c += 4)
2114 R_Mesh_ColorPointer(nomodelcolor4f);
2115 R_Mesh_ResetTextureState();
2116 R_Mesh_Draw(0, 6, 8, nomodelelements);
2119 void R_DrawNoModel(entity_render_t *ent)
2122 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
2123 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
2124 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, r_shadow_rtlight);
2126 // R_DrawNoModelCallback(ent, 0);
2129 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
2131 vec3_t right1, right2, diff, normal;
2133 VectorSubtract (org2, org1, normal);
2135 // calculate 'right' vector for start
2136 VectorSubtract (r_view.origin, org1, diff);
2137 CrossProduct (normal, diff, right1);
2138 VectorNormalize (right1);
2140 // calculate 'right' vector for end
2141 VectorSubtract (r_view.origin, org2, diff);
2142 CrossProduct (normal, diff, right2);
2143 VectorNormalize (right2);
2145 vert[ 0] = org1[0] + width * right1[0];
2146 vert[ 1] = org1[1] + width * right1[1];
2147 vert[ 2] = org1[2] + width * right1[2];
2148 vert[ 3] = org1[0] - width * right1[0];
2149 vert[ 4] = org1[1] - width * right1[1];
2150 vert[ 5] = org1[2] - width * right1[2];
2151 vert[ 6] = org2[0] - width * right2[0];
2152 vert[ 7] = org2[1] - width * right2[1];
2153 vert[ 8] = org2[2] - width * right2[2];
2154 vert[ 9] = org2[0] + width * right2[0];
2155 vert[10] = org2[1] + width * right2[1];
2156 vert[11] = org2[2] + width * right2[2];
2159 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
2161 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)
2163 float fog = 0.0f, ifog;
2166 if (r_refdef.fogenabled)
2167 fog = VERTEXFOGTABLE(VectorDistance(origin, r_view.origin));
2170 R_Mesh_Matrix(&identitymatrix);
2171 GL_BlendFunc(blendfunc1, blendfunc2);
2172 GL_DepthMask(false);
2173 GL_DepthTest(!depthdisable);
2175 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
2176 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
2177 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
2178 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
2179 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
2180 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
2181 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
2182 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
2183 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
2184 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
2185 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
2186 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
2188 R_Mesh_VertexPointer(vertex3f);
2189 R_Mesh_ColorPointer(NULL);
2190 R_Mesh_ResetTextureState();
2191 R_Mesh_TexBind(0, R_GetTexture(texture));
2192 R_Mesh_TexCoordPointer(0, 2, spritetexcoord2f);
2193 // FIXME: fixed function path can't properly handle r_view.colorscale > 1
2194 GL_Color(cr * ifog * r_view.colorscale, cg * ifog * r_view.colorscale, cb * ifog * r_view.colorscale, ca);
2195 R_Mesh_Draw(0, 4, 2, polygonelements);
2197 if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
2199 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
2200 GL_BlendFunc(blendfunc1, GL_ONE);
2201 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);
2202 R_Mesh_Draw(0, 4, 2, polygonelements);
2206 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
2211 VectorSet(v, x, y, z);
2212 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
2213 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
2215 if (i == mesh->numvertices)
2217 if (mesh->numvertices < mesh->maxvertices)
2219 VectorCopy(v, vertex3f);
2220 mesh->numvertices++;
2222 return mesh->numvertices;
2228 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
2232 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
2233 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
2234 e = mesh->element3i + mesh->numtriangles * 3;
2235 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
2237 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
2238 if (mesh->numtriangles < mesh->maxtriangles)
2243 mesh->numtriangles++;
2245 element[1] = element[2];
2249 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
2253 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
2254 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
2255 e = mesh->element3i + mesh->numtriangles * 3;
2256 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
2258 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
2259 if (mesh->numtriangles < mesh->maxtriangles)
2264 mesh->numtriangles++;
2266 element[1] = element[2];
2270 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
2271 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
2273 int planenum, planenum2;
2276 mplane_t *plane, *plane2;
2278 double temppoints[2][256*3];
2279 // figure out how large a bounding box we need to properly compute this brush
2281 for (w = 0;w < numplanes;w++)
2282 maxdist = max(maxdist, planes[w].dist);
2283 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
2284 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
2285 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
2289 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
2290 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
2292 if (planenum2 == planenum)
2294 PolygonD_Divide(tempnumpoints, temppoints[w], plane2->normal[0], plane2->normal[1], plane2->normal[2], plane2->dist, R_MESH_PLANE_DIST_EPSILON, 0, NULL, NULL, 256, temppoints[!w], &tempnumpoints, NULL);
2297 if (tempnumpoints < 3)
2299 // generate elements forming a triangle fan for this polygon
2300 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
2304 static void R_DrawCollisionBrush(const colbrushf_t *brush)
2307 R_Mesh_VertexPointer(brush->points->v);
2308 i = (int)(((size_t)brush) / sizeof(colbrushf_t));
2309 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);
2310 GL_LockArrays(0, brush->numpoints);
2311 R_Mesh_Draw(0, brush->numpoints, brush->numtriangles, brush->elements);
2312 GL_LockArrays(0, 0);
2315 static void R_DrawCollisionSurface(const entity_render_t *ent, const msurface_t *surface)
2318 if (!surface->num_collisiontriangles)
2320 R_Mesh_VertexPointer(surface->data_collisionvertex3f);
2321 i = (int)(((size_t)surface) / sizeof(msurface_t));
2322 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);
2323 GL_LockArrays(0, surface->num_collisionvertices);
2324 R_Mesh_Draw(0, surface->num_collisionvertices, surface->num_collisiontriangles, surface->data_collisionelement3i);
2325 GL_LockArrays(0, 0);
2328 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)
2330 texturelayer_t *layer;
2331 layer = t->currentlayers + t->currentnumlayers++;
2333 layer->depthmask = depthmask;
2334 layer->blendfunc1 = blendfunc1;
2335 layer->blendfunc2 = blendfunc2;
2336 layer->texture = texture;
2337 layer->texmatrix = *matrix;
2338 layer->color[0] = r * r_view.colorscale;
2339 layer->color[1] = g * r_view.colorscale;
2340 layer->color[2] = b * r_view.colorscale;
2341 layer->color[3] = a;
2344 void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
2346 // FIXME: identify models using a better check than ent->model->brush.shadowmesh
2347 //int lightmode = ((ent->effects & EF_FULLBRIGHT) || ent->model->brush.shadowmesh) ? 0 : 2;
2349 // switch to an alternate material if this is a q1bsp animated material
2351 texture_t *texture = t;
2352 model_t *model = ent->model;
2353 int s = ent->skinnum;
2354 if ((unsigned int)s >= (unsigned int)model->numskins)
2356 if (model->skinscenes)
2358 if (model->skinscenes[s].framecount > 1)
2359 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
2361 s = model->skinscenes[s].firstframe;
2364 t = t + s * model->num_surfaces;
2367 // use an alternate animation if the entity's frame is not 0,
2368 // and only if the texture has an alternate animation
2369 if (ent->frame != 0 && t->anim_total[1])
2370 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.time * 5.0f) % t->anim_total[1]) : 0];
2372 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.time * 5.0f) % t->anim_total[0]) : 0];
2374 texture->currentframe = t;
2377 // pick a new currentskinframe if the material is animated
2378 if (t->numskinframes >= 2)
2379 t->currentskinframe = t->skinframes + ((int)(t->skinframerate * (cl.time - ent->frame2time)) % t->numskinframes);
2381 t->currentmaterialflags = t->basematerialflags;
2382 t->currentalpha = ent->alpha;
2383 if (t->basematerialflags & MATERIALFLAG_WATERALPHA)
2384 t->currentalpha *= r_wateralpha.value;
2385 if (!(ent->flags & RENDER_LIGHT))
2386 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
2387 if (ent->effects & EF_ADDITIVE)
2388 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_TRANSPARENT;
2389 else if (t->currentalpha < 1)
2390 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_TRANSPARENT;
2391 if (ent->effects & EF_NODEPTHTEST)
2392 t->currentmaterialflags |= MATERIALFLAG_NODEPTHTEST;
2393 if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
2394 t->currenttexmatrix = r_waterscrollmatrix;
2396 t->currenttexmatrix = identitymatrix;
2398 t->colormapping = VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f);
2399 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
2400 t->glosstexture = r_texture_white;
2401 t->specularpower = 8;
2402 t->specularscale = 0;
2403 if (r_shadow_gloss.integer > 0)
2405 if (t->currentskinframe->gloss)
2407 if (r_shadow_glossintensity.value > 0)
2409 t->glosstexture = t->currentskinframe->gloss;
2410 t->specularscale = r_shadow_glossintensity.value;
2413 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
2414 t->specularscale = r_shadow_gloss2intensity.value;
2417 t->currentnumlayers = 0;
2418 if (!(t->currentmaterialflags & MATERIALFLAG_NODRAW))
2420 if (gl_lightmaps.integer)
2421 R_Texture_AddLayer(t, true, GL_ONE, GL_ZERO, TEXTURELAYERTYPE_LITTEXTURE, r_texture_white, &identitymatrix, 1, 1, 1, 1);
2422 else if (!(t->currentmaterialflags & MATERIALFLAG_SKY))
2424 int blendfunc1, blendfunc2, depthmask;
2425 if (t->currentmaterialflags & MATERIALFLAG_ADD)
2427 blendfunc1 = GL_SRC_ALPHA;
2428 blendfunc2 = GL_ONE;
2430 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
2432 blendfunc1 = GL_SRC_ALPHA;
2433 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
2435 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
2437 blendfunc1 = t->customblendfunc[0];
2438 blendfunc2 = t->customblendfunc[1];
2442 blendfunc1 = GL_ONE;
2443 blendfunc2 = GL_ZERO;
2445 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
2446 if (t->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL))
2448 rtexture_t *currentbasetexture;
2450 if (r_refdef.fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED))
2451 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
2452 currentbasetexture = (VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) < (1.0f / 1048576.0f) && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
2453 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2455 // fullbright is not affected by r_refdef.lightmapintensity
2456 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
2457 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
2458 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->pants, &t->currenttexmatrix, ent->colormap_pantscolor[0] * ent->colormod[0], ent->colormap_pantscolor[1] * ent->colormod[1], ent->colormap_pantscolor[2] * ent->colormod[2], t->currentalpha);
2459 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
2460 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->shirt, &t->currenttexmatrix, ent->colormap_shirtcolor[0] * ent->colormod[0], ent->colormap_shirtcolor[1] * ent->colormod[1], ent->colormap_shirtcolor[2] * ent->colormod[2], t->currentalpha);
2466 // q3bsp has no lightmap updates, so the lightstylevalue that
2467 // would normally be baked into the lightmap must be
2468 // applied to the color
2469 if (ent->model->type == mod_brushq3)
2470 colorscale *= r_refdef.lightstylevalue[0] * (1.0f / 256.0f);
2471 colorscale *= r_refdef.lightmapintensity;
2472 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);
2473 if (r_ambient.value >= (1.0f/64.0f))
2474 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);
2475 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
2477 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->currentskinframe->pants, &t->currenttexmatrix, ent->colormap_pantscolor[0] * ent->colormod[0] * colorscale, ent->colormap_pantscolor[1] * ent->colormod[1] * colorscale, ent->colormap_pantscolor[2] * ent->colormod[2] * colorscale, t->currentalpha);
2478 if (r_ambient.value >= (1.0f/64.0f))
2479 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->pants, &t->currenttexmatrix, ent->colormap_pantscolor[0] * ent->colormod[0] * r_ambient.value * (1.0f / 64.0f), ent->colormap_pantscolor[1] * ent->colormod[1] * r_ambient.value * (1.0f / 64.0f), ent->colormap_pantscolor[2] * ent->colormod[2] * r_ambient.value * (1.0f / 64.0f), t->currentalpha);
2481 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
2483 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->currentskinframe->shirt, &t->currenttexmatrix, ent->colormap_shirtcolor[0] * ent->colormod[0] * colorscale, ent->colormap_shirtcolor[1] * ent->colormod[1] * colorscale, ent->colormap_shirtcolor[2] * ent->colormod[2] * colorscale, t->currentalpha);
2484 if (r_ambient.value >= (1.0f/64.0f))
2485 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->shirt, &t->currenttexmatrix, ent->colormap_shirtcolor[0] * ent->colormod[0] * r_ambient.value * (1.0f / 64.0f), ent->colormap_shirtcolor[1] * ent->colormod[1] * r_ambient.value * (1.0f / 64.0f), ent->colormap_shirtcolor[2] * ent->colormod[2] * r_ambient.value * (1.0f / 64.0f), t->currentalpha);
2488 if (t->currentskinframe->glow != NULL)
2489 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->glow, &t->currenttexmatrix, r_hdr_glowintensity.value, r_hdr_glowintensity.value, r_hdr_glowintensity.value, t->currentalpha);
2490 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
2492 // if this is opaque use alpha blend which will darken the earlier
2495 // if this is an alpha blended material, all the earlier passes
2496 // were darkened by fog already, so we only need to add the fog
2497 // color ontop through the fog mask texture
2499 // if this is an additive blended material, all the earlier passes
2500 // were darkened by fog already, and we should not add fog color
2501 // (because the background was not darkened, there is no fog color
2502 // that was lost behind it).
2503 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, (t->currentmaterialflags & MATERIALFLAG_BLENDED) ? GL_ONE : GL_ONE_MINUS_SRC_ALPHA, TEXTURELAYERTYPE_FOG, t->currentskinframe->fog, &identitymatrix, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], t->currentalpha);
2510 void R_UpdateAllTextureInfo(entity_render_t *ent)
2514 for (i = 0;i < ent->model->num_textures;i++)
2515 R_UpdateTextureInfo(ent, ent->model->data_textures + i);
2518 int rsurface_array_size = 0;
2519 float *rsurface_array_modelvertex3f = NULL;
2520 float *rsurface_array_modelsvector3f = NULL;
2521 float *rsurface_array_modeltvector3f = NULL;
2522 float *rsurface_array_modelnormal3f = NULL;
2523 float *rsurface_array_deformedvertex3f = NULL;
2524 float *rsurface_array_deformedsvector3f = NULL;
2525 float *rsurface_array_deformedtvector3f = NULL;
2526 float *rsurface_array_deformednormal3f = NULL;
2527 float *rsurface_array_color4f = NULL;
2528 float *rsurface_array_texcoord3f = NULL;
2530 void R_Mesh_ResizeArrays(int newvertices)
2533 if (rsurface_array_size >= newvertices)
2535 if (rsurface_array_modelvertex3f)
2536 Mem_Free(rsurface_array_modelvertex3f);
2537 rsurface_array_size = (newvertices + 1023) & ~1023;
2538 base = (float *)Mem_Alloc(r_main_mempool, rsurface_array_size * sizeof(float[31]));
2539 rsurface_array_modelvertex3f = base + rsurface_array_size * 0;
2540 rsurface_array_modelsvector3f = base + rsurface_array_size * 3;
2541 rsurface_array_modeltvector3f = base + rsurface_array_size * 6;
2542 rsurface_array_modelnormal3f = base + rsurface_array_size * 9;
2543 rsurface_array_deformedvertex3f = base + rsurface_array_size * 12;
2544 rsurface_array_deformedsvector3f = base + rsurface_array_size * 15;
2545 rsurface_array_deformedtvector3f = base + rsurface_array_size * 18;
2546 rsurface_array_deformednormal3f = base + rsurface_array_size * 21;
2547 rsurface_array_texcoord3f = base + rsurface_array_size * 24;
2548 rsurface_array_color4f = base + rsurface_array_size * 27;
2551 float *rsurface_modelvertex3f;
2552 float *rsurface_modelsvector3f;
2553 float *rsurface_modeltvector3f;
2554 float *rsurface_modelnormal3f;
2555 float *rsurface_vertex3f;
2556 float *rsurface_svector3f;
2557 float *rsurface_tvector3f;
2558 float *rsurface_normal3f;
2559 float *rsurface_lightmapcolor4f;
2560 vec3_t rsurface_modelorg;
2561 qboolean rsurface_generatedvertex;
2562 const entity_render_t *rsurface_entity;
2563 const model_t *rsurface_model;
2564 texture_t *rsurface_texture;
2565 rtexture_t *rsurface_lightmaptexture;
2566 rsurfmode_t rsurface_mode;
2567 texture_t *rsurface_glsl_texture;
2568 qboolean rsurface_glsl_uselightmap;
2570 void RSurf_CleanUp(void)
2573 if (rsurface_mode == RSURFMODE_GLSL)
2575 qglUseProgramObjectARB(0);CHECKGLERROR
2577 GL_AlphaTest(false);
2578 rsurface_mode = RSURFMODE_NONE;
2579 rsurface_lightmaptexture = NULL;
2580 rsurface_texture = NULL;
2581 rsurface_glsl_texture = NULL;
2582 rsurface_glsl_uselightmap = false;
2585 void RSurf_ActiveEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
2588 Matrix4x4_Transform(&ent->inversematrix, r_view.origin, rsurface_modelorg);
2589 rsurface_entity = ent;
2590 rsurface_model = ent->model;
2591 if (rsurface_array_size < rsurface_model->surfmesh.num_vertices)
2592 R_Mesh_ResizeArrays(rsurface_model->surfmesh.num_vertices);
2593 R_Mesh_Matrix(&ent->matrix);
2594 Matrix4x4_Transform(&ent->inversematrix, r_view.origin, rsurface_modelorg);
2595 if ((rsurface_entity->frameblend[0].lerp != 1 || rsurface_entity->frameblend[0].frame != 0) && rsurface_model->surfmesh.isanimated)
2599 rsurface_modelvertex3f = rsurface_array_modelvertex3f;
2600 rsurface_modelsvector3f = rsurface_array_modelsvector3f;
2601 rsurface_modeltvector3f = rsurface_array_modeltvector3f;
2602 rsurface_modelnormal3f = rsurface_array_modelnormal3f;
2603 Mod_Alias_GetMesh_Vertices(rsurface_model, rsurface_entity->frameblend, rsurface_array_modelvertex3f, rsurface_array_modelnormal3f, rsurface_array_modelsvector3f, rsurface_array_modeltvector3f);
2605 else if (wantnormals)
2607 rsurface_modelvertex3f = rsurface_array_modelvertex3f;
2608 rsurface_modelsvector3f = NULL;
2609 rsurface_modeltvector3f = NULL;
2610 rsurface_modelnormal3f = rsurface_array_modelnormal3f;
2611 Mod_Alias_GetMesh_Vertices(rsurface_model, rsurface_entity->frameblend, rsurface_array_modelvertex3f, rsurface_array_modelnormal3f, NULL, NULL);
2615 rsurface_modelvertex3f = rsurface_array_modelvertex3f;
2616 rsurface_modelsvector3f = NULL;
2617 rsurface_modeltvector3f = NULL;
2618 rsurface_modelnormal3f = NULL;
2619 Mod_Alias_GetMesh_Vertices(rsurface_model, rsurface_entity->frameblend, rsurface_array_modelvertex3f, NULL, NULL, NULL);
2621 rsurface_generatedvertex = true;
2625 rsurface_modelvertex3f = rsurface_model->surfmesh.data_vertex3f;
2626 rsurface_modelsvector3f = rsurface_model->surfmesh.data_svector3f;
2627 rsurface_modeltvector3f = rsurface_model->surfmesh.data_tvector3f;
2628 rsurface_modelnormal3f = rsurface_model->surfmesh.data_normal3f;
2629 rsurface_generatedvertex = false;
2631 rsurface_vertex3f = rsurface_modelvertex3f;
2632 rsurface_svector3f = rsurface_modelsvector3f;
2633 rsurface_tvector3f = rsurface_modeltvector3f;
2634 rsurface_normal3f = rsurface_modelnormal3f;
2637 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, msurface_t **texturesurfacelist)
2639 // if vertices are dynamic (animated models), generate them into the temporary rsurface_array_model* arrays and point rsurface_model* at them instead of the static data from the model itself
2640 if (rsurface_generatedvertex)
2642 if (rsurface_texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
2643 generatetangents = true;
2644 if (generatetangents)
2645 generatenormals = true;
2646 if (generatenormals && !rsurface_modelnormal3f)
2648 rsurface_normal3f = rsurface_modelnormal3f = rsurface_array_modelnormal3f;
2649 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);
2651 if (generatetangents && !rsurface_modelsvector3f)
2653 rsurface_svector3f = rsurface_modelsvector3f = rsurface_array_modelsvector3f;
2654 rsurface_tvector3f = rsurface_modeltvector3f = rsurface_array_modeltvector3f;
2655 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);
2658 // if vertices are deformed (sprite flares and things in maps, possibly water waves, bulges and other deformations), generate them into rsurface_deform* arrays from whatever the rsurface_model* array pointers point to (may be static model data or generated data for an animated model)
2659 if (rsurface_texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
2661 int texturesurfaceindex;
2662 float center[3], forward[3], right[3], up[3], v[4][3];
2663 matrix4x4_t matrix1, imatrix1;
2664 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_view.forward, forward);
2665 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_view.right, right);
2666 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_view.up, up);
2667 // make deformed versions of only the model vertices used by the specified surfaces
2668 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2671 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2672 // a single autosprite surface can contain multiple sprites...
2673 for (j = 0;j < surface->num_vertices - 3;j += 4)
2675 VectorClear(center);
2676 for (i = 0;i < 4;i++)
2677 VectorAdd(center, (rsurface_modelvertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
2678 VectorScale(center, 0.25f, center);
2679 if (rsurface_texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE2)
2681 forward[0] = rsurface_modelorg[0] - center[0];
2682 forward[1] = rsurface_modelorg[1] - center[1];
2684 VectorNormalize(forward);
2685 right[0] = forward[1];
2686 right[1] = -forward[0];
2688 VectorSet(up, 0, 0, 1);
2690 // FIXME: calculate vectors from triangle edges instead of using texture vectors as an easy way out?
2691 Matrix4x4_FromVectors(&matrix1, (rsurface_modelnormal3f + 3 * surface->num_firstvertex) + j*3, (rsurface_modelsvector3f + 3 * surface->num_firstvertex) + j*3, (rsurface_modeltvector3f + 3 * surface->num_firstvertex) + j*3, center);
2692 Matrix4x4_Invert_Simple(&imatrix1, &matrix1);
2693 for (i = 0;i < 4;i++)
2694 Matrix4x4_Transform(&imatrix1, (rsurface_modelvertex3f + 3 * surface->num_firstvertex) + (j+i)*3, v[i]);
2695 for (i = 0;i < 4;i++)
2696 VectorMAMAMAM(1, center, v[i][0], forward, v[i][1], right, v[i][2], up, rsurface_array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
2698 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);
2699 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);
2701 rsurface_vertex3f = rsurface_array_deformedvertex3f;
2702 rsurface_svector3f = rsurface_array_deformedsvector3f;
2703 rsurface_tvector3f = rsurface_array_deformedtvector3f;
2704 rsurface_normal3f = rsurface_array_deformednormal3f;
2708 rsurface_vertex3f = rsurface_modelvertex3f;
2709 rsurface_svector3f = rsurface_modelsvector3f;
2710 rsurface_tvector3f = rsurface_modeltvector3f;
2711 rsurface_normal3f = rsurface_modelnormal3f;
2713 R_Mesh_VertexPointer(rsurface_vertex3f);
2716 void RSurf_DrawBatch_Simple(int texturenumsurfaces, msurface_t **texturesurfacelist)
2718 int texturesurfaceindex;
2719 const msurface_t *surface = texturesurfacelist[0];
2720 int firstvertex = surface->num_firstvertex;
2721 int endvertex = surface->num_firstvertex + surface->num_vertices;
2722 if (texturenumsurfaces == 1)
2724 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2725 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
2727 else if (r_batchmode.integer == 2)
2729 #define MAXBATCHTRIANGLES 4096
2730 int batchtriangles = 0;
2731 int batchelements[MAXBATCHTRIANGLES*3];
2732 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2734 surface = texturesurfacelist[texturesurfaceindex];
2735 if (surface->num_triangles >= 256 || (batchtriangles == 0 && texturesurfaceindex + 1 >= texturenumsurfaces))
2737 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
2740 if (batchtriangles + surface->num_triangles > MAXBATCHTRIANGLES)
2742 R_Mesh_Draw(firstvertex, endvertex - firstvertex, batchtriangles, batchelements);
2744 firstvertex = surface->num_firstvertex;
2745 endvertex = surface->num_firstvertex + surface->num_vertices;
2749 firstvertex = min(firstvertex, surface->num_firstvertex);
2750 endvertex = max(endvertex, surface->num_firstvertex + surface->num_vertices);
2752 memcpy(batchelements + batchtriangles * 3, rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
2753 batchtriangles += surface->num_triangles;
2756 R_Mesh_Draw(firstvertex, endvertex - firstvertex, batchtriangles, batchelements);
2758 else if (r_batchmode.integer == 1)
2760 int firsttriangle = 0;
2761 int endtriangle = -1;
2762 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2764 surface = texturesurfacelist[texturesurfaceindex];
2765 if (surface->num_firsttriangle != endtriangle)
2767 if (endtriangle > firsttriangle)
2769 GL_LockArrays(firstvertex, endvertex - firstvertex);
2770 R_Mesh_Draw(firstvertex, endvertex - firstvertex, endtriangle - firsttriangle, (rsurface_model->surfmesh.data_element3i + 3 * firsttriangle));
2772 firstvertex = surface->num_firstvertex;
2773 endvertex = surface->num_firstvertex + surface->num_vertices;
2774 firsttriangle = surface->num_firsttriangle;
2778 firstvertex = min(firstvertex, surface->num_firstvertex);
2779 endvertex = max(endvertex, surface->num_firstvertex + surface->num_vertices);
2781 endtriangle = surface->num_firsttriangle + surface->num_triangles;
2783 if (endtriangle > firsttriangle)
2785 GL_LockArrays(firstvertex, endvertex - firstvertex);
2786 R_Mesh_Draw(firstvertex, endvertex - firstvertex, endtriangle - firsttriangle, (rsurface_model->surfmesh.data_element3i + 3 * firsttriangle));
2791 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2793 surface = texturesurfacelist[texturesurfaceindex];
2794 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2795 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
2800 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
2802 int texturesurfaceindex;
2803 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2805 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2806 int k = (int)(((size_t)surface) / sizeof(msurface_t));
2807 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);
2808 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2809 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
2813 static void RSurf_DrawBatch_Lightmap(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, int lightmode, qboolean applycolor, qboolean applyfog)
2815 int texturesurfaceindex;
2823 vec3_t ambientcolor;
2824 vec3_t diffusecolor;
2826 VectorCopy(rsurface_entity->modellight_lightdir, lightdir);
2827 ambientcolor[0] = rsurface_entity->modellight_ambient[0] * r * 0.5f;
2828 ambientcolor[1] = rsurface_entity->modellight_ambient[1] * g * 0.5f;
2829 ambientcolor[2] = rsurface_entity->modellight_ambient[2] * b * 0.5f;
2830 diffusecolor[0] = rsurface_entity->modellight_diffuse[0] * r * 0.5f;
2831 diffusecolor[1] = rsurface_entity->modellight_diffuse[1] * g * 0.5f;
2832 diffusecolor[2] = rsurface_entity->modellight_diffuse[2] * b * 0.5f;
2833 if (VectorLength2(diffusecolor) > 0)
2835 // generate color arrays for the surfaces in this list
2836 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2838 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2839 int numverts = surface->num_vertices;
2840 v = rsurface_vertex3f + 3 * surface->num_firstvertex;
2841 c2 = rsurface_normal3f + 3 * surface->num_firstvertex;
2842 c = rsurface_array_color4f + 4 * surface->num_firstvertex;
2843 // q3-style directional shading
2844 for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
2846 if ((f = DotProduct(c2, lightdir)) > 0)
2847 VectorMA(ambientcolor, f, diffusecolor, c);
2849 VectorCopy(ambientcolor, c);
2858 rsurface_lightmapcolor4f = rsurface_array_color4f;
2862 r = ambientcolor[0];
2863 g = ambientcolor[1];
2864 b = ambientcolor[2];
2865 rsurface_lightmapcolor4f = NULL;
2868 else if (lightmode >= 1 || !rsurface_lightmaptexture)
2870 if (texturesurfacelist[0]->lightmapinfo && texturesurfacelist[0]->lightmapinfo->stainsamples)
2872 // generate color arrays for the surfaces in this list
2873 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2875 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2876 for (i = 0, c = rsurface_array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
2878 if (surface->lightmapinfo->samples)
2880 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface_model->surfmesh.data_lightmapoffsets + surface->num_firstvertex)[i];
2881 float scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
2882 VectorScale(lm, scale, c);
2883 if (surface->lightmapinfo->styles[1] != 255)
2885 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
2887 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
2888 VectorMA(c, scale, lm, c);
2889 if (surface->lightmapinfo->styles[2] != 255)
2892 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
2893 VectorMA(c, scale, lm, c);
2894 if (surface->lightmapinfo->styles[3] != 255)
2897 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
2898 VectorMA(c, scale, lm, c);
2908 rsurface_lightmapcolor4f = rsurface_array_color4f;
2911 rsurface_lightmapcolor4f = rsurface_model->surfmesh.data_lightmapcolor4f;
2916 rsurface_lightmapcolor4f = NULL;
2920 if (rsurface_lightmapcolor4f)
2922 // generate color arrays for the surfaces in this list
2923 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2925 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2926 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)
2928 f = 1 - VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
2938 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2940 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2941 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)
2943 f = 1 - VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
2951 rsurface_lightmapcolor4f = rsurface_array_color4f;
2953 if (applycolor && rsurface_lightmapcolor4f)
2955 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2957 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2958 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)
2966 rsurface_lightmapcolor4f = rsurface_array_color4f;
2968 R_Mesh_ColorPointer(rsurface_lightmapcolor4f);
2969 GL_Color(r, g, b, a);
2970 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
2973 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
2975 if (rsurface_mode != RSURFMODE_SHOWSURFACES)
2977 rsurface_mode = RSURFMODE_SHOWSURFACES;
2979 GL_BlendFunc(GL_ONE, GL_ZERO);
2980 R_Mesh_ColorPointer(NULL);
2981 R_Mesh_ResetTextureState();
2983 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
2984 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
2987 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, msurface_t **texturesurfacelist)
2989 // transparent sky would be ridiculous
2990 if ((rsurface_texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
2992 if (rsurface_mode != RSURFMODE_SKY)
2994 if (rsurface_mode == RSURFMODE_GLSL)
2996 qglUseProgramObjectARB(0);CHECKGLERROR
2998 rsurface_mode = RSURFMODE_SKY;
3002 skyrendernow = false;
3004 // restore entity matrix
3005 R_Mesh_Matrix(&rsurface_entity->matrix);
3008 // LordHavoc: HalfLife maps have freaky skypolys so don't use
3009 // skymasking on them, and Quake3 never did sky masking (unlike
3010 // software Quake and software Quake2), so disable the sky masking
3011 // in Quake3 maps as it causes problems with q3map2 sky tricks,
3012 // and skymasking also looks very bad when noclipping outside the
3013 // level, so don't use it then either.
3014 if (rsurface_model->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_viewcache.world_novis)
3016 GL_Color(r_refdef.fogcolor[0] * r_view.colorscale, r_refdef.fogcolor[1] * r_view.colorscale, r_refdef.fogcolor[2] * r_view.colorscale, 1);
3017 R_Mesh_ColorPointer(NULL);
3018 R_Mesh_ResetTextureState();
3019 if (skyrendermasked)
3021 // depth-only (masking)
3022 GL_ColorMask(0,0,0,0);
3023 // just to make sure that braindead drivers don't draw
3024 // anything despite that colormask...
3025 GL_BlendFunc(GL_ZERO, GL_ONE);
3030 GL_BlendFunc(GL_ONE, GL_ZERO);
3032 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
3033 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3034 if (skyrendermasked)
3035 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
3039 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, msurface_t **texturesurfacelist)
3042 // FIXME: identify models using a better check than rsurface_model->brush.shadowmesh
3043 lightmode = ((rsurface_entity->effects & EF_FULLBRIGHT) || rsurface_model->brush.shadowmesh) ? 0 : 2;
3044 if (rsurface_mode != RSURFMODE_GLSL)
3046 rsurface_mode = RSURFMODE_GLSL;
3047 rsurface_glsl_texture = NULL;
3048 rsurface_glsl_uselightmap = false;
3049 R_Mesh_ResetTextureState();
3051 if (rsurface_glsl_texture != rsurface_texture || rsurface_glsl_uselightmap != (rsurface_lightmaptexture != NULL))
3053 rsurface_glsl_texture = rsurface_texture;
3054 rsurface_glsl_uselightmap = rsurface_lightmaptexture != NULL;
3055 GL_BlendFunc(rsurface_texture->currentlayers[0].blendfunc1, rsurface_texture->currentlayers[0].blendfunc2);
3056 GL_DepthMask(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_BLENDED));
3057 GL_Color(rsurface_entity->colormod[0], rsurface_entity->colormod[1], rsurface_entity->colormod[2], rsurface_texture->currentalpha);
3058 R_SetupSurfaceShader(vec3_origin, lightmode == 2);
3059 //permutation_deluxemapping = permutation_lightmapping = R_SetupSurfaceShader(vec3_origin, lightmode == 2, false);
3060 //if (r_glsl_deluxemapping.integer)
3061 // permutation_deluxemapping = R_SetupSurfaceShader(vec3_origin, lightmode == 2, true);
3062 R_Mesh_TexCoordPointer(0, 2, rsurface_model->surfmesh.data_texcoordtexture2f);
3063 R_Mesh_TexCoordPointer(4, 2, rsurface_model->surfmesh.data_texcoordlightmap2f);
3064 GL_AlphaTest((rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
3066 if (!r_glsl_permutation)
3068 RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
3069 R_Mesh_TexCoordPointer(1, 3, rsurface_svector3f);
3070 R_Mesh_TexCoordPointer(2, 3, rsurface_tvector3f);
3071 R_Mesh_TexCoordPointer(3, 3, rsurface_normal3f);
3072 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
3074 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
3075 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
3076 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
3077 R_Mesh_ColorPointer(NULL);
3079 else if (rsurface_lightmaptexture)
3081 R_Mesh_TexBind(7, R_GetTexture(rsurface_lightmaptexture));
3082 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
3083 R_Mesh_TexBind(8, R_GetTexture(texturesurfacelist[0]->deluxemaptexture));
3084 R_Mesh_ColorPointer(NULL);
3088 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
3089 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
3090 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
3091 R_Mesh_ColorPointer(rsurface_model->surfmesh.data_lightmapcolor4f);
3093 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3096 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, msurface_t **texturesurfacelist)
3098 // OpenGL 1.3 path - anything not completely ancient
3099 int texturesurfaceindex;
3101 qboolean applycolor;
3105 const texturelayer_t *layer;
3107 // FIXME: identify models using a better check than rsurface_model->brush.shadowmesh
3108 lightmode = ((rsurface_entity->effects & EF_FULLBRIGHT) || rsurface_model->brush.shadowmesh) ? 0 : 2;
3109 if (rsurface_mode != RSURFMODE_MULTIPASS)
3110 rsurface_mode = RSURFMODE_MULTIPASS;
3111 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
3112 for (layerindex = 0, layer = rsurface_texture->currentlayers;layerindex < rsurface_texture->currentnumlayers;layerindex++, layer++)
3115 int layertexrgbscale;
3116 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
3118 if (layerindex == 0)
3122 GL_AlphaTest(false);
3123 qglDepthFunc(GL_EQUAL);CHECKGLERROR
3126 GL_DepthMask(layer->depthmask);
3127 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
3128 if ((layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2) && (gl_combine.integer || layer->depthmask))
3130 layertexrgbscale = 4;
3131 VectorScale(layer->color, 0.25f, layercolor);
3133 else if ((layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1) && (gl_combine.integer || layer->depthmask))
3135 layertexrgbscale = 2;
3136 VectorScale(layer->color, 0.5f, layercolor);
3140 layertexrgbscale = 1;
3141 VectorScale(layer->color, 1.0f, layercolor);
3143 layercolor[3] = layer->color[3];
3144 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
3145 R_Mesh_ColorPointer(NULL);
3146 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
3147 switch (layer->type)
3149 case TEXTURELAYERTYPE_LITTEXTURE:
3150 memset(&m, 0, sizeof(m));
3151 if (lightmode >= 1 || !rsurface_lightmaptexture)
3152 m.tex[0] = R_GetTexture(r_texture_white);
3154 m.tex[0] = R_GetTexture(rsurface_lightmaptexture);
3155 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordlightmap2f;
3156 m.tex[1] = R_GetTexture(layer->texture);
3157 m.texmatrix[1] = layer->texmatrix;
3158 m.texrgbscale[1] = layertexrgbscale;
3159 m.pointer_texcoord[1] = rsurface_model->surfmesh.data_texcoordtexture2f;
3160 R_Mesh_TextureState(&m);
3161 RSurf_DrawBatch_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], lightmode, applycolor, applyfog);
3163 case TEXTURELAYERTYPE_TEXTURE:
3164 memset(&m, 0, sizeof(m));
3165 m.tex[0] = R_GetTexture(layer->texture);
3166 m.texmatrix[0] = layer->texmatrix;
3167 m.texrgbscale[0] = layertexrgbscale;
3168 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3169 R_Mesh_TextureState(&m);
3170 RSurf_DrawBatch_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, applyfog);
3172 case TEXTURELAYERTYPE_FOG:
3173 memset(&m, 0, sizeof(m));
3174 m.texrgbscale[0] = layertexrgbscale;
3177 m.tex[0] = R_GetTexture(layer->texture);
3178 m.texmatrix[0] = layer->texmatrix;
3179 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3181 R_Mesh_TextureState(&m);
3182 // generate a color array for the fog pass
3183 R_Mesh_ColorPointer(rsurface_array_color4f);
3184 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3188 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3189 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)
3191 f = VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
3192 c[0] = layercolor[0];
3193 c[1] = layercolor[1];
3194 c[2] = layercolor[2];
3195 c[3] = f * layercolor[3];
3198 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3201 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
3203 GL_LockArrays(0, 0);
3206 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
3208 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3209 GL_AlphaTest(false);
3213 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, msurface_t **texturesurfacelist)
3215 // OpenGL 1.1 - crusty old voodoo path
3216 int texturesurfaceindex;
3221 const texturelayer_t *layer;
3223 // FIXME: identify models using a better check than rsurface_model->brush.shadowmesh
3224 lightmode = ((rsurface_entity->effects & EF_FULLBRIGHT) || rsurface_model->brush.shadowmesh) ? 0 : 2;
3225 if (rsurface_mode != RSURFMODE_MULTIPASS)
3226 rsurface_mode = RSURFMODE_MULTIPASS;
3227 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
3228 for (layerindex = 0, layer = rsurface_texture->currentlayers;layerindex < rsurface_texture->currentnumlayers;layerindex++, layer++)
3230 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
3232 if (layerindex == 0)
3236 GL_AlphaTest(false);
3237 qglDepthFunc(GL_EQUAL);CHECKGLERROR
3240 GL_DepthMask(layer->depthmask);
3241 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
3242 R_Mesh_ColorPointer(NULL);
3243 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
3244 switch (layer->type)
3246 case TEXTURELAYERTYPE_LITTEXTURE:
3247 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
3249 // two-pass lit texture with 2x rgbscale
3250 // first the lightmap pass
3251 memset(&m, 0, sizeof(m));
3252 if (lightmode >= 1 || !rsurface_lightmaptexture)
3253 m.tex[0] = R_GetTexture(r_texture_white);
3255 m.tex[0] = R_GetTexture(rsurface_lightmaptexture);
3256 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordlightmap2f;
3257 R_Mesh_TextureState(&m);
3258 RSurf_DrawBatch_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, lightmode, false, false);
3259 GL_LockArrays(0, 0);
3260 // then apply the texture to it
3261 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
3262 memset(&m, 0, sizeof(m));
3263 m.tex[0] = R_GetTexture(layer->texture);
3264 m.texmatrix[0] = layer->texmatrix;
3265 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3266 R_Mesh_TextureState(&m);
3267 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);
3271 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
3272 memset(&m, 0, sizeof(m));
3273 m.tex[0] = R_GetTexture(layer->texture);
3274 m.texmatrix[0] = layer->texmatrix;
3275 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3276 R_Mesh_TextureState(&m);
3277 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);
3280 case TEXTURELAYERTYPE_TEXTURE:
3281 // singletexture unlit texture with transparency support
3282 memset(&m, 0, sizeof(m));
3283 m.tex[0] = R_GetTexture(layer->texture);
3284 m.texmatrix[0] = layer->texmatrix;
3285 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3286 R_Mesh_TextureState(&m);
3287 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);
3289 case TEXTURELAYERTYPE_FOG:
3290 // singletexture fogging
3291 R_Mesh_ColorPointer(rsurface_array_color4f);
3294 memset(&m, 0, sizeof(m));
3295 m.tex[0] = R_GetTexture(layer->texture);
3296 m.texmatrix[0] = layer->texmatrix;
3297 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3298 R_Mesh_TextureState(&m);
3301 R_Mesh_ResetTextureState();
3302 // generate a color array for the fog pass
3303 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3307 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3308 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)
3310 f = VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
3311 c[0] = layer->color[0];
3312 c[1] = layer->color[1];
3313 c[2] = layer->color[2];
3314 c[3] = f * layer->color[3];
3317 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3320 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
3322 GL_LockArrays(0, 0);
3325 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
3327 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3328 GL_AlphaTest(false);
3332 static void R_DrawTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist)
3334 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_NODRAW)
3336 r_shadow_rtlight = NULL;
3337 r_refdef.stats.entities_surfaces += texturenumsurfaces;
3339 GL_DepthTest(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
3340 GL_CullFace(((rsurface_texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (rsurface_entity->flags & RENDER_NOCULLFACE)) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
3341 if (r_showsurfaces.integer)
3342 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
3343 else if (rsurface_texture->currentmaterialflags & MATERIALFLAG_SKY)
3344 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
3345 else if (rsurface_texture->currentnumlayers)
3347 if (r_glsl.integer && gl_support_fragment_shader)
3348 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist);
3349 else if (gl_combine.integer && r_textureunits.integer >= 2)
3350 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist);
3352 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist);
3355 GL_LockArrays(0, 0);
3358 #define BATCHSIZE 256
3359 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
3361 int surfacelistindex;
3364 msurface_t *texturesurfacelist[BATCHSIZE];
3365 // if the model is static it doesn't matter what value we give for
3366 // wantnormals and wanttangents, so this logic uses only rules applicable
3367 // to a model, knowing that they are meaningless otherwise
3368 if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
3369 RSurf_ActiveEntity(ent, false, false);
3371 RSurf_ActiveEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
3374 for (surfacelistindex = 0;surfacelistindex < numsurfaces;surfacelistindex++)
3376 msurface_t *surface = ent->model->data_surfaces + surfacelist[surfacelistindex];
3378 if (t != surface->texture || rsurface_lightmaptexture != surface->lightmaptexture)
3381 if (!(rsurface_texture->currentmaterialflags & MATERIALFLAG_SKY)) // transparent sky is too difficult
3382 R_DrawTextureSurfaceList(batchcount, texturesurfacelist);
3384 t = surface->texture;
3385 rsurface_lightmaptexture = surface->lightmaptexture;
3386 R_UpdateTextureInfo(ent, t);
3387 rsurface_texture = t->currentframe;
3390 texturesurfacelist[batchcount++] = surface;
3393 if (!(rsurface_texture->currentmaterialflags & MATERIALFLAG_SKY)) // transparent sky is too difficult
3394 R_DrawTextureSurfaceList(batchcount, texturesurfacelist);
3398 void R_QueueTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist)
3400 int texturesurfaceindex;
3401 vec3_t tempcenter, center;
3402 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_BLENDED)
3404 // drawing sky transparently would be too difficult
3405 if (!(rsurface_texture->currentmaterialflags & MATERIALFLAG_SKY))
3407 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3409 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3410 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
3411 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
3412 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
3413 Matrix4x4_Transform(&rsurface_entity->matrix, tempcenter, center);
3414 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);
3419 R_DrawTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
3422 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
3423 void R_DrawSurfaces(entity_render_t *ent, qboolean skysurfaces)
3425 int i, j, f, flagsmask;
3426 int counttriangles = 0;
3428 model_t *model = ent->model;
3429 const int maxsurfacelist = 1024;
3430 int numsurfacelist = 0;
3431 msurface_t *surfacelist[1024];
3435 // if the model is static it doesn't matter what value we give for
3436 // wantnormals and wanttangents, so this logic uses only rules applicable
3437 // to a model, knowing that they are meaningless otherwise
3438 if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
3439 RSurf_ActiveEntity(ent, false, false);
3441 RSurf_ActiveEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
3443 // update light styles
3444 if (!skysurfaces && model->brushq1.light_styleupdatechains)
3446 msurface_t *surface, **surfacechain;
3447 for (i = 0;i < model->brushq1.light_styles;i++)
3449 if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
3451 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
3452 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
3453 for (;(surface = *surfacechain);surfacechain++)
3454 surface->cached_dlight = true;
3459 R_UpdateAllTextureInfo(ent);
3460 flagsmask = skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL);
3463 rsurface_lightmaptexture = NULL;
3464 rsurface_texture = NULL;
3466 if (ent == r_refdef.worldentity)
3468 msurface_t *surface;
3469 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
3471 if (!r_viewcache.world_surfacevisible[j])
3473 if (t != surface->texture || rsurface_lightmaptexture != surface->lightmaptexture)
3477 R_QueueTextureSurfaceList(numsurfacelist, surfacelist);
3480 t = surface->texture;
3481 rsurface_lightmaptexture = surface->lightmaptexture;
3482 rsurface_texture = t->currentframe;
3483 f = rsurface_texture->currentmaterialflags & flagsmask;
3485 if (f && surface->num_triangles)
3487 // if lightmap parameters changed, rebuild lightmap texture
3488 if (surface->cached_dlight)
3489 R_BuildLightMap(ent, surface);
3490 // add face to draw list
3491 surfacelist[numsurfacelist++] = surface;
3492 counttriangles += surface->num_triangles;
3493 if (numsurfacelist >= maxsurfacelist)
3495 R_QueueTextureSurfaceList(numsurfacelist, surfacelist);
3503 msurface_t *surface;
3504 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
3506 if (t != surface->texture || rsurface_lightmaptexture != surface->lightmaptexture)
3510 R_QueueTextureSurfaceList(numsurfacelist, surfacelist);
3513 t = surface->texture;
3514 rsurface_lightmaptexture = surface->lightmaptexture;
3515 rsurface_texture = t->currentframe;
3516 f = rsurface_texture->currentmaterialflags & flagsmask;
3518 if (f && surface->num_triangles)
3520 // if lightmap parameters changed, rebuild lightmap texture
3521 if (surface->cached_dlight)
3522 R_BuildLightMap(ent, surface);
3523 // add face to draw list
3524 surfacelist[numsurfacelist++] = surface;
3525 counttriangles += surface->num_triangles;
3526 if (numsurfacelist >= maxsurfacelist)
3528 R_QueueTextureSurfaceList(numsurfacelist, surfacelist);
3535 R_QueueTextureSurfaceList(numsurfacelist, surfacelist);
3536 r_refdef.stats.entities_triangles += counttriangles;
3539 if (r_showcollisionbrushes.integer && model->brush.num_brushes && !skysurfaces)
3542 const msurface_t *surface;
3545 R_Mesh_Matrix(&ent->matrix);
3546 R_Mesh_ColorPointer(NULL);
3547 R_Mesh_ResetTextureState();
3548 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
3549 GL_DepthMask(false);
3550 GL_DepthTest(!r_showdisabledepthtest.integer);
3551 qglPolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);CHECKGLERROR
3552 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
3553 if (brush->colbrushf && brush->colbrushf->numtriangles)
3554 R_DrawCollisionBrush(brush->colbrushf);
3555 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
3556 if (surface->num_collisiontriangles)
3557 R_DrawCollisionSurface(ent, surface);
3558 qglPolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR
3561 if (r_showtris.integer || r_shownormals.integer)
3564 msurface_t *surface;
3565 const int *elements;
3570 if (r_showdisabledepthtest.integer)
3572 qglDepthFunc(GL_ALWAYS);CHECKGLERROR
3574 GL_BlendFunc(GL_ONE, GL_ZERO);
3575 R_Mesh_ColorPointer(NULL);
3576 R_Mesh_ResetTextureState();
3577 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
3579 if (ent == r_refdef.worldentity && !r_viewcache.world_surfacevisible[j])
3581 rsurface_texture = surface->texture->currentframe;
3582 if ((rsurface_texture->currentmaterialflags & flagsmask) && surface->num_triangles)
3584 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
3585 if (r_showtris.integer)
3587 if (!rsurface_texture->currentlayers->depthmask)
3588 GL_Color(r_showtris.value * r_view.colorscale, 0, 0, 1);
3589 else if (ent == r_refdef.worldentity)
3590 GL_Color(r_showtris.value * r_view.colorscale, r_showtris.value * r_view.colorscale, r_showtris.value * r_view.colorscale, 1);
3592 GL_Color(0, r_showtris.value * r_view.colorscale, 0, 1);
3593 elements = (ent->model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
3596 for (k = 0;k < surface->num_triangles;k++, elements += 3)
3598 qglArrayElement(elements[0]);qglArrayElement(elements[1]);
3599 qglArrayElement(elements[1]);qglArrayElement(elements[2]);
3600 qglArrayElement(elements[2]);qglArrayElement(elements[0]);
3605 if (r_shownormals.integer)
3607 GL_Color(r_shownormals.value * r_view.colorscale, 0, 0, 1);
3609 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
3611 VectorCopy(rsurface_vertex3f + l * 3, v);
3612 qglVertex3f(v[0], v[1], v[2]);
3613 VectorMA(v, 8, rsurface_svector3f + l * 3, v);
3614 qglVertex3f(v[0], v[1], v[2]);
3618 GL_Color(0, 0, r_shownormals.value * r_view.colorscale, 1);
3620 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
3622 VectorCopy(rsurface_vertex3f + l * 3, v);
3623 qglVertex3f(v[0], v[1], v[2]);
3624 VectorMA(v, 8, rsurface_tvector3f + l * 3, v);
3625 qglVertex3f(v[0], v[1], v[2]);
3629 GL_Color(0, r_shownormals.value * r_view.colorscale, 0, 1);
3631 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
3633 VectorCopy(rsurface_vertex3f + l * 3, v);
3634 qglVertex3f(v[0], v[1], v[2]);
3635 VectorMA(v, 8, rsurface_normal3f + l * 3, v);
3636 qglVertex3f(v[0], v[1], v[2]);
3643 rsurface_texture = NULL;
3644 if (r_showdisabledepthtest.integer)
3646 qglDepthFunc(GL_LEQUAL);CHECKGLERROR