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_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
50 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling"};
51 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
52 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
53 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
54 cvar_t r_fullbright = {0, "r_fullbright","0", "make everything bright cheat (not allowed in multiplayer)"};
55 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
56 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
57 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
58 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this)"};
59 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
60 cvar_t r_q1bsp_skymasking = {0, "r_qb1sp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
62 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
63 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
64 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
65 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
66 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
67 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
68 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
70 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)"};
72 cvar_t r_glsl = {0, "r_glsl", "1", "enables use of OpenGL 2.0 pixel shaders for lighting"};
73 cvar_t r_glsl_offsetmapping = {0, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
74 cvar_t r_glsl_offsetmapping_reliefmapping = {0, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
75 cvar_t r_glsl_offsetmapping_scale = {0, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
76 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)"};
78 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1", "enables animation smoothing on sprites (requires r_lerpmodels 1)"};
79 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
80 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
82 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
83 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
84 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
85 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
86 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
87 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
88 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
90 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
91 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
92 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
93 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)"};
95 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"};
97 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"};
99 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
101 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
102 cvar_t r_batchmode = {0, "r_batchmode", "1", "selects method of rendering multiple surfaces with one driver call (values are 0, 1, 2, etc...)"};
104 typedef struct r_glsl_bloomshader_s
107 int loc_Texture_Bloom;
109 r_glsl_bloomshader_t;
111 static struct r_bloomstate_s
116 int bloomwidth, bloomheight;
118 int screentexturewidth, screentextureheight;
119 rtexture_t *texture_screen;
121 int bloomtexturewidth, bloomtextureheight;
122 rtexture_t *texture_bloom;
124 r_glsl_bloomshader_t *shader;
126 // arrays for rendering the screen passes
127 float screentexcoord2f[8];
128 float bloomtexcoord2f[8];
129 float offsettexcoord2f[8];
133 // shadow volume bsp struct with automatically growing nodes buffer
136 rtexture_t *r_texture_blanknormalmap;
137 rtexture_t *r_texture_white;
138 rtexture_t *r_texture_black;
139 rtexture_t *r_texture_notexture;
140 rtexture_t *r_texture_whitecube;
141 rtexture_t *r_texture_normalizationcube;
142 rtexture_t *r_texture_fogattenuation;
143 //rtexture_t *r_texture_fogintensity;
145 // information about each possible shader permutation
146 r_glsl_permutation_t r_glsl_permutations[SHADERPERMUTATION_COUNT];
147 // currently selected permutation
148 r_glsl_permutation_t *r_glsl_permutation;
150 // temporary variable used by a macro
153 // vertex coordinates for a quad that covers the screen exactly
154 const static float r_screenvertex3f[12] =
162 extern void R_DrawModelShadows(void);
164 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
167 for (i = 0;i < verts;i++)
178 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
181 for (i = 0;i < verts;i++)
191 // FIXME: move this to client?
194 if (gamemode == GAME_NEHAHRA)
196 Cvar_Set("gl_fogenable", "0");
197 Cvar_Set("gl_fogdensity", "0.2");
198 Cvar_Set("gl_fogred", "0.3");
199 Cvar_Set("gl_foggreen", "0.3");
200 Cvar_Set("gl_fogblue", "0.3");
202 r_refdef.fog_density = r_refdef.fog_red = r_refdef.fog_green = r_refdef.fog_blue = 0.0f;
205 // FIXME: move this to client?
206 void FOG_registercvars(void)
211 if (gamemode == GAME_NEHAHRA)
213 Cvar_RegisterVariable (&gl_fogenable);
214 Cvar_RegisterVariable (&gl_fogdensity);
215 Cvar_RegisterVariable (&gl_fogred);
216 Cvar_RegisterVariable (&gl_foggreen);
217 Cvar_RegisterVariable (&gl_fogblue);
218 Cvar_RegisterVariable (&gl_fogstart);
219 Cvar_RegisterVariable (&gl_fogend);
222 r = (-1.0/256.0) * (FOGTABLEWIDTH * FOGTABLEWIDTH);
223 for (x = 0;x < FOGTABLEWIDTH;x++)
225 alpha = exp(r / ((double)x*(double)x));
226 if (x == FOGTABLEWIDTH - 1)
228 r_refdef.fogtable[x] = bound(0, alpha, 1);
232 static void R_BuildBlankTextures(void)
234 unsigned char data[4];
235 data[0] = 128; // normal X
236 data[1] = 128; // normal Y
237 data[2] = 255; // normal Z
238 data[3] = 128; // height
239 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
244 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
249 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
252 static void R_BuildNoTexture(void)
255 unsigned char pix[16][16][4];
256 // this makes a light grey/dark grey checkerboard texture
257 for (y = 0;y < 16;y++)
259 for (x = 0;x < 16;x++)
261 if ((y < 8) ^ (x < 8))
277 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_RGBA, TEXF_MIPMAP, NULL);
280 static void R_BuildWhiteCube(void)
282 unsigned char data[6*1*1*4];
283 data[ 0] = 255;data[ 1] = 255;data[ 2] = 255;data[ 3] = 255;
284 data[ 4] = 255;data[ 5] = 255;data[ 6] = 255;data[ 7] = 255;
285 data[ 8] = 255;data[ 9] = 255;data[10] = 255;data[11] = 255;
286 data[12] = 255;data[13] = 255;data[14] = 255;data[15] = 255;
287 data[16] = 255;data[17] = 255;data[18] = 255;data[19] = 255;
288 data[20] = 255;data[21] = 255;data[22] = 255;data[23] = 255;
289 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
292 static void R_BuildNormalizationCube(void)
296 vec_t s, t, intensity;
298 unsigned char data[6][NORMSIZE][NORMSIZE][4];
299 for (side = 0;side < 6;side++)
301 for (y = 0;y < NORMSIZE;y++)
303 for (x = 0;x < NORMSIZE;x++)
305 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
306 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
341 intensity = 127.0f / sqrt(DotProduct(v, v));
342 data[side][y][x][0] = (unsigned char)(128.0f + intensity * v[0]);
343 data[side][y][x][1] = (unsigned char)(128.0f + intensity * v[1]);
344 data[side][y][x][2] = (unsigned char)(128.0f + intensity * v[2]);
345 data[side][y][x][3] = 255;
349 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, &data[0][0][0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
352 static void R_BuildFogTexture(void)
357 unsigned char data1[FOGWIDTH][4];
358 //unsigned char data2[FOGWIDTH][4];
359 r = (-1.0/256.0) * (FOGWIDTH * FOGWIDTH);
360 for (x = 0;x < FOGWIDTH;x++)
362 alpha = exp(r / ((double)x*(double)x));
363 if (x == FOGWIDTH - 1)
365 b = (int)(256.0 * alpha);
366 b = bound(0, b, 255);
367 data1[x][0] = 255 - b;
368 data1[x][1] = 255 - b;
369 data1[x][2] = 255 - b;
376 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
377 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
380 static const char *builtinshaderstring =
381 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
382 "// written by Forest 'LordHavoc' Hale\n"
384 "// common definitions between vertex shader and fragment shader:\n"
386 "#ifdef __GLSL_CG_DATA_TYPES\n"
387 "#define myhalf half\n"
388 "#define myhvec2 hvec2\n"
389 "#define myhvec3 hvec3\n"
390 "#define myhvec4 hvec4\n"
392 "#define myhalf float\n"
393 "#define myhvec2 vec2\n"
394 "#define myhvec3 vec3\n"
395 "#define myhvec4 vec4\n"
398 "varying vec2 TexCoord;\n"
399 "varying vec2 TexCoordLightmap;\n"
401 "varying vec3 CubeVector;\n"
402 "varying vec3 LightVector;\n"
403 "varying vec3 EyeVector;\n"
405 "varying vec3 EyeVectorModelSpace;\n"
408 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
409 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
410 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
415 "// vertex shader specific:\n"
416 "#ifdef VERTEX_SHADER\n"
418 "uniform vec3 LightPosition;\n"
419 "uniform vec3 EyePosition;\n"
420 "uniform vec3 LightDir;\n"
422 "// TODO: get rid of tangentt (texcoord2) and use a crossproduct to regenerate it from tangents (texcoord1) and normal (texcoord3)\n"
426 " gl_FrontColor = gl_Color;\n"
427 " // copy the surface texcoord\n"
428 " TexCoord = vec2(gl_TextureMatrix[0] * gl_MultiTexCoord0);\n"
429 "#if !defined(MODE_LIGHTSOURCE) && !defined(MODE_LIGHTDIRECTION)\n"
430 " TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
433 "#ifdef MODE_LIGHTSOURCE\n"
434 " // transform vertex position into light attenuation/cubemap space\n"
435 " // (-1 to +1 across the light box)\n"
436 " CubeVector = vec3(gl_TextureMatrix[3] * gl_Vertex);\n"
438 " // transform unnormalized light direction into tangent space\n"
439 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
440 " // normalize it per pixel)\n"
441 " vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
442 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
443 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
444 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
447 "#ifdef MODE_LIGHTDIRECTION\n"
448 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
449 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
450 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
453 " // transform unnormalized eye direction into tangent space\n"
455 " vec3 EyeVectorModelSpace;\n"
457 " EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
458 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
459 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
460 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
462 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
463 " VectorS = gl_MultiTexCoord1.xyz;\n"
464 " VectorT = gl_MultiTexCoord2.xyz;\n"
465 " VectorR = gl_MultiTexCoord3.xyz;\n"
468 " // transform vertex to camera space, using ftransform to match non-VS\n"
470 " gl_Position = ftransform();\n"
473 "#endif // VERTEX_SHADER\n"
478 "// fragment shader specific:\n"
479 "#ifdef FRAGMENT_SHADER\n"
481 "uniform sampler2D Texture_Normal;\n"
482 "uniform sampler2D Texture_Color;\n"
483 "uniform sampler2D Texture_Gloss;\n"
484 "uniform samplerCube Texture_Cube;\n"
485 "uniform sampler2D Texture_FogMask;\n"
486 "uniform sampler2D Texture_Pants;\n"
487 "uniform sampler2D Texture_Shirt;\n"
488 "uniform sampler2D Texture_Lightmap;\n"
489 "uniform sampler2D Texture_Deluxemap;\n"
490 "uniform sampler2D Texture_Glow;\n"
492 "uniform myhvec3 LightColor;\n"
493 "uniform myhvec3 AmbientColor;\n"
494 "uniform myhvec3 DiffuseColor;\n"
495 "uniform myhvec3 SpecularColor;\n"
496 "uniform myhvec3 Color_Pants;\n"
497 "uniform myhvec3 Color_Shirt;\n"
498 "uniform myhvec3 FogColor;\n"
500 "uniform myhalf GlowScale;\n"
501 "uniform myhalf SceneBrightness;\n"
503 "uniform float OffsetMapping_Scale;\n"
504 "uniform float OffsetMapping_Bias;\n"
505 "uniform float FogRangeRecip;\n"
507 "uniform myhalf AmbientScale;\n"
508 "uniform myhalf DiffuseScale;\n"
509 "uniform myhalf SpecularScale;\n"
510 "uniform myhalf SpecularPower;\n"
514 " // apply offsetmapping\n"
515 "#ifdef USEOFFSETMAPPING\n"
516 " vec2 TexCoordOffset = TexCoord;\n"
517 "#define TexCoord TexCoordOffset\n"
519 " vec3 eyedir = vec3(normalize(EyeVector));\n"
520 " float depthbias = 1.0 - eyedir.z; // should this be a -?\n"
521 " depthbias = 1.0 - depthbias * depthbias;\n"
523 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
524 " // 14 sample relief mapping: linear search and then binary search\n"
525 " //vec3 OffsetVector = vec3(EyeVector.xy * (1.0 / EyeVector.z) * depthbias * OffsetMapping_Scale * vec2(-0.1, 0.1), -0.1);\n"
526 " //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-0.1, 0.1), -0.1);\n"
527 " vec3 OffsetVector = vec3(eyedir.xy * OffsetMapping_Scale * vec2(-0.1, 0.1), -0.1);\n"
528 " vec3 RT = vec3(TexCoord - OffsetVector.xy * 10.0, 1.0) + 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;\n"
534 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
535 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
536 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) 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 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;OffsetVector *= 0.5;RT -= OffsetVector;\n"
540 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;OffsetVector *= 0.5;RT -= OffsetVector;\n"
541 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;OffsetVector *= 0.5;RT -= OffsetVector;\n"
542 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;OffsetVector *= 0.5;RT -= OffsetVector;\n"
543 " TexCoord = RT.xy;\n"
545 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
546 " //vec2 OffsetVector = vec2(EyeVector.xy * (1.0 / EyeVector.z) * depthbias) * OffsetMapping_Scale * vec2(-0.333, 0.333);\n"
547 " //vec2 OffsetVector = vec2(normalize(EyeVector.xy)) * OffsetMapping_Scale * vec2(-0.333, 0.333);\n"
548 " vec2 OffsetVector = vec2(eyedir.xy) * OffsetMapping_Scale * vec2(-0.333, 0.333);\n"
549 " //TexCoord += OffsetVector * 3.0;\n"
550 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
551 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
552 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
554 " // 10 sample offset mapping\n"
555 " //vec2 OffsetVector = vec2(EyeVector.xy * (1.0 / EyeVector.z) * depthbias) * OffsetMapping_Scale * vec2(-0.333, 0.333);\n"
556 " //vec2 OffsetVector = vec2(normalize(EyeVector.xy)) * OffsetMapping_Scale * vec2(-0.333, 0.333);\n"
557 " vec2 OffsetVector = vec2(eyedir.xy) * OffsetMapping_Scale * vec2(-0.1, 0.1);\n"
558 " //TexCoord += OffsetVector * 3.0;\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"
565 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
566 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
567 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
568 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
570 " // parallax mapping as described in the paper\n"
571 " // 'Parallax Mapping with Offset Limiting: A Per-Pixel Approximation of Uneven Surfaces' by Terry Welsh\n"
572 " // The paper provides code in the ARB fragment program assembly language\n"
573 " // I translated it to GLSL but may have done something wrong - SavageX\n"
574 " // LordHavoc: removed bias and simplified to one line\n"
575 " // LordHavoc: this is just a single sample offsetmapping...\n"
576 " TexCoordOffset += vec2(eyedir.x, -1.0 * eyedir.y) * OffsetMapping_Scale * texture2D(Texture_Normal, TexCoord).a;\n"
578 " // parallax mapping as described in the paper\n"
579 " // 'Parallax Mapping with Offset Limiting: A Per-Pixel Approximation of Uneven Surfaces' by Terry Welsh\n"
580 " // The paper provides code in the ARB fragment program assembly language\n"
581 " // I translated it to GLSL but may have done something wrong - SavageX\n"
582 " float height = texture2D(Texture_Normal, TexCoord).a;\n"
583 " height = (height - 0.5) * OffsetMapping_Scale; // bias and scale\n"
584 " TexCoordOffset += height * vec2(eyedir.x, -1.0 * eyedir.y);\n"
588 " // combine the diffuse textures (base, pants, shirt)\n"
589 " myhvec4 color = myhvec4(texture2D(Texture_Color, TexCoord));\n"
590 "#ifdef USECOLORMAPPING\n"
591 " color.rgb += myhvec3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhvec3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
597 "#ifdef MODE_LIGHTSOURCE\n"
600 " // get the surface normal and light normal\n"
601 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
602 " myhvec3 diffusenormal = myhvec3(normalize(LightVector));\n"
604 " // calculate directional shading\n"
605 " color.rgb *= AmbientScale + DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
606 "#ifdef USESPECULAR\n"
607 " myhvec3 specularnormal = normalize(diffusenormal + myhvec3(normalize(EyeVector)));\n"
608 " color.rgb += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
611 "#ifdef USECUBEFILTER\n"
612 " // apply light cubemap filter\n"
613 " //color.rgb *= normalize(CubeVector) * 0.5 + 0.5;//vec3(textureCube(Texture_Cube, CubeVector));\n"
614 " color.rgb *= myhvec3(textureCube(Texture_Cube, CubeVector));\n"
617 " // apply light color\n"
618 " color.rgb *= LightColor;\n"
620 " // apply attenuation\n"
622 " // the attenuation is (1-(x*x+y*y+z*z)) which gives a large bright\n"
623 " // center and sharp falloff at the edge, this is about the most efficient\n"
624 " // we can get away with as far as providing illumination.\n"
626 " // pow(1-(x*x+y*y+z*z), 4) is far more realistic but needs large lights to\n"
627 " // provide significant illumination, large = slow = pain.\n"
628 "// color.rgb *= myhalf(max(1.0 - dot(CubeVector, CubeVector), 0.0));\n"
629 " color.rgb *= myhalf(max(2.0 - 2.0 * length(CubeVector), 0.0) / (1 + dot(CubeVector, CubeVector)));\n"
634 "#elif defined(MODE_LIGHTDIRECTION)\n"
635 " // directional model lighting\n"
637 " // get the surface normal and light normal\n"
638 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
639 " myhvec3 diffusenormal = myhvec3(normalize(LightVector));\n"
641 " // calculate directional shading\n"
642 " color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
643 "#ifdef USESPECULAR\n"
644 " myhvec3 specularnormal = normalize(diffusenormal + myhvec3(normalize(EyeVector)));\n"
645 " color.rgb += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
651 "#elif defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
652 " // deluxemap lightmapping using light vectors in modelspace (evil q3map2)\n"
654 " // get the surface normal and light normal\n"
655 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
657 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
658 " myhvec3 diffusenormal_modelspace = myhvec3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - myhvec3(0.5);\n"
659 " myhvec3 diffusenormal = normalize(myhvec3(dot(diffusenormal_modelspace, myhvec3(VectorS)), dot(diffusenormal_modelspace, myhvec3(VectorT)), dot(diffusenormal_modelspace, myhvec3(VectorR))));\n"
661 " myhvec3 diffusenormal = normalize(myhvec3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - myhvec3(0.5));\n"
663 " // calculate directional shading\n"
664 " myhvec3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0)));\n"
665 "#ifdef USESPECULAR\n"
666 " myhvec3 specularnormal = myhvec3(normalize(diffusenormal + myhvec3(normalize(EyeVector))));\n"
667 " tempcolor += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
670 " // apply lightmap color\n"
671 " color.rgb = tempcolor * myhvec3(texture2D(Texture_Lightmap, TexCoordLightmap)) + color.rgb * AmbientScale;\n"
674 "#else // MODE none (lightmap)\n"
675 " // apply lightmap color\n"
676 " color.rgb *= myhvec3(texture2D(Texture_Lightmap, TexCoordLightmap)) * DiffuseScale + myhvec3(AmbientScale);\n"
679 " color *= myhvec4(gl_Color);\n"
682 " color.rgb += myhvec3(texture2D(Texture_Glow, TexCoord)) * GlowScale;\n"
687 " myhalf fog = myhalf(texture2D(Texture_FogMask, myhvec2(length(EyeVectorModelSpace)*FogRangeRecip, 0.0)).x);\n"
688 " color.rgb = color.rgb * fog + FogColor * (1.0 - fog);\n"
691 " color.rgb *= SceneBrightness;\n"
693 " gl_FragColor = vec4(color);\n"
696 "#endif // FRAGMENT_SHADER\n"
699 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
700 const char *permutationinfo[][2] =
702 {"#define MODE_LIGHTSOURCE\n", " lightsource"},
703 {"#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
704 {"#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
705 {"#define MODE_LIGHTDIRECTION\n", " lightdirection"},
706 {"#define USEGLOW\n", " glow"},
707 {"#define USEFOG\n", " fog"},
708 {"#define USECOLORMAPPING\n", " colormapping"},
709 {"#define USESPECULAR\n", " specular"},
710 {"#define USECUBEFILTER\n", " cubefilter"},
711 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
712 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
716 void R_GLSL_CompilePermutation(const char *filename, int permutation)
719 qboolean shaderfound;
720 r_glsl_permutation_t *p = r_glsl_permutations + (permutation & SHADERPERMUTATION_COUNTMASK);
721 int vertstrings_count;
722 int geomstrings_count;
723 int fragstrings_count;
725 const char *vertstrings_list[SHADERPERMUTATION_COUNT+1];
726 const char *geomstrings_list[SHADERPERMUTATION_COUNT+1];
727 const char *fragstrings_list[SHADERPERMUTATION_COUNT+1];
728 char permutationname[256];
733 vertstrings_list[0] = "#define VERTEX_SHADER\n";
734 geomstrings_list[0] = "#define GEOMETRY_SHADER\n";
735 fragstrings_list[0] = "#define FRAGMENT_SHADER\n";
736 vertstrings_count = 1;
737 geomstrings_count = 1;
738 fragstrings_count = 1;
739 permutationname[0] = 0;
740 for (i = 0;permutationinfo[i][0];i++)
742 if (permutation & (1<<i))
744 vertstrings_list[vertstrings_count++] = permutationinfo[i][0];
745 geomstrings_list[geomstrings_count++] = permutationinfo[i][0];
746 fragstrings_list[fragstrings_count++] = permutationinfo[i][0];
747 strlcat(permutationname, permutationinfo[i][1], sizeof(permutationname));
751 // keep line numbers correct
752 vertstrings_list[vertstrings_count++] = "\n";
753 geomstrings_list[geomstrings_count++] = "\n";
754 fragstrings_list[fragstrings_count++] = "\n";
757 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
761 Con_DPrintf("GLSL shader text for \"%s\" loaded from disk\n", filename);
762 vertstrings_list[vertstrings_count++] = shaderstring;
763 geomstrings_list[geomstrings_count++] = shaderstring;
764 fragstrings_list[fragstrings_count++] = shaderstring;
767 else if (!strcmp(filename, "glsl/default.glsl"))
769 Con_DPrintf("GLSL shader text for \"%s\" loaded from engine\n", filename);
770 vertstrings_list[vertstrings_count++] = builtinshaderstring;
771 geomstrings_list[geomstrings_count++] = builtinshaderstring;
772 fragstrings_list[fragstrings_count++] = builtinshaderstring;
775 // clear any lists that are not needed by this shader
776 if (!(permutation & SHADERPERMUTATION_USES_VERTEXSHADER))
777 vertstrings_count = 0;
778 if (!(permutation & SHADERPERMUTATION_USES_GEOMETRYSHADER))
779 geomstrings_count = 0;
780 if (!(permutation & SHADERPERMUTATION_USES_FRAGMENTSHADER))
781 fragstrings_count = 0;
782 // compile the shader program
783 if (shaderfound && vertstrings_count + geomstrings_count + fragstrings_count)
784 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
788 qglUseProgramObjectARB(p->program);CHECKGLERROR
789 // look up all the uniform variable names we care about, so we don't
790 // have to look them up every time we set them
791 p->loc_Texture_Normal = qglGetUniformLocationARB(p->program, "Texture_Normal");
792 p->loc_Texture_Color = qglGetUniformLocationARB(p->program, "Texture_Color");
793 p->loc_Texture_Gloss = qglGetUniformLocationARB(p->program, "Texture_Gloss");
794 p->loc_Texture_Cube = qglGetUniformLocationARB(p->program, "Texture_Cube");
795 p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
796 p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
797 p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
798 p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
799 p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
800 p->loc_Texture_Glow = qglGetUniformLocationARB(p->program, "Texture_Glow");
801 p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
802 p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
803 p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
804 p->loc_LightColor = qglGetUniformLocationARB(p->program, "LightColor");
805 p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants");
806 p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt");
807 p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip");
808 p->loc_AmbientScale = qglGetUniformLocationARB(p->program, "AmbientScale");
809 p->loc_DiffuseScale = qglGetUniformLocationARB(p->program, "DiffuseScale");
810 p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
811 p->loc_SpecularScale = qglGetUniformLocationARB(p->program, "SpecularScale");
812 p->loc_GlowScale = qglGetUniformLocationARB(p->program, "GlowScale");
813 p->loc_SceneBrightness = qglGetUniformLocationARB(p->program, "SceneBrightness");
814 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
815 p->loc_AmbientColor = qglGetUniformLocationARB(p->program, "AmbientColor");
816 p->loc_DiffuseColor = qglGetUniformLocationARB(p->program, "DiffuseColor");
817 p->loc_SpecularColor = qglGetUniformLocationARB(p->program, "SpecularColor");
818 p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
819 // initialize the samplers to refer to the texture units we use
820 if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal, 0);
821 if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color, 1);
822 if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss, 2);
823 if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube, 3);
824 if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask, 4);
825 if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants, 5);
826 if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt, 6);
827 if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap, 7);
828 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap, 8);
829 if (p->loc_Texture_Glow >= 0) qglUniform1iARB(p->loc_Texture_Glow, 9);
831 qglUseProgramObjectARB(0);CHECKGLERROR
834 Con_Printf("permutation%s failed for shader %s, some features may not work properly!\n", permutationname, "glsl/default.glsl");
836 Mem_Free(shaderstring);
839 void R_GLSL_Restart_f(void)
842 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
843 if (r_glsl_permutations[i].program)
844 GL_Backend_FreeProgram(r_glsl_permutations[i].program);
845 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
848 int R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting)
850 // select a permutation of the lighting shader appropriate to this
851 // combination of texture, entity, light source, and fogging, only use the
852 // minimum features necessary to avoid wasting rendering time in the
853 // fragment shader on features that are not being used
854 const char *shaderfilename = NULL;
856 float specularscale = rsurface_texture->specularscale;
857 r_glsl_permutation = NULL;
858 // TODO: implement geometry-shader based shadow volumes someday
859 if (r_shadow_rtlight)
862 shaderfilename = "glsl/default.glsl";
863 permutation = SHADERPERMUTATION_MODE_LIGHTSOURCE | SHADERPERMUTATION_USES_VERTEXSHADER | SHADERPERMUTATION_USES_FRAGMENTSHADER;
864 specularscale *= r_shadow_rtlight->specularscale;
865 if (r_shadow_rtlight->currentcubemap != r_texture_whitecube)
866 permutation |= SHADERPERMUTATION_CUBEFILTER;
867 if (specularscale > 0)
868 permutation |= SHADERPERMUTATION_SPECULAR;
869 if (r_refdef.fogenabled)
870 permutation |= SHADERPERMUTATION_FOG;
871 if (rsurface_texture->colormapping)
872 permutation |= SHADERPERMUTATION_COLORMAPPING;
873 if (r_glsl_offsetmapping.integer)
875 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
876 if (r_glsl_offsetmapping_reliefmapping.integer)
877 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
880 else if (rsurface_texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
882 // bright unshaded geometry
883 shaderfilename = "glsl/default.glsl";
884 permutation = SHADERPERMUTATION_USES_VERTEXSHADER | SHADERPERMUTATION_USES_FRAGMENTSHADER;
885 if (rsurface_texture->currentskinframe->glow)
886 permutation |= SHADERPERMUTATION_GLOW;
887 if (r_refdef.fogenabled)
888 permutation |= SHADERPERMUTATION_FOG;
889 if (rsurface_texture->colormapping)
890 permutation |= SHADERPERMUTATION_COLORMAPPING;
891 if (r_glsl_offsetmapping.integer)
893 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
894 if (r_glsl_offsetmapping_reliefmapping.integer)
895 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
898 else if (modellighting)
900 // directional model lighting
901 shaderfilename = "glsl/default.glsl";
902 permutation = SHADERPERMUTATION_USES_VERTEXSHADER | SHADERPERMUTATION_USES_FRAGMENTSHADER;
903 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTION;
904 if (rsurface_texture->currentskinframe->glow)
905 permutation |= SHADERPERMUTATION_GLOW;
906 if (specularscale > 0)
907 permutation |= SHADERPERMUTATION_SPECULAR;
908 if (r_refdef.fogenabled)
909 permutation |= SHADERPERMUTATION_FOG;
910 if (rsurface_texture->colormapping)
911 permutation |= SHADERPERMUTATION_COLORMAPPING;
912 if (r_glsl_offsetmapping.integer)
914 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
915 if (r_glsl_offsetmapping_reliefmapping.integer)
916 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
922 shaderfilename = "glsl/default.glsl";
923 permutation = SHADERPERMUTATION_USES_VERTEXSHADER | SHADERPERMUTATION_USES_FRAGMENTSHADER;
924 if (r_glsl_deluxemapping.integer >= 1 && rsurface_uselightmaptexture && r_refdef.worldmodel && r_refdef.worldmodel->brushq3.deluxemapping)
926 // deluxemapping (light direction texture)
927 if (rsurface_uselightmaptexture && r_refdef.worldmodel && r_refdef.worldmodel->brushq3.deluxemapping && r_refdef.worldmodel->brushq3.deluxemapping_modelspace)
928 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_MODELSPACE;
930 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
931 if (specularscale > 0)
932 permutation |= SHADERPERMUTATION_SPECULAR;
934 else if (r_glsl_deluxemapping.integer >= 2)
936 // fake deluxemapping (uniform light direction in tangentspace)
937 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
938 if (specularscale > 0)
939 permutation |= SHADERPERMUTATION_SPECULAR;
943 // ordinary lightmapping
946 if (rsurface_texture->currentskinframe->glow)
947 permutation |= SHADERPERMUTATION_GLOW;
948 if (r_refdef.fogenabled)
949 permutation |= SHADERPERMUTATION_FOG;
950 if (rsurface_texture->colormapping)
951 permutation |= SHADERPERMUTATION_COLORMAPPING;
952 if (r_glsl_offsetmapping.integer)
954 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
955 if (r_glsl_offsetmapping_reliefmapping.integer)
956 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
959 if (!r_glsl_permutations[permutation & SHADERPERMUTATION_COUNTMASK].program)
961 if (!r_glsl_permutations[permutation & SHADERPERMUTATION_COUNTMASK].compiled)
962 R_GLSL_CompilePermutation(shaderfilename, permutation);
963 if (!r_glsl_permutations[permutation & SHADERPERMUTATION_COUNTMASK].program)
965 // remove features until we find a valid permutation
967 for (i = SHADERPERMUTATION_COUNT-1;;i>>=1)
969 // reduce i more quickly whenever it would not remove any bits
973 if (!r_glsl_permutations[permutation & SHADERPERMUTATION_COUNTMASK].compiled)
974 R_GLSL_CompilePermutation(shaderfilename, permutation);
975 if (r_glsl_permutations[permutation & SHADERPERMUTATION_COUNTMASK].program)
978 return 0; // utterly failed
982 r_glsl_permutation = r_glsl_permutations + (permutation & SHADERPERMUTATION_COUNTMASK);
984 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
985 R_Mesh_TexMatrix(0, &rsurface_texture->currenttexmatrix);
986 if (permutation & SHADERPERMUTATION_MODE_LIGHTSOURCE)
988 if (r_glsl_permutation->loc_Texture_Cube >= 0 && r_shadow_rtlight) R_Mesh_TexBindCubeMap(3, R_GetTexture(r_shadow_rtlight->currentcubemap));
989 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]);
990 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
991 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_shadow_rtlight->ambientscale);
992 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_shadow_rtlight->diffusescale);
993 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, specularscale);
995 else if (permutation & SHADERPERMUTATION_MODE_LIGHTDIRECTION)
997 if (r_glsl_permutation->loc_AmbientColor >= 0)
998 qglUniform3fARB(r_glsl_permutation->loc_AmbientColor, rsurface_entity->modellight_ambient[0], rsurface_entity->modellight_ambient[1], rsurface_entity->modellight_ambient[2]);
999 if (r_glsl_permutation->loc_DiffuseColor >= 0)
1000 qglUniform3fARB(r_glsl_permutation->loc_DiffuseColor, rsurface_entity->modellight_diffuse[0], rsurface_entity->modellight_diffuse[1], rsurface_entity->modellight_diffuse[2]);
1001 if (r_glsl_permutation->loc_SpecularColor >= 0)
1002 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);
1003 if (r_glsl_permutation->loc_LightDir >= 0)
1004 qglUniform3fARB(r_glsl_permutation->loc_LightDir, rsurface_entity->modellight_lightdir[0], rsurface_entity->modellight_lightdir[1], rsurface_entity->modellight_lightdir[2]);
1008 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_ambient.value * 2.0f / 128.0f);
1009 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_refdef.lightmapintensity * 2.0f);
1010 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, r_refdef.lightmapintensity * specularscale * 2.0f);
1012 if (r_glsl_permutation->loc_Texture_Normal >= 0) R_Mesh_TexBind(0, R_GetTexture(rsurface_texture->currentskinframe->nmap));
1013 if (r_glsl_permutation->loc_Texture_Color >= 0) R_Mesh_TexBind(1, R_GetTexture(rsurface_texture->basetexture));
1014 if (r_glsl_permutation->loc_Texture_Gloss >= 0) R_Mesh_TexBind(2, R_GetTexture(rsurface_texture->glosstexture));
1015 //if (r_glsl_permutation->loc_Texture_Cube >= 0 && permutation & SHADERPERMUTATION_MODE_LIGHTSOURCE) R_Mesh_TexBindCubeMap(3, R_GetTexture(r_shadow_rtlight->currentcubemap));
1016 if (r_glsl_permutation->loc_Texture_FogMask >= 0) R_Mesh_TexBind(4, R_GetTexture(r_texture_fogattenuation));
1017 if (r_glsl_permutation->loc_Texture_Pants >= 0) R_Mesh_TexBind(5, R_GetTexture(rsurface_texture->currentskinframe->pants));
1018 if (r_glsl_permutation->loc_Texture_Shirt >= 0) R_Mesh_TexBind(6, R_GetTexture(rsurface_texture->currentskinframe->shirt));
1019 //if (r_glsl_permutation->loc_Texture_Lightmap >= 0) R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
1020 //if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
1021 if (r_glsl_permutation->loc_Texture_Glow >= 0) R_Mesh_TexBind(9, R_GetTexture(rsurface_texture->currentskinframe->glow));
1022 if (r_glsl_permutation->loc_GlowScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_GlowScale, r_hdr_glowintensity.value);
1023 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_view.colorscale);
1024 if (r_glsl_permutation->loc_FogColor >= 0)
1026 // additive passes are only darkened by fog, not tinted
1027 if (r_shadow_rtlight || (rsurface_texture->currentmaterialflags & MATERIALFLAG_ADD))
1028 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
1030 qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
1032 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface_modelorg[0], rsurface_modelorg[1], rsurface_modelorg[2]);
1033 if (r_glsl_permutation->loc_Color_Pants >= 0)
1035 if (rsurface_texture->currentskinframe->pants)
1036 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface_entity->colormap_pantscolor[0], rsurface_entity->colormap_pantscolor[1], rsurface_entity->colormap_pantscolor[2]);
1038 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
1040 if (r_glsl_permutation->loc_Color_Shirt >= 0)
1042 if (rsurface_texture->currentskinframe->shirt)
1043 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface_entity->colormap_shirtcolor[0], rsurface_entity->colormap_shirtcolor[1], rsurface_entity->colormap_shirtcolor[2]);
1045 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
1047 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, r_refdef.fograngerecip);
1048 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface_texture->specularpower);
1049 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
1054 void R_SwitchSurfaceShader(int permutation)
1056 if (r_glsl_permutation != r_glsl_permutations + (permutation & SHADERPERMUTATION_COUNTMASK))
1058 r_glsl_permutation = r_glsl_permutations + (permutation & SHADERPERMUTATION_COUNTMASK);
1060 qglUseProgramObjectARB(r_glsl_permutation->program);
1065 void gl_main_start(void)
1067 r_main_texturepool = R_AllocTexturePool();
1068 R_BuildBlankTextures();
1070 if (gl_texturecubemap)
1073 R_BuildNormalizationCube();
1075 R_BuildFogTexture();
1076 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
1077 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
1078 memset(&r_svbsp, 0, sizeof (r_svbsp));
1081 void gl_main_shutdown(void)
1084 Mem_Free(r_svbsp.nodes);
1085 memset(&r_svbsp, 0, sizeof (r_svbsp));
1086 R_FreeTexturePool(&r_main_texturepool);
1087 r_texture_blanknormalmap = NULL;
1088 r_texture_white = NULL;
1089 r_texture_black = NULL;
1090 r_texture_whitecube = NULL;
1091 r_texture_normalizationcube = NULL;
1092 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
1096 extern void CL_ParseEntityLump(char *entitystring);
1097 void gl_main_newmap(void)
1099 // FIXME: move this code to client
1101 char *entities, entname[MAX_QPATH];
1104 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
1105 l = (int)strlen(entname) - 4;
1106 if (l >= 0 && !strcmp(entname + l, ".bsp"))
1108 memcpy(entname + l, ".ent", 5);
1109 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
1111 CL_ParseEntityLump(entities);
1116 if (cl.worldmodel->brush.entities)
1117 CL_ParseEntityLump(cl.worldmodel->brush.entities);
1121 void GL_Main_Init(void)
1123 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
1125 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
1126 FOG_registercvars(); // FIXME: move this fog stuff to client?
1127 Cvar_RegisterVariable(&r_nearclip);
1128 Cvar_RegisterVariable(&r_showsurfaces);
1129 Cvar_RegisterVariable(&r_showtris);
1130 Cvar_RegisterVariable(&r_shownormals);
1131 Cvar_RegisterVariable(&r_showlighting);
1132 Cvar_RegisterVariable(&r_showshadowvolumes);
1133 Cvar_RegisterVariable(&r_showcollisionbrushes);
1134 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
1135 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
1136 Cvar_RegisterVariable(&r_showdisabledepthtest);
1137 Cvar_RegisterVariable(&r_drawportals);
1138 Cvar_RegisterVariable(&r_drawentities);
1139 Cvar_RegisterVariable(&r_cullentities_trace);
1140 Cvar_RegisterVariable(&r_cullentities_trace_samples);
1141 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
1142 Cvar_RegisterVariable(&r_cullentities_trace_delay);
1143 Cvar_RegisterVariable(&r_drawviewmodel);
1144 Cvar_RegisterVariable(&r_speeds);
1145 Cvar_RegisterVariable(&r_fullbrights);
1146 Cvar_RegisterVariable(&r_wateralpha);
1147 Cvar_RegisterVariable(&r_dynamic);
1148 Cvar_RegisterVariable(&r_fullbright);
1149 Cvar_RegisterVariable(&r_shadows);
1150 Cvar_RegisterVariable(&r_shadows_throwdistance);
1151 Cvar_RegisterVariable(&r_q1bsp_skymasking);
1152 Cvar_RegisterVariable(&r_textureunits);
1153 Cvar_RegisterVariable(&r_glsl);
1154 Cvar_RegisterVariable(&r_glsl_offsetmapping);
1155 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
1156 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
1157 Cvar_RegisterVariable(&r_glsl_deluxemapping);
1158 Cvar_RegisterVariable(&r_lerpsprites);
1159 Cvar_RegisterVariable(&r_lerpmodels);
1160 Cvar_RegisterVariable(&r_waterscroll);
1161 Cvar_RegisterVariable(&r_bloom);
1162 Cvar_RegisterVariable(&r_bloom_colorscale);
1163 Cvar_RegisterVariable(&r_bloom_brighten);
1164 Cvar_RegisterVariable(&r_bloom_blur);
1165 Cvar_RegisterVariable(&r_bloom_resolution);
1166 Cvar_RegisterVariable(&r_bloom_colorexponent);
1167 Cvar_RegisterVariable(&r_bloom_colorsubtract);
1168 Cvar_RegisterVariable(&r_hdr);
1169 Cvar_RegisterVariable(&r_hdr_scenebrightness);
1170 Cvar_RegisterVariable(&r_hdr_glowintensity);
1171 Cvar_RegisterVariable(&r_hdr_range);
1172 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
1173 Cvar_RegisterVariable(&developer_texturelogging);
1174 Cvar_RegisterVariable(&gl_lightmaps);
1175 Cvar_RegisterVariable(&r_test);
1176 Cvar_RegisterVariable(&r_batchmode);
1177 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
1178 Cvar_SetValue("r_fullbrights", 0);
1179 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
1182 extern void R_Textures_Init(void);
1183 extern void GL_Draw_Init(void);
1184 extern void GL_Main_Init(void);
1185 extern void R_Shadow_Init(void);
1186 extern void R_Sky_Init(void);
1187 extern void GL_Surf_Init(void);
1188 extern void R_Light_Init(void);
1189 extern void R_Particles_Init(void);
1190 extern void R_Explosion_Init(void);
1191 extern void gl_backend_init(void);
1192 extern void Sbar_Init(void);
1193 extern void R_LightningBeams_Init(void);
1194 extern void Mod_RenderInit(void);
1196 void Render_Init(void)
1209 R_LightningBeams_Init();
1218 extern char *ENGINE_EXTENSIONS;
1221 VID_CheckExtensions();
1223 // LordHavoc: report supported extensions
1224 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
1226 // clear to black (loading plaque will be seen over this)
1228 qglClearColor(0,0,0,1);CHECKGLERROR
1229 qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
1232 int R_CullBox(const vec3_t mins, const vec3_t maxs)
1236 for (i = 0;i < 4;i++)
1238 p = r_view.frustum + i;
1243 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1247 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1251 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1255 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1259 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1263 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1267 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1271 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1279 //==================================================================================
1281 static void R_UpdateEntityLighting(entity_render_t *ent)
1283 vec3_t tempdiffusenormal;
1285 // fetch the lighting from the worldmodel data
1286 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));
1287 VectorClear(ent->modellight_diffuse);
1288 VectorClear(tempdiffusenormal);
1289 if ((ent->flags & RENDER_LIGHT) && r_refdef.worldmodel && r_refdef.worldmodel->brush.LightPoint)
1292 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
1293 r_refdef.worldmodel->brush.LightPoint(r_refdef.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
1296 VectorSet(ent->modellight_ambient, 1, 1, 1);
1298 // move the light direction into modelspace coordinates for lighting code
1299 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
1300 VectorNormalize(ent->modellight_lightdir);
1302 // scale ambient and directional light contributions according to rendering variables
1303 ent->modellight_ambient[0] *= ent->colormod[0] * r_refdef.lightmapintensity;
1304 ent->modellight_ambient[1] *= ent->colormod[1] * r_refdef.lightmapintensity;
1305 ent->modellight_ambient[2] *= ent->colormod[2] * r_refdef.lightmapintensity;
1306 ent->modellight_diffuse[0] *= ent->colormod[0] * r_refdef.lightmapintensity;
1307 ent->modellight_diffuse[1] *= ent->colormod[1] * r_refdef.lightmapintensity;
1308 ent->modellight_diffuse[2] *= ent->colormod[2] * r_refdef.lightmapintensity;
1311 static void R_View_UpdateEntityVisible (void)
1314 entity_render_t *ent;
1316 if (!r_drawentities.integer)
1319 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : (chase_active.integer ? 0 : RENDER_EXTERIORMODEL);
1320 if (r_refdef.worldmodel && r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs)
1322 // worldmodel can check visibility
1323 for (i = 0;i < r_refdef.numentities;i++)
1325 ent = r_refdef.entities[i];
1326 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));
1328 if(r_cullentities_trace.integer)
1330 for (i = 0;i < r_refdef.numentities;i++)
1332 ent = r_refdef.entities[i];
1333 if(r_viewcache.entityvisible[i] && !(ent->effects & EF_NODEPTHTEST) && !(ent->model && (ent->model->name[0] == '*')))
1335 if(Mod_CanSeeBox_Trace(r_cullentities_trace_samples.integer, r_cullentities_trace_enlarge.value, r_refdef.worldmodel, r_view.origin, ent->mins, ent->maxs))
1336 ent->last_trace_visibility = realtime;
1337 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
1338 r_viewcache.entityvisible[i] = 0;
1345 // no worldmodel or it can't check visibility
1346 for (i = 0;i < r_refdef.numentities;i++)
1348 ent = r_refdef.entities[i];
1349 r_viewcache.entityvisible[i] = !(ent->flags & renderimask) && !R_CullBox(ent->mins, ent->maxs);
1353 // update entity lighting (even on hidden entities for r_shadows)
1354 for (i = 0;i < r_refdef.numentities;i++)
1355 R_UpdateEntityLighting(r_refdef.entities[i]);
1358 // only used if skyrendermasked, and normally returns false
1359 int R_DrawBrushModelsSky (void)
1362 entity_render_t *ent;
1364 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 if (!ent->model || !ent->model->DrawSky)
1375 ent->model->DrawSky(ent);
1381 void R_DrawNoModel(entity_render_t *ent);
1382 void R_DrawModels(void)
1385 entity_render_t *ent;
1387 if (!r_drawentities.integer)
1390 for (i = 0;i < r_refdef.numentities;i++)
1392 if (!r_viewcache.entityvisible[i])
1394 ent = r_refdef.entities[i];
1395 r_refdef.stats.entities++;
1396 if (ent->model && ent->model->Draw != NULL)
1397 ent->model->Draw(ent);
1403 static void R_View_SetFrustum(void)
1405 // break apart the view matrix into vectors for various purposes
1406 Matrix4x4_ToVectors(&r_view.matrix, r_view.forward, r_view.left, r_view.up, r_view.origin);
1407 VectorNegate(r_view.left, r_view.right);
1410 r_view.frustum[0].normal[0] = 0 - 1.0 / r_view.frustum_x;
1411 r_view.frustum[0].normal[1] = 0 - 0;
1412 r_view.frustum[0].normal[2] = -1 - 0;
1413 r_view.frustum[1].normal[0] = 0 + 1.0 / r_view.frustum_x;
1414 r_view.frustum[1].normal[1] = 0 + 0;
1415 r_view.frustum[1].normal[2] = -1 + 0;
1416 r_view.frustum[2].normal[0] = 0 - 0;
1417 r_view.frustum[2].normal[1] = 0 - 1.0 / r_view.frustum_y;
1418 r_view.frustum[2].normal[2] = -1 - 0;
1419 r_view.frustum[3].normal[0] = 0 + 0;
1420 r_view.frustum[3].normal[1] = 0 + 1.0 / r_view.frustum_y;
1421 r_view.frustum[3].normal[2] = -1 + 0;
1425 zNear = r_refdef.nearclip;
1426 nudge = 1.0 - 1.0 / (1<<23);
1427 r_view.frustum[4].normal[0] = 0 - 0;
1428 r_view.frustum[4].normal[1] = 0 - 0;
1429 r_view.frustum[4].normal[2] = -1 - -nudge;
1430 r_view.frustum[4].dist = 0 - -2 * zNear * nudge;
1431 r_view.frustum[5].normal[0] = 0 + 0;
1432 r_view.frustum[5].normal[1] = 0 + 0;
1433 r_view.frustum[5].normal[2] = -1 + -nudge;
1434 r_view.frustum[5].dist = 0 + -2 * zNear * nudge;
1440 r_view.frustum[0].normal[0] = m[3] - m[0];
1441 r_view.frustum[0].normal[1] = m[7] - m[4];
1442 r_view.frustum[0].normal[2] = m[11] - m[8];
1443 r_view.frustum[0].dist = m[15] - m[12];
1445 r_view.frustum[1].normal[0] = m[3] + m[0];
1446 r_view.frustum[1].normal[1] = m[7] + m[4];
1447 r_view.frustum[1].normal[2] = m[11] + m[8];
1448 r_view.frustum[1].dist = m[15] + m[12];
1450 r_view.frustum[2].normal[0] = m[3] - m[1];
1451 r_view.frustum[2].normal[1] = m[7] - m[5];
1452 r_view.frustum[2].normal[2] = m[11] - m[9];
1453 r_view.frustum[2].dist = m[15] - m[13];
1455 r_view.frustum[3].normal[0] = m[3] + m[1];
1456 r_view.frustum[3].normal[1] = m[7] + m[5];
1457 r_view.frustum[3].normal[2] = m[11] + m[9];
1458 r_view.frustum[3].dist = m[15] + m[13];
1460 r_view.frustum[4].normal[0] = m[3] - m[2];
1461 r_view.frustum[4].normal[1] = m[7] - m[6];
1462 r_view.frustum[4].normal[2] = m[11] - m[10];
1463 r_view.frustum[4].dist = m[15] - m[14];
1465 r_view.frustum[5].normal[0] = m[3] + m[2];
1466 r_view.frustum[5].normal[1] = m[7] + m[6];
1467 r_view.frustum[5].normal[2] = m[11] + m[10];
1468 r_view.frustum[5].dist = m[15] + m[14];
1473 VectorMAM(1, r_view.forward, 1.0 / -r_view.frustum_x, r_view.left, r_view.frustum[0].normal);
1474 VectorMAM(1, r_view.forward, 1.0 / r_view.frustum_x, r_view.left, r_view.frustum[1].normal);
1475 VectorMAM(1, r_view.forward, 1.0 / -r_view.frustum_y, r_view.up, r_view.frustum[2].normal);
1476 VectorMAM(1, r_view.forward, 1.0 / r_view.frustum_y, r_view.up, r_view.frustum[3].normal);
1477 VectorCopy(r_view.forward, r_view.frustum[4].normal);
1478 VectorNormalize(r_view.frustum[0].normal);
1479 VectorNormalize(r_view.frustum[1].normal);
1480 VectorNormalize(r_view.frustum[2].normal);
1481 VectorNormalize(r_view.frustum[3].normal);
1482 r_view.frustum[0].dist = DotProduct (r_view.origin, r_view.frustum[0].normal);
1483 r_view.frustum[1].dist = DotProduct (r_view.origin, r_view.frustum[1].normal);
1484 r_view.frustum[2].dist = DotProduct (r_view.origin, r_view.frustum[2].normal);
1485 r_view.frustum[3].dist = DotProduct (r_view.origin, r_view.frustum[3].normal);
1486 r_view.frustum[4].dist = DotProduct (r_view.origin, r_view.frustum[4].normal) + r_refdef.nearclip;
1487 PlaneClassify(&r_view.frustum[0]);
1488 PlaneClassify(&r_view.frustum[1]);
1489 PlaneClassify(&r_view.frustum[2]);
1490 PlaneClassify(&r_view.frustum[3]);
1491 PlaneClassify(&r_view.frustum[4]);
1493 // LordHavoc: note to all quake engine coders, Quake had a special case
1494 // for 90 degrees which assumed a square view (wrong), so I removed it,
1495 // Quake2 has it disabled as well.
1497 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
1498 //RotatePointAroundVector( r_view.frustum[0].normal, r_view.up, r_view.forward, -(90 - r_refdef.fov_x / 2));
1499 //r_view.frustum[0].dist = DotProduct (r_view.origin, frustum[0].normal);
1500 //PlaneClassify(&frustum[0]);
1502 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
1503 //RotatePointAroundVector( r_view.frustum[1].normal, r_view.up, r_view.forward, (90 - r_refdef.fov_x / 2));
1504 //r_view.frustum[1].dist = DotProduct (r_view.origin, frustum[1].normal);
1505 //PlaneClassify(&frustum[1]);
1507 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
1508 //RotatePointAroundVector( r_view.frustum[2].normal, r_view.left, r_view.forward, -(90 - r_refdef.fov_y / 2));
1509 //r_view.frustum[2].dist = DotProduct (r_view.origin, frustum[2].normal);
1510 //PlaneClassify(&frustum[2]);
1512 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
1513 //RotatePointAroundVector( r_view.frustum[3].normal, r_view.left, r_view.forward, (90 - r_refdef.fov_y / 2));
1514 //r_view.frustum[3].dist = DotProduct (r_view.origin, frustum[3].normal);
1515 //PlaneClassify(&frustum[3]);
1518 //VectorCopy(r_view.forward, r_view.frustum[4].normal);
1519 //r_view.frustum[4].dist = DotProduct (r_view.origin, frustum[4].normal) + r_nearclip.value;
1520 //PlaneClassify(&frustum[4]);
1523 void R_View_Update(void)
1525 R_View_SetFrustum();
1526 R_View_WorldVisibility();
1527 R_View_UpdateEntityVisible();
1530 void R_SetupView(const matrix4x4_t *matrix)
1532 if (r_refdef.rtworldshadows || r_refdef.rtdlightshadows)
1533 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_view.frustum_x, r_view.frustum_y, r_refdef.nearclip);
1535 GL_SetupView_Mode_Perspective(r_view.frustum_x, r_view.frustum_y, r_refdef.nearclip, r_refdef.farclip);
1537 GL_SetupView_Orientation_FromEntity(matrix);
1540 void R_ResetViewRendering2D(void)
1542 if (gl_support_fragment_shader)
1544 qglUseProgramObjectARB(0);CHECKGLERROR
1549 // GL is weird because it's bottom to top, r_view.y is top to bottom
1550 qglViewport(r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
1551 GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
1552 GL_Scissor(r_view.x, r_view.y, r_view.width, r_view.height);
1553 GL_Color(1, 1, 1, 1);
1554 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
1555 GL_BlendFunc(GL_ONE, GL_ZERO);
1556 GL_AlphaTest(false);
1557 GL_ScissorTest(false);
1558 GL_DepthMask(false);
1559 GL_DepthTest(false);
1560 R_Mesh_Matrix(&identitymatrix);
1561 R_Mesh_ResetTextureState();
1562 qglPolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR
1563 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
1564 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
1565 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
1566 qglStencilMask(~0);CHECKGLERROR
1567 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
1568 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
1569 GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
1572 void R_ResetViewRendering3D(void)
1574 if (gl_support_fragment_shader)
1576 qglUseProgramObjectARB(0);CHECKGLERROR
1581 // GL is weird because it's bottom to top, r_view.y is top to bottom
1582 qglViewport(r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
1583 R_SetupView(&r_view.matrix);
1584 GL_Scissor(r_view.x, r_view.y, r_view.width, r_view.height);
1585 GL_Color(1, 1, 1, 1);
1586 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
1587 GL_BlendFunc(GL_ONE, GL_ZERO);
1588 GL_AlphaTest(false);
1589 GL_ScissorTest(true);
1592 R_Mesh_Matrix(&identitymatrix);
1593 R_Mesh_ResetTextureState();
1594 qglPolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR
1595 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
1596 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
1597 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
1598 qglStencilMask(~0);CHECKGLERROR
1599 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
1600 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
1601 GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
1605 R_Bloom_SetupShader(
1607 "// written by Forest 'LordHavoc' Hale\n"
1609 "// common definitions between vertex shader and fragment shader:\n"
1611 "#ifdef __GLSL_CG_DATA_TYPES\n"
1612 "#define myhalf half\n"
1613 "#define myhvec2 hvec2\n"
1614 "#define myhvec3 hvec3\n"
1615 "#define myhvec4 hvec4\n"
1617 "#define myhalf float\n"
1618 "#define myhvec2 vec2\n"
1619 "#define myhvec3 vec3\n"
1620 "#define myhvec4 vec4\n"
1623 "varying vec2 ScreenTexCoord;\n"
1624 "varying vec2 BloomTexCoord;\n"
1629 "// vertex shader specific:\n"
1630 "#ifdef VERTEX_SHADER\n"
1634 " ScreenTexCoord = vec2(gl_MultiTexCoord0);\n"
1635 " BloomTexCoord = vec2(gl_MultiTexCoord1);\n"
1636 " // transform vertex to camera space, using ftransform to match non-VS\n"
1638 " gl_Position = ftransform();\n"
1641 "#endif // VERTEX_SHADER\n"
1646 "// fragment shader specific:\n"
1647 "#ifdef FRAGMENT_SHADER\n"
1652 " myhvec3 color = myhvec3(texture2D(Texture_Screen, ScreenTexCoord));\n"
1653 " for (x = -BLUR_X;x <= BLUR_X;x++)
1654 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
1655 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
1656 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
1657 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
1659 " gl_FragColor = vec4(color);\n"
1662 "#endif // FRAGMENT_SHADER\n"
1665 void R_RenderScene(void);
1667 void R_Bloom_StartFrame(void)
1669 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
1671 // set bloomwidth and bloomheight to the bloom resolution that will be
1672 // used (often less than the screen resolution for faster rendering)
1673 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_view.width);
1674 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_view.height / r_view.width;
1675 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_view.height);
1677 // calculate desired texture sizes
1678 if (gl_support_arb_texture_non_power_of_two)
1680 screentexturewidth = r_view.width;
1681 screentextureheight = r_view.height;
1682 bloomtexturewidth = r_bloomstate.bloomwidth;
1683 bloomtextureheight = r_bloomstate.bloomheight;
1687 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
1688 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
1689 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
1690 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
1695 screentexturewidth = screentextureheight = 0;
1697 else if (r_bloom.integer)
1702 screentexturewidth = screentextureheight = 0;
1703 bloomtexturewidth = bloomtextureheight = 0;
1706 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)
1708 // can't use bloom if the parameters are too weird
1709 // can't use bloom if the card does not support the texture size
1710 if (r_bloomstate.texture_screen)
1711 R_FreeTexture(r_bloomstate.texture_screen);
1712 if (r_bloomstate.texture_bloom)
1713 R_FreeTexture(r_bloomstate.texture_bloom);
1714 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
1718 r_bloomstate.enabled = true;
1719 r_bloomstate.hdr = r_hdr.integer != 0;
1721 // allocate textures as needed
1722 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
1724 if (r_bloomstate.texture_screen)
1725 R_FreeTexture(r_bloomstate.texture_screen);
1726 r_bloomstate.texture_screen = NULL;
1727 r_bloomstate.screentexturewidth = screentexturewidth;
1728 r_bloomstate.screentextureheight = screentextureheight;
1729 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
1730 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);
1732 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
1734 if (r_bloomstate.texture_bloom)
1735 R_FreeTexture(r_bloomstate.texture_bloom);
1736 r_bloomstate.texture_bloom = NULL;
1737 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
1738 r_bloomstate.bloomtextureheight = bloomtextureheight;
1739 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
1740 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);
1743 // set up a texcoord array for the full resolution screen image
1744 // (we have to keep this around to copy back during final render)
1745 r_bloomstate.screentexcoord2f[0] = 0;
1746 r_bloomstate.screentexcoord2f[1] = (float)r_view.height / (float)r_bloomstate.screentextureheight;
1747 r_bloomstate.screentexcoord2f[2] = (float)r_view.width / (float)r_bloomstate.screentexturewidth;
1748 r_bloomstate.screentexcoord2f[3] = (float)r_view.height / (float)r_bloomstate.screentextureheight;
1749 r_bloomstate.screentexcoord2f[4] = (float)r_view.width / (float)r_bloomstate.screentexturewidth;
1750 r_bloomstate.screentexcoord2f[5] = 0;
1751 r_bloomstate.screentexcoord2f[6] = 0;
1752 r_bloomstate.screentexcoord2f[7] = 0;
1754 // set up a texcoord array for the reduced resolution bloom image
1755 // (which will be additive blended over the screen image)
1756 r_bloomstate.bloomtexcoord2f[0] = 0;
1757 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
1758 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
1759 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
1760 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
1761 r_bloomstate.bloomtexcoord2f[5] = 0;
1762 r_bloomstate.bloomtexcoord2f[6] = 0;
1763 r_bloomstate.bloomtexcoord2f[7] = 0;
1766 void R_Bloom_CopyScreenTexture(float colorscale)
1768 r_refdef.stats.bloom++;
1770 R_ResetViewRendering2D();
1771 R_Mesh_VertexPointer(r_screenvertex3f);
1772 R_Mesh_ColorPointer(NULL);
1773 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f);
1774 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
1776 // copy view into the screen texture
1777 GL_ActiveTexture(0);
1779 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
1780 r_refdef.stats.bloom_copypixels += r_view.width * r_view.height;
1782 // now scale it down to the bloom texture size
1784 qglViewport(r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
1785 GL_BlendFunc(GL_ONE, GL_ZERO);
1786 GL_Color(colorscale, colorscale, colorscale, 1);
1787 // TODO: optimize with multitexture or GLSL
1788 R_Mesh_Draw(0, 4, 2, polygonelements);
1789 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
1791 // we now have a bloom image in the framebuffer
1792 // copy it into the bloom image texture for later processing
1793 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
1794 GL_ActiveTexture(0);
1796 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
1797 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
1800 void R_Bloom_CopyHDRTexture(void)
1802 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
1803 GL_ActiveTexture(0);
1805 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
1806 r_refdef.stats.bloom_copypixels += r_view.width * r_view.height;
1809 void R_Bloom_MakeTexture(void)
1812 float xoffset, yoffset, r, brighten;
1814 r_refdef.stats.bloom++;
1816 R_ResetViewRendering2D();
1817 R_Mesh_VertexPointer(r_screenvertex3f);
1818 R_Mesh_ColorPointer(NULL);
1820 // we have a bloom image in the framebuffer
1822 qglViewport(r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
1824 for (x = 1;x < r_bloom_colorexponent.value;)
1827 r = bound(0, r_bloom_colorexponent.value / x, 1);
1828 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
1829 GL_Color(r, r, r, 1);
1830 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
1831 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f);
1832 R_Mesh_Draw(0, 4, 2, polygonelements);
1833 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
1835 // copy the vertically blurred bloom view to a texture
1836 GL_ActiveTexture(0);
1838 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
1839 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
1842 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
1843 brighten = r_bloom_brighten.value;
1845 brighten *= r_hdr_range.value;
1846 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
1847 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f);
1849 for (dir = 0;dir < 2;dir++)
1851 // blend on at multiple vertical offsets to achieve a vertical blur
1852 // TODO: do offset blends using GLSL
1853 GL_BlendFunc(GL_ONE, GL_ZERO);
1854 for (x = -range;x <= range;x++)
1856 if (!dir){xoffset = 0;yoffset = x;}
1857 else {xoffset = x;yoffset = 0;}
1858 xoffset /= (float)r_bloomstate.bloomtexturewidth;
1859 yoffset /= (float)r_bloomstate.bloomtextureheight;
1860 // compute a texcoord array with the specified x and y offset
1861 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
1862 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
1863 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
1864 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
1865 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
1866 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
1867 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
1868 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
1869 // this r value looks like a 'dot' particle, fading sharply to
1870 // black at the edges
1871 // (probably not realistic but looks good enough)
1872 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
1873 //r = (dir ? 1.0f : brighten)/(range*2+1);
1874 r = (dir ? 1.0f : brighten)/(range*2+1)*(1 - x*x/(float)(range*range));
1875 GL_Color(r, r, r, 1);
1876 R_Mesh_Draw(0, 4, 2, polygonelements);
1877 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
1878 GL_BlendFunc(GL_ONE, GL_ONE);
1881 // copy the vertically blurred bloom view to a texture
1882 GL_ActiveTexture(0);
1884 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
1885 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
1888 // apply subtract last
1889 // (just like it would be in a GLSL shader)
1890 if (r_bloom_colorsubtract.value > 0 && gl_support_ext_blend_subtract)
1892 GL_BlendFunc(GL_ONE, GL_ZERO);
1893 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
1894 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f);
1895 GL_Color(1, 1, 1, 1);
1896 R_Mesh_Draw(0, 4, 2, polygonelements);
1897 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
1899 GL_BlendFunc(GL_ONE, GL_ONE);
1900 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
1901 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
1902 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f);
1903 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
1904 R_Mesh_Draw(0, 4, 2, polygonelements);
1905 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
1906 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
1908 // copy the darkened bloom view to a texture
1909 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
1910 GL_ActiveTexture(0);
1912 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
1913 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
1917 void R_HDR_RenderBloomTexture(void)
1919 int oldwidth, oldheight;
1921 oldwidth = r_view.width;
1922 oldheight = r_view.height;
1923 r_view.width = r_bloomstate.bloomwidth;
1924 r_view.height = r_bloomstate.bloomheight;
1926 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
1927 // TODO: add exposure compensation features
1928 // TODO: add fp16 framebuffer support
1930 r_view.colorscale = r_bloom_colorscale.value * r_hdr_scenebrightness.value;
1932 r_view.colorscale /= r_hdr_range.value;
1935 R_ResetViewRendering2D();
1937 R_Bloom_CopyHDRTexture();
1938 R_Bloom_MakeTexture();
1940 R_ResetViewRendering3D();
1943 if (r_timereport_active)
1944 R_TimeReport("clear");
1947 // restore the view settings
1948 r_view.width = oldwidth;
1949 r_view.height = oldheight;
1952 static void R_BlendView(void)
1954 if (r_bloomstate.enabled && r_bloomstate.hdr)
1956 // render high dynamic range bloom effect
1957 // the bloom texture was made earlier this render, so we just need to
1958 // blend it onto the screen...
1959 R_ResetViewRendering2D();
1960 R_Mesh_VertexPointer(r_screenvertex3f);
1961 R_Mesh_ColorPointer(NULL);
1962 GL_Color(1, 1, 1, 1);
1963 GL_BlendFunc(GL_ONE, GL_ONE);
1964 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
1965 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f);
1966 R_Mesh_Draw(0, 4, 2, polygonelements);
1967 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
1969 else if (r_bloomstate.enabled)
1971 // render simple bloom effect
1972 // copy the screen and shrink it and darken it for the bloom process
1973 R_Bloom_CopyScreenTexture(r_bloom_colorscale.value);
1974 // make the bloom texture
1975 R_Bloom_MakeTexture();
1976 // put the original screen image back in place and blend the bloom
1978 R_ResetViewRendering2D();
1979 R_Mesh_VertexPointer(r_screenvertex3f);
1980 R_Mesh_ColorPointer(NULL);
1981 GL_Color(1, 1, 1, 1);
1982 GL_BlendFunc(GL_ONE, GL_ZERO);
1983 // do both in one pass if possible
1984 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
1985 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f);
1986 if (r_textureunits.integer >= 2 && gl_combine.integer)
1988 R_Mesh_TexCombine(1, GL_ADD, GL_ADD, 1, 1);
1989 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_screen));
1990 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.screentexcoord2f);
1994 R_Mesh_Draw(0, 4, 2, polygonelements);
1995 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
1996 // now blend on the bloom texture
1997 GL_BlendFunc(GL_ONE, GL_ONE);
1998 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
1999 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f);
2001 R_Mesh_Draw(0, 4, 2, polygonelements);
2002 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
2004 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
2006 // apply a color tint to the whole view
2007 R_ResetViewRendering2D();
2008 R_Mesh_VertexPointer(r_screenvertex3f);
2009 R_Mesh_ColorPointer(NULL);
2010 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2011 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
2012 R_Mesh_Draw(0, 4, 2, polygonelements);
2016 void R_RenderScene(void);
2018 matrix4x4_t r_waterscrollmatrix;
2020 void R_UpdateVariables(void)
2024 r_refdef.farclip = 4096;
2025 if (r_refdef.worldmodel)
2026 r_refdef.farclip += VectorDistance(r_refdef.worldmodel->normalmins, r_refdef.worldmodel->normalmaxs);
2027 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
2029 r_refdef.polygonfactor = 0;
2030 r_refdef.polygonoffset = 0;
2031 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_shadow_polygonfactor.value;
2032 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_shadow_polygonoffset.value;
2034 r_refdef.rtworld = r_shadow_realtime_world.integer;
2035 r_refdef.rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
2036 r_refdef.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
2037 r_refdef.rtdlightshadows = r_refdef.rtdlight && (r_refdef.rtworld ? r_shadow_realtime_world_dlightshadows.integer : r_shadow_realtime_dlight_shadows.integer) && gl_stencil;
2038 r_refdef.lightmapintensity = r_refdef.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
2039 if (r_showsurfaces.integer)
2041 r_refdef.rtworld = false;
2042 r_refdef.rtworldshadows = false;
2043 r_refdef.rtdlight = false;
2044 r_refdef.rtdlightshadows = false;
2045 r_refdef.lightmapintensity = 0;
2048 if (gamemode == GAME_NEHAHRA)
2050 if (gl_fogenable.integer)
2052 r_refdef.oldgl_fogenable = true;
2053 r_refdef.fog_density = gl_fogdensity.value;
2054 r_refdef.fog_red = gl_fogred.value;
2055 r_refdef.fog_green = gl_foggreen.value;
2056 r_refdef.fog_blue = gl_fogblue.value;
2058 else if (r_refdef.oldgl_fogenable)
2060 r_refdef.oldgl_fogenable = false;
2061 r_refdef.fog_density = 0;
2062 r_refdef.fog_red = 0;
2063 r_refdef.fog_green = 0;
2064 r_refdef.fog_blue = 0;
2067 if (r_refdef.fog_density)
2069 r_refdef.fogcolor[0] = bound(0.0f, r_refdef.fog_red , 1.0f);
2070 r_refdef.fogcolor[1] = bound(0.0f, r_refdef.fog_green, 1.0f);
2071 r_refdef.fogcolor[2] = bound(0.0f, r_refdef.fog_blue , 1.0f);
2073 if (r_refdef.fog_density)
2075 r_refdef.fogenabled = true;
2076 // this is the point where the fog reaches 0.9986 alpha, which we
2077 // consider a good enough cutoff point for the texture
2078 // (0.9986 * 256 == 255.6)
2079 r_refdef.fogrange = 400 / r_refdef.fog_density;
2080 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
2081 r_refdef.fogtabledistmultiplier = FOGTABLEWIDTH * r_refdef.fograngerecip;
2082 // fog color was already set
2085 r_refdef.fogenabled = false;
2093 void R_RenderView(void)
2095 if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
2096 return; //Host_Error ("R_RenderView: NULL worldmodel");
2098 R_Shadow_UpdateWorldLightSelection();
2101 if (r_timereport_active)
2102 R_TimeReport("setup");
2105 if (r_timereport_active)
2106 R_TimeReport("visibility");
2108 R_ResetViewRendering3D();
2111 if (r_timereport_active)
2112 R_TimeReport("clear");
2114 R_Bloom_StartFrame();
2116 // this produces a bloom texture to be used in R_BlendView() later
2118 R_HDR_RenderBloomTexture();
2120 r_view.colorscale = r_hdr_scenebrightness.value;
2124 if (r_timereport_active)
2125 R_TimeReport("blendview");
2127 GL_Scissor(0, 0, vid.width, vid.height);
2128 GL_ScissorTest(false);
2132 extern void R_DrawLightningBeams (void);
2133 extern void VM_CL_AddPolygonsToMeshQueue (void);
2134 extern void R_DrawPortals (void);
2135 void R_RenderScene(void)
2137 // don't let sound skip if going slow
2138 if (r_refdef.extraupdate)
2141 R_ResetViewRendering3D();
2143 R_MeshQueue_BeginScene();
2147 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);
2149 if (cl.csqc_vidvars.drawworld)
2151 // don't let sound skip if going slow
2152 if (r_refdef.extraupdate)
2155 if (r_refdef.worldmodel && r_refdef.worldmodel->DrawSky)
2157 r_refdef.worldmodel->DrawSky(r_refdef.worldentity);
2158 if (r_timereport_active)
2159 R_TimeReport("worldsky");
2162 if (R_DrawBrushModelsSky() && r_timereport_active)
2163 R_TimeReport("bmodelsky");
2165 if (r_refdef.worldmodel && r_refdef.worldmodel->Draw)
2167 r_refdef.worldmodel->Draw(r_refdef.worldentity);
2168 if (r_timereport_active)
2169 R_TimeReport("world");
2173 // don't let sound skip if going slow
2174 if (r_refdef.extraupdate)
2178 if (r_timereport_active)
2179 R_TimeReport("models");
2181 // don't let sound skip if going slow
2182 if (r_refdef.extraupdate)
2185 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
2187 R_DrawModelShadows();
2189 R_ResetViewRendering3D();
2191 // don't let sound skip if going slow
2192 if (r_refdef.extraupdate)
2196 R_ShadowVolumeLighting(false);
2197 if (r_timereport_active)
2198 R_TimeReport("rtlights");
2200 // don't let sound skip if going slow
2201 if (r_refdef.extraupdate)
2204 if (cl.csqc_vidvars.drawworld)
2206 R_DrawLightningBeams();
2207 if (r_timereport_active)
2208 R_TimeReport("lightning");
2211 if (r_timereport_active)
2212 R_TimeReport("particles");
2215 if (r_timereport_active)
2216 R_TimeReport("explosions");
2219 if (gl_support_fragment_shader)
2221 qglUseProgramObjectARB(0);CHECKGLERROR
2223 VM_CL_AddPolygonsToMeshQueue();
2225 if (r_drawportals.integer)
2228 if (r_timereport_active)
2229 R_TimeReport("portals");
2232 if (gl_support_fragment_shader)
2234 qglUseProgramObjectARB(0);CHECKGLERROR
2236 R_MeshQueue_RenderTransparent();
2237 if (r_timereport_active)
2238 R_TimeReport("drawtrans");
2240 if (gl_support_fragment_shader)
2242 qglUseProgramObjectARB(0);CHECKGLERROR
2245 if (cl.csqc_vidvars.drawworld)
2248 if (r_timereport_active)
2249 R_TimeReport("coronas");
2252 // don't let sound skip if going slow
2253 if (r_refdef.extraupdate)
2256 R_ResetViewRendering2D();
2260 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
2263 float *v, *c, f1, f2, diff[3], vertex3f[8*3], color4f[8*4];
2264 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2265 GL_DepthMask(false);
2267 R_Mesh_Matrix(&identitymatrix);
2269 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2];
2270 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
2271 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
2272 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
2273 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
2274 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
2275 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
2276 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
2277 R_FillColors(color, 8, cr, cg, cb, ca);
2278 if (r_refdef.fogenabled)
2280 for (i = 0, v = vertex, c = color;i < 8;i++, v += 4, c += 4)
2282 f2 = VERTEXFOGTABLE(VectorDistance(v, r_view.origin));
2284 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
2285 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
2286 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
2289 R_Mesh_VertexPointer(vertex3f);
2290 R_Mesh_ColorPointer(color);
2291 R_Mesh_ResetTextureState();
2296 int nomodelelements[24] =
2308 float nomodelvertex3f[6*3] =
2318 float nomodelcolor4f[6*4] =
2320 0.0f, 0.0f, 0.5f, 1.0f,
2321 0.0f, 0.0f, 0.5f, 1.0f,
2322 0.0f, 0.5f, 0.0f, 1.0f,
2323 0.0f, 0.5f, 0.0f, 1.0f,
2324 0.5f, 0.0f, 0.0f, 1.0f,
2325 0.5f, 0.0f, 0.0f, 1.0f
2328 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
2333 // this is only called once per entity so numsurfaces is always 1, and
2334 // surfacelist is always {0}, so this code does not handle batches
2335 R_Mesh_Matrix(&ent->matrix);
2337 if (ent->flags & EF_ADDITIVE)
2339 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2340 GL_DepthMask(false);
2342 else if (ent->alpha < 1)
2344 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2345 GL_DepthMask(false);
2349 GL_BlendFunc(GL_ONE, GL_ZERO);
2352 GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
2353 GL_CullFace((ent->effects & EF_DOUBLESIDED) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
2354 R_Mesh_VertexPointer(nomodelvertex3f);
2355 if (r_refdef.fogenabled)
2358 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
2359 R_Mesh_ColorPointer(color4f);
2360 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
2361 f2 = VERTEXFOGTABLE(VectorDistance(org, r_view.origin));
2363 for (i = 0, c = color4f;i < 6;i++, c += 4)
2365 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
2366 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
2367 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
2371 else if (ent->alpha != 1)
2373 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
2374 R_Mesh_ColorPointer(color4f);
2375 for (i = 0, c = color4f;i < 6;i++, c += 4)
2379 R_Mesh_ColorPointer(nomodelcolor4f);
2380 R_Mesh_ResetTextureState();
2381 R_Mesh_Draw(0, 6, 8, nomodelelements);
2384 void R_DrawNoModel(entity_render_t *ent)
2387 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
2388 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
2389 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, r_shadow_rtlight);
2391 // R_DrawNoModelCallback(ent, 0);
2394 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
2396 vec3_t right1, right2, diff, normal;
2398 VectorSubtract (org2, org1, normal);
2400 // calculate 'right' vector for start
2401 VectorSubtract (r_view.origin, org1, diff);
2402 CrossProduct (normal, diff, right1);
2403 VectorNormalize (right1);
2405 // calculate 'right' vector for end
2406 VectorSubtract (r_view.origin, org2, diff);
2407 CrossProduct (normal, diff, right2);
2408 VectorNormalize (right2);
2410 vert[ 0] = org1[0] + width * right1[0];
2411 vert[ 1] = org1[1] + width * right1[1];
2412 vert[ 2] = org1[2] + width * right1[2];
2413 vert[ 3] = org1[0] - width * right1[0];
2414 vert[ 4] = org1[1] - width * right1[1];
2415 vert[ 5] = org1[2] - width * right1[2];
2416 vert[ 6] = org2[0] - width * right2[0];
2417 vert[ 7] = org2[1] - width * right2[1];
2418 vert[ 8] = org2[2] - width * right2[2];
2419 vert[ 9] = org2[0] + width * right2[0];
2420 vert[10] = org2[1] + width * right2[1];
2421 vert[11] = org2[2] + width * right2[2];
2424 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
2426 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)
2428 float fog = 0.0f, ifog;
2431 if (r_refdef.fogenabled)
2432 fog = VERTEXFOGTABLE(VectorDistance(origin, r_view.origin));
2435 R_Mesh_Matrix(&identitymatrix);
2436 GL_BlendFunc(blendfunc1, blendfunc2);
2437 GL_DepthMask(false);
2438 GL_DepthTest(!depthdisable);
2440 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
2441 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
2442 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
2443 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
2444 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
2445 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
2446 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
2447 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
2448 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
2449 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
2450 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
2451 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
2453 R_Mesh_VertexPointer(vertex3f);
2454 R_Mesh_ColorPointer(NULL);
2455 R_Mesh_ResetTextureState();
2456 R_Mesh_TexBind(0, R_GetTexture(texture));
2457 R_Mesh_TexCoordPointer(0, 2, spritetexcoord2f);
2458 // FIXME: fixed function path can't properly handle r_view.colorscale > 1
2459 GL_Color(cr * ifog * r_view.colorscale, cg * ifog * r_view.colorscale, cb * ifog * r_view.colorscale, ca);
2460 R_Mesh_Draw(0, 4, 2, polygonelements);
2462 if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
2464 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
2465 GL_BlendFunc(blendfunc1, GL_ONE);
2466 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);
2467 R_Mesh_Draw(0, 4, 2, polygonelements);
2471 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
2476 VectorSet(v, x, y, z);
2477 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
2478 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
2480 if (i == mesh->numvertices)
2482 if (mesh->numvertices < mesh->maxvertices)
2484 VectorCopy(v, vertex3f);
2485 mesh->numvertices++;
2487 return mesh->numvertices;
2493 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
2497 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
2498 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
2499 e = mesh->element3i + mesh->numtriangles * 3;
2500 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
2502 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
2503 if (mesh->numtriangles < mesh->maxtriangles)
2508 mesh->numtriangles++;
2510 element[1] = element[2];
2514 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
2518 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
2519 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
2520 e = mesh->element3i + mesh->numtriangles * 3;
2521 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
2523 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
2524 if (mesh->numtriangles < mesh->maxtriangles)
2529 mesh->numtriangles++;
2531 element[1] = element[2];
2535 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
2536 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
2538 int planenum, planenum2;
2541 mplane_t *plane, *plane2;
2543 double temppoints[2][256*3];
2544 // figure out how large a bounding box we need to properly compute this brush
2546 for (w = 0;w < numplanes;w++)
2547 maxdist = max(maxdist, planes[w].dist);
2548 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
2549 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
2550 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
2554 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
2555 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
2557 if (planenum2 == planenum)
2559 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);
2562 if (tempnumpoints < 3)
2564 // generate elements forming a triangle fan for this polygon
2565 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
2569 static void R_DrawCollisionBrush(const colbrushf_t *brush)
2572 R_Mesh_VertexPointer(brush->points->v);
2573 i = (int)(((size_t)brush) / sizeof(colbrushf_t));
2574 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);
2575 GL_LockArrays(0, brush->numpoints);
2576 R_Mesh_Draw(0, brush->numpoints, brush->numtriangles, brush->elements);
2577 GL_LockArrays(0, 0);
2580 static void R_DrawCollisionSurface(const entity_render_t *ent, const msurface_t *surface)
2583 if (!surface->num_collisiontriangles)
2585 R_Mesh_VertexPointer(surface->data_collisionvertex3f);
2586 i = (int)(((size_t)surface) / sizeof(msurface_t));
2587 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);
2588 GL_LockArrays(0, surface->num_collisionvertices);
2589 R_Mesh_Draw(0, surface->num_collisionvertices, surface->num_collisiontriangles, surface->data_collisionelement3i);
2590 GL_LockArrays(0, 0);
2593 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)
2595 texturelayer_t *layer;
2596 layer = t->currentlayers + t->currentnumlayers++;
2598 layer->depthmask = depthmask;
2599 layer->blendfunc1 = blendfunc1;
2600 layer->blendfunc2 = blendfunc2;
2601 layer->texture = texture;
2602 layer->texmatrix = *matrix;
2603 layer->color[0] = r * r_view.colorscale;
2604 layer->color[1] = g * r_view.colorscale;
2605 layer->color[2] = b * r_view.colorscale;
2606 layer->color[3] = a;
2609 void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
2611 model_t *model = ent->model;
2613 // switch to an alternate material if this is a q1bsp animated material
2615 texture_t *texture = t;
2616 int s = ent->skinnum;
2617 if ((unsigned int)s >= (unsigned int)model->numskins)
2619 if (model->skinscenes)
2621 if (model->skinscenes[s].framecount > 1)
2622 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
2624 s = model->skinscenes[s].firstframe;
2627 t = t + s * model->num_surfaces;
2630 // use an alternate animation if the entity's frame is not 0,
2631 // and only if the texture has an alternate animation
2632 if (ent->frame != 0 && t->anim_total[1])
2633 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.time * 5.0f) % t->anim_total[1]) : 0];
2635 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.time * 5.0f) % t->anim_total[0]) : 0];
2637 texture->currentframe = t;
2640 // pick a new currentskinframe if the material is animated
2641 if (t->numskinframes >= 2)
2642 t->currentskinframe = t->skinframes + ((int)(t->skinframerate * (cl.time - ent->frame2time)) % t->numskinframes);
2643 if (t->backgroundnumskinframes >= 2)
2644 t->backgroundcurrentskinframe = t->backgroundskinframes + ((int)(t->backgroundskinframerate * (cl.time - ent->frame2time)) % t->backgroundnumskinframes);
2646 t->currentmaterialflags = t->basematerialflags;
2647 t->currentalpha = ent->alpha;
2648 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
2649 t->currentalpha *= r_wateralpha.value;
2650 if (!(ent->flags & RENDER_LIGHT))
2651 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
2652 if (ent->effects & EF_ADDITIVE)
2653 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_TRANSPARENT | MATERIALFLAG_NOSHADOW;
2654 else if (t->currentalpha < 1)
2655 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_TRANSPARENT | MATERIALFLAG_NOSHADOW;
2656 if (ent->effects & EF_DOUBLESIDED)
2657 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
2658 if (ent->effects & EF_NODEPTHTEST)
2659 t->currentmaterialflags |= MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_NOSHADOW;
2660 if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
2661 t->currenttexmatrix = r_waterscrollmatrix;
2663 t->currenttexmatrix = identitymatrix;
2664 if (t->backgroundnumskinframes && !(t->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
2665 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
2667 t->colormapping = VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f);
2668 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
2669 t->glosstexture = r_texture_white;
2670 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
2671 t->backgroundglosstexture = r_texture_white;
2672 t->specularpower = r_shadow_glossexponent.value;
2673 t->specularscale = 0;
2674 if (r_shadow_gloss.integer > 0)
2676 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
2678 if (r_shadow_glossintensity.value > 0)
2680 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_black;
2681 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_black;
2682 t->specularscale = r_shadow_glossintensity.value;
2685 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
2686 t->specularscale = r_shadow_gloss2intensity.value;
2689 t->currentnumlayers = 0;
2690 if (!(t->currentmaterialflags & MATERIALFLAG_NODRAW))
2692 if (gl_lightmaps.integer)
2693 R_Texture_AddLayer(t, true, GL_ONE, GL_ZERO, TEXTURELAYERTYPE_LITTEXTURE, r_texture_white, &identitymatrix, 1, 1, 1, 1);
2694 else if (!(t->currentmaterialflags & MATERIALFLAG_SKY))
2696 int blendfunc1, blendfunc2, depthmask;
2697 if (t->currentmaterialflags & MATERIALFLAG_ADD)
2699 blendfunc1 = GL_SRC_ALPHA;
2700 blendfunc2 = GL_ONE;
2702 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
2704 blendfunc1 = GL_SRC_ALPHA;
2705 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
2707 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
2709 blendfunc1 = t->customblendfunc[0];
2710 blendfunc2 = t->customblendfunc[1];
2714 blendfunc1 = GL_ONE;
2715 blendfunc2 = GL_ZERO;
2717 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
2718 if (t->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL))
2720 rtexture_t *currentbasetexture;
2722 if (r_refdef.fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED))
2723 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
2724 currentbasetexture = (VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) < (1.0f / 1048576.0f) && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
2725 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2727 // fullbright is not affected by r_refdef.lightmapintensity
2728 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
2729 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
2730 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);
2731 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
2732 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);
2738 // q3bsp has no lightmap updates, so the lightstylevalue that
2739 // would normally be baked into the lightmap must be
2740 // applied to the color
2741 if (ent->model->type == mod_brushq3)
2742 colorscale *= r_refdef.lightstylevalue[0] * (1.0f / 256.0f);
2743 colorscale *= r_refdef.lightmapintensity;
2744 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);
2745 if (r_ambient.value >= (1.0f/64.0f))
2746 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);
2747 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
2749 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);
2750 if (r_ambient.value >= (1.0f/64.0f))
2751 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);
2753 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
2755 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);
2756 if (r_ambient.value >= (1.0f/64.0f))
2757 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);
2760 if (t->currentskinframe->glow != NULL)
2761 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);
2762 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
2764 // if this is opaque use alpha blend which will darken the earlier
2767 // if this is an alpha blended material, all the earlier passes
2768 // were darkened by fog already, so we only need to add the fog
2769 // color ontop through the fog mask texture
2771 // if this is an additive blended material, all the earlier passes
2772 // were darkened by fog already, and we should not add fog color
2773 // (because the background was not darkened, there is no fog color
2774 // that was lost behind it).
2775 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);
2782 void R_UpdateAllTextureInfo(entity_render_t *ent)
2786 for (i = 0;i < ent->model->num_textures;i++)
2787 R_UpdateTextureInfo(ent, ent->model->data_textures + i);
2790 int rsurface_array_size = 0;
2791 float *rsurface_array_modelvertex3f = NULL;
2792 float *rsurface_array_modelsvector3f = NULL;
2793 float *rsurface_array_modeltvector3f = NULL;
2794 float *rsurface_array_modelnormal3f = NULL;
2795 float *rsurface_array_deformedvertex3f = NULL;
2796 float *rsurface_array_deformedsvector3f = NULL;
2797 float *rsurface_array_deformedtvector3f = NULL;
2798 float *rsurface_array_deformednormal3f = NULL;
2799 float *rsurface_array_color4f = NULL;
2800 float *rsurface_array_texcoord3f = NULL;
2802 void R_Mesh_ResizeArrays(int newvertices)
2805 if (rsurface_array_size >= newvertices)
2807 if (rsurface_array_modelvertex3f)
2808 Mem_Free(rsurface_array_modelvertex3f);
2809 rsurface_array_size = (newvertices + 1023) & ~1023;
2810 base = (float *)Mem_Alloc(r_main_mempool, rsurface_array_size * sizeof(float[31]));
2811 rsurface_array_modelvertex3f = base + rsurface_array_size * 0;
2812 rsurface_array_modelsvector3f = base + rsurface_array_size * 3;
2813 rsurface_array_modeltvector3f = base + rsurface_array_size * 6;
2814 rsurface_array_modelnormal3f = base + rsurface_array_size * 9;
2815 rsurface_array_deformedvertex3f = base + rsurface_array_size * 12;
2816 rsurface_array_deformedsvector3f = base + rsurface_array_size * 15;
2817 rsurface_array_deformedtvector3f = base + rsurface_array_size * 18;
2818 rsurface_array_deformednormal3f = base + rsurface_array_size * 21;
2819 rsurface_array_texcoord3f = base + rsurface_array_size * 24;
2820 rsurface_array_color4f = base + rsurface_array_size * 27;
2823 float *rsurface_modelvertex3f;
2824 float *rsurface_modelsvector3f;
2825 float *rsurface_modeltvector3f;
2826 float *rsurface_modelnormal3f;
2827 float *rsurface_vertex3f;
2828 float *rsurface_svector3f;
2829 float *rsurface_tvector3f;
2830 float *rsurface_normal3f;
2831 float *rsurface_lightmapcolor4f;
2832 vec3_t rsurface_modelorg;
2833 qboolean rsurface_generatedvertex;
2834 const entity_render_t *rsurface_entity;
2835 const model_t *rsurface_model;
2836 texture_t *rsurface_texture;
2837 qboolean rsurface_uselightmaptexture;
2838 rsurfmode_t rsurface_mode;
2839 int rsurface_lightmode; // 0 = lightmap or fullbright, 1 = color array from q3bsp, 2 = vertex shaded model
2841 void RSurf_CleanUp(void)
2844 if (rsurface_mode == RSURFMODE_GLSL)
2846 qglUseProgramObjectARB(0);CHECKGLERROR
2848 GL_AlphaTest(false);
2849 rsurface_mode = RSURFMODE_NONE;
2850 rsurface_uselightmaptexture = false;
2851 rsurface_texture = NULL;
2854 void RSurf_ActiveWorldEntity(void)
2857 rsurface_entity = r_refdef.worldentity;
2858 rsurface_model = r_refdef.worldmodel;
2859 if (rsurface_array_size < rsurface_model->surfmesh.num_vertices)
2860 R_Mesh_ResizeArrays(rsurface_model->surfmesh.num_vertices);
2861 R_Mesh_Matrix(&identitymatrix);
2862 VectorCopy(r_view.origin, rsurface_modelorg);
2863 rsurface_modelvertex3f = rsurface_model->surfmesh.data_vertex3f;
2864 rsurface_modelsvector3f = rsurface_model->surfmesh.data_svector3f;
2865 rsurface_modeltvector3f = rsurface_model->surfmesh.data_tvector3f;
2866 rsurface_modelnormal3f = rsurface_model->surfmesh.data_normal3f;
2867 rsurface_generatedvertex = false;
2868 rsurface_vertex3f = rsurface_modelvertex3f;
2869 rsurface_svector3f = rsurface_modelsvector3f;
2870 rsurface_tvector3f = rsurface_modeltvector3f;
2871 rsurface_normal3f = rsurface_modelnormal3f;
2874 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
2877 rsurface_entity = ent;
2878 rsurface_model = ent->model;
2879 if (rsurface_array_size < rsurface_model->surfmesh.num_vertices)
2880 R_Mesh_ResizeArrays(rsurface_model->surfmesh.num_vertices);
2881 R_Mesh_Matrix(&ent->matrix);
2882 Matrix4x4_Transform(&ent->inversematrix, r_view.origin, rsurface_modelorg);
2883 if (rsurface_model->surfmesh.isanimated && (rsurface_entity->frameblend[0].lerp != 1 || rsurface_entity->frameblend[0].frame != 0))
2887 rsurface_modelvertex3f = rsurface_array_modelvertex3f;
2888 rsurface_modelsvector3f = rsurface_array_modelsvector3f;
2889 rsurface_modeltvector3f = rsurface_array_modeltvector3f;
2890 rsurface_modelnormal3f = rsurface_array_modelnormal3f;
2891 Mod_Alias_GetMesh_Vertices(rsurface_model, rsurface_entity->frameblend, rsurface_array_modelvertex3f, rsurface_array_modelnormal3f, rsurface_array_modelsvector3f, rsurface_array_modeltvector3f);
2893 else if (wantnormals)
2895 rsurface_modelvertex3f = rsurface_array_modelvertex3f;
2896 rsurface_modelsvector3f = NULL;
2897 rsurface_modeltvector3f = NULL;
2898 rsurface_modelnormal3f = rsurface_array_modelnormal3f;
2899 Mod_Alias_GetMesh_Vertices(rsurface_model, rsurface_entity->frameblend, rsurface_array_modelvertex3f, rsurface_array_modelnormal3f, NULL, NULL);
2903 rsurface_modelvertex3f = rsurface_array_modelvertex3f;
2904 rsurface_modelsvector3f = NULL;
2905 rsurface_modeltvector3f = NULL;
2906 rsurface_modelnormal3f = NULL;
2907 Mod_Alias_GetMesh_Vertices(rsurface_model, rsurface_entity->frameblend, rsurface_array_modelvertex3f, NULL, NULL, NULL);
2909 rsurface_generatedvertex = true;
2913 rsurface_modelvertex3f = rsurface_model->surfmesh.data_vertex3f;
2914 rsurface_modelsvector3f = rsurface_model->surfmesh.data_svector3f;
2915 rsurface_modeltvector3f = rsurface_model->surfmesh.data_tvector3f;
2916 rsurface_modelnormal3f = rsurface_model->surfmesh.data_normal3f;
2917 rsurface_generatedvertex = false;
2919 rsurface_vertex3f = rsurface_modelvertex3f;
2920 rsurface_svector3f = rsurface_modelsvector3f;
2921 rsurface_tvector3f = rsurface_modeltvector3f;
2922 rsurface_normal3f = rsurface_modelnormal3f;
2925 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, msurface_t **texturesurfacelist)
2927 // 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
2928 if (rsurface_generatedvertex)
2930 if (rsurface_texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
2931 generatetangents = true;
2932 if (generatetangents)
2933 generatenormals = true;
2934 if (generatenormals && !rsurface_modelnormal3f)
2936 rsurface_normal3f = rsurface_modelnormal3f = rsurface_array_modelnormal3f;
2937 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);
2939 if (generatetangents && !rsurface_modelsvector3f)
2941 rsurface_svector3f = rsurface_modelsvector3f = rsurface_array_modelsvector3f;
2942 rsurface_tvector3f = rsurface_modeltvector3f = rsurface_array_modeltvector3f;
2943 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);
2946 // 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)
2947 if (rsurface_texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
2949 int texturesurfaceindex;
2950 float center[3], forward[3], right[3], up[3], v[4][3];
2951 matrix4x4_t matrix1, imatrix1;
2952 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_view.forward, forward);
2953 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_view.right, right);
2954 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_view.up, up);
2955 // make deformed versions of only the model vertices used by the specified surfaces
2956 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2959 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2960 // a single autosprite surface can contain multiple sprites...
2961 for (j = 0;j < surface->num_vertices - 3;j += 4)
2963 VectorClear(center);
2964 for (i = 0;i < 4;i++)
2965 VectorAdd(center, (rsurface_modelvertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
2966 VectorScale(center, 0.25f, center);
2967 if (rsurface_texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE2)
2969 forward[0] = rsurface_modelorg[0] - center[0];
2970 forward[1] = rsurface_modelorg[1] - center[1];
2972 VectorNormalize(forward);
2973 right[0] = forward[1];
2974 right[1] = -forward[0];
2976 VectorSet(up, 0, 0, 1);
2978 // FIXME: calculate vectors from triangle edges instead of using texture vectors as an easy way out?
2979 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);
2980 Matrix4x4_Invert_Simple(&imatrix1, &matrix1);
2981 for (i = 0;i < 4;i++)
2982 Matrix4x4_Transform(&imatrix1, (rsurface_modelvertex3f + 3 * surface->num_firstvertex) + (j+i)*3, v[i]);
2983 for (i = 0;i < 4;i++)
2984 VectorMAMAMAM(1, center, v[i][0], forward, v[i][1], right, v[i][2], up, rsurface_array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
2986 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);
2987 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);
2989 rsurface_vertex3f = rsurface_array_deformedvertex3f;
2990 rsurface_svector3f = rsurface_array_deformedsvector3f;
2991 rsurface_tvector3f = rsurface_array_deformedtvector3f;
2992 rsurface_normal3f = rsurface_array_deformednormal3f;
2996 rsurface_vertex3f = rsurface_modelvertex3f;
2997 rsurface_svector3f = rsurface_modelsvector3f;
2998 rsurface_tvector3f = rsurface_modeltvector3f;
2999 rsurface_normal3f = rsurface_modelnormal3f;
3001 R_Mesh_VertexPointer(rsurface_vertex3f);
3004 void RSurf_DrawBatch_Simple(int texturenumsurfaces, msurface_t **texturesurfacelist)
3007 const msurface_t *surface = texturesurfacelist[0];
3008 const msurface_t *surface2;
3013 // TODO: lock all array ranges before render, rather than on each surface
3014 if (texturenumsurfaces == 1)
3016 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
3017 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
3019 else if (r_batchmode.integer == 2)
3021 #define MAXBATCHTRIANGLES 4096
3022 int batchtriangles = 0;
3023 int batchelements[MAXBATCHTRIANGLES*3];
3024 for (i = 0;i < texturenumsurfaces;i = j)
3026 surface = texturesurfacelist[i];
3028 if (surface->num_triangles > MAXBATCHTRIANGLES)
3030 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
3033 memcpy(batchelements, rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
3034 batchtriangles = surface->num_triangles;
3035 firstvertex = surface->num_firstvertex;
3036 endvertex = surface->num_firstvertex + surface->num_vertices;
3037 for (;j < texturenumsurfaces;j++)
3039 surface2 = texturesurfacelist[j];
3040 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
3042 memcpy(batchelements + batchtriangles * 3, rsurface_model->surfmesh.data_element3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
3043 batchtriangles += surface2->num_triangles;
3044 firstvertex = min(firstvertex, surface2->num_firstvertex);
3045 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
3047 surface2 = texturesurfacelist[j-1];
3048 numvertices = endvertex - firstvertex;
3049 R_Mesh_Draw(firstvertex, numvertices, batchtriangles, batchelements);
3052 else if (r_batchmode.integer == 1)
3054 for (i = 0;i < texturenumsurfaces;i = j)
3056 surface = texturesurfacelist[i];
3057 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
3058 if (texturesurfacelist[j] != surface2)
3060 surface2 = texturesurfacelist[j-1];
3061 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
3062 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
3063 GL_LockArrays(surface->num_firstvertex, numvertices);
3064 R_Mesh_Draw(surface->num_firstvertex, numvertices, numtriangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
3069 for (i = 0;i < texturenumsurfaces;i++)
3071 surface = texturesurfacelist[i];
3072 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
3073 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
3078 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit)
3082 const msurface_t *surface = texturesurfacelist[0];
3083 const msurface_t *surface2;
3088 // TODO: lock all array ranges before render, rather than on each surface
3089 if (texturenumsurfaces == 1)
3091 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
3092 if (deluxemaptexunit >= 0)
3093 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
3094 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
3095 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
3097 else if (r_batchmode.integer == 2)
3099 #define MAXBATCHTRIANGLES 4096
3100 int batchtriangles = 0;
3101 int batchelements[MAXBATCHTRIANGLES*3];
3102 for (i = 0;i < texturenumsurfaces;i = j)
3104 surface = texturesurfacelist[i];
3105 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
3106 if (deluxemaptexunit >= 0)
3107 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
3109 if (surface->num_triangles > MAXBATCHTRIANGLES)
3111 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
3114 memcpy(batchelements, rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
3115 batchtriangles = surface->num_triangles;
3116 firstvertex = surface->num_firstvertex;
3117 endvertex = surface->num_firstvertex + surface->num_vertices;
3118 for (;j < texturenumsurfaces;j++)
3120 surface2 = texturesurfacelist[j];
3121 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
3123 memcpy(batchelements + batchtriangles * 3, rsurface_model->surfmesh.data_element3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
3124 batchtriangles += surface2->num_triangles;
3125 firstvertex = min(firstvertex, surface2->num_firstvertex);
3126 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
3128 surface2 = texturesurfacelist[j-1];
3129 numvertices = endvertex - firstvertex;
3130 R_Mesh_Draw(firstvertex, numvertices, batchtriangles, batchelements);
3133 else if (r_batchmode.integer == 1)
3136 Con_Printf("%s batch sizes ignoring lightmap:", rsurface_texture->name);
3137 for (i = 0;i < texturenumsurfaces;i = j)
3139 surface = texturesurfacelist[i];
3140 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
3141 if (texturesurfacelist[j] != surface2)
3143 Con_Printf(" %i", j - i);
3146 Con_Printf("%s batch sizes honoring lightmap:", rsurface_texture->name);
3148 for (i = 0;i < texturenumsurfaces;i = j)
3150 surface = texturesurfacelist[i];
3151 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
3152 if (deluxemaptexunit >= 0)
3153 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
3154 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
3155 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
3158 Con_Printf(" %i", j - i);
3160 surface2 = texturesurfacelist[j-1];
3161 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
3162 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
3163 GL_LockArrays(surface->num_firstvertex, numvertices);
3164 R_Mesh_Draw(surface->num_firstvertex, numvertices, numtriangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
3172 for (i = 0;i < texturenumsurfaces;i++)
3174 surface = texturesurfacelist[i];
3175 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
3176 if (deluxemaptexunit >= 0)
3177 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
3178 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
3179 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
3184 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
3187 int texturesurfaceindex;
3188 if (r_showsurfaces.integer == 2)
3190 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3192 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3193 for (j = 0;j < surface->num_triangles;j++)
3195 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_view.colorscale;
3196 GL_Color(f, f, f, 1);
3197 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, 1, (rsurface_model->surfmesh.data_element3i + 3 * (j + surface->num_firsttriangle)));
3203 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3205 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3206 int k = (int)(((size_t)surface) / sizeof(msurface_t));
3207 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);
3208 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
3209 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
3214 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, msurface_t **texturesurfacelist)
3216 int texturesurfaceindex;
3220 if (rsurface_lightmapcolor4f)
3222 // generate color arrays for the surfaces in this list
3223 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3225 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3226 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)
3228 f = 1 - VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
3238 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3240 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3241 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)
3243 f = 1 - VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
3251 rsurface_lightmapcolor4f = rsurface_array_color4f;
3254 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a)
3256 int texturesurfaceindex;
3259 if (!rsurface_lightmapcolor4f)
3261 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3263 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3264 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)
3272 rsurface_lightmapcolor4f = rsurface_array_color4f;
3275 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
3278 rsurface_lightmapcolor4f = NULL;
3279 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
3280 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
3281 R_Mesh_ColorPointer(rsurface_lightmapcolor4f);
3282 GL_Color(r, g, b, a);
3283 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 0, -1);
3286 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
3288 // TODO: optimize applyfog && applycolor case
3289 // just apply fog if necessary, and tint the fog color array if necessary
3290 rsurface_lightmapcolor4f = NULL;
3291 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
3292 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
3293 R_Mesh_ColorPointer(rsurface_lightmapcolor4f);
3294 GL_Color(r, g, b, a);
3295 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3298 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
3300 int texturesurfaceindex;
3304 if (texturesurfacelist[0]->lightmapinfo && texturesurfacelist[0]->lightmapinfo->stainsamples)
3306 // generate color arrays for the surfaces in this list
3307 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3309 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3310 for (i = 0, c = rsurface_array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
3312 if (surface->lightmapinfo->samples)
3314 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface_model->surfmesh.data_lightmapoffsets + surface->num_firstvertex)[i];
3315 float scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
3316 VectorScale(lm, scale, c);
3317 if (surface->lightmapinfo->styles[1] != 255)
3319 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
3321 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
3322 VectorMA(c, scale, lm, c);
3323 if (surface->lightmapinfo->styles[2] != 255)
3326 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
3327 VectorMA(c, scale, lm, c);
3328 if (surface->lightmapinfo->styles[3] != 255)
3331 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
3332 VectorMA(c, scale, lm, c);
3342 rsurface_lightmapcolor4f = rsurface_array_color4f;
3345 rsurface_lightmapcolor4f = rsurface_model->surfmesh.data_lightmapcolor4f;
3346 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
3347 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
3348 R_Mesh_ColorPointer(rsurface_lightmapcolor4f);
3349 GL_Color(r, g, b, a);
3350 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3353 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
3355 int texturesurfaceindex;
3359 vec3_t ambientcolor;
3360 vec3_t diffusecolor;
3364 VectorCopy(rsurface_entity->modellight_lightdir, lightdir);
3365 ambientcolor[0] = rsurface_entity->modellight_ambient[0] * r * 0.5f;
3366 ambientcolor[1] = rsurface_entity->modellight_ambient[1] * g * 0.5f;
3367 ambientcolor[2] = rsurface_entity->modellight_ambient[2] * b * 0.5f;
3368 diffusecolor[0] = rsurface_entity->modellight_diffuse[0] * r * 0.5f;
3369 diffusecolor[1] = rsurface_entity->modellight_diffuse[1] * g * 0.5f;
3370 diffusecolor[2] = rsurface_entity->modellight_diffuse[2] * b * 0.5f;
3371 if (VectorLength2(diffusecolor) > 0)
3373 // generate color arrays for the surfaces in this list
3374 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3376 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3377 int numverts = surface->num_vertices;
3378 v = rsurface_vertex3f + 3 * surface->num_firstvertex;
3379 c2 = rsurface_normal3f + 3 * surface->num_firstvertex;
3380 c = rsurface_array_color4f + 4 * surface->num_firstvertex;
3381 // q3-style directional shading
3382 for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
3384 if ((f = DotProduct(c2, lightdir)) > 0)
3385 VectorMA(ambientcolor, f, diffusecolor, c);
3387 VectorCopy(ambientcolor, c);
3396 rsurface_lightmapcolor4f = rsurface_array_color4f;
3400 r = ambientcolor[0];
3401 g = ambientcolor[1];
3402 b = ambientcolor[2];
3403 rsurface_lightmapcolor4f = NULL;
3405 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
3406 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
3407 R_Mesh_ColorPointer(rsurface_lightmapcolor4f);
3408 GL_Color(r, g, b, a);
3409 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3412 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
3414 GL_DepthTest(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
3415 GL_CullFace((rsurface_texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
3416 if (rsurface_mode != RSURFMODE_SHOWSURFACES)
3418 rsurface_mode = RSURFMODE_SHOWSURFACES;
3420 GL_BlendFunc(GL_ONE, GL_ZERO);
3421 R_Mesh_ColorPointer(NULL);
3422 R_Mesh_ResetTextureState();
3424 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
3425 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
3428 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, msurface_t **texturesurfacelist)
3430 // transparent sky would be ridiculous
3431 if ((rsurface_texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
3433 if (rsurface_mode != RSURFMODE_SKY)
3435 if (rsurface_mode == RSURFMODE_GLSL)
3437 qglUseProgramObjectARB(0);CHECKGLERROR
3439 rsurface_mode = RSURFMODE_SKY;
3443 skyrendernow = false;
3445 // restore entity matrix
3446 R_Mesh_Matrix(&rsurface_entity->matrix);
3448 GL_DepthTest(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
3449 GL_CullFace((rsurface_texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
3451 // LordHavoc: HalfLife maps have freaky skypolys so don't use
3452 // skymasking on them, and Quake3 never did sky masking (unlike
3453 // software Quake and software Quake2), so disable the sky masking
3454 // in Quake3 maps as it causes problems with q3map2 sky tricks,
3455 // and skymasking also looks very bad when noclipping outside the
3456 // level, so don't use it then either.
3457 if (rsurface_model->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_viewcache.world_novis)
3459 GL_Color(r_refdef.fogcolor[0] * r_view.colorscale, r_refdef.fogcolor[1] * r_view.colorscale, r_refdef.fogcolor[2] * r_view.colorscale, 1);
3460 R_Mesh_ColorPointer(NULL);
3461 R_Mesh_ResetTextureState();
3462 if (skyrendermasked)
3464 // depth-only (masking)
3465 GL_ColorMask(0,0,0,0);
3466 // just to make sure that braindead drivers don't draw
3467 // anything despite that colormask...
3468 GL_BlendFunc(GL_ZERO, GL_ONE);
3473 GL_BlendFunc(GL_ONE, GL_ZERO);
3475 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
3476 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3477 if (skyrendermasked)
3478 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
3482 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, msurface_t **texturesurfacelist)
3484 if (rsurface_mode != RSURFMODE_GLSL)
3486 rsurface_mode = RSURFMODE_GLSL;
3487 R_Mesh_ResetTextureState();
3490 R_SetupSurfaceShader(vec3_origin, rsurface_lightmode == 2);
3491 if (!r_glsl_permutation)
3494 if (rsurface_lightmode == 2)
3495 RSurf_PrepareVerticesForBatch(true, r_glsl_permutation->loc_Texture_Normal, texturenumsurfaces, texturesurfacelist);
3497 RSurf_PrepareVerticesForBatch(r_glsl_permutation->loc_Texture_Normal, r_glsl_permutation->loc_Texture_Normal, texturenumsurfaces, texturesurfacelist);
3498 R_Mesh_TexCoordPointer(0, 2, rsurface_model->surfmesh.data_texcoordtexture2f);
3499 R_Mesh_TexCoordPointer(1, 3, rsurface_svector3f);
3500 R_Mesh_TexCoordPointer(2, 3, rsurface_tvector3f);
3501 R_Mesh_TexCoordPointer(3, 3, rsurface_normal3f);
3502 R_Mesh_TexCoordPointer(4, 2, rsurface_model->surfmesh.data_texcoordlightmap2f);
3504 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
3506 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
3507 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
3508 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
3509 R_Mesh_ColorPointer(NULL);
3511 else if (rsurface_uselightmaptexture)
3513 R_Mesh_TexBind(7, R_GetTexture(texturesurfacelist[0]->lightmaptexture));
3514 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
3515 R_Mesh_TexBind(8, R_GetTexture(texturesurfacelist[0]->deluxemaptexture));
3516 R_Mesh_ColorPointer(NULL);
3520 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
3521 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
3522 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
3523 R_Mesh_ColorPointer(rsurface_model->surfmesh.data_lightmapcolor4f);
3526 if (rsurface_uselightmaptexture && !(rsurface_texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
3527 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 7, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? 8 : -1);
3529 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3530 if (rsurface_texture->backgroundnumskinframes && !(rsurface_texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
3535 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, msurface_t **texturesurfacelist)
3537 // OpenGL 1.3 path - anything not completely ancient
3538 int texturesurfaceindex;
3539 qboolean applycolor;
3543 const texturelayer_t *layer;
3544 if (rsurface_mode != RSURFMODE_MULTIPASS)
3545 rsurface_mode = RSURFMODE_MULTIPASS;
3546 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
3547 for (layerindex = 0, layer = rsurface_texture->currentlayers;layerindex < rsurface_texture->currentnumlayers;layerindex++, layer++)
3550 int layertexrgbscale;
3551 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
3553 if (layerindex == 0)
3557 GL_AlphaTest(false);
3558 qglDepthFunc(GL_EQUAL);CHECKGLERROR
3561 GL_DepthMask(layer->depthmask);
3562 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
3563 if ((layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2) && (gl_combine.integer || layer->depthmask))
3565 layertexrgbscale = 4;
3566 VectorScale(layer->color, 0.25f, layercolor);
3568 else if ((layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1) && (gl_combine.integer || layer->depthmask))
3570 layertexrgbscale = 2;
3571 VectorScale(layer->color, 0.5f, layercolor);
3575 layertexrgbscale = 1;
3576 VectorScale(layer->color, 1.0f, layercolor);
3578 layercolor[3] = layer->color[3];
3579 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
3580 R_Mesh_ColorPointer(NULL);
3581 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
3582 switch (layer->type)
3584 case TEXTURELAYERTYPE_LITTEXTURE:
3585 memset(&m, 0, sizeof(m));
3586 m.tex[0] = R_GetTexture(r_texture_white);
3587 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordlightmap2f;
3588 m.tex[1] = R_GetTexture(layer->texture);
3589 m.texmatrix[1] = layer->texmatrix;
3590 m.texrgbscale[1] = layertexrgbscale;
3591 m.pointer_texcoord[1] = rsurface_model->surfmesh.data_texcoordtexture2f;
3592 R_Mesh_TextureState(&m);
3593 if (rsurface_lightmode == 2)
3594 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
3595 else if (rsurface_uselightmaptexture)
3596 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
3598 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
3600 case TEXTURELAYERTYPE_TEXTURE:
3601 memset(&m, 0, sizeof(m));
3602 m.tex[0] = R_GetTexture(layer->texture);
3603 m.texmatrix[0] = layer->texmatrix;
3604 m.texrgbscale[0] = layertexrgbscale;
3605 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3606 R_Mesh_TextureState(&m);
3607 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
3609 case TEXTURELAYERTYPE_FOG:
3610 memset(&m, 0, sizeof(m));
3611 m.texrgbscale[0] = layertexrgbscale;
3614 m.tex[0] = R_GetTexture(layer->texture);
3615 m.texmatrix[0] = layer->texmatrix;
3616 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3618 R_Mesh_TextureState(&m);
3619 // generate a color array for the fog pass
3620 R_Mesh_ColorPointer(rsurface_array_color4f);
3621 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3625 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3626 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)
3628 f = VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
3629 c[0] = layercolor[0];
3630 c[1] = layercolor[1];
3631 c[2] = layercolor[2];
3632 c[3] = f * layercolor[3];
3635 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3638 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
3640 GL_LockArrays(0, 0);
3643 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
3645 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3646 GL_AlphaTest(false);
3650 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, msurface_t **texturesurfacelist)
3652 // OpenGL 1.1 - crusty old voodoo path
3653 int texturesurfaceindex;
3657 const texturelayer_t *layer;
3658 if (rsurface_mode != RSURFMODE_MULTIPASS)
3659 rsurface_mode = RSURFMODE_MULTIPASS;
3660 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
3661 for (layerindex = 0, layer = rsurface_texture->currentlayers;layerindex < rsurface_texture->currentnumlayers;layerindex++, layer++)
3663 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
3665 if (layerindex == 0)
3669 GL_AlphaTest(false);
3670 qglDepthFunc(GL_EQUAL);CHECKGLERROR
3673 GL_DepthMask(layer->depthmask);
3674 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
3675 R_Mesh_ColorPointer(NULL);
3676 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
3677 switch (layer->type)
3679 case TEXTURELAYERTYPE_LITTEXTURE:
3680 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
3682 // two-pass lit texture with 2x rgbscale
3683 // first the lightmap pass
3684 memset(&m, 0, sizeof(m));
3685 m.tex[0] = R_GetTexture(r_texture_white);
3686 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordlightmap2f;
3687 R_Mesh_TextureState(&m);
3688 if (rsurface_lightmode == 2)
3689 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
3690 else if (rsurface_uselightmaptexture)
3691 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
3693 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
3694 GL_LockArrays(0, 0);
3695 // then apply the texture to it
3696 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
3697 memset(&m, 0, sizeof(m));
3698 m.tex[0] = R_GetTexture(layer->texture);
3699 m.texmatrix[0] = layer->texmatrix;
3700 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3701 R_Mesh_TextureState(&m);
3702 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);
3706 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
3707 memset(&m, 0, sizeof(m));
3708 m.tex[0] = R_GetTexture(layer->texture);
3709 m.texmatrix[0] = layer->texmatrix;
3710 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3711 R_Mesh_TextureState(&m);
3712 if (rsurface_lightmode == 2)
3713 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);
3715 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);
3718 case TEXTURELAYERTYPE_TEXTURE:
3719 // singletexture unlit texture with transparency support
3720 memset(&m, 0, sizeof(m));
3721 m.tex[0] = R_GetTexture(layer->texture);
3722 m.texmatrix[0] = layer->texmatrix;
3723 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3724 R_Mesh_TextureState(&m);
3725 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);
3727 case TEXTURELAYERTYPE_FOG:
3728 // singletexture fogging
3729 R_Mesh_ColorPointer(rsurface_array_color4f);
3732 memset(&m, 0, sizeof(m));
3733 m.tex[0] = R_GetTexture(layer->texture);
3734 m.texmatrix[0] = layer->texmatrix;
3735 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3736 R_Mesh_TextureState(&m);
3739 R_Mesh_ResetTextureState();
3740 // generate a color array for the fog pass
3741 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3745 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3746 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)
3748 f = VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
3749 c[0] = layer->color[0];
3750 c[1] = layer->color[1];
3751 c[2] = layer->color[2];
3752 c[3] = f * layer->color[3];
3755 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3758 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
3760 GL_LockArrays(0, 0);
3763 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
3765 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3766 GL_AlphaTest(false);
3770 static void R_DrawTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist)
3772 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_NODRAW)
3774 r_shadow_rtlight = NULL;
3775 r_refdef.stats.entities_surfaces += texturenumsurfaces;
3777 if (r_showsurfaces.integer)
3778 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
3779 else if (rsurface_texture->currentmaterialflags & MATERIALFLAG_SKY)
3780 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
3781 else if (rsurface_texture->currentnumlayers)
3783 GL_DepthTest(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
3784 GL_CullFace((rsurface_texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
3785 GL_BlendFunc(rsurface_texture->currentlayers[0].blendfunc1, rsurface_texture->currentlayers[0].blendfunc2);
3786 GL_DepthMask(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_BLENDED));
3787 GL_Color(rsurface_entity->colormod[0], rsurface_entity->colormod[1], rsurface_entity->colormod[2], rsurface_texture->currentalpha);
3788 GL_AlphaTest((rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
3789 // FIXME: identify models using a better check than rsurface_model->brush.shadowmesh
3790 rsurface_lightmode = ((rsurface_texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT) || rsurface_model->brush.shadowmesh) ? 0 : 2;
3791 if (r_glsl.integer && gl_support_fragment_shader)
3792 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist);
3793 else if (gl_combine.integer && r_textureunits.integer >= 2)
3794 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist);
3796 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist);
3799 GL_LockArrays(0, 0);
3802 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
3805 int texturenumsurfaces, endsurface;
3807 msurface_t *surface;
3808 msurface_t *texturesurfacelist[1024];
3810 // if the model is static it doesn't matter what value we give for
3811 // wantnormals and wanttangents, so this logic uses only rules applicable
3812 // to a model, knowing that they are meaningless otherwise
3813 if (ent == r_refdef.worldentity)
3814 RSurf_ActiveWorldEntity();
3815 else if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
3816 RSurf_ActiveModelEntity(ent, false, false);
3818 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
3820 for (i = 0;i < numsurfaces;i = j)
3823 surface = rsurface_model->data_surfaces + surfacelist[i];
3824 texture = surface->texture;
3825 rsurface_texture = texture->currentframe;
3826 rsurface_uselightmaptexture = surface->lightmaptexture != NULL;
3827 // scan ahead until we find a different texture
3828 endsurface = min(i + 1024, numsurfaces);
3829 texturenumsurfaces = 0;
3830 texturesurfacelist[texturenumsurfaces++] = surface;
3831 for (;j < endsurface;j++)
3833 surface = rsurface_model->data_surfaces + surfacelist[j];
3834 if (texture != surface->texture || rsurface_uselightmaptexture != (surface->lightmaptexture != NULL))
3836 texturesurfacelist[texturenumsurfaces++] = surface;
3838 // render the range of surfaces
3839 R_DrawTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
3845 void R_QueueSurfaceList(int numsurfaces, msurface_t **surfacelist, int flagsmask)
3848 vec3_t tempcenter, center;
3850 // break the surface list down into batches by texture and use of lightmapping
3851 for (i = 0;i < numsurfaces;i = j)
3854 // texture is the base texture pointer, rsurface_texture is the
3855 // current frame/skin the texture is directing us to use (for example
3856 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
3857 // use skin 1 instead)
3858 texture = surfacelist[i]->texture;
3859 rsurface_texture = texture->currentframe;
3860 rsurface_uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
3861 if (!(rsurface_texture->currentmaterialflags & flagsmask))
3863 // if this texture is not the kind we want, skip ahead to the next one
3864 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
3868 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_BLENDED)
3870 // transparent surfaces get pushed off into the transparent queue
3871 const msurface_t *surface = surfacelist[i];
3872 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
3873 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
3874 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
3875 Matrix4x4_Transform(&rsurface_entity->matrix, tempcenter, center);
3876 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);
3880 // simply scan ahead until we find a different texture or lightmap state
3881 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface_uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
3883 // render the range of surfaces
3884 R_DrawTextureSurfaceList(j - i, surfacelist + i);
3889 void R_DrawCollisionBrushes(entity_render_t *ent)
3893 msurface_t *surface;
3894 model_t *model = ent->model;
3895 if (!model->brush.num_brushes)
3898 R_Mesh_ColorPointer(NULL);
3899 R_Mesh_ResetTextureState();
3900 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
3901 GL_DepthMask(false);
3902 GL_DepthTest(!r_showdisabledepthtest.integer);
3903 qglPolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);CHECKGLERROR
3904 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
3905 if (brush->colbrushf && brush->colbrushf->numtriangles)
3906 R_DrawCollisionBrush(brush->colbrushf);
3907 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
3908 if (surface->num_collisiontriangles)
3909 R_DrawCollisionSurface(ent, surface);
3910 qglPolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR
3913 void R_DrawTrianglesAndNormals(entity_render_t *ent, qboolean drawtris, qboolean drawnormals, int flagsmask)
3916 const int *elements;
3917 msurface_t *surface;
3918 model_t *model = ent->model;
3921 GL_DepthTest(!r_showdisabledepthtest.integer);
3923 GL_BlendFunc(GL_ONE, GL_ZERO);
3924 R_Mesh_ColorPointer(NULL);
3925 R_Mesh_ResetTextureState();
3926 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
3928 if (ent == r_refdef.worldentity && !r_viewcache.world_surfacevisible[j])
3930 rsurface_texture = surface->texture->currentframe;
3931 if ((rsurface_texture->currentmaterialflags & flagsmask) && surface->num_triangles)
3933 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
3936 if (!rsurface_texture->currentlayers->depthmask)
3937 GL_Color(r_showtris.value * r_view.colorscale, 0, 0, 1);
3938 else if (ent == r_refdef.worldentity)
3939 GL_Color(r_showtris.value * r_view.colorscale, r_showtris.value * r_view.colorscale, r_showtris.value * r_view.colorscale, 1);
3941 GL_Color(0, r_showtris.value * r_view.colorscale, 0, 1);
3942 elements = (ent->model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
3945 for (k = 0;k < surface->num_triangles;k++, elements += 3)
3947 qglArrayElement(elements[0]);qglArrayElement(elements[1]);
3948 qglArrayElement(elements[1]);qglArrayElement(elements[2]);
3949 qglArrayElement(elements[2]);qglArrayElement(elements[0]);
3956 GL_Color(r_shownormals.value * r_view.colorscale, 0, 0, 1);
3958 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
3960 VectorCopy(rsurface_vertex3f + l * 3, v);
3961 qglVertex3f(v[0], v[1], v[2]);
3962 VectorMA(v, 8, rsurface_svector3f + l * 3, v);
3963 qglVertex3f(v[0], v[1], v[2]);
3967 GL_Color(0, 0, r_shownormals.value * r_view.colorscale, 1);
3969 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
3971 VectorCopy(rsurface_vertex3f + l * 3, v);
3972 qglVertex3f(v[0], v[1], v[2]);
3973 VectorMA(v, 8, rsurface_tvector3f + l * 3, v);
3974 qglVertex3f(v[0], v[1], v[2]);
3978 GL_Color(0, r_shownormals.value * r_view.colorscale, 0, 1);
3980 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
3982 VectorCopy(rsurface_vertex3f + l * 3, v);
3983 qglVertex3f(v[0], v[1], v[2]);
3984 VectorMA(v, 8, rsurface_normal3f + l * 3, v);
3985 qglVertex3f(v[0], v[1], v[2]);
3992 rsurface_texture = NULL;
3995 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
3996 void R_DrawWorldSurfaces(qboolean skysurfaces)
3998 int i, j, endj, f, flagsmask;
3999 int counttriangles = 0;
4000 msurface_t *surface, **surfacechain;
4002 model_t *model = r_refdef.worldmodel;
4003 const int maxsurfacelist = 1024;
4004 int numsurfacelist = 0;
4005 msurface_t *surfacelist[1024];
4009 RSurf_ActiveWorldEntity();
4011 // update light styles
4012 if (!skysurfaces && model->brushq1.light_styleupdatechains)
4014 for (i = 0;i < model->brushq1.light_styles;i++)
4016 if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
4018 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
4019 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
4020 for (;(surface = *surfacechain);surfacechain++)
4021 surface->cached_dlight = true;
4026 R_UpdateAllTextureInfo(r_refdef.worldentity);
4027 flagsmask = skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL);
4030 rsurface_uselightmaptexture = false;
4031 rsurface_texture = NULL;
4033 j = model->firstmodelsurface;
4034 endj = j + model->nummodelsurfaces;
4037 // quickly skip over non-visible surfaces
4038 for (;j < endj && !r_viewcache.world_surfacevisible[j];j++)
4040 // quickly iterate over visible surfaces
4041 for (;j < endj && r_viewcache.world_surfacevisible[j];j++)
4043 // process this surface
4044 surface = model->data_surfaces + j;
4045 // if this surface fits the criteria, add it to the list
4046 if (surface->num_triangles)
4048 // if lightmap parameters changed, rebuild lightmap texture
4049 if (surface->cached_dlight)
4050 R_BuildLightMap(r_refdef.worldentity, surface);
4051 // add face to draw list
4052 surfacelist[numsurfacelist++] = surface;
4053 counttriangles += surface->num_triangles;
4054 if (numsurfacelist >= maxsurfacelist)
4056 R_QueueSurfaceList(numsurfacelist, surfacelist, flagsmask);
4063 R_QueueSurfaceList(numsurfacelist, surfacelist, flagsmask);
4064 r_refdef.stats.entities_triangles += counttriangles;
4067 if (r_showcollisionbrushes.integer && !skysurfaces)
4068 R_DrawCollisionBrushes(r_refdef.worldentity);
4070 if (r_showtris.integer || r_shownormals.integer)
4071 R_DrawTrianglesAndNormals(r_refdef.worldentity, r_showtris.integer, r_shownormals.integer, flagsmask);
4074 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces)
4076 int i, f, flagsmask;
4077 int counttriangles = 0;
4078 msurface_t *surface, *endsurface, **surfacechain;
4080 model_t *model = ent->model;
4081 const int maxsurfacelist = 1024;
4082 int numsurfacelist = 0;
4083 msurface_t *surfacelist[1024];
4087 // if the model is static it doesn't matter what value we give for
4088 // wantnormals and wanttangents, so this logic uses only rules applicable
4089 // to a model, knowing that they are meaningless otherwise
4090 if (ent == r_refdef.worldentity)
4091 RSurf_ActiveWorldEntity();
4092 else if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
4093 RSurf_ActiveModelEntity(ent, false, false);
4095 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
4097 // update light styles
4098 if (!skysurfaces && model->brushq1.light_styleupdatechains)
4100 for (i = 0;i < model->brushq1.light_styles;i++)
4102 if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
4104 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
4105 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
4106 for (;(surface = *surfacechain);surfacechain++)
4107 surface->cached_dlight = true;
4112 R_UpdateAllTextureInfo(ent);
4113 flagsmask = skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL);
4116 rsurface_uselightmaptexture = false;
4117 rsurface_texture = NULL;
4119 surface = model->data_surfaces + model->firstmodelsurface;
4120 endsurface = surface + model->nummodelsurfaces;
4121 for (;surface < endsurface;surface++)
4123 // if this surface fits the criteria, add it to the list
4124 if (surface->num_triangles)
4126 // if lightmap parameters changed, rebuild lightmap texture
4127 if (surface->cached_dlight)
4128 R_BuildLightMap(ent, surface);
4129 // add face to draw list
4130 surfacelist[numsurfacelist++] = surface;
4131 counttriangles += surface->num_triangles;
4132 if (numsurfacelist >= maxsurfacelist)
4134 R_QueueSurfaceList(numsurfacelist, surfacelist, flagsmask);
4140 R_QueueSurfaceList(numsurfacelist, surfacelist, flagsmask);
4141 r_refdef.stats.entities_triangles += counttriangles;
4144 if (r_showcollisionbrushes.integer && !skysurfaces)
4145 R_DrawCollisionBrushes(ent);
4147 if (r_showtris.integer || r_shownormals.integer)
4148 R_DrawTrianglesAndNormals(ent, r_showtris.integer, r_shownormals.integer, flagsmask);