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", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
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_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
80 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
81 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
82 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
83 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
84 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
86 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
87 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
88 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
89 cvar_t r_hdr_range = {CVAR_SAVE, "r_hdr_range", "4", "how much dynamic range to render bloom with (equivilant to multiplying r_bloom_brighten by this value and dividing r_bloom_colorscale by this value)"};
91 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"};
93 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"};
95 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
97 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
98 cvar_t r_batchmode = {0, "r_batchmode", "1", "selects method of rendering multiple surfaces with one driver call (values are 0, 1, 2, etc...)"};
100 typedef struct r_glsl_bloomshader_s
103 int loc_Texture_Bloom;
105 r_glsl_bloomshader_t;
107 static struct r_bloomstate_s
112 int bloomwidth, bloomheight;
114 int screentexturewidth, screentextureheight;
115 rtexture_t *texture_screen;
117 int bloomtexturewidth, bloomtextureheight;
118 rtexture_t *texture_bloom;
120 r_glsl_bloomshader_t *shader;
122 // arrays for rendering the screen passes
123 float screentexcoord2f[8];
124 float bloomtexcoord2f[8];
125 float offsettexcoord2f[8];
129 // shadow volume bsp struct with automatically growing nodes buffer
132 rtexture_t *r_texture_blanknormalmap;
133 rtexture_t *r_texture_white;
134 rtexture_t *r_texture_black;
135 rtexture_t *r_texture_notexture;
136 rtexture_t *r_texture_whitecube;
137 rtexture_t *r_texture_normalizationcube;
138 rtexture_t *r_texture_fogattenuation;
139 //rtexture_t *r_texture_fogintensity;
141 // information about each possible shader permutation
142 r_glsl_permutation_t r_glsl_permutations[SHADERPERMUTATION_COUNT];
143 // currently selected permutation
144 r_glsl_permutation_t *r_glsl_permutation;
146 // temporary variable used by a macro
149 // vertex coordinates for a quad that covers the screen exactly
150 const static float r_screenvertex3f[12] =
158 extern void R_DrawModelShadows(void);
160 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
163 for (i = 0;i < verts;i++)
174 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
177 for (i = 0;i < verts;i++)
187 // FIXME: move this to client?
190 if (gamemode == GAME_NEHAHRA)
192 Cvar_Set("gl_fogenable", "0");
193 Cvar_Set("gl_fogdensity", "0.2");
194 Cvar_Set("gl_fogred", "0.3");
195 Cvar_Set("gl_foggreen", "0.3");
196 Cvar_Set("gl_fogblue", "0.3");
198 r_refdef.fog_density = r_refdef.fog_red = r_refdef.fog_green = r_refdef.fog_blue = 0.0f;
201 // FIXME: move this to client?
202 void FOG_registercvars(void)
207 if (gamemode == GAME_NEHAHRA)
209 Cvar_RegisterVariable (&gl_fogenable);
210 Cvar_RegisterVariable (&gl_fogdensity);
211 Cvar_RegisterVariable (&gl_fogred);
212 Cvar_RegisterVariable (&gl_foggreen);
213 Cvar_RegisterVariable (&gl_fogblue);
214 Cvar_RegisterVariable (&gl_fogstart);
215 Cvar_RegisterVariable (&gl_fogend);
218 r = (-1.0/256.0) * (FOGTABLEWIDTH * FOGTABLEWIDTH);
219 for (x = 0;x < FOGTABLEWIDTH;x++)
221 alpha = exp(r / ((double)x*(double)x));
222 if (x == FOGTABLEWIDTH - 1)
224 r_refdef.fogtable[x] = bound(0, alpha, 1);
228 static void R_BuildBlankTextures(void)
230 unsigned char data[4];
231 data[0] = 128; // normal X
232 data[1] = 128; // normal Y
233 data[2] = 255; // normal Z
234 data[3] = 128; // height
235 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
240 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
245 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
248 static void R_BuildNoTexture(void)
251 unsigned char pix[16][16][4];
252 // this makes a light grey/dark grey checkerboard texture
253 for (y = 0;y < 16;y++)
255 for (x = 0;x < 16;x++)
257 if ((y < 8) ^ (x < 8))
273 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_RGBA, TEXF_MIPMAP, NULL);
276 static void R_BuildWhiteCube(void)
278 unsigned char data[6*1*1*4];
279 data[ 0] = 255;data[ 1] = 255;data[ 2] = 255;data[ 3] = 255;
280 data[ 4] = 255;data[ 5] = 255;data[ 6] = 255;data[ 7] = 255;
281 data[ 8] = 255;data[ 9] = 255;data[10] = 255;data[11] = 255;
282 data[12] = 255;data[13] = 255;data[14] = 255;data[15] = 255;
283 data[16] = 255;data[17] = 255;data[18] = 255;data[19] = 255;
284 data[20] = 255;data[21] = 255;data[22] = 255;data[23] = 255;
285 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
288 static void R_BuildNormalizationCube(void)
292 vec_t s, t, intensity;
294 unsigned char data[6][NORMSIZE][NORMSIZE][4];
295 for (side = 0;side < 6;side++)
297 for (y = 0;y < NORMSIZE;y++)
299 for (x = 0;x < NORMSIZE;x++)
301 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
302 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
337 intensity = 127.0f / sqrt(DotProduct(v, v));
338 data[side][y][x][0] = (unsigned char)(128.0f + intensity * v[0]);
339 data[side][y][x][1] = (unsigned char)(128.0f + intensity * v[1]);
340 data[side][y][x][2] = (unsigned char)(128.0f + intensity * v[2]);
341 data[side][y][x][3] = 255;
345 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, &data[0][0][0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
348 static void R_BuildFogTexture(void)
353 unsigned char data1[FOGWIDTH][4];
354 //unsigned char data2[FOGWIDTH][4];
355 r = (-1.0/256.0) * (FOGWIDTH * FOGWIDTH);
356 for (x = 0;x < FOGWIDTH;x++)
358 alpha = exp(r / ((double)x*(double)x));
359 if (x == FOGWIDTH - 1)
361 b = (int)(256.0 * alpha);
362 b = bound(0, b, 255);
363 data1[x][0] = 255 - b;
364 data1[x][1] = 255 - b;
365 data1[x][2] = 255 - b;
372 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
373 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
376 static const char *builtinshaderstring =
377 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
378 "// written by Forest 'LordHavoc' Hale\n"
380 "// common definitions between vertex shader and fragment shader:\n"
382 "#ifdef __GLSL_CG_DATA_TYPES\n"
383 "#define myhalf half\n"
384 "#define myhvec2 hvec2\n"
385 "#define myhvec3 hvec3\n"
386 "#define myhvec4 hvec4\n"
388 "#define myhalf float\n"
389 "#define myhvec2 vec2\n"
390 "#define myhvec3 vec3\n"
391 "#define myhvec4 vec4\n"
394 "varying vec2 TexCoord;\n"
395 "varying vec2 TexCoordLightmap;\n"
397 "varying vec3 CubeVector;\n"
398 "varying vec3 LightVector;\n"
399 "varying vec3 EyeVector;\n"
401 "varying vec3 EyeVectorModelSpace;\n"
404 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
405 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
406 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
411 "// vertex shader specific:\n"
412 "#ifdef VERTEX_SHADER\n"
414 "uniform vec3 LightPosition;\n"
415 "uniform vec3 EyePosition;\n"
416 "uniform vec3 LightDir;\n"
418 "// TODO: get rid of tangentt (texcoord2) and use a crossproduct to regenerate it from tangents (texcoord1) and normal (texcoord3)\n"
422 " gl_FrontColor = gl_Color;\n"
423 " // copy the surface texcoord\n"
424 " TexCoord = vec2(gl_TextureMatrix[0] * gl_MultiTexCoord0);\n"
425 "#if !defined(MODE_LIGHTSOURCE) && !defined(MODE_LIGHTDIRECTION)\n"
426 " TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
429 "#ifdef MODE_LIGHTSOURCE\n"
430 " // transform vertex position into light attenuation/cubemap space\n"
431 " // (-1 to +1 across the light box)\n"
432 " CubeVector = vec3(gl_TextureMatrix[3] * gl_Vertex);\n"
434 " // transform unnormalized light direction into tangent space\n"
435 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
436 " // normalize it per pixel)\n"
437 " vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
438 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
439 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
440 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
443 "#ifdef MODE_LIGHTDIRECTION\n"
444 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
445 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
446 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
449 " // transform unnormalized eye direction into tangent space\n"
451 " vec3 EyeVectorModelSpace;\n"
453 " EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
454 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
455 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
456 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
458 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
459 " VectorS = gl_MultiTexCoord1.xyz;\n"
460 " VectorT = gl_MultiTexCoord2.xyz;\n"
461 " VectorR = gl_MultiTexCoord3.xyz;\n"
464 " // transform vertex to camera space, using ftransform to match non-VS\n"
466 " gl_Position = ftransform();\n"
469 "#endif // VERTEX_SHADER\n"
474 "// fragment shader specific:\n"
475 "#ifdef FRAGMENT_SHADER\n"
477 "uniform sampler2D Texture_Normal;\n"
478 "uniform sampler2D Texture_Color;\n"
479 "uniform sampler2D Texture_Gloss;\n"
480 "uniform samplerCube Texture_Cube;\n"
481 "uniform sampler2D Texture_FogMask;\n"
482 "uniform sampler2D Texture_Pants;\n"
483 "uniform sampler2D Texture_Shirt;\n"
484 "uniform sampler2D Texture_Lightmap;\n"
485 "uniform sampler2D Texture_Deluxemap;\n"
486 "uniform sampler2D Texture_Glow;\n"
488 "uniform myhvec3 LightColor;\n"
489 "uniform myhvec3 AmbientColor;\n"
490 "uniform myhvec3 DiffuseColor;\n"
491 "uniform myhvec3 SpecularColor;\n"
492 "uniform myhvec3 Color_Pants;\n"
493 "uniform myhvec3 Color_Shirt;\n"
494 "uniform myhvec3 FogColor;\n"
496 "uniform myhalf GlowScale;\n"
497 "uniform myhalf SceneBrightness;\n"
499 "uniform float OffsetMapping_Scale;\n"
500 "uniform float OffsetMapping_Bias;\n"
501 "uniform float FogRangeRecip;\n"
503 "uniform myhalf AmbientScale;\n"
504 "uniform myhalf DiffuseScale;\n"
505 "uniform myhalf SpecularScale;\n"
506 "uniform myhalf SpecularPower;\n"
510 " // apply offsetmapping\n"
511 "#ifdef USEOFFSETMAPPING\n"
512 " vec2 TexCoordOffset = TexCoord;\n"
513 "#define TexCoord TexCoordOffset\n"
515 " vec3 eyedir = vec3(normalize(EyeVector));\n"
516 " float depthbias = 1.0 - eyedir.z; // should this be a -?\n"
517 " depthbias = 1.0 - depthbias * depthbias;\n"
519 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
520 " // 14 sample relief mapping: linear search and then binary search\n"
521 " //vec3 OffsetVector = vec3(EyeVector.xy * (1.0 / EyeVector.z) * depthbias * OffsetMapping_Scale * vec2(-0.1, 0.1), -0.1);\n"
522 " //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-0.1, 0.1), -0.1);\n"
523 " vec3 OffsetVector = vec3(eyedir.xy * OffsetMapping_Scale * vec2(-0.1, 0.1), -0.1);\n"
524 " vec3 RT = vec3(TexCoord - OffsetVector.xy * 10.0, 1.0) + OffsetVector;\n"
525 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
526 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
527 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
528 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
529 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
530 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
531 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
532 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
533 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;OffsetVector *= 0.5;RT -= OffsetVector;\n"
534 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;OffsetVector *= 0.5;RT -= OffsetVector;\n"
535 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;OffsetVector *= 0.5;RT -= OffsetVector;\n"
536 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;OffsetVector *= 0.5;RT -= OffsetVector;\n"
537 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;OffsetVector *= 0.5;RT -= OffsetVector;\n"
538 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;OffsetVector *= 0.5;RT -= OffsetVector;\n"
539 " TexCoord = RT.xy;\n"
541 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
542 " //vec2 OffsetVector = vec2(EyeVector.xy * (1.0 / EyeVector.z) * depthbias) * OffsetMapping_Scale * vec2(-0.333, 0.333);\n"
543 " //vec2 OffsetVector = vec2(normalize(EyeVector.xy)) * OffsetMapping_Scale * vec2(-0.333, 0.333);\n"
544 " vec2 OffsetVector = vec2(eyedir.xy) * OffsetMapping_Scale * vec2(-0.333, 0.333);\n"
545 " //TexCoord += OffsetVector * 3.0;\n"
546 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
547 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
548 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
550 " // 10 sample offset mapping\n"
551 " //vec2 OffsetVector = vec2(EyeVector.xy * (1.0 / EyeVector.z) * depthbias) * OffsetMapping_Scale * vec2(-0.333, 0.333);\n"
552 " //vec2 OffsetVector = vec2(normalize(EyeVector.xy)) * OffsetMapping_Scale * vec2(-0.333, 0.333);\n"
553 " vec2 OffsetVector = vec2(eyedir.xy) * OffsetMapping_Scale * vec2(-0.1, 0.1);\n"
554 " //TexCoord += OffsetVector * 3.0;\n"
555 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
556 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
557 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
558 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
559 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
560 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
561 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
562 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
563 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
564 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
566 " // parallax mapping as described in the paper\n"
567 " // 'Parallax Mapping with Offset Limiting: A Per-Pixel Approximation of Uneven Surfaces' by Terry Welsh\n"
568 " // The paper provides code in the ARB fragment program assembly language\n"
569 " // I translated it to GLSL but may have done something wrong - SavageX\n"
570 " // LordHavoc: removed bias and simplified to one line\n"
571 " // LordHavoc: this is just a single sample offsetmapping...\n"
572 " TexCoordOffset += vec2(eyedir.x, -1.0 * eyedir.y) * OffsetMapping_Scale * texture2D(Texture_Normal, TexCoord).a;\n"
574 " // parallax mapping as described in the paper\n"
575 " // 'Parallax Mapping with Offset Limiting: A Per-Pixel Approximation of Uneven Surfaces' by Terry Welsh\n"
576 " // The paper provides code in the ARB fragment program assembly language\n"
577 " // I translated it to GLSL but may have done something wrong - SavageX\n"
578 " float height = texture2D(Texture_Normal, TexCoord).a;\n"
579 " height = (height - 0.5) * OffsetMapping_Scale; // bias and scale\n"
580 " TexCoordOffset += height * vec2(eyedir.x, -1.0 * eyedir.y);\n"
584 " // combine the diffuse textures (base, pants, shirt)\n"
585 " myhvec4 color = myhvec4(texture2D(Texture_Color, TexCoord));\n"
586 "#ifdef USECOLORMAPPING\n"
587 " color.rgb += myhvec3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhvec3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
593 "#ifdef MODE_LIGHTSOURCE\n"
596 " // get the surface normal and light normal\n"
597 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
598 " myhvec3 diffusenormal = myhvec3(normalize(LightVector));\n"
600 " // calculate directional shading\n"
601 " color.rgb *= AmbientScale + DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
602 "#ifdef USESPECULAR\n"
603 " myhvec3 specularnormal = normalize(diffusenormal + myhvec3(normalize(EyeVector)));\n"
604 " color.rgb += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
607 "#ifdef USECUBEFILTER\n"
608 " // apply light cubemap filter\n"
609 " //color.rgb *= normalize(CubeVector) * 0.5 + 0.5;//vec3(textureCube(Texture_Cube, CubeVector));\n"
610 " color.rgb *= myhvec3(textureCube(Texture_Cube, CubeVector));\n"
613 " // apply light color\n"
614 " color.rgb *= LightColor;\n"
616 " // apply attenuation\n"
618 " // the attenuation is (1-(x*x+y*y+z*z)) which gives a large bright\n"
619 " // center and sharp falloff at the edge, this is about the most efficient\n"
620 " // we can get away with as far as providing illumination.\n"
622 " // pow(1-(x*x+y*y+z*z), 4) is far more realistic but needs large lights to\n"
623 " // provide significant illumination, large = slow = pain.\n"
624 "// color.rgb *= myhalf(max(1.0 - dot(CubeVector, CubeVector), 0.0));\n"
625 " color.rgb *= myhalf(max(2.0 - 2.0 * length(CubeVector), 0.0) / (1 + dot(CubeVector, CubeVector)));\n"
630 "#elif defined(MODE_LIGHTDIRECTION)\n"
631 " // directional model lighting\n"
633 " // get the surface normal and light normal\n"
634 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
635 " myhvec3 diffusenormal = myhvec3(normalize(LightVector));\n"
637 " // calculate directional shading\n"
638 " color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
639 "#ifdef USESPECULAR\n"
640 " myhvec3 specularnormal = normalize(diffusenormal + myhvec3(normalize(EyeVector)));\n"
641 " color.rgb += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
647 "#elif defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
648 " // deluxemap lightmapping using light vectors in modelspace (evil q3map2)\n"
650 " // get the surface normal and light normal\n"
651 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
653 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
654 " myhvec3 diffusenormal_modelspace = myhvec3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - myhvec3(0.5);\n"
655 " myhvec3 diffusenormal = normalize(myhvec3(dot(diffusenormal_modelspace, myhvec3(VectorS)), dot(diffusenormal_modelspace, myhvec3(VectorT)), dot(diffusenormal_modelspace, myhvec3(VectorR))));\n"
657 " myhvec3 diffusenormal = normalize(myhvec3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - myhvec3(0.5));\n"
659 " // calculate directional shading\n"
660 " myhvec3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0)));\n"
661 "#ifdef USESPECULAR\n"
662 " myhvec3 specularnormal = myhvec3(normalize(diffusenormal + myhvec3(normalize(EyeVector))));\n"
663 " tempcolor += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
666 " // apply lightmap color\n"
667 " color.rgb = tempcolor * myhvec3(texture2D(Texture_Lightmap, TexCoordLightmap)) + color.rgb * AmbientScale;\n"
670 "#else // MODE none (lightmap)\n"
671 " // apply lightmap color\n"
672 " color.rgb *= myhvec3(texture2D(Texture_Lightmap, TexCoordLightmap)) * DiffuseScale + myhvec3(AmbientScale);\n"
675 " color *= myhvec4(gl_Color);\n"
678 " color.rgb += myhvec3(texture2D(Texture_Glow, TexCoord)) * GlowScale;\n"
683 " myhalf fog = myhalf(texture2D(Texture_FogMask, myhvec2(length(EyeVectorModelSpace)*FogRangeRecip, 0.0)).x);\n"
684 " color.rgb = color.rgb * fog + FogColor * (1.0 - fog);\n"
687 " color.rgb *= SceneBrightness;\n"
689 " gl_FragColor = vec4(color);\n"
692 "#endif // FRAGMENT_SHADER\n"
695 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
696 const char *permutationinfo[][2] =
698 {"#define MODE_LIGHTSOURCE\n", " lightsource"},
699 {"#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
700 {"#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
701 {"#define MODE_LIGHTDIRECTION\n", " lightdirection"},
702 {"#define USEGLOW\n", " glow"},
703 {"#define USEFOG\n", " fog"},
704 {"#define USECOLORMAPPING\n", " colormapping"},
705 {"#define USESPECULAR\n", " specular"},
706 {"#define USECUBEFILTER\n", " cubefilter"},
707 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
708 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
712 void R_GLSL_CompilePermutation(const char *filename, int permutation)
715 qboolean shaderfound;
716 r_glsl_permutation_t *p = r_glsl_permutations + (permutation & SHADERPERMUTATION_COUNTMASK);
717 int vertstrings_count;
718 int geomstrings_count;
719 int fragstrings_count;
721 const char *vertstrings_list[SHADERPERMUTATION_COUNT+1];
722 const char *geomstrings_list[SHADERPERMUTATION_COUNT+1];
723 const char *fragstrings_list[SHADERPERMUTATION_COUNT+1];
724 char permutationname[256];
729 vertstrings_list[0] = "#define VERTEX_SHADER\n";
730 geomstrings_list[0] = "#define GEOMETRY_SHADER\n";
731 fragstrings_list[0] = "#define FRAGMENT_SHADER\n";
732 vertstrings_count = 1;
733 geomstrings_count = 1;
734 fragstrings_count = 1;
735 permutationname[0] = 0;
736 for (i = 0;permutationinfo[i][0];i++)
738 if (permutation & (1<<i))
740 vertstrings_list[vertstrings_count++] = permutationinfo[i][0];
741 geomstrings_list[geomstrings_count++] = permutationinfo[i][0];
742 fragstrings_list[fragstrings_count++] = permutationinfo[i][0];
743 strlcat(permutationname, permutationinfo[i][1], sizeof(permutationname));
747 // keep line numbers correct
748 vertstrings_list[vertstrings_count++] = "\n";
749 geomstrings_list[geomstrings_count++] = "\n";
750 fragstrings_list[fragstrings_count++] = "\n";
753 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
757 Con_DPrintf("GLSL shader text for \"%s\" loaded from disk\n", filename);
758 vertstrings_list[vertstrings_count++] = shaderstring;
759 geomstrings_list[geomstrings_count++] = shaderstring;
760 fragstrings_list[fragstrings_count++] = shaderstring;
763 else if (!strcmp(filename, "glsl/default.glsl"))
765 Con_DPrintf("GLSL shader text for \"%s\" loaded from engine\n", filename);
766 vertstrings_list[vertstrings_count++] = builtinshaderstring;
767 geomstrings_list[geomstrings_count++] = builtinshaderstring;
768 fragstrings_list[fragstrings_count++] = builtinshaderstring;
771 // clear any lists that are not needed by this shader
772 if (!(permutation & SHADERPERMUTATION_USES_VERTEXSHADER))
773 vertstrings_count = 0;
774 if (!(permutation & SHADERPERMUTATION_USES_GEOMETRYSHADER))
775 geomstrings_count = 0;
776 if (!(permutation & SHADERPERMUTATION_USES_FRAGMENTSHADER))
777 fragstrings_count = 0;
778 // compile the shader program
779 if (shaderfound && vertstrings_count + geomstrings_count + fragstrings_count)
780 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
784 qglUseProgramObjectARB(p->program);CHECKGLERROR
785 // look up all the uniform variable names we care about, so we don't
786 // have to look them up every time we set them
787 p->loc_Texture_Normal = qglGetUniformLocationARB(p->program, "Texture_Normal");
788 p->loc_Texture_Color = qglGetUniformLocationARB(p->program, "Texture_Color");
789 p->loc_Texture_Gloss = qglGetUniformLocationARB(p->program, "Texture_Gloss");
790 p->loc_Texture_Cube = qglGetUniformLocationARB(p->program, "Texture_Cube");
791 p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
792 p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
793 p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
794 p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
795 p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
796 p->loc_Texture_Glow = qglGetUniformLocationARB(p->program, "Texture_Glow");
797 p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
798 p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
799 p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
800 p->loc_LightColor = qglGetUniformLocationARB(p->program, "LightColor");
801 p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants");
802 p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt");
803 p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip");
804 p->loc_AmbientScale = qglGetUniformLocationARB(p->program, "AmbientScale");
805 p->loc_DiffuseScale = qglGetUniformLocationARB(p->program, "DiffuseScale");
806 p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
807 p->loc_SpecularScale = qglGetUniformLocationARB(p->program, "SpecularScale");
808 p->loc_GlowScale = qglGetUniformLocationARB(p->program, "GlowScale");
809 p->loc_SceneBrightness = qglGetUniformLocationARB(p->program, "SceneBrightness");
810 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
811 p->loc_AmbientColor = qglGetUniformLocationARB(p->program, "AmbientColor");
812 p->loc_DiffuseColor = qglGetUniformLocationARB(p->program, "DiffuseColor");
813 p->loc_SpecularColor = qglGetUniformLocationARB(p->program, "SpecularColor");
814 p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
815 // initialize the samplers to refer to the texture units we use
816 if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal, 0);
817 if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color, 1);
818 if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss, 2);
819 if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube, 3);
820 if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask, 4);
821 if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants, 5);
822 if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt, 6);
823 if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap, 7);
824 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap, 8);
825 if (p->loc_Texture_Glow >= 0) qglUniform1iARB(p->loc_Texture_Glow, 9);
827 qglUseProgramObjectARB(0);CHECKGLERROR
830 Con_Printf("permutation%s failed for shader %s, some features may not work properly!\n", permutationname, "glsl/default.glsl");
832 Mem_Free(shaderstring);
835 void R_GLSL_Restart_f(void)
838 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
839 if (r_glsl_permutations[i].program)
840 GL_Backend_FreeProgram(r_glsl_permutations[i].program);
841 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
844 int R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting)
846 // select a permutation of the lighting shader appropriate to this
847 // combination of texture, entity, light source, and fogging, only use the
848 // minimum features necessary to avoid wasting rendering time in the
849 // fragment shader on features that are not being used
850 const char *shaderfilename = NULL;
852 float specularscale = rsurface_texture->specularscale;
853 r_glsl_permutation = NULL;
854 // TODO: implement geometry-shader based shadow volumes someday
855 if (r_shadow_rtlight)
858 shaderfilename = "glsl/default.glsl";
859 permutation = SHADERPERMUTATION_MODE_LIGHTSOURCE | SHADERPERMUTATION_USES_VERTEXSHADER | SHADERPERMUTATION_USES_FRAGMENTSHADER;
860 specularscale *= r_shadow_rtlight->specularscale;
861 if (r_shadow_rtlight->currentcubemap != r_texture_whitecube)
862 permutation |= SHADERPERMUTATION_CUBEFILTER;
863 if (specularscale > 0)
864 permutation |= SHADERPERMUTATION_SPECULAR;
865 if (r_refdef.fogenabled)
866 permutation |= SHADERPERMUTATION_FOG;
867 if (rsurface_texture->colormapping)
868 permutation |= SHADERPERMUTATION_COLORMAPPING;
869 if (r_glsl_offsetmapping.integer)
871 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
872 if (r_glsl_offsetmapping_reliefmapping.integer)
873 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
876 else if (rsurface_texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
878 // bright unshaded geometry
879 shaderfilename = "glsl/default.glsl";
880 permutation = SHADERPERMUTATION_USES_VERTEXSHADER | SHADERPERMUTATION_USES_FRAGMENTSHADER;
881 if (rsurface_texture->currentskinframe->glow)
882 permutation |= SHADERPERMUTATION_GLOW;
883 if (r_refdef.fogenabled)
884 permutation |= SHADERPERMUTATION_FOG;
885 if (rsurface_texture->colormapping)
886 permutation |= SHADERPERMUTATION_COLORMAPPING;
887 if (r_glsl_offsetmapping.integer)
889 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
890 if (r_glsl_offsetmapping_reliefmapping.integer)
891 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
894 else if (modellighting)
896 // directional model lighting
897 shaderfilename = "glsl/default.glsl";
898 permutation = SHADERPERMUTATION_USES_VERTEXSHADER | SHADERPERMUTATION_USES_FRAGMENTSHADER;
899 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTION;
900 if (rsurface_texture->currentskinframe->glow)
901 permutation |= SHADERPERMUTATION_GLOW;
902 if (specularscale > 0)
903 permutation |= SHADERPERMUTATION_SPECULAR;
904 if (r_refdef.fogenabled)
905 permutation |= SHADERPERMUTATION_FOG;
906 if (rsurface_texture->colormapping)
907 permutation |= SHADERPERMUTATION_COLORMAPPING;
908 if (r_glsl_offsetmapping.integer)
910 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
911 if (r_glsl_offsetmapping_reliefmapping.integer)
912 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
918 shaderfilename = "glsl/default.glsl";
919 permutation = SHADERPERMUTATION_USES_VERTEXSHADER | SHADERPERMUTATION_USES_FRAGMENTSHADER;
920 if (r_glsl_deluxemapping.integer >= 1 && rsurface_uselightmaptexture && r_refdef.worldmodel && r_refdef.worldmodel->brushq3.deluxemapping)
922 // deluxemapping (light direction texture)
923 if (rsurface_uselightmaptexture && r_refdef.worldmodel && r_refdef.worldmodel->brushq3.deluxemapping && r_refdef.worldmodel->brushq3.deluxemapping_modelspace)
924 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_MODELSPACE;
926 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
927 if (specularscale > 0)
928 permutation |= SHADERPERMUTATION_SPECULAR;
930 else if (r_glsl_deluxemapping.integer >= 2)
932 // fake deluxemapping (uniform light direction in tangentspace)
933 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
934 if (specularscale > 0)
935 permutation |= SHADERPERMUTATION_SPECULAR;
939 // ordinary lightmapping
942 if (rsurface_texture->currentskinframe->glow)
943 permutation |= SHADERPERMUTATION_GLOW;
944 if (r_refdef.fogenabled)
945 permutation |= SHADERPERMUTATION_FOG;
946 if (rsurface_texture->colormapping)
947 permutation |= SHADERPERMUTATION_COLORMAPPING;
948 if (r_glsl_offsetmapping.integer)
950 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
951 if (r_glsl_offsetmapping_reliefmapping.integer)
952 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
955 if (!r_glsl_permutations[permutation & SHADERPERMUTATION_COUNTMASK].program)
957 if (!r_glsl_permutations[permutation & SHADERPERMUTATION_COUNTMASK].compiled)
958 R_GLSL_CompilePermutation(shaderfilename, permutation);
959 if (!r_glsl_permutations[permutation & SHADERPERMUTATION_COUNTMASK].program)
961 // remove features until we find a valid permutation
963 for (i = SHADERPERMUTATION_COUNT-1;;i>>=1)
965 // reduce i more quickly whenever it would not remove any bits
969 if (!r_glsl_permutations[permutation & SHADERPERMUTATION_COUNTMASK].compiled)
970 R_GLSL_CompilePermutation(shaderfilename, permutation);
971 if (r_glsl_permutations[permutation & SHADERPERMUTATION_COUNTMASK].program)
974 return 0; // utterly failed
978 r_glsl_permutation = r_glsl_permutations + (permutation & SHADERPERMUTATION_COUNTMASK);
980 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
981 R_Mesh_TexMatrix(0, &rsurface_texture->currenttexmatrix);
982 if (permutation & SHADERPERMUTATION_MODE_LIGHTSOURCE)
984 if (r_glsl_permutation->loc_Texture_Cube >= 0 && r_shadow_rtlight) R_Mesh_TexBindCubeMap(3, R_GetTexture(r_shadow_rtlight->currentcubemap));
985 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]);
986 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
987 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_shadow_rtlight->ambientscale);
988 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_shadow_rtlight->diffusescale);
989 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, specularscale);
991 else if (permutation & SHADERPERMUTATION_MODE_LIGHTDIRECTION)
993 if (r_glsl_permutation->loc_AmbientColor >= 0)
994 qglUniform3fARB(r_glsl_permutation->loc_AmbientColor, rsurface_entity->modellight_ambient[0], rsurface_entity->modellight_ambient[1], rsurface_entity->modellight_ambient[2]);
995 if (r_glsl_permutation->loc_DiffuseColor >= 0)
996 qglUniform3fARB(r_glsl_permutation->loc_DiffuseColor, rsurface_entity->modellight_diffuse[0], rsurface_entity->modellight_diffuse[1], rsurface_entity->modellight_diffuse[2]);
997 if (r_glsl_permutation->loc_SpecularColor >= 0)
998 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);
999 if (r_glsl_permutation->loc_LightDir >= 0)
1000 qglUniform3fARB(r_glsl_permutation->loc_LightDir, rsurface_entity->modellight_lightdir[0], rsurface_entity->modellight_lightdir[1], rsurface_entity->modellight_lightdir[2]);
1004 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_ambient.value * 2.0f / 128.0f);
1005 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_refdef.lightmapintensity * 2.0f);
1006 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, r_refdef.lightmapintensity * specularscale * 2.0f);
1008 if (r_glsl_permutation->loc_Texture_Normal >= 0) R_Mesh_TexBind(0, R_GetTexture(rsurface_texture->currentskinframe->nmap));
1009 if (r_glsl_permutation->loc_Texture_Color >= 0) R_Mesh_TexBind(1, R_GetTexture(rsurface_texture->basetexture));
1010 if (r_glsl_permutation->loc_Texture_Gloss >= 0) R_Mesh_TexBind(2, R_GetTexture(rsurface_texture->glosstexture));
1011 //if (r_glsl_permutation->loc_Texture_Cube >= 0 && permutation & SHADERPERMUTATION_MODE_LIGHTSOURCE) R_Mesh_TexBindCubeMap(3, R_GetTexture(r_shadow_rtlight->currentcubemap));
1012 if (r_glsl_permutation->loc_Texture_FogMask >= 0) R_Mesh_TexBind(4, R_GetTexture(r_texture_fogattenuation));
1013 if (r_glsl_permutation->loc_Texture_Pants >= 0) R_Mesh_TexBind(5, R_GetTexture(rsurface_texture->currentskinframe->pants));
1014 if (r_glsl_permutation->loc_Texture_Shirt >= 0) R_Mesh_TexBind(6, R_GetTexture(rsurface_texture->currentskinframe->shirt));
1015 //if (r_glsl_permutation->loc_Texture_Lightmap >= 0) R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
1016 //if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
1017 if (r_glsl_permutation->loc_Texture_Glow >= 0) R_Mesh_TexBind(9, R_GetTexture(rsurface_texture->currentskinframe->glow));
1018 if (r_glsl_permutation->loc_GlowScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_GlowScale, r_hdr_glowintensity.value);
1019 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_view.colorscale);
1020 if (r_glsl_permutation->loc_FogColor >= 0)
1022 // additive passes are only darkened by fog, not tinted
1023 if (r_shadow_rtlight || (rsurface_texture->currentmaterialflags & MATERIALFLAG_ADD))
1024 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
1026 qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
1028 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface_modelorg[0], rsurface_modelorg[1], rsurface_modelorg[2]);
1029 if (r_glsl_permutation->loc_Color_Pants >= 0)
1031 if (rsurface_texture->currentskinframe->pants)
1032 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface_entity->colormap_pantscolor[0], rsurface_entity->colormap_pantscolor[1], rsurface_entity->colormap_pantscolor[2]);
1034 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
1036 if (r_glsl_permutation->loc_Color_Shirt >= 0)
1038 if (rsurface_texture->currentskinframe->shirt)
1039 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface_entity->colormap_shirtcolor[0], rsurface_entity->colormap_shirtcolor[1], rsurface_entity->colormap_shirtcolor[2]);
1041 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
1043 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, r_refdef.fograngerecip);
1044 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface_texture->specularpower);
1045 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
1050 void R_SwitchSurfaceShader(int permutation)
1052 if (r_glsl_permutation != r_glsl_permutations + (permutation & SHADERPERMUTATION_COUNTMASK))
1054 r_glsl_permutation = r_glsl_permutations + (permutation & SHADERPERMUTATION_COUNTMASK);
1056 qglUseProgramObjectARB(r_glsl_permutation->program);
1061 void gl_main_start(void)
1063 r_main_texturepool = R_AllocTexturePool();
1064 R_BuildBlankTextures();
1066 if (gl_texturecubemap)
1069 R_BuildNormalizationCube();
1071 R_BuildFogTexture();
1072 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
1073 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
1074 memset(&r_svbsp, 0, sizeof (r_svbsp));
1077 void gl_main_shutdown(void)
1080 Mem_Free(r_svbsp.nodes);
1081 memset(&r_svbsp, 0, sizeof (r_svbsp));
1082 R_FreeTexturePool(&r_main_texturepool);
1083 r_texture_blanknormalmap = NULL;
1084 r_texture_white = NULL;
1085 r_texture_black = NULL;
1086 r_texture_whitecube = NULL;
1087 r_texture_normalizationcube = NULL;
1088 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
1092 extern void CL_ParseEntityLump(char *entitystring);
1093 void gl_main_newmap(void)
1095 // FIXME: move this code to client
1097 char *entities, entname[MAX_QPATH];
1100 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
1101 l = (int)strlen(entname) - 4;
1102 if (l >= 0 && !strcmp(entname + l, ".bsp"))
1104 memcpy(entname + l, ".ent", 5);
1105 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
1107 CL_ParseEntityLump(entities);
1112 if (cl.worldmodel->brush.entities)
1113 CL_ParseEntityLump(cl.worldmodel->brush.entities);
1117 void GL_Main_Init(void)
1119 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
1121 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed\n");
1122 FOG_registercvars(); // FIXME: move this fog stuff to client?
1123 Cvar_RegisterVariable(&r_nearclip);
1124 Cvar_RegisterVariable(&r_showsurfaces);
1125 Cvar_RegisterVariable(&r_showtris);
1126 Cvar_RegisterVariable(&r_shownormals);
1127 Cvar_RegisterVariable(&r_showlighting);
1128 Cvar_RegisterVariable(&r_showshadowvolumes);
1129 Cvar_RegisterVariable(&r_showcollisionbrushes);
1130 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
1131 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
1132 Cvar_RegisterVariable(&r_showdisabledepthtest);
1133 Cvar_RegisterVariable(&r_drawportals);
1134 Cvar_RegisterVariable(&r_drawentities);
1135 Cvar_RegisterVariable(&r_drawviewmodel);
1136 Cvar_RegisterVariable(&r_speeds);
1137 Cvar_RegisterVariable(&r_fullbrights);
1138 Cvar_RegisterVariable(&r_wateralpha);
1139 Cvar_RegisterVariable(&r_dynamic);
1140 Cvar_RegisterVariable(&r_fullbright);
1141 Cvar_RegisterVariable(&r_shadows);
1142 Cvar_RegisterVariable(&r_shadows_throwdistance);
1143 Cvar_RegisterVariable(&r_q1bsp_skymasking);
1144 Cvar_RegisterVariable(&r_textureunits);
1145 Cvar_RegisterVariable(&r_glsl);
1146 Cvar_RegisterVariable(&r_glsl_offsetmapping);
1147 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
1148 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
1149 Cvar_RegisterVariable(&r_glsl_deluxemapping);
1150 Cvar_RegisterVariable(&r_lerpsprites);
1151 Cvar_RegisterVariable(&r_lerpmodels);
1152 Cvar_RegisterVariable(&r_waterscroll);
1153 Cvar_RegisterVariable(&r_bloom);
1154 Cvar_RegisterVariable(&r_bloom_colorscale);
1155 Cvar_RegisterVariable(&r_bloom_brighten);
1156 Cvar_RegisterVariable(&r_bloom_blur);
1157 Cvar_RegisterVariable(&r_bloom_resolution);
1158 Cvar_RegisterVariable(&r_bloom_colorexponent);
1159 Cvar_RegisterVariable(&r_bloom_colorsubtract);
1160 Cvar_RegisterVariable(&r_hdr);
1161 Cvar_RegisterVariable(&r_hdr_scenebrightness);
1162 Cvar_RegisterVariable(&r_hdr_glowintensity);
1163 Cvar_RegisterVariable(&r_hdr_range);
1164 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
1165 Cvar_RegisterVariable(&developer_texturelogging);
1166 Cvar_RegisterVariable(&gl_lightmaps);
1167 Cvar_RegisterVariable(&r_test);
1168 Cvar_RegisterVariable(&r_batchmode);
1169 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
1170 Cvar_SetValue("r_fullbrights", 0);
1171 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
1174 extern void R_Textures_Init(void);
1175 extern void GL_Draw_Init(void);
1176 extern void GL_Main_Init(void);
1177 extern void R_Shadow_Init(void);
1178 extern void R_Sky_Init(void);
1179 extern void GL_Surf_Init(void);
1180 extern void R_Light_Init(void);
1181 extern void R_Particles_Init(void);
1182 extern void R_Explosion_Init(void);
1183 extern void gl_backend_init(void);
1184 extern void Sbar_Init(void);
1185 extern void R_LightningBeams_Init(void);
1186 extern void Mod_RenderInit(void);
1188 void Render_Init(void)
1201 R_LightningBeams_Init();
1210 extern char *ENGINE_EXTENSIONS;
1213 VID_CheckExtensions();
1215 // LordHavoc: report supported extensions
1216 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
1218 // clear to black (loading plaque will be seen over this)
1220 qglClearColor(0,0,0,1);CHECKGLERROR
1221 qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
1224 int R_CullBox(const vec3_t mins, const vec3_t maxs)
1228 for (i = 0;i < 4;i++)
1230 p = r_view.frustum + i;
1235 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1239 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1243 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1247 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1251 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1255 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1259 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1263 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1271 //==================================================================================
1273 static void R_UpdateEntityLighting(entity_render_t *ent)
1275 vec3_t tempdiffusenormal;
1277 // fetch the lighting from the worldmodel data
1278 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));
1279 VectorClear(ent->modellight_diffuse);
1280 VectorClear(tempdiffusenormal);
1281 if ((ent->flags & RENDER_LIGHT) && r_refdef.worldmodel && r_refdef.worldmodel->brush.LightPoint)
1284 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
1285 r_refdef.worldmodel->brush.LightPoint(r_refdef.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
1288 VectorSet(ent->modellight_ambient, 1, 1, 1);
1290 // move the light direction into modelspace coordinates for lighting code
1291 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
1292 VectorNormalize(ent->modellight_lightdir);
1294 // scale ambient and directional light contributions according to rendering variables
1295 ent->modellight_ambient[0] *= ent->colormod[0] * r_refdef.lightmapintensity;
1296 ent->modellight_ambient[1] *= ent->colormod[1] * r_refdef.lightmapintensity;
1297 ent->modellight_ambient[2] *= ent->colormod[2] * r_refdef.lightmapintensity;
1298 ent->modellight_diffuse[0] *= ent->colormod[0] * r_refdef.lightmapintensity;
1299 ent->modellight_diffuse[1] *= ent->colormod[1] * r_refdef.lightmapintensity;
1300 ent->modellight_diffuse[2] *= ent->colormod[2] * r_refdef.lightmapintensity;
1303 static void R_View_UpdateEntityVisible (void)
1306 entity_render_t *ent;
1308 if (!r_drawentities.integer)
1311 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : (chase_active.integer ? 0 : RENDER_EXTERIORMODEL);
1312 if (r_refdef.worldmodel && r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs)
1314 // worldmodel can check visibility
1315 for (i = 0;i < r_refdef.numentities;i++)
1317 ent = r_refdef.entities[i];
1318 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));
1323 // no worldmodel or it can't check visibility
1324 for (i = 0;i < r_refdef.numentities;i++)
1326 ent = r_refdef.entities[i];
1327 r_viewcache.entityvisible[i] = !(ent->flags & renderimask) && !R_CullBox(ent->mins, ent->maxs);
1331 // update entity lighting (even on hidden entities for r_shadows)
1332 for (i = 0;i < r_refdef.numentities;i++)
1333 R_UpdateEntityLighting(r_refdef.entities[i]);
1336 // only used if skyrendermasked, and normally returns false
1337 int R_DrawBrushModelsSky (void)
1340 entity_render_t *ent;
1342 if (!r_drawentities.integer)
1346 for (i = 0;i < r_refdef.numentities;i++)
1348 if (!r_viewcache.entityvisible[i])
1350 ent = r_refdef.entities[i];
1351 if (!ent->model || !ent->model->DrawSky)
1353 ent->model->DrawSky(ent);
1359 void R_DrawNoModel(entity_render_t *ent);
1360 void R_DrawModels(void)
1363 entity_render_t *ent;
1365 if (!r_drawentities.integer)
1368 for (i = 0;i < r_refdef.numentities;i++)
1370 if (!r_viewcache.entityvisible[i])
1372 ent = r_refdef.entities[i];
1373 r_refdef.stats.entities++;
1374 if (ent->model && ent->model->Draw != NULL)
1375 ent->model->Draw(ent);
1381 static void R_View_SetFrustum(void)
1383 // break apart the view matrix into vectors for various purposes
1384 Matrix4x4_ToVectors(&r_view.matrix, r_view.forward, r_view.left, r_view.up, r_view.origin);
1385 VectorNegate(r_view.left, r_view.right);
1388 r_view.frustum[0].normal[0] = 0 - 1.0 / r_view.frustum_x;
1389 r_view.frustum[0].normal[1] = 0 - 0;
1390 r_view.frustum[0].normal[2] = -1 - 0;
1391 r_view.frustum[1].normal[0] = 0 + 1.0 / r_view.frustum_x;
1392 r_view.frustum[1].normal[1] = 0 + 0;
1393 r_view.frustum[1].normal[2] = -1 + 0;
1394 r_view.frustum[2].normal[0] = 0 - 0;
1395 r_view.frustum[2].normal[1] = 0 - 1.0 / r_view.frustum_y;
1396 r_view.frustum[2].normal[2] = -1 - 0;
1397 r_view.frustum[3].normal[0] = 0 + 0;
1398 r_view.frustum[3].normal[1] = 0 + 1.0 / r_view.frustum_y;
1399 r_view.frustum[3].normal[2] = -1 + 0;
1403 zNear = r_refdef.nearclip;
1404 nudge = 1.0 - 1.0 / (1<<23);
1405 r_view.frustum[4].normal[0] = 0 - 0;
1406 r_view.frustum[4].normal[1] = 0 - 0;
1407 r_view.frustum[4].normal[2] = -1 - -nudge;
1408 r_view.frustum[4].dist = 0 - -2 * zNear * nudge;
1409 r_view.frustum[5].normal[0] = 0 + 0;
1410 r_view.frustum[5].normal[1] = 0 + 0;
1411 r_view.frustum[5].normal[2] = -1 + -nudge;
1412 r_view.frustum[5].dist = 0 + -2 * zNear * nudge;
1418 r_view.frustum[0].normal[0] = m[3] - m[0];
1419 r_view.frustum[0].normal[1] = m[7] - m[4];
1420 r_view.frustum[0].normal[2] = m[11] - m[8];
1421 r_view.frustum[0].dist = m[15] - m[12];
1423 r_view.frustum[1].normal[0] = m[3] + m[0];
1424 r_view.frustum[1].normal[1] = m[7] + m[4];
1425 r_view.frustum[1].normal[2] = m[11] + m[8];
1426 r_view.frustum[1].dist = m[15] + m[12];
1428 r_view.frustum[2].normal[0] = m[3] - m[1];
1429 r_view.frustum[2].normal[1] = m[7] - m[5];
1430 r_view.frustum[2].normal[2] = m[11] - m[9];
1431 r_view.frustum[2].dist = m[15] - m[13];
1433 r_view.frustum[3].normal[0] = m[3] + m[1];
1434 r_view.frustum[3].normal[1] = m[7] + m[5];
1435 r_view.frustum[3].normal[2] = m[11] + m[9];
1436 r_view.frustum[3].dist = m[15] + m[13];
1438 r_view.frustum[4].normal[0] = m[3] - m[2];
1439 r_view.frustum[4].normal[1] = m[7] - m[6];
1440 r_view.frustum[4].normal[2] = m[11] - m[10];
1441 r_view.frustum[4].dist = m[15] - m[14];
1443 r_view.frustum[5].normal[0] = m[3] + m[2];
1444 r_view.frustum[5].normal[1] = m[7] + m[6];
1445 r_view.frustum[5].normal[2] = m[11] + m[10];
1446 r_view.frustum[5].dist = m[15] + m[14];
1451 VectorMAM(1, r_view.forward, 1.0 / -r_view.frustum_x, r_view.left, r_view.frustum[0].normal);
1452 VectorMAM(1, r_view.forward, 1.0 / r_view.frustum_x, r_view.left, r_view.frustum[1].normal);
1453 VectorMAM(1, r_view.forward, 1.0 / -r_view.frustum_y, r_view.up, r_view.frustum[2].normal);
1454 VectorMAM(1, r_view.forward, 1.0 / r_view.frustum_y, r_view.up, r_view.frustum[3].normal);
1455 VectorCopy(r_view.forward, r_view.frustum[4].normal);
1456 VectorNormalize(r_view.frustum[0].normal);
1457 VectorNormalize(r_view.frustum[1].normal);
1458 VectorNormalize(r_view.frustum[2].normal);
1459 VectorNormalize(r_view.frustum[3].normal);
1460 r_view.frustum[0].dist = DotProduct (r_view.origin, r_view.frustum[0].normal);
1461 r_view.frustum[1].dist = DotProduct (r_view.origin, r_view.frustum[1].normal);
1462 r_view.frustum[2].dist = DotProduct (r_view.origin, r_view.frustum[2].normal);
1463 r_view.frustum[3].dist = DotProduct (r_view.origin, r_view.frustum[3].normal);
1464 r_view.frustum[4].dist = DotProduct (r_view.origin, r_view.frustum[4].normal) + r_refdef.nearclip;
1465 PlaneClassify(&r_view.frustum[0]);
1466 PlaneClassify(&r_view.frustum[1]);
1467 PlaneClassify(&r_view.frustum[2]);
1468 PlaneClassify(&r_view.frustum[3]);
1469 PlaneClassify(&r_view.frustum[4]);
1471 // LordHavoc: note to all quake engine coders, Quake had a special case
1472 // for 90 degrees which assumed a square view (wrong), so I removed it,
1473 // Quake2 has it disabled as well.
1475 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
1476 //RotatePointAroundVector( r_view.frustum[0].normal, r_view.up, r_view.forward, -(90 - r_refdef.fov_x / 2));
1477 //r_view.frustum[0].dist = DotProduct (r_view.origin, frustum[0].normal);
1478 //PlaneClassify(&frustum[0]);
1480 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
1481 //RotatePointAroundVector( r_view.frustum[1].normal, r_view.up, r_view.forward, (90 - r_refdef.fov_x / 2));
1482 //r_view.frustum[1].dist = DotProduct (r_view.origin, frustum[1].normal);
1483 //PlaneClassify(&frustum[1]);
1485 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
1486 //RotatePointAroundVector( r_view.frustum[2].normal, r_view.left, r_view.forward, -(90 - r_refdef.fov_y / 2));
1487 //r_view.frustum[2].dist = DotProduct (r_view.origin, frustum[2].normal);
1488 //PlaneClassify(&frustum[2]);
1490 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
1491 //RotatePointAroundVector( r_view.frustum[3].normal, r_view.left, r_view.forward, (90 - r_refdef.fov_y / 2));
1492 //r_view.frustum[3].dist = DotProduct (r_view.origin, frustum[3].normal);
1493 //PlaneClassify(&frustum[3]);
1496 //VectorCopy(r_view.forward, r_view.frustum[4].normal);
1497 //r_view.frustum[4].dist = DotProduct (r_view.origin, frustum[4].normal) + r_nearclip.value;
1498 //PlaneClassify(&frustum[4]);
1501 void R_View_Update(void)
1503 R_View_SetFrustum();
1504 R_View_WorldVisibility();
1505 R_View_UpdateEntityVisible();
1508 void R_SetupView(const matrix4x4_t *matrix)
1510 if (r_refdef.rtworldshadows || r_refdef.rtdlightshadows)
1511 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_view.frustum_x, r_view.frustum_y, r_refdef.nearclip);
1513 GL_SetupView_Mode_Perspective(r_view.frustum_x, r_view.frustum_y, r_refdef.nearclip, r_refdef.farclip);
1515 GL_SetupView_Orientation_FromEntity(matrix);
1518 void R_ResetViewRendering2D(void)
1520 if (gl_support_fragment_shader)
1522 qglUseProgramObjectARB(0);CHECKGLERROR
1527 // GL is weird because it's bottom to top, r_view.y is top to bottom
1528 qglViewport(r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
1529 GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
1530 GL_Scissor(r_view.x, r_view.y, r_view.width, r_view.height);
1531 GL_Color(1, 1, 1, 1);
1532 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
1533 GL_BlendFunc(GL_ONE, GL_ZERO);
1534 GL_AlphaTest(false);
1535 GL_ScissorTest(false);
1536 GL_DepthMask(false);
1537 GL_DepthTest(false);
1538 R_Mesh_Matrix(&identitymatrix);
1539 R_Mesh_ResetTextureState();
1540 qglPolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR
1541 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
1542 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
1543 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
1544 qglStencilMask(~0);CHECKGLERROR
1545 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
1546 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
1547 GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
1550 void R_ResetViewRendering3D(void)
1552 if (gl_support_fragment_shader)
1554 qglUseProgramObjectARB(0);CHECKGLERROR
1559 // GL is weird because it's bottom to top, r_view.y is top to bottom
1560 qglViewport(r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
1561 R_SetupView(&r_view.matrix);
1562 GL_Scissor(r_view.x, r_view.y, r_view.width, r_view.height);
1563 GL_Color(1, 1, 1, 1);
1564 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
1565 GL_BlendFunc(GL_ONE, GL_ZERO);
1566 GL_AlphaTest(false);
1567 GL_ScissorTest(true);
1570 R_Mesh_Matrix(&identitymatrix);
1571 R_Mesh_ResetTextureState();
1572 qglPolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR
1573 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
1574 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
1575 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
1576 qglStencilMask(~0);CHECKGLERROR
1577 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
1578 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
1579 GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
1583 R_Bloom_SetupShader(
1585 "// written by Forest 'LordHavoc' Hale\n"
1587 "// common definitions between vertex shader and fragment shader:\n"
1589 "#ifdef __GLSL_CG_DATA_TYPES\n"
1590 "#define myhalf half\n"
1591 "#define myhvec2 hvec2\n"
1592 "#define myhvec3 hvec3\n"
1593 "#define myhvec4 hvec4\n"
1595 "#define myhalf float\n"
1596 "#define myhvec2 vec2\n"
1597 "#define myhvec3 vec3\n"
1598 "#define myhvec4 vec4\n"
1601 "varying vec2 ScreenTexCoord;\n"
1602 "varying vec2 BloomTexCoord;\n"
1607 "// vertex shader specific:\n"
1608 "#ifdef VERTEX_SHADER\n"
1612 " ScreenTexCoord = vec2(gl_MultiTexCoord0);\n"
1613 " BloomTexCoord = vec2(gl_MultiTexCoord1);\n"
1614 " // transform vertex to camera space, using ftransform to match non-VS\n"
1616 " gl_Position = ftransform();\n"
1619 "#endif // VERTEX_SHADER\n"
1624 "// fragment shader specific:\n"
1625 "#ifdef FRAGMENT_SHADER\n"
1630 " myhvec3 color = myhvec3(texture2D(Texture_Screen, ScreenTexCoord));\n"
1631 " for (x = -BLUR_X;x <= BLUR_X;x++)
1632 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
1633 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
1634 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
1635 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
1637 " gl_FragColor = vec4(color);\n"
1640 "#endif // FRAGMENT_SHADER\n"
1643 void R_RenderScene(void);
1645 void R_Bloom_StartFrame(void)
1647 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
1649 // set bloomwidth and bloomheight to the bloom resolution that will be
1650 // used (often less than the screen resolution for faster rendering)
1651 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_view.width);
1652 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_view.height / r_view.width;
1653 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_view.height);
1655 // calculate desired texture sizes
1656 if (gl_support_arb_texture_non_power_of_two)
1658 screentexturewidth = r_view.width;
1659 screentextureheight = r_view.height;
1660 bloomtexturewidth = r_bloomstate.bloomwidth;
1661 bloomtextureheight = r_bloomstate.bloomheight;
1665 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
1666 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
1667 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
1668 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
1673 screentexturewidth = screentextureheight = 0;
1675 else if (r_bloom.integer)
1680 screentexturewidth = screentextureheight = 0;
1681 bloomtexturewidth = bloomtextureheight = 0;
1684 if ((!bloomtexturewidth && !bloomtextureheight) || r_bloom_resolution.integer < 4 || r_bloom_blur.value < 1 || r_bloom_blur.value >= 512 || screentexturewidth > gl_max_texture_size || screentextureheight > gl_max_texture_size || bloomtexturewidth > gl_max_texture_size || bloomtextureheight > gl_max_texture_size)
1686 // can't use bloom if the parameters are too weird
1687 // can't use bloom if the card does not support the texture size
1688 if (r_bloomstate.texture_screen)
1689 R_FreeTexture(r_bloomstate.texture_screen);
1690 if (r_bloomstate.texture_bloom)
1691 R_FreeTexture(r_bloomstate.texture_bloom);
1692 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
1696 r_bloomstate.enabled = true;
1697 r_bloomstate.hdr = r_hdr.integer != 0;
1699 // allocate textures as needed
1700 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
1702 if (r_bloomstate.texture_screen)
1703 R_FreeTexture(r_bloomstate.texture_screen);
1704 r_bloomstate.texture_screen = NULL;
1705 r_bloomstate.screentexturewidth = screentexturewidth;
1706 r_bloomstate.screentextureheight = screentextureheight;
1707 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
1708 r_bloomstate.texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, TEXTYPE_RGBA, TEXF_FORCENEAREST | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
1710 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
1712 if (r_bloomstate.texture_bloom)
1713 R_FreeTexture(r_bloomstate.texture_bloom);
1714 r_bloomstate.texture_bloom = NULL;
1715 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
1716 r_bloomstate.bloomtextureheight = bloomtextureheight;
1717 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
1718 r_bloomstate.texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", r_bloomstate.bloomtexturewidth, r_bloomstate.bloomtextureheight, NULL, TEXTYPE_RGBA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
1721 // set up a texcoord array for the full resolution screen image
1722 // (we have to keep this around to copy back during final render)
1723 r_bloomstate.screentexcoord2f[0] = 0;
1724 r_bloomstate.screentexcoord2f[1] = (float)r_view.height / (float)r_bloomstate.screentextureheight;
1725 r_bloomstate.screentexcoord2f[2] = (float)r_view.width / (float)r_bloomstate.screentexturewidth;
1726 r_bloomstate.screentexcoord2f[3] = (float)r_view.height / (float)r_bloomstate.screentextureheight;
1727 r_bloomstate.screentexcoord2f[4] = (float)r_view.width / (float)r_bloomstate.screentexturewidth;
1728 r_bloomstate.screentexcoord2f[5] = 0;
1729 r_bloomstate.screentexcoord2f[6] = 0;
1730 r_bloomstate.screentexcoord2f[7] = 0;
1732 // set up a texcoord array for the reduced resolution bloom image
1733 // (which will be additive blended over the screen image)
1734 r_bloomstate.bloomtexcoord2f[0] = 0;
1735 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
1736 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
1737 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
1738 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
1739 r_bloomstate.bloomtexcoord2f[5] = 0;
1740 r_bloomstate.bloomtexcoord2f[6] = 0;
1741 r_bloomstate.bloomtexcoord2f[7] = 0;
1744 void R_Bloom_CopyScreenTexture(float colorscale)
1746 r_refdef.stats.bloom++;
1748 R_ResetViewRendering2D();
1749 R_Mesh_VertexPointer(r_screenvertex3f);
1750 R_Mesh_ColorPointer(NULL);
1751 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f);
1752 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
1754 // copy view into the screen texture
1755 GL_ActiveTexture(0);
1757 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
1758 r_refdef.stats.bloom_copypixels += r_view.width * r_view.height;
1760 // now scale it down to the bloom texture size
1762 qglViewport(r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
1763 GL_BlendFunc(GL_ONE, GL_ZERO);
1764 GL_Color(colorscale, colorscale, colorscale, 1);
1765 // TODO: optimize with multitexture or GLSL
1766 R_Mesh_Draw(0, 4, 2, polygonelements);
1767 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
1769 // we now have a bloom image in the framebuffer
1770 // copy it into the bloom image texture for later processing
1771 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
1772 GL_ActiveTexture(0);
1774 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
1775 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
1778 void R_Bloom_CopyHDRTexture(void)
1780 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
1781 GL_ActiveTexture(0);
1783 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
1784 r_refdef.stats.bloom_copypixels += r_view.width * r_view.height;
1787 void R_Bloom_MakeTexture(void)
1790 float xoffset, yoffset, r, brighten;
1792 r_refdef.stats.bloom++;
1794 R_ResetViewRendering2D();
1795 R_Mesh_VertexPointer(r_screenvertex3f);
1796 R_Mesh_ColorPointer(NULL);
1798 // we have a bloom image in the framebuffer
1800 qglViewport(r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
1802 for (x = 1;x < r_bloom_colorexponent.value;)
1805 r = bound(0, r_bloom_colorexponent.value / x, 1);
1806 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
1807 GL_Color(r, r, r, 1);
1808 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
1809 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f);
1810 R_Mesh_Draw(0, 4, 2, polygonelements);
1811 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
1813 // copy the vertically blurred bloom view to a texture
1814 GL_ActiveTexture(0);
1816 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
1817 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
1820 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
1821 brighten = r_bloom_brighten.value;
1823 brighten *= r_hdr_range.value;
1824 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
1825 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f);
1827 for (dir = 0;dir < 2;dir++)
1829 // blend on at multiple vertical offsets to achieve a vertical blur
1830 // TODO: do offset blends using GLSL
1831 GL_BlendFunc(GL_ONE, GL_ZERO);
1832 for (x = -range;x <= range;x++)
1834 if (!dir){xoffset = 0;yoffset = x;}
1835 else {xoffset = x;yoffset = 0;}
1836 xoffset /= (float)r_bloomstate.bloomtexturewidth;
1837 yoffset /= (float)r_bloomstate.bloomtextureheight;
1838 // compute a texcoord array with the specified x and y offset
1839 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
1840 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
1841 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
1842 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
1843 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
1844 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
1845 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
1846 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
1847 // this r value looks like a 'dot' particle, fading sharply to
1848 // black at the edges
1849 // (probably not realistic but looks good enough)
1850 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
1851 //r = (dir ? 1.0f : brighten)/(range*2+1);
1852 r = (dir ? 1.0f : brighten)/(range*2+1)*(1 - x*x/(float)(range*range));
1853 GL_Color(r, r, r, 1);
1854 R_Mesh_Draw(0, 4, 2, polygonelements);
1855 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
1856 GL_BlendFunc(GL_ONE, GL_ONE);
1859 // copy the vertically blurred bloom view to a texture
1860 GL_ActiveTexture(0);
1862 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
1863 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
1866 // apply subtract last
1867 // (just like it would be in a GLSL shader)
1868 if (r_bloom_colorsubtract.value > 0 && gl_support_ext_blend_subtract)
1870 GL_BlendFunc(GL_ONE, GL_ZERO);
1871 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
1872 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f);
1873 GL_Color(1, 1, 1, 1);
1874 R_Mesh_Draw(0, 4, 2, polygonelements);
1875 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
1877 GL_BlendFunc(GL_ONE, GL_ONE);
1878 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
1879 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
1880 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f);
1881 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
1882 R_Mesh_Draw(0, 4, 2, polygonelements);
1883 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
1884 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
1886 // copy the darkened bloom view to a texture
1887 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
1888 GL_ActiveTexture(0);
1890 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
1891 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
1895 void R_HDR_RenderBloomTexture(void)
1897 int oldwidth, oldheight;
1899 oldwidth = r_view.width;
1900 oldheight = r_view.height;
1901 r_view.width = r_bloomstate.bloomwidth;
1902 r_view.height = r_bloomstate.bloomheight;
1904 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
1905 // TODO: add exposure compensation features
1906 // TODO: add fp16 framebuffer support
1908 r_view.colorscale = r_bloom_colorscale.value * r_hdr_scenebrightness.value;
1910 r_view.colorscale /= r_hdr_range.value;
1913 R_ResetViewRendering2D();
1915 R_Bloom_CopyHDRTexture();
1916 R_Bloom_MakeTexture();
1918 R_ResetViewRendering3D();
1921 if (r_timereport_active)
1922 R_TimeReport("clear");
1925 // restore the view settings
1926 r_view.width = oldwidth;
1927 r_view.height = oldheight;
1930 static void R_BlendView(void)
1932 if (r_bloomstate.enabled && r_bloomstate.hdr)
1934 // render high dynamic range bloom effect
1935 // the bloom texture was made earlier this render, so we just need to
1936 // blend it onto the screen...
1937 R_ResetViewRendering2D();
1938 R_Mesh_VertexPointer(r_screenvertex3f);
1939 R_Mesh_ColorPointer(NULL);
1940 GL_Color(1, 1, 1, 1);
1941 GL_BlendFunc(GL_ONE, GL_ONE);
1942 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
1943 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f);
1944 R_Mesh_Draw(0, 4, 2, polygonelements);
1945 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
1947 else if (r_bloomstate.enabled)
1949 // render simple bloom effect
1950 // copy the screen and shrink it and darken it for the bloom process
1951 R_Bloom_CopyScreenTexture(r_bloom_colorscale.value);
1952 // make the bloom texture
1953 R_Bloom_MakeTexture();
1954 // put the original screen image back in place and blend the bloom
1956 R_ResetViewRendering2D();
1957 R_Mesh_VertexPointer(r_screenvertex3f);
1958 R_Mesh_ColorPointer(NULL);
1959 GL_Color(1, 1, 1, 1);
1960 GL_BlendFunc(GL_ONE, GL_ZERO);
1961 // do both in one pass if possible
1962 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
1963 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f);
1964 if (r_textureunits.integer >= 2 && gl_combine.integer)
1966 R_Mesh_TexCombine(1, GL_ADD, GL_ADD, 1, 1);
1967 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_screen));
1968 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.screentexcoord2f);
1972 R_Mesh_Draw(0, 4, 2, polygonelements);
1973 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
1974 // now blend on the bloom texture
1975 GL_BlendFunc(GL_ONE, GL_ONE);
1976 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
1977 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f);
1979 R_Mesh_Draw(0, 4, 2, polygonelements);
1980 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
1982 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
1984 // apply a color tint to the whole view
1985 R_ResetViewRendering2D();
1986 R_Mesh_VertexPointer(r_screenvertex3f);
1987 R_Mesh_ColorPointer(NULL);
1988 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1989 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
1990 R_Mesh_Draw(0, 4, 2, polygonelements);
1994 void R_RenderScene(void);
1996 matrix4x4_t r_waterscrollmatrix;
1998 void R_UpdateVariables(void)
2002 r_refdef.farclip = 4096;
2003 if (r_refdef.worldmodel)
2004 r_refdef.farclip += VectorDistance(r_refdef.worldmodel->normalmins, r_refdef.worldmodel->normalmaxs);
2005 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
2007 r_refdef.polygonfactor = 0;
2008 r_refdef.polygonoffset = 0;
2009 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_shadow_polygonfactor.value;
2010 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_shadow_polygonoffset.value;
2012 r_refdef.rtworld = r_shadow_realtime_world.integer;
2013 r_refdef.rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
2014 r_refdef.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
2015 r_refdef.rtdlightshadows = r_refdef.rtdlight && (r_refdef.rtworld ? r_shadow_realtime_world_dlightshadows.integer : r_shadow_realtime_dlight_shadows.integer) && gl_stencil;
2016 r_refdef.lightmapintensity = r_refdef.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
2017 if (r_showsurfaces.integer)
2019 r_refdef.rtworld = false;
2020 r_refdef.rtworldshadows = false;
2021 r_refdef.rtdlight = false;
2022 r_refdef.rtdlightshadows = false;
2023 r_refdef.lightmapintensity = 0;
2026 if (gamemode == GAME_NEHAHRA)
2028 if (gl_fogenable.integer)
2030 r_refdef.oldgl_fogenable = true;
2031 r_refdef.fog_density = gl_fogdensity.value;
2032 r_refdef.fog_red = gl_fogred.value;
2033 r_refdef.fog_green = gl_foggreen.value;
2034 r_refdef.fog_blue = gl_fogblue.value;
2036 else if (r_refdef.oldgl_fogenable)
2038 r_refdef.oldgl_fogenable = false;
2039 r_refdef.fog_density = 0;
2040 r_refdef.fog_red = 0;
2041 r_refdef.fog_green = 0;
2042 r_refdef.fog_blue = 0;
2045 if (r_refdef.fog_density)
2047 r_refdef.fogcolor[0] = bound(0.0f, r_refdef.fog_red , 1.0f);
2048 r_refdef.fogcolor[1] = bound(0.0f, r_refdef.fog_green, 1.0f);
2049 r_refdef.fogcolor[2] = bound(0.0f, r_refdef.fog_blue , 1.0f);
2051 if (r_refdef.fog_density)
2053 r_refdef.fogenabled = true;
2054 // this is the point where the fog reaches 0.9986 alpha, which we
2055 // consider a good enough cutoff point for the texture
2056 // (0.9986 * 256 == 255.6)
2057 r_refdef.fogrange = 400 / r_refdef.fog_density;
2058 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
2059 r_refdef.fogtabledistmultiplier = FOGTABLEWIDTH * r_refdef.fograngerecip;
2060 // fog color was already set
2063 r_refdef.fogenabled = false;
2071 void R_RenderView(void)
2073 if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
2074 return; //Host_Error ("R_RenderView: NULL worldmodel");
2076 R_Shadow_UpdateWorldLightSelection();
2079 if (r_timereport_active)
2080 R_TimeReport("setup");
2083 if (r_timereport_active)
2084 R_TimeReport("visibility");
2086 R_ResetViewRendering3D();
2089 if (r_timereport_active)
2090 R_TimeReport("clear");
2092 R_Bloom_StartFrame();
2094 // this produces a bloom texture to be used in R_BlendView() later
2096 R_HDR_RenderBloomTexture();
2098 r_view.colorscale = r_hdr_scenebrightness.value;
2102 if (r_timereport_active)
2103 R_TimeReport("blendview");
2105 GL_Scissor(0, 0, vid.width, vid.height);
2106 GL_ScissorTest(false);
2110 extern void R_DrawLightningBeams (void);
2111 extern void VM_CL_AddPolygonsToMeshQueue (void);
2112 extern void R_DrawPortals (void);
2113 void R_RenderScene(void)
2115 // don't let sound skip if going slow
2116 if (r_refdef.extraupdate)
2119 R_ResetViewRendering3D();
2121 R_MeshQueue_BeginScene();
2125 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);
2127 if (cl.csqc_vidvars.drawworld)
2129 // don't let sound skip if going slow
2130 if (r_refdef.extraupdate)
2133 if (r_refdef.worldmodel && r_refdef.worldmodel->DrawSky)
2135 r_refdef.worldmodel->DrawSky(r_refdef.worldentity);
2136 if (r_timereport_active)
2137 R_TimeReport("worldsky");
2140 if (R_DrawBrushModelsSky() && r_timereport_active)
2141 R_TimeReport("bmodelsky");
2143 if (r_refdef.worldmodel && r_refdef.worldmodel->Draw)
2145 r_refdef.worldmodel->Draw(r_refdef.worldentity);
2146 if (r_timereport_active)
2147 R_TimeReport("world");
2151 // don't let sound skip if going slow
2152 if (r_refdef.extraupdate)
2156 if (r_timereport_active)
2157 R_TimeReport("models");
2159 // don't let sound skip if going slow
2160 if (r_refdef.extraupdate)
2163 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
2165 R_DrawModelShadows();
2167 R_ResetViewRendering3D();
2169 // don't let sound skip if going slow
2170 if (r_refdef.extraupdate)
2174 R_ShadowVolumeLighting(false);
2175 if (r_timereport_active)
2176 R_TimeReport("rtlights");
2178 // don't let sound skip if going slow
2179 if (r_refdef.extraupdate)
2182 if (cl.csqc_vidvars.drawworld)
2184 R_DrawLightningBeams();
2185 if (r_timereport_active)
2186 R_TimeReport("lightning");
2189 if (r_timereport_active)
2190 R_TimeReport("particles");
2193 if (r_timereport_active)
2194 R_TimeReport("explosions");
2197 if (gl_support_fragment_shader)
2199 qglUseProgramObjectARB(0);CHECKGLERROR
2201 VM_CL_AddPolygonsToMeshQueue();
2203 if (r_drawportals.integer)
2206 if (r_timereport_active)
2207 R_TimeReport("portals");
2210 if (gl_support_fragment_shader)
2212 qglUseProgramObjectARB(0);CHECKGLERROR
2214 R_MeshQueue_RenderTransparent();
2215 if (r_timereport_active)
2216 R_TimeReport("drawtrans");
2218 if (gl_support_fragment_shader)
2220 qglUseProgramObjectARB(0);CHECKGLERROR
2223 if (cl.csqc_vidvars.drawworld)
2226 if (r_timereport_active)
2227 R_TimeReport("coronas");
2230 // don't let sound skip if going slow
2231 if (r_refdef.extraupdate)
2234 R_ResetViewRendering2D();
2238 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
2241 float *v, *c, f1, f2, diff[3], vertex3f[8*3], color4f[8*4];
2242 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2243 GL_DepthMask(false);
2245 R_Mesh_Matrix(&identitymatrix);
2247 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2];
2248 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
2249 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
2250 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
2251 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
2252 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
2253 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
2254 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
2255 R_FillColors(color, 8, cr, cg, cb, ca);
2256 if (r_refdef.fogenabled)
2258 for (i = 0, v = vertex, c = color;i < 8;i++, v += 4, c += 4)
2260 f2 = VERTEXFOGTABLE(VectorDistance(v, r_view.origin));
2262 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
2263 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
2264 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
2267 R_Mesh_VertexPointer(vertex3f);
2268 R_Mesh_ColorPointer(color);
2269 R_Mesh_ResetTextureState();
2274 int nomodelelements[24] =
2286 float nomodelvertex3f[6*3] =
2296 float nomodelcolor4f[6*4] =
2298 0.0f, 0.0f, 0.5f, 1.0f,
2299 0.0f, 0.0f, 0.5f, 1.0f,
2300 0.0f, 0.5f, 0.0f, 1.0f,
2301 0.0f, 0.5f, 0.0f, 1.0f,
2302 0.5f, 0.0f, 0.0f, 1.0f,
2303 0.5f, 0.0f, 0.0f, 1.0f
2306 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
2311 // this is only called once per entity so numsurfaces is always 1, and
2312 // surfacelist is always {0}, so this code does not handle batches
2313 R_Mesh_Matrix(&ent->matrix);
2315 if (ent->flags & EF_ADDITIVE)
2317 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2318 GL_DepthMask(false);
2320 else if (ent->alpha < 1)
2322 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2323 GL_DepthMask(false);
2327 GL_BlendFunc(GL_ONE, GL_ZERO);
2330 GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
2331 GL_CullFace((ent->flags & RENDER_NOCULLFACE) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
2332 R_Mesh_VertexPointer(nomodelvertex3f);
2333 if (r_refdef.fogenabled)
2336 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
2337 R_Mesh_ColorPointer(color4f);
2338 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
2339 f2 = VERTEXFOGTABLE(VectorDistance(org, r_view.origin));
2341 for (i = 0, c = color4f;i < 6;i++, c += 4)
2343 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
2344 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
2345 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
2349 else if (ent->alpha != 1)
2351 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
2352 R_Mesh_ColorPointer(color4f);
2353 for (i = 0, c = color4f;i < 6;i++, c += 4)
2357 R_Mesh_ColorPointer(nomodelcolor4f);
2358 R_Mesh_ResetTextureState();
2359 R_Mesh_Draw(0, 6, 8, nomodelelements);
2362 void R_DrawNoModel(entity_render_t *ent)
2365 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
2366 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
2367 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, r_shadow_rtlight);
2369 // R_DrawNoModelCallback(ent, 0);
2372 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
2374 vec3_t right1, right2, diff, normal;
2376 VectorSubtract (org2, org1, normal);
2378 // calculate 'right' vector for start
2379 VectorSubtract (r_view.origin, org1, diff);
2380 CrossProduct (normal, diff, right1);
2381 VectorNormalize (right1);
2383 // calculate 'right' vector for end
2384 VectorSubtract (r_view.origin, org2, diff);
2385 CrossProduct (normal, diff, right2);
2386 VectorNormalize (right2);
2388 vert[ 0] = org1[0] + width * right1[0];
2389 vert[ 1] = org1[1] + width * right1[1];
2390 vert[ 2] = org1[2] + width * right1[2];
2391 vert[ 3] = org1[0] - width * right1[0];
2392 vert[ 4] = org1[1] - width * right1[1];
2393 vert[ 5] = org1[2] - width * right1[2];
2394 vert[ 6] = org2[0] - width * right2[0];
2395 vert[ 7] = org2[1] - width * right2[1];
2396 vert[ 8] = org2[2] - width * right2[2];
2397 vert[ 9] = org2[0] + width * right2[0];
2398 vert[10] = org2[1] + width * right2[1];
2399 vert[11] = org2[2] + width * right2[2];
2402 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
2404 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)
2406 float fog = 0.0f, ifog;
2409 if (r_refdef.fogenabled)
2410 fog = VERTEXFOGTABLE(VectorDistance(origin, r_view.origin));
2413 R_Mesh_Matrix(&identitymatrix);
2414 GL_BlendFunc(blendfunc1, blendfunc2);
2415 GL_DepthMask(false);
2416 GL_DepthTest(!depthdisable);
2418 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
2419 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
2420 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
2421 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
2422 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
2423 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
2424 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
2425 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
2426 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
2427 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
2428 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
2429 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
2431 R_Mesh_VertexPointer(vertex3f);
2432 R_Mesh_ColorPointer(NULL);
2433 R_Mesh_ResetTextureState();
2434 R_Mesh_TexBind(0, R_GetTexture(texture));
2435 R_Mesh_TexCoordPointer(0, 2, spritetexcoord2f);
2436 // FIXME: fixed function path can't properly handle r_view.colorscale > 1
2437 GL_Color(cr * ifog * r_view.colorscale, cg * ifog * r_view.colorscale, cb * ifog * r_view.colorscale, ca);
2438 R_Mesh_Draw(0, 4, 2, polygonelements);
2440 if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
2442 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
2443 GL_BlendFunc(blendfunc1, GL_ONE);
2444 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);
2445 R_Mesh_Draw(0, 4, 2, polygonelements);
2449 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
2454 VectorSet(v, x, y, z);
2455 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
2456 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
2458 if (i == mesh->numvertices)
2460 if (mesh->numvertices < mesh->maxvertices)
2462 VectorCopy(v, vertex3f);
2463 mesh->numvertices++;
2465 return mesh->numvertices;
2471 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
2475 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
2476 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
2477 e = mesh->element3i + mesh->numtriangles * 3;
2478 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
2480 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
2481 if (mesh->numtriangles < mesh->maxtriangles)
2486 mesh->numtriangles++;
2488 element[1] = element[2];
2492 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
2496 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
2497 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
2498 e = mesh->element3i + mesh->numtriangles * 3;
2499 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
2501 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
2502 if (mesh->numtriangles < mesh->maxtriangles)
2507 mesh->numtriangles++;
2509 element[1] = element[2];
2513 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
2514 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
2516 int planenum, planenum2;
2519 mplane_t *plane, *plane2;
2521 double temppoints[2][256*3];
2522 // figure out how large a bounding box we need to properly compute this brush
2524 for (w = 0;w < numplanes;w++)
2525 maxdist = max(maxdist, planes[w].dist);
2526 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
2527 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
2528 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
2532 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
2533 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
2535 if (planenum2 == planenum)
2537 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);
2540 if (tempnumpoints < 3)
2542 // generate elements forming a triangle fan for this polygon
2543 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
2547 static void R_DrawCollisionBrush(const colbrushf_t *brush)
2550 R_Mesh_VertexPointer(brush->points->v);
2551 i = (int)(((size_t)brush) / sizeof(colbrushf_t));
2552 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);
2553 GL_LockArrays(0, brush->numpoints);
2554 R_Mesh_Draw(0, brush->numpoints, brush->numtriangles, brush->elements);
2555 GL_LockArrays(0, 0);
2558 static void R_DrawCollisionSurface(const entity_render_t *ent, const msurface_t *surface)
2561 if (!surface->num_collisiontriangles)
2563 R_Mesh_VertexPointer(surface->data_collisionvertex3f);
2564 i = (int)(((size_t)surface) / sizeof(msurface_t));
2565 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);
2566 GL_LockArrays(0, surface->num_collisionvertices);
2567 R_Mesh_Draw(0, surface->num_collisionvertices, surface->num_collisiontriangles, surface->data_collisionelement3i);
2568 GL_LockArrays(0, 0);
2571 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)
2573 texturelayer_t *layer;
2574 layer = t->currentlayers + t->currentnumlayers++;
2576 layer->depthmask = depthmask;
2577 layer->blendfunc1 = blendfunc1;
2578 layer->blendfunc2 = blendfunc2;
2579 layer->texture = texture;
2580 layer->texmatrix = *matrix;
2581 layer->color[0] = r * r_view.colorscale;
2582 layer->color[1] = g * r_view.colorscale;
2583 layer->color[2] = b * r_view.colorscale;
2584 layer->color[3] = a;
2587 void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
2589 model_t *model = ent->model;
2591 // switch to an alternate material if this is a q1bsp animated material
2593 texture_t *texture = t;
2594 int s = ent->skinnum;
2595 if ((unsigned int)s >= (unsigned int)model->numskins)
2597 if (model->skinscenes)
2599 if (model->skinscenes[s].framecount > 1)
2600 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
2602 s = model->skinscenes[s].firstframe;
2605 t = t + s * model->num_surfaces;
2608 // use an alternate animation if the entity's frame is not 0,
2609 // and only if the texture has an alternate animation
2610 if (ent->frame != 0 && t->anim_total[1])
2611 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.time * 5.0f) % t->anim_total[1]) : 0];
2613 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.time * 5.0f) % t->anim_total[0]) : 0];
2615 texture->currentframe = t;
2618 // pick a new currentskinframe if the material is animated
2619 if (t->numskinframes >= 2)
2620 t->currentskinframe = t->skinframes + ((int)(t->skinframerate * (cl.time - ent->frame2time)) % t->numskinframes);
2621 if (t->backgroundnumskinframes >= 2)
2622 t->backgroundcurrentskinframe = t->backgroundskinframes + ((int)(t->backgroundskinframerate * (cl.time - ent->frame2time)) % t->backgroundnumskinframes);
2624 t->currentmaterialflags = t->basematerialflags;
2625 t->currentalpha = ent->alpha;
2626 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
2627 t->currentalpha *= r_wateralpha.value;
2628 if (!(ent->flags & RENDER_LIGHT))
2629 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
2630 if (ent->effects & EF_ADDITIVE)
2631 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_TRANSPARENT | MATERIALFLAG_NOSHADOW;
2632 else if (t->currentalpha < 1)
2633 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_TRANSPARENT | MATERIALFLAG_NOSHADOW;
2634 if (ent->flags & RENDER_NOCULLFACE)
2635 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW;
2636 if (ent->effects & EF_NODEPTHTEST)
2637 t->currentmaterialflags |= MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_NOSHADOW;
2638 if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
2639 t->currenttexmatrix = r_waterscrollmatrix;
2641 t->currenttexmatrix = identitymatrix;
2642 if (t->backgroundnumskinframes && !(t->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
2643 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
2645 t->colormapping = VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f);
2646 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
2647 t->glosstexture = r_texture_white;
2648 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
2649 t->backgroundglosstexture = r_texture_white;
2650 t->specularpower = r_shadow_glossexponent.value;
2651 t->specularscale = 0;
2652 if (r_shadow_gloss.integer > 0)
2654 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
2656 if (r_shadow_glossintensity.value > 0)
2658 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_black;
2659 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_black;
2660 t->specularscale = r_shadow_glossintensity.value;
2663 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
2664 t->specularscale = r_shadow_gloss2intensity.value;
2667 t->currentnumlayers = 0;
2668 if (!(t->currentmaterialflags & MATERIALFLAG_NODRAW))
2670 if (gl_lightmaps.integer)
2671 R_Texture_AddLayer(t, true, GL_ONE, GL_ZERO, TEXTURELAYERTYPE_LITTEXTURE, r_texture_white, &identitymatrix, 1, 1, 1, 1);
2672 else if (!(t->currentmaterialflags & MATERIALFLAG_SKY))
2674 int blendfunc1, blendfunc2, depthmask;
2675 if (t->currentmaterialflags & MATERIALFLAG_ADD)
2677 blendfunc1 = GL_SRC_ALPHA;
2678 blendfunc2 = GL_ONE;
2680 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
2682 blendfunc1 = GL_SRC_ALPHA;
2683 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
2685 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
2687 blendfunc1 = t->customblendfunc[0];
2688 blendfunc2 = t->customblendfunc[1];
2692 blendfunc1 = GL_ONE;
2693 blendfunc2 = GL_ZERO;
2695 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
2696 if (t->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL))
2698 rtexture_t *currentbasetexture;
2700 if (r_refdef.fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED))
2701 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
2702 currentbasetexture = (VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) < (1.0f / 1048576.0f) && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
2703 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2705 // fullbright is not affected by r_refdef.lightmapintensity
2706 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
2707 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
2708 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);
2709 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
2710 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);
2716 // q3bsp has no lightmap updates, so the lightstylevalue that
2717 // would normally be baked into the lightmap must be
2718 // applied to the color
2719 if (ent->model->type == mod_brushq3)
2720 colorscale *= r_refdef.lightstylevalue[0] * (1.0f / 256.0f);
2721 colorscale *= r_refdef.lightmapintensity;
2722 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);
2723 if (r_ambient.value >= (1.0f/64.0f))
2724 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);
2725 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
2727 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);
2728 if (r_ambient.value >= (1.0f/64.0f))
2729 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);
2731 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
2733 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);
2734 if (r_ambient.value >= (1.0f/64.0f))
2735 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);
2738 if (t->currentskinframe->glow != NULL)
2739 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);
2740 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
2742 // if this is opaque use alpha blend which will darken the earlier
2745 // if this is an alpha blended material, all the earlier passes
2746 // were darkened by fog already, so we only need to add the fog
2747 // color ontop through the fog mask texture
2749 // if this is an additive blended material, all the earlier passes
2750 // were darkened by fog already, and we should not add fog color
2751 // (because the background was not darkened, there is no fog color
2752 // that was lost behind it).
2753 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);
2760 void R_UpdateAllTextureInfo(entity_render_t *ent)
2764 for (i = 0;i < ent->model->num_textures;i++)
2765 R_UpdateTextureInfo(ent, ent->model->data_textures + i);
2768 int rsurface_array_size = 0;
2769 float *rsurface_array_modelvertex3f = NULL;
2770 float *rsurface_array_modelsvector3f = NULL;
2771 float *rsurface_array_modeltvector3f = NULL;
2772 float *rsurface_array_modelnormal3f = NULL;
2773 float *rsurface_array_deformedvertex3f = NULL;
2774 float *rsurface_array_deformedsvector3f = NULL;
2775 float *rsurface_array_deformedtvector3f = NULL;
2776 float *rsurface_array_deformednormal3f = NULL;
2777 float *rsurface_array_color4f = NULL;
2778 float *rsurface_array_texcoord3f = NULL;
2780 void R_Mesh_ResizeArrays(int newvertices)
2783 if (rsurface_array_size >= newvertices)
2785 if (rsurface_array_modelvertex3f)
2786 Mem_Free(rsurface_array_modelvertex3f);
2787 rsurface_array_size = (newvertices + 1023) & ~1023;
2788 base = (float *)Mem_Alloc(r_main_mempool, rsurface_array_size * sizeof(float[31]));
2789 rsurface_array_modelvertex3f = base + rsurface_array_size * 0;
2790 rsurface_array_modelsvector3f = base + rsurface_array_size * 3;
2791 rsurface_array_modeltvector3f = base + rsurface_array_size * 6;
2792 rsurface_array_modelnormal3f = base + rsurface_array_size * 9;
2793 rsurface_array_deformedvertex3f = base + rsurface_array_size * 12;
2794 rsurface_array_deformedsvector3f = base + rsurface_array_size * 15;
2795 rsurface_array_deformedtvector3f = base + rsurface_array_size * 18;
2796 rsurface_array_deformednormal3f = base + rsurface_array_size * 21;
2797 rsurface_array_texcoord3f = base + rsurface_array_size * 24;
2798 rsurface_array_color4f = base + rsurface_array_size * 27;
2801 float *rsurface_modelvertex3f;
2802 float *rsurface_modelsvector3f;
2803 float *rsurface_modeltvector3f;
2804 float *rsurface_modelnormal3f;
2805 float *rsurface_vertex3f;
2806 float *rsurface_svector3f;
2807 float *rsurface_tvector3f;
2808 float *rsurface_normal3f;
2809 float *rsurface_lightmapcolor4f;
2810 vec3_t rsurface_modelorg;
2811 qboolean rsurface_generatedvertex;
2812 const entity_render_t *rsurface_entity;
2813 const model_t *rsurface_model;
2814 texture_t *rsurface_texture;
2815 qboolean rsurface_uselightmaptexture;
2816 rsurfmode_t rsurface_mode;
2817 int rsurface_lightmode; // 0 = lightmap or fullbright, 1 = color array from q3bsp, 2 = vertex shaded model
2819 void RSurf_CleanUp(void)
2822 if (rsurface_mode == RSURFMODE_GLSL)
2824 qglUseProgramObjectARB(0);CHECKGLERROR
2826 GL_AlphaTest(false);
2827 rsurface_mode = RSURFMODE_NONE;
2828 rsurface_uselightmaptexture = false;
2829 rsurface_texture = NULL;
2832 void RSurf_ActiveEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
2835 Matrix4x4_Transform(&ent->inversematrix, r_view.origin, rsurface_modelorg);
2836 rsurface_entity = ent;
2837 rsurface_model = ent->model;
2838 if (rsurface_array_size < rsurface_model->surfmesh.num_vertices)
2839 R_Mesh_ResizeArrays(rsurface_model->surfmesh.num_vertices);
2840 R_Mesh_Matrix(&ent->matrix);
2841 Matrix4x4_Transform(&ent->inversematrix, r_view.origin, rsurface_modelorg);
2842 if ((rsurface_entity->frameblend[0].lerp != 1 || rsurface_entity->frameblend[0].frame != 0) && rsurface_model->surfmesh.isanimated)
2846 rsurface_modelvertex3f = rsurface_array_modelvertex3f;
2847 rsurface_modelsvector3f = rsurface_array_modelsvector3f;
2848 rsurface_modeltvector3f = rsurface_array_modeltvector3f;
2849 rsurface_modelnormal3f = rsurface_array_modelnormal3f;
2850 Mod_Alias_GetMesh_Vertices(rsurface_model, rsurface_entity->frameblend, rsurface_array_modelvertex3f, rsurface_array_modelnormal3f, rsurface_array_modelsvector3f, rsurface_array_modeltvector3f);
2852 else if (wantnormals)
2854 rsurface_modelvertex3f = rsurface_array_modelvertex3f;
2855 rsurface_modelsvector3f = NULL;
2856 rsurface_modeltvector3f = NULL;
2857 rsurface_modelnormal3f = rsurface_array_modelnormal3f;
2858 Mod_Alias_GetMesh_Vertices(rsurface_model, rsurface_entity->frameblend, rsurface_array_modelvertex3f, rsurface_array_modelnormal3f, NULL, NULL);
2862 rsurface_modelvertex3f = rsurface_array_modelvertex3f;
2863 rsurface_modelsvector3f = NULL;
2864 rsurface_modeltvector3f = NULL;
2865 rsurface_modelnormal3f = NULL;
2866 Mod_Alias_GetMesh_Vertices(rsurface_model, rsurface_entity->frameblend, rsurface_array_modelvertex3f, NULL, NULL, NULL);
2868 rsurface_generatedvertex = true;
2872 rsurface_modelvertex3f = rsurface_model->surfmesh.data_vertex3f;
2873 rsurface_modelsvector3f = rsurface_model->surfmesh.data_svector3f;
2874 rsurface_modeltvector3f = rsurface_model->surfmesh.data_tvector3f;
2875 rsurface_modelnormal3f = rsurface_model->surfmesh.data_normal3f;
2876 rsurface_generatedvertex = false;
2878 rsurface_vertex3f = rsurface_modelvertex3f;
2879 rsurface_svector3f = rsurface_modelsvector3f;
2880 rsurface_tvector3f = rsurface_modeltvector3f;
2881 rsurface_normal3f = rsurface_modelnormal3f;
2884 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, msurface_t **texturesurfacelist)
2886 // 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
2887 if (rsurface_generatedvertex)
2889 if (rsurface_texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
2890 generatetangents = true;
2891 if (generatetangents)
2892 generatenormals = true;
2893 if (generatenormals && !rsurface_modelnormal3f)
2895 rsurface_normal3f = rsurface_modelnormal3f = rsurface_array_modelnormal3f;
2896 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);
2898 if (generatetangents && !rsurface_modelsvector3f)
2900 rsurface_svector3f = rsurface_modelsvector3f = rsurface_array_modelsvector3f;
2901 rsurface_tvector3f = rsurface_modeltvector3f = rsurface_array_modeltvector3f;
2902 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);
2905 // 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)
2906 if (rsurface_texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
2908 int texturesurfaceindex;
2909 float center[3], forward[3], right[3], up[3], v[4][3];
2910 matrix4x4_t matrix1, imatrix1;
2911 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_view.forward, forward);
2912 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_view.right, right);
2913 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_view.up, up);
2914 // make deformed versions of only the model vertices used by the specified surfaces
2915 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2918 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2919 // a single autosprite surface can contain multiple sprites...
2920 for (j = 0;j < surface->num_vertices - 3;j += 4)
2922 VectorClear(center);
2923 for (i = 0;i < 4;i++)
2924 VectorAdd(center, (rsurface_modelvertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
2925 VectorScale(center, 0.25f, center);
2926 if (rsurface_texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE2)
2928 forward[0] = rsurface_modelorg[0] - center[0];
2929 forward[1] = rsurface_modelorg[1] - center[1];
2931 VectorNormalize(forward);
2932 right[0] = forward[1];
2933 right[1] = -forward[0];
2935 VectorSet(up, 0, 0, 1);
2937 // FIXME: calculate vectors from triangle edges instead of using texture vectors as an easy way out?
2938 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);
2939 Matrix4x4_Invert_Simple(&imatrix1, &matrix1);
2940 for (i = 0;i < 4;i++)
2941 Matrix4x4_Transform(&imatrix1, (rsurface_modelvertex3f + 3 * surface->num_firstvertex) + (j+i)*3, v[i]);
2942 for (i = 0;i < 4;i++)
2943 VectorMAMAMAM(1, center, v[i][0], forward, v[i][1], right, v[i][2], up, rsurface_array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
2945 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);
2946 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);
2948 rsurface_vertex3f = rsurface_array_deformedvertex3f;
2949 rsurface_svector3f = rsurface_array_deformedsvector3f;
2950 rsurface_tvector3f = rsurface_array_deformedtvector3f;
2951 rsurface_normal3f = rsurface_array_deformednormal3f;
2955 rsurface_vertex3f = rsurface_modelvertex3f;
2956 rsurface_svector3f = rsurface_modelsvector3f;
2957 rsurface_tvector3f = rsurface_modeltvector3f;
2958 rsurface_normal3f = rsurface_modelnormal3f;
2960 R_Mesh_VertexPointer(rsurface_vertex3f);
2963 void RSurf_DrawBatch_Simple(int texturenumsurfaces, msurface_t **texturesurfacelist)
2966 const msurface_t *surface = texturesurfacelist[0];
2967 const msurface_t *surface2;
2972 // TODO: lock all array ranges before render, rather than on each surface
2973 if (texturenumsurfaces == 1)
2975 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2976 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
2978 else if (r_batchmode.integer == 2)
2980 #define MAXBATCHTRIANGLES 4096
2981 int batchtriangles = 0;
2982 int batchelements[MAXBATCHTRIANGLES*3];
2983 for (i = 0;i < texturenumsurfaces;i = j)
2985 surface = texturesurfacelist[i];
2987 if (surface->num_triangles > MAXBATCHTRIANGLES)
2989 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
2992 memcpy(batchelements, rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
2993 batchtriangles = surface->num_triangles;
2994 firstvertex = surface->num_firstvertex;
2995 endvertex = surface->num_firstvertex + surface->num_vertices;
2996 for (;j < texturenumsurfaces;j++)
2998 surface2 = texturesurfacelist[j];
2999 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
3001 memcpy(batchelements + batchtriangles * 3, rsurface_model->surfmesh.data_element3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
3002 batchtriangles += surface2->num_triangles;
3003 firstvertex = min(firstvertex, surface2->num_firstvertex);
3004 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
3006 surface2 = texturesurfacelist[j-1];
3007 numvertices = endvertex - firstvertex;
3008 R_Mesh_Draw(firstvertex, numvertices, batchtriangles, batchelements);
3011 else if (r_batchmode.integer == 1)
3013 for (i = 0;i < texturenumsurfaces;i = j)
3015 surface = texturesurfacelist[i];
3016 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
3017 if (texturesurfacelist[j] != surface2)
3019 surface2 = texturesurfacelist[j-1];
3020 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
3021 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
3022 GL_LockArrays(surface->num_firstvertex, numvertices);
3023 R_Mesh_Draw(surface->num_firstvertex, numvertices, numtriangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
3028 for (i = 0;i < texturenumsurfaces;i++)
3030 surface = texturesurfacelist[i];
3031 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
3032 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
3037 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit)
3041 const msurface_t *surface = texturesurfacelist[0];
3042 const msurface_t *surface2;
3047 // TODO: lock all array ranges before render, rather than on each surface
3048 if (texturenumsurfaces == 1)
3050 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
3051 if (deluxemaptexunit >= 0)
3052 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
3053 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
3054 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
3056 else if (r_batchmode.integer == 2)
3058 #define MAXBATCHTRIANGLES 4096
3059 int batchtriangles = 0;
3060 int batchelements[MAXBATCHTRIANGLES*3];
3061 for (i = 0;i < texturenumsurfaces;i = j)
3063 surface = texturesurfacelist[i];
3064 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
3065 if (deluxemaptexunit >= 0)
3066 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
3068 if (surface->num_triangles > MAXBATCHTRIANGLES)
3070 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
3073 memcpy(batchelements, rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
3074 batchtriangles = surface->num_triangles;
3075 firstvertex = surface->num_firstvertex;
3076 endvertex = surface->num_firstvertex + surface->num_vertices;
3077 for (;j < texturenumsurfaces;j++)
3079 surface2 = texturesurfacelist[j];
3080 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
3082 memcpy(batchelements + batchtriangles * 3, rsurface_model->surfmesh.data_element3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
3083 batchtriangles += surface2->num_triangles;
3084 firstvertex = min(firstvertex, surface2->num_firstvertex);
3085 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
3087 surface2 = texturesurfacelist[j-1];
3088 numvertices = endvertex - firstvertex;
3089 R_Mesh_Draw(firstvertex, numvertices, batchtriangles, batchelements);
3092 else if (r_batchmode.integer == 1)
3095 Con_Printf("%s batch sizes ignoring lightmap:", rsurface_texture->name);
3096 for (i = 0;i < texturenumsurfaces;i = j)
3098 surface = texturesurfacelist[i];
3099 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
3100 if (texturesurfacelist[j] != surface2)
3102 Con_Printf(" %i", j - i);
3105 Con_Printf("%s batch sizes honoring lightmap:", rsurface_texture->name);
3107 for (i = 0;i < texturenumsurfaces;i = j)
3109 surface = texturesurfacelist[i];
3110 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
3111 if (deluxemaptexunit >= 0)
3112 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
3113 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
3114 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
3117 Con_Printf(" %i", j - i);
3119 surface2 = texturesurfacelist[j-1];
3120 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
3121 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
3122 GL_LockArrays(surface->num_firstvertex, numvertices);
3123 R_Mesh_Draw(surface->num_firstvertex, numvertices, numtriangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
3131 for (i = 0;i < texturenumsurfaces;i++)
3133 surface = texturesurfacelist[i];
3134 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
3135 if (deluxemaptexunit >= 0)
3136 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
3137 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
3138 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
3143 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
3146 int texturesurfaceindex;
3147 if (r_showsurfaces.integer == 2)
3149 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3151 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3152 for (j = 0;j < surface->num_triangles;j++)
3154 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_view.colorscale;
3155 GL_Color(f, f, f, 1);
3156 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, 1, (rsurface_model->surfmesh.data_element3i + 3 * (j + surface->num_firsttriangle)));
3162 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3164 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3165 int k = (int)(((size_t)surface) / sizeof(msurface_t));
3166 GL_Color((k & 15) * (1.0f / 16.0f) * r_view.colorscale, ((k >> 4) & 15) * (1.0f / 16.0f) * r_view.colorscale, ((k >> 8) & 15) * (1.0f / 16.0f) * r_view.colorscale, 1);
3167 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
3168 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
3173 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, msurface_t **texturesurfacelist)
3175 int texturesurfaceindex;
3179 if (rsurface_lightmapcolor4f)
3181 // generate color arrays for the surfaces in this list
3182 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3184 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3185 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)
3187 f = 1 - VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
3197 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3199 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3200 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)
3202 f = 1 - VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
3210 rsurface_lightmapcolor4f = rsurface_array_color4f;
3213 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a)
3215 int texturesurfaceindex;
3218 if (!rsurface_lightmapcolor4f)
3220 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3222 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3223 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)
3231 rsurface_lightmapcolor4f = rsurface_array_color4f;
3234 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
3237 rsurface_lightmapcolor4f = NULL;
3238 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
3239 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
3240 R_Mesh_ColorPointer(rsurface_lightmapcolor4f);
3241 GL_Color(r, g, b, a);
3242 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 0, -1);
3245 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
3247 // TODO: optimize applyfog && applycolor case
3248 // just apply fog if necessary, and tint the fog color array if necessary
3249 rsurface_lightmapcolor4f = NULL;
3250 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
3251 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
3252 R_Mesh_ColorPointer(rsurface_lightmapcolor4f);
3253 GL_Color(r, g, b, a);
3254 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3257 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
3259 int texturesurfaceindex;
3263 if (texturesurfacelist[0]->lightmapinfo && texturesurfacelist[0]->lightmapinfo->stainsamples)
3265 // generate color arrays for the surfaces in this list
3266 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3268 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3269 for (i = 0, c = rsurface_array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
3271 if (surface->lightmapinfo->samples)
3273 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface_model->surfmesh.data_lightmapoffsets + surface->num_firstvertex)[i];
3274 float scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
3275 VectorScale(lm, scale, c);
3276 if (surface->lightmapinfo->styles[1] != 255)
3278 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
3280 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
3281 VectorMA(c, scale, lm, c);
3282 if (surface->lightmapinfo->styles[2] != 255)
3285 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
3286 VectorMA(c, scale, lm, c);
3287 if (surface->lightmapinfo->styles[3] != 255)
3290 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
3291 VectorMA(c, scale, lm, c);
3301 rsurface_lightmapcolor4f = rsurface_array_color4f;
3304 rsurface_lightmapcolor4f = rsurface_model->surfmesh.data_lightmapcolor4f;
3305 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
3306 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
3307 R_Mesh_ColorPointer(rsurface_lightmapcolor4f);
3308 GL_Color(r, g, b, a);
3309 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3312 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
3314 int texturesurfaceindex;
3318 vec3_t ambientcolor;
3319 vec3_t diffusecolor;
3323 VectorCopy(rsurface_entity->modellight_lightdir, lightdir);
3324 ambientcolor[0] = rsurface_entity->modellight_ambient[0] * r * 0.5f;
3325 ambientcolor[1] = rsurface_entity->modellight_ambient[1] * g * 0.5f;
3326 ambientcolor[2] = rsurface_entity->modellight_ambient[2] * b * 0.5f;
3327 diffusecolor[0] = rsurface_entity->modellight_diffuse[0] * r * 0.5f;
3328 diffusecolor[1] = rsurface_entity->modellight_diffuse[1] * g * 0.5f;
3329 diffusecolor[2] = rsurface_entity->modellight_diffuse[2] * b * 0.5f;
3330 if (VectorLength2(diffusecolor) > 0)
3332 // generate color arrays for the surfaces in this list
3333 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3335 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3336 int numverts = surface->num_vertices;
3337 v = rsurface_vertex3f + 3 * surface->num_firstvertex;
3338 c2 = rsurface_normal3f + 3 * surface->num_firstvertex;
3339 c = rsurface_array_color4f + 4 * surface->num_firstvertex;
3340 // q3-style directional shading
3341 for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
3343 if ((f = DotProduct(c2, lightdir)) > 0)
3344 VectorMA(ambientcolor, f, diffusecolor, c);
3346 VectorCopy(ambientcolor, c);
3355 rsurface_lightmapcolor4f = rsurface_array_color4f;
3359 r = ambientcolor[0];
3360 g = ambientcolor[1];
3361 b = ambientcolor[2];
3362 rsurface_lightmapcolor4f = NULL;
3364 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
3365 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
3366 R_Mesh_ColorPointer(rsurface_lightmapcolor4f);
3367 GL_Color(r, g, b, a);
3368 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3371 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
3373 GL_DepthTest(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
3374 GL_CullFace(((rsurface_texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (rsurface_entity->flags & RENDER_NOCULLFACE)) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
3375 if (rsurface_mode != RSURFMODE_SHOWSURFACES)
3377 rsurface_mode = RSURFMODE_SHOWSURFACES;
3379 GL_BlendFunc(GL_ONE, GL_ZERO);
3380 R_Mesh_ColorPointer(NULL);
3381 R_Mesh_ResetTextureState();
3383 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
3384 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
3387 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, msurface_t **texturesurfacelist)
3389 // transparent sky would be ridiculous
3390 if ((rsurface_texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
3392 if (rsurface_mode != RSURFMODE_SKY)
3394 if (rsurface_mode == RSURFMODE_GLSL)
3396 qglUseProgramObjectARB(0);CHECKGLERROR
3398 rsurface_mode = RSURFMODE_SKY;
3402 skyrendernow = false;
3404 // restore entity matrix
3405 R_Mesh_Matrix(&rsurface_entity->matrix);
3407 GL_DepthTest(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
3408 GL_CullFace(((rsurface_texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (rsurface_entity->flags & RENDER_NOCULLFACE)) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
3410 // LordHavoc: HalfLife maps have freaky skypolys so don't use
3411 // skymasking on them, and Quake3 never did sky masking (unlike
3412 // software Quake and software Quake2), so disable the sky masking
3413 // in Quake3 maps as it causes problems with q3map2 sky tricks,
3414 // and skymasking also looks very bad when noclipping outside the
3415 // level, so don't use it then either.
3416 if (rsurface_model->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_viewcache.world_novis)
3418 GL_Color(r_refdef.fogcolor[0] * r_view.colorscale, r_refdef.fogcolor[1] * r_view.colorscale, r_refdef.fogcolor[2] * r_view.colorscale, 1);
3419 R_Mesh_ColorPointer(NULL);
3420 R_Mesh_ResetTextureState();
3421 if (skyrendermasked)
3423 // depth-only (masking)
3424 GL_ColorMask(0,0,0,0);
3425 // just to make sure that braindead drivers don't draw
3426 // anything despite that colormask...
3427 GL_BlendFunc(GL_ZERO, GL_ONE);
3432 GL_BlendFunc(GL_ONE, GL_ZERO);
3434 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
3435 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3436 if (skyrendermasked)
3437 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
3441 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, msurface_t **texturesurfacelist)
3443 if (rsurface_mode != RSURFMODE_GLSL)
3445 rsurface_mode = RSURFMODE_GLSL;
3446 R_Mesh_ResetTextureState();
3449 R_SetupSurfaceShader(vec3_origin, rsurface_lightmode == 2);
3450 if (!r_glsl_permutation)
3453 if (rsurface_lightmode == 2)
3454 RSurf_PrepareVerticesForBatch(true, r_glsl_permutation->loc_Texture_Normal, texturenumsurfaces, texturesurfacelist);
3456 RSurf_PrepareVerticesForBatch(r_glsl_permutation->loc_Texture_Normal, r_glsl_permutation->loc_Texture_Normal, texturenumsurfaces, texturesurfacelist);
3457 R_Mesh_TexCoordPointer(0, 2, rsurface_model->surfmesh.data_texcoordtexture2f);
3458 R_Mesh_TexCoordPointer(1, 3, rsurface_svector3f);
3459 R_Mesh_TexCoordPointer(2, 3, rsurface_tvector3f);
3460 R_Mesh_TexCoordPointer(3, 3, rsurface_normal3f);
3461 R_Mesh_TexCoordPointer(4, 2, rsurface_model->surfmesh.data_texcoordlightmap2f);
3463 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
3465 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
3466 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
3467 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
3468 R_Mesh_ColorPointer(NULL);
3470 else if (rsurface_uselightmaptexture)
3472 R_Mesh_TexBind(7, R_GetTexture(texturesurfacelist[0]->lightmaptexture));
3473 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
3474 R_Mesh_TexBind(8, R_GetTexture(texturesurfacelist[0]->deluxemaptexture));
3475 R_Mesh_ColorPointer(NULL);
3479 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
3480 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
3481 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
3482 R_Mesh_ColorPointer(rsurface_model->surfmesh.data_lightmapcolor4f);
3485 if (rsurface_uselightmaptexture && !(rsurface_texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
3486 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 7, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? 8 : -1);
3488 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3489 if (rsurface_texture->backgroundnumskinframes && !(rsurface_texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
3494 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, msurface_t **texturesurfacelist)
3496 // OpenGL 1.3 path - anything not completely ancient
3497 int texturesurfaceindex;
3498 qboolean applycolor;
3502 const texturelayer_t *layer;
3503 if (rsurface_mode != RSURFMODE_MULTIPASS)
3504 rsurface_mode = RSURFMODE_MULTIPASS;
3505 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
3506 for (layerindex = 0, layer = rsurface_texture->currentlayers;layerindex < rsurface_texture->currentnumlayers;layerindex++, layer++)
3509 int layertexrgbscale;
3510 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
3512 if (layerindex == 0)
3516 GL_AlphaTest(false);
3517 qglDepthFunc(GL_EQUAL);CHECKGLERROR
3520 GL_DepthMask(layer->depthmask);
3521 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
3522 if ((layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2) && (gl_combine.integer || layer->depthmask))
3524 layertexrgbscale = 4;
3525 VectorScale(layer->color, 0.25f, layercolor);
3527 else if ((layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1) && (gl_combine.integer || layer->depthmask))
3529 layertexrgbscale = 2;
3530 VectorScale(layer->color, 0.5f, layercolor);
3534 layertexrgbscale = 1;
3535 VectorScale(layer->color, 1.0f, layercolor);
3537 layercolor[3] = layer->color[3];
3538 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
3539 R_Mesh_ColorPointer(NULL);
3540 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
3541 switch (layer->type)
3543 case TEXTURELAYERTYPE_LITTEXTURE:
3544 memset(&m, 0, sizeof(m));
3545 m.tex[0] = R_GetTexture(r_texture_white);
3546 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordlightmap2f;
3547 m.tex[1] = R_GetTexture(layer->texture);
3548 m.texmatrix[1] = layer->texmatrix;
3549 m.texrgbscale[1] = layertexrgbscale;
3550 m.pointer_texcoord[1] = rsurface_model->surfmesh.data_texcoordtexture2f;
3551 R_Mesh_TextureState(&m);
3552 if (rsurface_lightmode == 2)
3553 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
3554 else if (rsurface_uselightmaptexture)
3555 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
3557 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
3559 case TEXTURELAYERTYPE_TEXTURE:
3560 memset(&m, 0, sizeof(m));
3561 m.tex[0] = R_GetTexture(layer->texture);
3562 m.texmatrix[0] = layer->texmatrix;
3563 m.texrgbscale[0] = layertexrgbscale;
3564 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3565 R_Mesh_TextureState(&m);
3566 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
3568 case TEXTURELAYERTYPE_FOG:
3569 memset(&m, 0, sizeof(m));
3570 m.texrgbscale[0] = layertexrgbscale;
3573 m.tex[0] = R_GetTexture(layer->texture);
3574 m.texmatrix[0] = layer->texmatrix;
3575 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3577 R_Mesh_TextureState(&m);
3578 // generate a color array for the fog pass
3579 R_Mesh_ColorPointer(rsurface_array_color4f);
3580 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3584 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3585 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)
3587 f = VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
3588 c[0] = layercolor[0];
3589 c[1] = layercolor[1];
3590 c[2] = layercolor[2];
3591 c[3] = f * layercolor[3];
3594 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3597 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
3599 GL_LockArrays(0, 0);
3602 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
3604 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3605 GL_AlphaTest(false);
3609 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, msurface_t **texturesurfacelist)
3611 // OpenGL 1.1 - crusty old voodoo path
3612 int texturesurfaceindex;
3616 const texturelayer_t *layer;
3617 if (rsurface_mode != RSURFMODE_MULTIPASS)
3618 rsurface_mode = RSURFMODE_MULTIPASS;
3619 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
3620 for (layerindex = 0, layer = rsurface_texture->currentlayers;layerindex < rsurface_texture->currentnumlayers;layerindex++, layer++)
3622 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
3624 if (layerindex == 0)
3628 GL_AlphaTest(false);
3629 qglDepthFunc(GL_EQUAL);CHECKGLERROR
3632 GL_DepthMask(layer->depthmask);
3633 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
3634 R_Mesh_ColorPointer(NULL);
3635 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
3636 switch (layer->type)
3638 case TEXTURELAYERTYPE_LITTEXTURE:
3639 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
3641 // two-pass lit texture with 2x rgbscale
3642 // first the lightmap pass
3643 memset(&m, 0, sizeof(m));
3644 m.tex[0] = R_GetTexture(r_texture_white);
3645 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordlightmap2f;
3646 R_Mesh_TextureState(&m);
3647 if (rsurface_lightmode == 2)
3648 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
3649 else if (rsurface_uselightmaptexture)
3650 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
3652 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
3653 GL_LockArrays(0, 0);
3654 // then apply the texture to it
3655 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
3656 memset(&m, 0, sizeof(m));
3657 m.tex[0] = R_GetTexture(layer->texture);
3658 m.texmatrix[0] = layer->texmatrix;
3659 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3660 R_Mesh_TextureState(&m);
3661 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layer->color[0] * 0.5f, layer->color[1] * 0.5f, layer->color[2] * 0.5f, layer->color[3], layer->color[0] != 2 || layer->color[1] != 2 || layer->color[2] != 2 || layer->color[3] != 1, false);
3665 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
3666 memset(&m, 0, sizeof(m));
3667 m.tex[0] = R_GetTexture(layer->texture);
3668 m.texmatrix[0] = layer->texmatrix;
3669 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3670 R_Mesh_TextureState(&m);
3671 if (rsurface_lightmode == 2)
3672 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layer->color[0], layer->color[1], layer->color[2], layer->color[3], layer->color[0] != 1 || layer->color[1] != 1 || layer->color[2] != 1 || layer->color[3] != 1, applyfog);
3674 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layer->color[0], layer->color[1], layer->color[2], layer->color[3], layer->color[0] != 1 || layer->color[1] != 1 || layer->color[2] != 1 || layer->color[3] != 1, applyfog);
3677 case TEXTURELAYERTYPE_TEXTURE:
3678 // singletexture unlit texture with transparency support
3679 memset(&m, 0, sizeof(m));
3680 m.tex[0] = R_GetTexture(layer->texture);
3681 m.texmatrix[0] = layer->texmatrix;
3682 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3683 R_Mesh_TextureState(&m);
3684 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layer->color[0], layer->color[1], layer->color[2], layer->color[3], layer->color[0] != 1 || layer->color[1] != 1 || layer->color[2] != 1 || layer->color[3] != 1, applyfog);
3686 case TEXTURELAYERTYPE_FOG:
3687 // singletexture fogging
3688 R_Mesh_ColorPointer(rsurface_array_color4f);
3691 memset(&m, 0, sizeof(m));
3692 m.tex[0] = R_GetTexture(layer->texture);
3693 m.texmatrix[0] = layer->texmatrix;
3694 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3695 R_Mesh_TextureState(&m);
3698 R_Mesh_ResetTextureState();
3699 // generate a color array for the fog pass
3700 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3704 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3705 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)
3707 f = VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
3708 c[0] = layer->color[0];
3709 c[1] = layer->color[1];
3710 c[2] = layer->color[2];
3711 c[3] = f * layer->color[3];
3714 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3717 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
3719 GL_LockArrays(0, 0);
3722 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
3724 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3725 GL_AlphaTest(false);
3729 static void R_DrawTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist)
3731 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_NODRAW)
3733 r_shadow_rtlight = NULL;
3734 r_refdef.stats.entities_surfaces += texturenumsurfaces;
3736 if (r_showsurfaces.integer)
3737 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
3738 else if (rsurface_texture->currentmaterialflags & MATERIALFLAG_SKY)
3739 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
3740 else if (rsurface_texture->currentnumlayers)
3742 GL_DepthTest(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
3743 GL_CullFace(((rsurface_texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (rsurface_entity->flags & RENDER_NOCULLFACE)) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
3744 GL_BlendFunc(rsurface_texture->currentlayers[0].blendfunc1, rsurface_texture->currentlayers[0].blendfunc2);
3745 GL_DepthMask(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_BLENDED));
3746 GL_Color(rsurface_entity->colormod[0], rsurface_entity->colormod[1], rsurface_entity->colormod[2], rsurface_texture->currentalpha);
3747 GL_AlphaTest((rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
3748 // FIXME: identify models using a better check than rsurface_model->brush.shadowmesh
3749 rsurface_lightmode = ((rsurface_texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT) || rsurface_model->brush.shadowmesh) ? 0 : 2;
3750 if (r_glsl.integer && gl_support_fragment_shader)
3751 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist);
3752 else if (gl_combine.integer && r_textureunits.integer >= 2)
3753 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist);
3755 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist);
3758 GL_LockArrays(0, 0);
3761 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
3764 int texturenumsurfaces, endsurface;
3766 msurface_t *surface;
3767 msurface_t *texturesurfacelist[1024];
3769 // if the model is static it doesn't matter what value we give for
3770 // wantnormals and wanttangents, so this logic uses only rules applicable
3771 // to a model, knowing that they are meaningless otherwise
3772 if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
3773 RSurf_ActiveEntity(ent, false, false);
3775 RSurf_ActiveEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
3777 for (i = 0;i < numsurfaces;i = j)
3780 surface = rsurface_model->data_surfaces + surfacelist[i];
3781 texture = surface->texture;
3782 rsurface_texture = texture->currentframe;
3783 rsurface_uselightmaptexture = surface->lightmaptexture != NULL;
3784 // scan ahead until we find a different texture
3785 endsurface = min(i + 1024, numsurfaces);
3786 texturenumsurfaces = 0;
3787 texturesurfacelist[texturenumsurfaces++] = surface;
3788 for (;j < endsurface;j++)
3790 surface = rsurface_model->data_surfaces + surfacelist[j];
3791 if (texture != surface->texture || rsurface_uselightmaptexture != (surface->lightmaptexture != NULL))
3793 texturesurfacelist[texturenumsurfaces++] = surface;
3795 // render the range of surfaces
3796 R_DrawTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
3802 void R_QueueSurfaceList(int numsurfaces, msurface_t **surfacelist)
3805 vec3_t tempcenter, center;
3807 // break the surface list down into batches by texture and use of lightmapping
3808 for (i = 0;i < numsurfaces;i = j)
3811 // texture is the base texture pointer, rsurface_texture is the
3812 // current frame/skin the texture is directing us to use (for example
3813 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
3814 // use skin 1 instead)
3815 texture = surfacelist[i]->texture;
3816 rsurface_texture = texture->currentframe;
3817 rsurface_uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
3818 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_BLENDED)
3820 // transparent surfaces get pushed off into the transparent queue
3821 const msurface_t *surface = surfacelist[i];
3822 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
3823 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
3824 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
3825 Matrix4x4_Transform(&rsurface_entity->matrix, tempcenter, center);
3826 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);
3830 // simply scan ahead until we find a different texture
3831 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface_uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++);
3832 // render the range of surfaces
3833 R_DrawTextureSurfaceList(j - i, surfacelist + i);
3838 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
3839 void R_DrawSurfaces(entity_render_t *ent, qboolean skysurfaces)
3841 int i, j, k, l, endj, f, flagsmask;
3842 int counttriangles = 0;
3843 msurface_t *surface, *endsurface, **surfacechain;
3846 model_t *model = ent->model;
3847 const int *elements;
3848 const int maxsurfacelist = 1024;
3849 int numsurfacelist = 0;
3850 msurface_t *surfacelist[1024];
3855 // if the model is static it doesn't matter what value we give for
3856 // wantnormals and wanttangents, so this logic uses only rules applicable
3857 // to a model, knowing that they are meaningless otherwise
3858 if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
3859 RSurf_ActiveEntity(ent, false, false);
3861 RSurf_ActiveEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
3863 // update light styles
3864 if (!skysurfaces && model->brushq1.light_styleupdatechains)
3866 for (i = 0;i < model->brushq1.light_styles;i++)
3868 if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
3870 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
3871 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
3872 for (;(surface = *surfacechain);surfacechain++)
3873 surface->cached_dlight = true;
3878 R_UpdateAllTextureInfo(ent);
3879 flagsmask = skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL);
3882 rsurface_uselightmaptexture = false;
3883 rsurface_texture = NULL;
3885 if (ent == r_refdef.worldentity)
3887 j = model->firstmodelsurface;
3888 endj = j + model->nummodelsurfaces;
3891 // quickly skip over non-visible surfaces
3892 for (;j < endj && !r_viewcache.world_surfacevisible[j];j++)
3894 // quickly iterate over visible surfaces
3895 for (;j < endj && r_viewcache.world_surfacevisible[j];j++)
3897 // process this surface
3898 surface = model->data_surfaces + j;
3899 // if this surface fits the criteria, add it to the list
3900 if (surface->texture->basematerialflags & flagsmask && surface->num_triangles)
3902 // if lightmap parameters changed, rebuild lightmap texture
3903 if (surface->cached_dlight)
3904 R_BuildLightMap(ent, surface);
3905 // add face to draw list
3906 surfacelist[numsurfacelist++] = surface;
3907 counttriangles += surface->num_triangles;
3908 if (numsurfacelist >= maxsurfacelist)
3910 R_QueueSurfaceList(numsurfacelist, surfacelist);
3919 surface = model->data_surfaces + model->firstmodelsurface;
3920 endsurface = surface + model->nummodelsurfaces;
3921 for (;surface < endsurface;surface++)
3923 // if this surface fits the criteria, add it to the list
3924 if (surface->texture->basematerialflags & flagsmask && surface->num_triangles)
3926 // if lightmap parameters changed, rebuild lightmap texture
3927 if (surface->cached_dlight)
3928 R_BuildLightMap(ent, surface);
3929 // add face to draw list
3930 surfacelist[numsurfacelist++] = surface;
3931 counttriangles += surface->num_triangles;
3932 if (numsurfacelist >= maxsurfacelist)
3934 R_QueueSurfaceList(numsurfacelist, surfacelist);
3941 R_QueueSurfaceList(numsurfacelist, surfacelist);
3942 r_refdef.stats.entities_triangles += counttriangles;
3945 if (r_showcollisionbrushes.integer && model->brush.num_brushes && !skysurfaces)
3948 R_Mesh_Matrix(&ent->matrix);
3949 R_Mesh_ColorPointer(NULL);
3950 R_Mesh_ResetTextureState();
3951 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
3952 GL_DepthMask(false);
3953 GL_DepthTest(!r_showdisabledepthtest.integer);
3954 qglPolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);CHECKGLERROR
3955 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
3956 if (brush->colbrushf && brush->colbrushf->numtriangles)
3957 R_DrawCollisionBrush(brush->colbrushf);
3958 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
3959 if (surface->num_collisiontriangles)
3960 R_DrawCollisionSurface(ent, surface);
3961 qglPolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR
3964 if (r_showtris.integer || r_shownormals.integer)
3967 GL_DepthTest(!r_showdisabledepthtest.integer);
3969 GL_BlendFunc(GL_ONE, GL_ZERO);
3970 R_Mesh_ColorPointer(NULL);
3971 R_Mesh_ResetTextureState();
3972 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
3974 if (ent == r_refdef.worldentity && !r_viewcache.world_surfacevisible[j])
3976 rsurface_texture = surface->texture->currentframe;
3977 if ((rsurface_texture->currentmaterialflags & flagsmask) && surface->num_triangles)
3979 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
3980 if (r_showtris.integer)
3982 if (!rsurface_texture->currentlayers->depthmask)
3983 GL_Color(r_showtris.value * r_view.colorscale, 0, 0, 1);
3984 else if (ent == r_refdef.worldentity)
3985 GL_Color(r_showtris.value * r_view.colorscale, r_showtris.value * r_view.colorscale, r_showtris.value * r_view.colorscale, 1);
3987 GL_Color(0, r_showtris.value * r_view.colorscale, 0, 1);
3988 elements = (ent->model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
3991 for (k = 0;k < surface->num_triangles;k++, elements += 3)
3993 qglArrayElement(elements[0]);qglArrayElement(elements[1]);
3994 qglArrayElement(elements[1]);qglArrayElement(elements[2]);
3995 qglArrayElement(elements[2]);qglArrayElement(elements[0]);
4000 if (r_shownormals.integer)
4002 GL_Color(r_shownormals.value * r_view.colorscale, 0, 0, 1);
4004 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
4006 VectorCopy(rsurface_vertex3f + l * 3, v);
4007 qglVertex3f(v[0], v[1], v[2]);
4008 VectorMA(v, 8, rsurface_svector3f + l * 3, v);
4009 qglVertex3f(v[0], v[1], v[2]);
4013 GL_Color(0, 0, r_shownormals.value * r_view.colorscale, 1);
4015 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
4017 VectorCopy(rsurface_vertex3f + l * 3, v);
4018 qglVertex3f(v[0], v[1], v[2]);
4019 VectorMA(v, 8, rsurface_tvector3f + l * 3, v);
4020 qglVertex3f(v[0], v[1], v[2]);
4024 GL_Color(0, r_shownormals.value * r_view.colorscale, 0, 1);
4026 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
4028 VectorCopy(rsurface_vertex3f + l * 3, v);
4029 qglVertex3f(v[0], v[1], v[2]);
4030 VectorMA(v, 8, rsurface_normal3f + l * 3, v);
4031 qglVertex3f(v[0], v[1], v[2]);
4038 rsurface_texture = NULL;