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\n");
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->flags & RENDER_NOCULLFACE) ? 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->flags & RENDER_NOCULLFACE)
2657 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW;
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_ActiveEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
2857 Matrix4x4_Transform(&ent->inversematrix, r_view.origin, rsurface_modelorg);
2858 rsurface_entity = ent;
2859 rsurface_model = ent->model;
2860 if (rsurface_array_size < rsurface_model->surfmesh.num_vertices)
2861 R_Mesh_ResizeArrays(rsurface_model->surfmesh.num_vertices);
2862 R_Mesh_Matrix(&ent->matrix);
2863 Matrix4x4_Transform(&ent->inversematrix, r_view.origin, rsurface_modelorg);
2864 if (rsurface_model->surfmesh.isanimated && (rsurface_entity->frameblend[0].lerp != 1 || rsurface_entity->frameblend[0].frame != 0))
2868 rsurface_modelvertex3f = rsurface_array_modelvertex3f;
2869 rsurface_modelsvector3f = rsurface_array_modelsvector3f;
2870 rsurface_modeltvector3f = rsurface_array_modeltvector3f;
2871 rsurface_modelnormal3f = rsurface_array_modelnormal3f;
2872 Mod_Alias_GetMesh_Vertices(rsurface_model, rsurface_entity->frameblend, rsurface_array_modelvertex3f, rsurface_array_modelnormal3f, rsurface_array_modelsvector3f, rsurface_array_modeltvector3f);
2874 else if (wantnormals)
2876 rsurface_modelvertex3f = rsurface_array_modelvertex3f;
2877 rsurface_modelsvector3f = NULL;
2878 rsurface_modeltvector3f = NULL;
2879 rsurface_modelnormal3f = rsurface_array_modelnormal3f;
2880 Mod_Alias_GetMesh_Vertices(rsurface_model, rsurface_entity->frameblend, rsurface_array_modelvertex3f, rsurface_array_modelnormal3f, NULL, NULL);
2884 rsurface_modelvertex3f = rsurface_array_modelvertex3f;
2885 rsurface_modelsvector3f = NULL;
2886 rsurface_modeltvector3f = NULL;
2887 rsurface_modelnormal3f = NULL;
2888 Mod_Alias_GetMesh_Vertices(rsurface_model, rsurface_entity->frameblend, rsurface_array_modelvertex3f, NULL, NULL, NULL);
2890 rsurface_generatedvertex = true;
2894 rsurface_modelvertex3f = rsurface_model->surfmesh.data_vertex3f;
2895 rsurface_modelsvector3f = rsurface_model->surfmesh.data_svector3f;
2896 rsurface_modeltvector3f = rsurface_model->surfmesh.data_tvector3f;
2897 rsurface_modelnormal3f = rsurface_model->surfmesh.data_normal3f;
2898 rsurface_generatedvertex = false;
2900 rsurface_vertex3f = rsurface_modelvertex3f;
2901 rsurface_svector3f = rsurface_modelsvector3f;
2902 rsurface_tvector3f = rsurface_modeltvector3f;
2903 rsurface_normal3f = rsurface_modelnormal3f;
2906 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, msurface_t **texturesurfacelist)
2908 // 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
2909 if (rsurface_generatedvertex)
2911 if (rsurface_texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
2912 generatetangents = true;
2913 if (generatetangents)
2914 generatenormals = true;
2915 if (generatenormals && !rsurface_modelnormal3f)
2917 rsurface_normal3f = rsurface_modelnormal3f = rsurface_array_modelnormal3f;
2918 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);
2920 if (generatetangents && !rsurface_modelsvector3f)
2922 rsurface_svector3f = rsurface_modelsvector3f = rsurface_array_modelsvector3f;
2923 rsurface_tvector3f = rsurface_modeltvector3f = rsurface_array_modeltvector3f;
2924 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);
2927 // 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)
2928 if (rsurface_texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
2930 int texturesurfaceindex;
2931 float center[3], forward[3], right[3], up[3], v[4][3];
2932 matrix4x4_t matrix1, imatrix1;
2933 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_view.forward, forward);
2934 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_view.right, right);
2935 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_view.up, up);
2936 // make deformed versions of only the model vertices used by the specified surfaces
2937 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2940 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2941 // a single autosprite surface can contain multiple sprites...
2942 for (j = 0;j < surface->num_vertices - 3;j += 4)
2944 VectorClear(center);
2945 for (i = 0;i < 4;i++)
2946 VectorAdd(center, (rsurface_modelvertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
2947 VectorScale(center, 0.25f, center);
2948 if (rsurface_texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE2)
2950 forward[0] = rsurface_modelorg[0] - center[0];
2951 forward[1] = rsurface_modelorg[1] - center[1];
2953 VectorNormalize(forward);
2954 right[0] = forward[1];
2955 right[1] = -forward[0];
2957 VectorSet(up, 0, 0, 1);
2959 // FIXME: calculate vectors from triangle edges instead of using texture vectors as an easy way out?
2960 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);
2961 Matrix4x4_Invert_Simple(&imatrix1, &matrix1);
2962 for (i = 0;i < 4;i++)
2963 Matrix4x4_Transform(&imatrix1, (rsurface_modelvertex3f + 3 * surface->num_firstvertex) + (j+i)*3, v[i]);
2964 for (i = 0;i < 4;i++)
2965 VectorMAMAMAM(1, center, v[i][0], forward, v[i][1], right, v[i][2], up, rsurface_array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
2967 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);
2968 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);
2970 rsurface_vertex3f = rsurface_array_deformedvertex3f;
2971 rsurface_svector3f = rsurface_array_deformedsvector3f;
2972 rsurface_tvector3f = rsurface_array_deformedtvector3f;
2973 rsurface_normal3f = rsurface_array_deformednormal3f;
2977 rsurface_vertex3f = rsurface_modelvertex3f;
2978 rsurface_svector3f = rsurface_modelsvector3f;
2979 rsurface_tvector3f = rsurface_modeltvector3f;
2980 rsurface_normal3f = rsurface_modelnormal3f;
2982 R_Mesh_VertexPointer(rsurface_vertex3f);
2985 void RSurf_DrawBatch_Simple(int texturenumsurfaces, msurface_t **texturesurfacelist)
2988 const msurface_t *surface = texturesurfacelist[0];
2989 const msurface_t *surface2;
2994 // TODO: lock all array ranges before render, rather than on each surface
2995 if (texturenumsurfaces == 1)
2997 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2998 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
3000 else if (r_batchmode.integer == 2)
3002 #define MAXBATCHTRIANGLES 4096
3003 int batchtriangles = 0;
3004 int batchelements[MAXBATCHTRIANGLES*3];
3005 for (i = 0;i < texturenumsurfaces;i = j)
3007 surface = texturesurfacelist[i];
3009 if (surface->num_triangles > MAXBATCHTRIANGLES)
3011 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
3014 memcpy(batchelements, rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
3015 batchtriangles = surface->num_triangles;
3016 firstvertex = surface->num_firstvertex;
3017 endvertex = surface->num_firstvertex + surface->num_vertices;
3018 for (;j < texturenumsurfaces;j++)
3020 surface2 = texturesurfacelist[j];
3021 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
3023 memcpy(batchelements + batchtriangles * 3, rsurface_model->surfmesh.data_element3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
3024 batchtriangles += surface2->num_triangles;
3025 firstvertex = min(firstvertex, surface2->num_firstvertex);
3026 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
3028 surface2 = texturesurfacelist[j-1];
3029 numvertices = endvertex - firstvertex;
3030 R_Mesh_Draw(firstvertex, numvertices, batchtriangles, batchelements);
3033 else if (r_batchmode.integer == 1)
3035 for (i = 0;i < texturenumsurfaces;i = j)
3037 surface = texturesurfacelist[i];
3038 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
3039 if (texturesurfacelist[j] != surface2)
3041 surface2 = texturesurfacelist[j-1];
3042 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
3043 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
3044 GL_LockArrays(surface->num_firstvertex, numvertices);
3045 R_Mesh_Draw(surface->num_firstvertex, numvertices, numtriangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
3050 for (i = 0;i < texturenumsurfaces;i++)
3052 surface = texturesurfacelist[i];
3053 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
3054 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
3059 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit)
3063 const msurface_t *surface = texturesurfacelist[0];
3064 const msurface_t *surface2;
3069 // TODO: lock all array ranges before render, rather than on each surface
3070 if (texturenumsurfaces == 1)
3072 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
3073 if (deluxemaptexunit >= 0)
3074 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
3075 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
3076 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
3078 else if (r_batchmode.integer == 2)
3080 #define MAXBATCHTRIANGLES 4096
3081 int batchtriangles = 0;
3082 int batchelements[MAXBATCHTRIANGLES*3];
3083 for (i = 0;i < texturenumsurfaces;i = j)
3085 surface = texturesurfacelist[i];
3086 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
3087 if (deluxemaptexunit >= 0)
3088 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
3090 if (surface->num_triangles > MAXBATCHTRIANGLES)
3092 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
3095 memcpy(batchelements, rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
3096 batchtriangles = surface->num_triangles;
3097 firstvertex = surface->num_firstvertex;
3098 endvertex = surface->num_firstvertex + surface->num_vertices;
3099 for (;j < texturenumsurfaces;j++)
3101 surface2 = texturesurfacelist[j];
3102 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
3104 memcpy(batchelements + batchtriangles * 3, rsurface_model->surfmesh.data_element3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
3105 batchtriangles += surface2->num_triangles;
3106 firstvertex = min(firstvertex, surface2->num_firstvertex);
3107 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
3109 surface2 = texturesurfacelist[j-1];
3110 numvertices = endvertex - firstvertex;
3111 R_Mesh_Draw(firstvertex, numvertices, batchtriangles, batchelements);
3114 else if (r_batchmode.integer == 1)
3117 Con_Printf("%s batch sizes ignoring lightmap:", rsurface_texture->name);
3118 for (i = 0;i < texturenumsurfaces;i = j)
3120 surface = texturesurfacelist[i];
3121 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
3122 if (texturesurfacelist[j] != surface2)
3124 Con_Printf(" %i", j - i);
3127 Con_Printf("%s batch sizes honoring lightmap:", rsurface_texture->name);
3129 for (i = 0;i < texturenumsurfaces;i = j)
3131 surface = texturesurfacelist[i];
3132 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
3133 if (deluxemaptexunit >= 0)
3134 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
3135 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
3136 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
3139 Con_Printf(" %i", j - i);
3141 surface2 = texturesurfacelist[j-1];
3142 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
3143 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
3144 GL_LockArrays(surface->num_firstvertex, numvertices);
3145 R_Mesh_Draw(surface->num_firstvertex, numvertices, numtriangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
3153 for (i = 0;i < texturenumsurfaces;i++)
3155 surface = texturesurfacelist[i];
3156 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
3157 if (deluxemaptexunit >= 0)
3158 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
3159 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
3160 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
3165 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
3168 int texturesurfaceindex;
3169 if (r_showsurfaces.integer == 2)
3171 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3173 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3174 for (j = 0;j < surface->num_triangles;j++)
3176 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_view.colorscale;
3177 GL_Color(f, f, f, 1);
3178 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, 1, (rsurface_model->surfmesh.data_element3i + 3 * (j + surface->num_firsttriangle)));
3184 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3186 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3187 int k = (int)(((size_t)surface) / sizeof(msurface_t));
3188 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);
3189 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
3190 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
3195 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, msurface_t **texturesurfacelist)
3197 int texturesurfaceindex;
3201 if (rsurface_lightmapcolor4f)
3203 // generate color arrays for the surfaces in this list
3204 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3206 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3207 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)
3209 f = 1 - VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
3219 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3221 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3222 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)
3224 f = 1 - VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
3232 rsurface_lightmapcolor4f = rsurface_array_color4f;
3235 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a)
3237 int texturesurfaceindex;
3240 if (!rsurface_lightmapcolor4f)
3242 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3244 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3245 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)
3253 rsurface_lightmapcolor4f = rsurface_array_color4f;
3256 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
3259 rsurface_lightmapcolor4f = NULL;
3260 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
3261 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
3262 R_Mesh_ColorPointer(rsurface_lightmapcolor4f);
3263 GL_Color(r, g, b, a);
3264 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 0, -1);
3267 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
3269 // TODO: optimize applyfog && applycolor case
3270 // just apply fog if necessary, and tint the fog color array if necessary
3271 rsurface_lightmapcolor4f = NULL;
3272 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
3273 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
3274 R_Mesh_ColorPointer(rsurface_lightmapcolor4f);
3275 GL_Color(r, g, b, a);
3276 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3279 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
3281 int texturesurfaceindex;
3285 if (texturesurfacelist[0]->lightmapinfo && texturesurfacelist[0]->lightmapinfo->stainsamples)
3287 // generate color arrays for the surfaces in this list
3288 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3290 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3291 for (i = 0, c = rsurface_array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
3293 if (surface->lightmapinfo->samples)
3295 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface_model->surfmesh.data_lightmapoffsets + surface->num_firstvertex)[i];
3296 float scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
3297 VectorScale(lm, scale, c);
3298 if (surface->lightmapinfo->styles[1] != 255)
3300 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
3302 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
3303 VectorMA(c, scale, lm, c);
3304 if (surface->lightmapinfo->styles[2] != 255)
3307 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
3308 VectorMA(c, scale, lm, c);
3309 if (surface->lightmapinfo->styles[3] != 255)
3312 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
3313 VectorMA(c, scale, lm, c);
3323 rsurface_lightmapcolor4f = rsurface_array_color4f;
3326 rsurface_lightmapcolor4f = rsurface_model->surfmesh.data_lightmapcolor4f;
3327 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
3328 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
3329 R_Mesh_ColorPointer(rsurface_lightmapcolor4f);
3330 GL_Color(r, g, b, a);
3331 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3334 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
3336 int texturesurfaceindex;
3340 vec3_t ambientcolor;
3341 vec3_t diffusecolor;
3345 VectorCopy(rsurface_entity->modellight_lightdir, lightdir);
3346 ambientcolor[0] = rsurface_entity->modellight_ambient[0] * r * 0.5f;
3347 ambientcolor[1] = rsurface_entity->modellight_ambient[1] * g * 0.5f;
3348 ambientcolor[2] = rsurface_entity->modellight_ambient[2] * b * 0.5f;
3349 diffusecolor[0] = rsurface_entity->modellight_diffuse[0] * r * 0.5f;
3350 diffusecolor[1] = rsurface_entity->modellight_diffuse[1] * g * 0.5f;
3351 diffusecolor[2] = rsurface_entity->modellight_diffuse[2] * b * 0.5f;
3352 if (VectorLength2(diffusecolor) > 0)
3354 // generate color arrays for the surfaces in this list
3355 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3357 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3358 int numverts = surface->num_vertices;
3359 v = rsurface_vertex3f + 3 * surface->num_firstvertex;
3360 c2 = rsurface_normal3f + 3 * surface->num_firstvertex;
3361 c = rsurface_array_color4f + 4 * surface->num_firstvertex;
3362 // q3-style directional shading
3363 for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
3365 if ((f = DotProduct(c2, lightdir)) > 0)
3366 VectorMA(ambientcolor, f, diffusecolor, c);
3368 VectorCopy(ambientcolor, c);
3377 rsurface_lightmapcolor4f = rsurface_array_color4f;
3381 r = ambientcolor[0];
3382 g = ambientcolor[1];
3383 b = ambientcolor[2];
3384 rsurface_lightmapcolor4f = NULL;
3386 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
3387 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
3388 R_Mesh_ColorPointer(rsurface_lightmapcolor4f);
3389 GL_Color(r, g, b, a);
3390 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3393 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
3395 GL_DepthTest(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
3396 GL_CullFace(((rsurface_texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (rsurface_entity->flags & RENDER_NOCULLFACE)) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
3397 if (rsurface_mode != RSURFMODE_SHOWSURFACES)
3399 rsurface_mode = RSURFMODE_SHOWSURFACES;
3401 GL_BlendFunc(GL_ONE, GL_ZERO);
3402 R_Mesh_ColorPointer(NULL);
3403 R_Mesh_ResetTextureState();
3405 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
3406 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
3409 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, msurface_t **texturesurfacelist)
3411 // transparent sky would be ridiculous
3412 if ((rsurface_texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
3414 if (rsurface_mode != RSURFMODE_SKY)
3416 if (rsurface_mode == RSURFMODE_GLSL)
3418 qglUseProgramObjectARB(0);CHECKGLERROR
3420 rsurface_mode = RSURFMODE_SKY;
3424 skyrendernow = false;
3426 // restore entity matrix
3427 R_Mesh_Matrix(&rsurface_entity->matrix);
3429 GL_DepthTest(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
3430 GL_CullFace(((rsurface_texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (rsurface_entity->flags & RENDER_NOCULLFACE)) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
3432 // LordHavoc: HalfLife maps have freaky skypolys so don't use
3433 // skymasking on them, and Quake3 never did sky masking (unlike
3434 // software Quake and software Quake2), so disable the sky masking
3435 // in Quake3 maps as it causes problems with q3map2 sky tricks,
3436 // and skymasking also looks very bad when noclipping outside the
3437 // level, so don't use it then either.
3438 if (rsurface_model->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_viewcache.world_novis)
3440 GL_Color(r_refdef.fogcolor[0] * r_view.colorscale, r_refdef.fogcolor[1] * r_view.colorscale, r_refdef.fogcolor[2] * r_view.colorscale, 1);
3441 R_Mesh_ColorPointer(NULL);
3442 R_Mesh_ResetTextureState();
3443 if (skyrendermasked)
3445 // depth-only (masking)
3446 GL_ColorMask(0,0,0,0);
3447 // just to make sure that braindead drivers don't draw
3448 // anything despite that colormask...
3449 GL_BlendFunc(GL_ZERO, GL_ONE);
3454 GL_BlendFunc(GL_ONE, GL_ZERO);
3456 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
3457 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3458 if (skyrendermasked)
3459 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
3463 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, msurface_t **texturesurfacelist)
3465 if (rsurface_mode != RSURFMODE_GLSL)
3467 rsurface_mode = RSURFMODE_GLSL;
3468 R_Mesh_ResetTextureState();
3471 R_SetupSurfaceShader(vec3_origin, rsurface_lightmode == 2);
3472 if (!r_glsl_permutation)
3475 if (rsurface_lightmode == 2)
3476 RSurf_PrepareVerticesForBatch(true, r_glsl_permutation->loc_Texture_Normal, texturenumsurfaces, texturesurfacelist);
3478 RSurf_PrepareVerticesForBatch(r_glsl_permutation->loc_Texture_Normal, r_glsl_permutation->loc_Texture_Normal, texturenumsurfaces, texturesurfacelist);
3479 R_Mesh_TexCoordPointer(0, 2, rsurface_model->surfmesh.data_texcoordtexture2f);
3480 R_Mesh_TexCoordPointer(1, 3, rsurface_svector3f);
3481 R_Mesh_TexCoordPointer(2, 3, rsurface_tvector3f);
3482 R_Mesh_TexCoordPointer(3, 3, rsurface_normal3f);
3483 R_Mesh_TexCoordPointer(4, 2, rsurface_model->surfmesh.data_texcoordlightmap2f);
3485 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
3487 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
3488 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
3489 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
3490 R_Mesh_ColorPointer(NULL);
3492 else if (rsurface_uselightmaptexture)
3494 R_Mesh_TexBind(7, R_GetTexture(texturesurfacelist[0]->lightmaptexture));
3495 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
3496 R_Mesh_TexBind(8, R_GetTexture(texturesurfacelist[0]->deluxemaptexture));
3497 R_Mesh_ColorPointer(NULL);
3501 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
3502 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
3503 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
3504 R_Mesh_ColorPointer(rsurface_model->surfmesh.data_lightmapcolor4f);
3507 if (rsurface_uselightmaptexture && !(rsurface_texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
3508 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 7, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? 8 : -1);
3510 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3511 if (rsurface_texture->backgroundnumskinframes && !(rsurface_texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
3516 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, msurface_t **texturesurfacelist)
3518 // OpenGL 1.3 path - anything not completely ancient
3519 int texturesurfaceindex;
3520 qboolean applycolor;
3524 const texturelayer_t *layer;
3525 if (rsurface_mode != RSURFMODE_MULTIPASS)
3526 rsurface_mode = RSURFMODE_MULTIPASS;
3527 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
3528 for (layerindex = 0, layer = rsurface_texture->currentlayers;layerindex < rsurface_texture->currentnumlayers;layerindex++, layer++)
3531 int layertexrgbscale;
3532 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
3534 if (layerindex == 0)
3538 GL_AlphaTest(false);
3539 qglDepthFunc(GL_EQUAL);CHECKGLERROR
3542 GL_DepthMask(layer->depthmask);
3543 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
3544 if ((layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2) && (gl_combine.integer || layer->depthmask))
3546 layertexrgbscale = 4;
3547 VectorScale(layer->color, 0.25f, layercolor);
3549 else if ((layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1) && (gl_combine.integer || layer->depthmask))
3551 layertexrgbscale = 2;
3552 VectorScale(layer->color, 0.5f, layercolor);
3556 layertexrgbscale = 1;
3557 VectorScale(layer->color, 1.0f, layercolor);
3559 layercolor[3] = layer->color[3];
3560 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
3561 R_Mesh_ColorPointer(NULL);
3562 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
3563 switch (layer->type)
3565 case TEXTURELAYERTYPE_LITTEXTURE:
3566 memset(&m, 0, sizeof(m));
3567 m.tex[0] = R_GetTexture(r_texture_white);
3568 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordlightmap2f;
3569 m.tex[1] = R_GetTexture(layer->texture);
3570 m.texmatrix[1] = layer->texmatrix;
3571 m.texrgbscale[1] = layertexrgbscale;
3572 m.pointer_texcoord[1] = rsurface_model->surfmesh.data_texcoordtexture2f;
3573 R_Mesh_TextureState(&m);
3574 if (rsurface_lightmode == 2)
3575 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
3576 else if (rsurface_uselightmaptexture)
3577 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
3579 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
3581 case TEXTURELAYERTYPE_TEXTURE:
3582 memset(&m, 0, sizeof(m));
3583 m.tex[0] = R_GetTexture(layer->texture);
3584 m.texmatrix[0] = layer->texmatrix;
3585 m.texrgbscale[0] = layertexrgbscale;
3586 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3587 R_Mesh_TextureState(&m);
3588 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
3590 case TEXTURELAYERTYPE_FOG:
3591 memset(&m, 0, sizeof(m));
3592 m.texrgbscale[0] = layertexrgbscale;
3595 m.tex[0] = R_GetTexture(layer->texture);
3596 m.texmatrix[0] = layer->texmatrix;
3597 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3599 R_Mesh_TextureState(&m);
3600 // generate a color array for the fog pass
3601 R_Mesh_ColorPointer(rsurface_array_color4f);
3602 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3606 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3607 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)
3609 f = VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
3610 c[0] = layercolor[0];
3611 c[1] = layercolor[1];
3612 c[2] = layercolor[2];
3613 c[3] = f * layercolor[3];
3616 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3619 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
3621 GL_LockArrays(0, 0);
3624 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
3626 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3627 GL_AlphaTest(false);
3631 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, msurface_t **texturesurfacelist)
3633 // OpenGL 1.1 - crusty old voodoo path
3634 int texturesurfaceindex;
3638 const texturelayer_t *layer;
3639 if (rsurface_mode != RSURFMODE_MULTIPASS)
3640 rsurface_mode = RSURFMODE_MULTIPASS;
3641 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
3642 for (layerindex = 0, layer = rsurface_texture->currentlayers;layerindex < rsurface_texture->currentnumlayers;layerindex++, layer++)
3644 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
3646 if (layerindex == 0)
3650 GL_AlphaTest(false);
3651 qglDepthFunc(GL_EQUAL);CHECKGLERROR
3654 GL_DepthMask(layer->depthmask);
3655 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
3656 R_Mesh_ColorPointer(NULL);
3657 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
3658 switch (layer->type)
3660 case TEXTURELAYERTYPE_LITTEXTURE:
3661 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
3663 // two-pass lit texture with 2x rgbscale
3664 // first the lightmap pass
3665 memset(&m, 0, sizeof(m));
3666 m.tex[0] = R_GetTexture(r_texture_white);
3667 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordlightmap2f;
3668 R_Mesh_TextureState(&m);
3669 if (rsurface_lightmode == 2)
3670 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
3671 else if (rsurface_uselightmaptexture)
3672 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
3674 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
3675 GL_LockArrays(0, 0);
3676 // then apply the texture to it
3677 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
3678 memset(&m, 0, sizeof(m));
3679 m.tex[0] = R_GetTexture(layer->texture);
3680 m.texmatrix[0] = layer->texmatrix;
3681 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3682 R_Mesh_TextureState(&m);
3683 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);
3687 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
3688 memset(&m, 0, sizeof(m));
3689 m.tex[0] = R_GetTexture(layer->texture);
3690 m.texmatrix[0] = layer->texmatrix;
3691 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3692 R_Mesh_TextureState(&m);
3693 if (rsurface_lightmode == 2)
3694 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);
3696 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);
3699 case TEXTURELAYERTYPE_TEXTURE:
3700 // singletexture unlit texture with transparency support
3701 memset(&m, 0, sizeof(m));
3702 m.tex[0] = R_GetTexture(layer->texture);
3703 m.texmatrix[0] = layer->texmatrix;
3704 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3705 R_Mesh_TextureState(&m);
3706 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);
3708 case TEXTURELAYERTYPE_FOG:
3709 // singletexture fogging
3710 R_Mesh_ColorPointer(rsurface_array_color4f);
3713 memset(&m, 0, sizeof(m));
3714 m.tex[0] = R_GetTexture(layer->texture);
3715 m.texmatrix[0] = layer->texmatrix;
3716 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3717 R_Mesh_TextureState(&m);
3720 R_Mesh_ResetTextureState();
3721 // generate a color array for the fog pass
3722 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3726 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3727 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)
3729 f = VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
3730 c[0] = layer->color[0];
3731 c[1] = layer->color[1];
3732 c[2] = layer->color[2];
3733 c[3] = f * layer->color[3];
3736 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3739 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
3741 GL_LockArrays(0, 0);
3744 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
3746 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3747 GL_AlphaTest(false);
3751 static void R_DrawTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist)
3753 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_NODRAW)
3755 r_shadow_rtlight = NULL;
3756 r_refdef.stats.entities_surfaces += texturenumsurfaces;
3758 if (r_showsurfaces.integer)
3759 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
3760 else if (rsurface_texture->currentmaterialflags & MATERIALFLAG_SKY)
3761 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
3762 else if (rsurface_texture->currentnumlayers)
3764 GL_DepthTest(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
3765 GL_CullFace(((rsurface_texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (rsurface_entity->flags & RENDER_NOCULLFACE)) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
3766 GL_BlendFunc(rsurface_texture->currentlayers[0].blendfunc1, rsurface_texture->currentlayers[0].blendfunc2);
3767 GL_DepthMask(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_BLENDED));
3768 GL_Color(rsurface_entity->colormod[0], rsurface_entity->colormod[1], rsurface_entity->colormod[2], rsurface_texture->currentalpha);
3769 GL_AlphaTest((rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
3770 // FIXME: identify models using a better check than rsurface_model->brush.shadowmesh
3771 rsurface_lightmode = ((rsurface_texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT) || rsurface_model->brush.shadowmesh) ? 0 : 2;
3772 if (r_glsl.integer && gl_support_fragment_shader)
3773 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist);
3774 else if (gl_combine.integer && r_textureunits.integer >= 2)
3775 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist);
3777 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist);
3780 GL_LockArrays(0, 0);
3783 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
3786 int texturenumsurfaces, endsurface;
3788 msurface_t *surface;
3789 msurface_t *texturesurfacelist[1024];
3791 // if the model is static it doesn't matter what value we give for
3792 // wantnormals and wanttangents, so this logic uses only rules applicable
3793 // to a model, knowing that they are meaningless otherwise
3794 if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
3795 RSurf_ActiveEntity(ent, false, false);
3797 RSurf_ActiveEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
3799 for (i = 0;i < numsurfaces;i = j)
3802 surface = rsurface_model->data_surfaces + surfacelist[i];
3803 texture = surface->texture;
3804 rsurface_texture = texture->currentframe;
3805 rsurface_uselightmaptexture = surface->lightmaptexture != NULL;
3806 // scan ahead until we find a different texture
3807 endsurface = min(i + 1024, numsurfaces);
3808 texturenumsurfaces = 0;
3809 texturesurfacelist[texturenumsurfaces++] = surface;
3810 for (;j < endsurface;j++)
3812 surface = rsurface_model->data_surfaces + surfacelist[j];
3813 if (texture != surface->texture || rsurface_uselightmaptexture != (surface->lightmaptexture != NULL))
3815 texturesurfacelist[texturenumsurfaces++] = surface;
3817 // render the range of surfaces
3818 R_DrawTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
3824 void R_QueueSurfaceList(int numsurfaces, msurface_t **surfacelist)
3827 vec3_t tempcenter, center;
3829 // break the surface list down into batches by texture and use of lightmapping
3830 for (i = 0;i < numsurfaces;i = j)
3833 // texture is the base texture pointer, rsurface_texture is the
3834 // current frame/skin the texture is directing us to use (for example
3835 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
3836 // use skin 1 instead)
3837 texture = surfacelist[i]->texture;
3838 rsurface_texture = texture->currentframe;
3839 rsurface_uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
3840 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_BLENDED)
3842 // transparent surfaces get pushed off into the transparent queue
3843 const msurface_t *surface = surfacelist[i];
3844 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
3845 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
3846 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
3847 Matrix4x4_Transform(&rsurface_entity->matrix, tempcenter, center);
3848 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);
3852 // simply scan ahead until we find a different texture
3853 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface_uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++);
3854 // render the range of surfaces
3855 R_DrawTextureSurfaceList(j - i, surfacelist + i);
3860 void R_DrawCollisionBrushes(entity_render_t *ent)
3864 msurface_t *surface;
3865 model_t *model = ent->model;
3866 if (!model->brush.num_brushes)
3869 R_Mesh_ColorPointer(NULL);
3870 R_Mesh_ResetTextureState();
3871 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
3872 GL_DepthMask(false);
3873 GL_DepthTest(!r_showdisabledepthtest.integer);
3874 qglPolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);CHECKGLERROR
3875 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
3876 if (brush->colbrushf && brush->colbrushf->numtriangles)
3877 R_DrawCollisionBrush(brush->colbrushf);
3878 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
3879 if (surface->num_collisiontriangles)
3880 R_DrawCollisionSurface(ent, surface);
3881 qglPolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR
3884 void R_DrawTrianglesAndNormals(entity_render_t *ent, qboolean drawtris, qboolean drawnormals, int flagsmask)
3887 const int *elements;
3888 msurface_t *surface;
3889 model_t *model = ent->model;
3892 GL_DepthTest(!r_showdisabledepthtest.integer);
3894 GL_BlendFunc(GL_ONE, GL_ZERO);
3895 R_Mesh_ColorPointer(NULL);
3896 R_Mesh_ResetTextureState();
3897 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
3899 if (ent == r_refdef.worldentity && !r_viewcache.world_surfacevisible[j])
3901 rsurface_texture = surface->texture->currentframe;
3902 if ((rsurface_texture->currentmaterialflags & flagsmask) && surface->num_triangles)
3904 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
3907 if (!rsurface_texture->currentlayers->depthmask)
3908 GL_Color(r_showtris.value * r_view.colorscale, 0, 0, 1);
3909 else if (ent == r_refdef.worldentity)
3910 GL_Color(r_showtris.value * r_view.colorscale, r_showtris.value * r_view.colorscale, r_showtris.value * r_view.colorscale, 1);
3912 GL_Color(0, r_showtris.value * r_view.colorscale, 0, 1);
3913 elements = (ent->model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
3916 for (k = 0;k < surface->num_triangles;k++, elements += 3)
3918 qglArrayElement(elements[0]);qglArrayElement(elements[1]);
3919 qglArrayElement(elements[1]);qglArrayElement(elements[2]);
3920 qglArrayElement(elements[2]);qglArrayElement(elements[0]);
3927 GL_Color(r_shownormals.value * r_view.colorscale, 0, 0, 1);
3929 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
3931 VectorCopy(rsurface_vertex3f + l * 3, v);
3932 qglVertex3f(v[0], v[1], v[2]);
3933 VectorMA(v, 8, rsurface_svector3f + l * 3, v);
3934 qglVertex3f(v[0], v[1], v[2]);
3938 GL_Color(0, 0, r_shownormals.value * r_view.colorscale, 1);
3940 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
3942 VectorCopy(rsurface_vertex3f + l * 3, v);
3943 qglVertex3f(v[0], v[1], v[2]);
3944 VectorMA(v, 8, rsurface_tvector3f + l * 3, v);
3945 qglVertex3f(v[0], v[1], v[2]);
3949 GL_Color(0, r_shownormals.value * r_view.colorscale, 0, 1);
3951 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
3953 VectorCopy(rsurface_vertex3f + l * 3, v);
3954 qglVertex3f(v[0], v[1], v[2]);
3955 VectorMA(v, 8, rsurface_normal3f + l * 3, v);
3956 qglVertex3f(v[0], v[1], v[2]);
3963 rsurface_texture = NULL;
3966 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
3967 void R_DrawSurfaces(entity_render_t *ent, qboolean skysurfaces)
3969 int i, j, endj, f, flagsmask;
3970 int counttriangles = 0;
3971 msurface_t *surface, *endsurface, **surfacechain;
3973 model_t *model = ent->model;
3974 const int maxsurfacelist = 1024;
3975 int numsurfacelist = 0;
3976 msurface_t *surfacelist[1024];
3980 // if the model is static it doesn't matter what value we give for
3981 // wantnormals and wanttangents, so this logic uses only rules applicable
3982 // to a model, knowing that they are meaningless otherwise
3983 if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
3984 RSurf_ActiveEntity(ent, false, false);
3986 RSurf_ActiveEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
3988 // update light styles
3989 if (!skysurfaces && model->brushq1.light_styleupdatechains)
3991 for (i = 0;i < model->brushq1.light_styles;i++)
3993 if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
3995 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
3996 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
3997 for (;(surface = *surfacechain);surfacechain++)
3998 surface->cached_dlight = true;
4003 R_UpdateAllTextureInfo(ent);
4004 flagsmask = skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL);
4007 rsurface_uselightmaptexture = false;
4008 rsurface_texture = NULL;
4010 if (ent == r_refdef.worldentity)
4012 j = model->firstmodelsurface;
4013 endj = j + model->nummodelsurfaces;
4016 // quickly skip over non-visible surfaces
4017 for (;j < endj && !r_viewcache.world_surfacevisible[j];j++)
4019 // quickly iterate over visible surfaces
4020 for (;j < endj && r_viewcache.world_surfacevisible[j];j++)
4022 // process this surface
4023 surface = model->data_surfaces + j;
4024 // if this surface fits the criteria, add it to the list
4025 if (surface->texture->basematerialflags & flagsmask && surface->num_triangles)
4027 // if lightmap parameters changed, rebuild lightmap texture
4028 if (surface->cached_dlight)
4029 R_BuildLightMap(ent, surface);
4030 // add face to draw list
4031 surfacelist[numsurfacelist++] = surface;
4032 counttriangles += surface->num_triangles;
4033 if (numsurfacelist >= maxsurfacelist)
4035 R_QueueSurfaceList(numsurfacelist, surfacelist);
4044 surface = model->data_surfaces + model->firstmodelsurface;
4045 endsurface = surface + model->nummodelsurfaces;
4046 for (;surface < endsurface;surface++)
4048 // if this surface fits the criteria, add it to the list
4049 if (surface->texture->basematerialflags & flagsmask && surface->num_triangles)
4051 // if lightmap parameters changed, rebuild lightmap texture
4052 if (surface->cached_dlight)
4053 R_BuildLightMap(ent, surface);
4054 // add face to draw list
4055 surfacelist[numsurfacelist++] = surface;
4056 counttriangles += surface->num_triangles;
4057 if (numsurfacelist >= maxsurfacelist)
4059 R_QueueSurfaceList(numsurfacelist, surfacelist);
4066 R_QueueSurfaceList(numsurfacelist, surfacelist);
4067 r_refdef.stats.entities_triangles += counttriangles;
4070 if (r_showcollisionbrushes.integer && !skysurfaces)
4071 R_DrawCollisionBrushes(ent);
4073 if (r_showtris.integer || r_shownormals.integer)
4074 R_DrawTrianglesAndNormals(ent, r_showtris.integer, r_shownormals.integer, flagsmask);