2 Copyright (C) 1996-1997 Id Software, Inc.
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26 mempool_t *r_main_mempool;
27 rtexturepool_t *r_main_texturepool;
34 r_viewcache_t r_viewcache;
36 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
37 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
38 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
39 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
40 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
41 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
42 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
43 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
44 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
45 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
46 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
47 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
48 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
49 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
50 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling"};
51 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
52 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
53 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
54 cvar_t r_fullbright = {0, "r_fullbright","0", "make everything bright cheat (not allowed in multiplayer)"};
55 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
56 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
57 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
58 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this)"};
59 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
60 cvar_t r_q1bsp_skymasking = {0, "r_qb1sp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
62 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
63 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
64 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
65 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
66 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
67 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
68 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
70 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of hardware texture units reported by driver (note: setting this to 1 turns off gl_combine)"};
72 cvar_t r_glsl = {0, "r_glsl", "1", "enables use of OpenGL 2.0 pixel shaders for lighting"};
73 cvar_t r_glsl_offsetmapping = {0, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
74 cvar_t r_glsl_offsetmapping_reliefmapping = {0, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
75 cvar_t r_glsl_offsetmapping_scale = {0, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
76 cvar_t r_glsl_deluxemapping = {0, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"};
78 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1", "enables animation smoothing on sprites (requires r_lerpmodels 1)"};
79 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
80 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
82 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
83 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
84 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
85 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
86 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
87 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
88 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
90 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
91 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
92 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
93 cvar_t r_hdr_range = {CVAR_SAVE, "r_hdr_range", "4", "how much dynamic range to render bloom with (equivilant to multiplying r_bloom_brighten by this value and dividing r_bloom_colorscale by this value)"};
95 cvar_t r_smoothnormals_areaweighting = {0, "r_smoothnormals_areaweighting", "1", "uses significantly faster (and supposedly higher quality) area-weighted vertex normals and tangent vectors rather than summing normalized triangle normals and tangents"};
97 cvar_t developer_texturelogging = {0, "developer_texturelogging", "0", "produces a textures.log file containing names of skins and map textures the engine tried to load"};
99 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
101 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"}; // used for testing renderer code changes, otherwise does nothing
102 cvar_t r_batchmode = {0, "r_batchmode", "1", "selects method of rendering multiple surfaces with one driver call (values are 0, 1, 2, etc...)"};
104 typedef struct r_glsl_bloomshader_s
107 int loc_Texture_Bloom;
109 r_glsl_bloomshader_t;
111 static struct r_bloomstate_s
116 int bloomwidth, bloomheight;
118 int screentexturewidth, screentextureheight;
119 rtexture_t *texture_screen;
121 int bloomtexturewidth, bloomtextureheight;
122 rtexture_t *texture_bloom;
124 r_glsl_bloomshader_t *shader;
126 // arrays for rendering the screen passes
127 float screentexcoord2f[8];
128 float bloomtexcoord2f[8];
129 float offsettexcoord2f[8];
133 // shadow volume bsp struct with automatically growing nodes buffer
136 rtexture_t *r_texture_blanknormalmap;
137 rtexture_t *r_texture_white;
138 rtexture_t *r_texture_black;
139 rtexture_t *r_texture_notexture;
140 rtexture_t *r_texture_whitecube;
141 rtexture_t *r_texture_normalizationcube;
142 rtexture_t *r_texture_fogattenuation;
143 //rtexture_t *r_texture_fogintensity;
145 // information about each possible shader permutation
146 r_glsl_permutation_t r_glsl_permutations[SHADERPERMUTATION_COUNT];
147 // currently selected permutation
148 r_glsl_permutation_t *r_glsl_permutation;
150 // temporary variable used by a macro
153 // vertex coordinates for a quad that covers the screen exactly
154 const static float r_screenvertex3f[12] =
162 extern void R_DrawModelShadows(void);
164 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
167 for (i = 0;i < verts;i++)
178 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
181 for (i = 0;i < verts;i++)
191 // FIXME: move this to client?
194 if (gamemode == GAME_NEHAHRA)
196 Cvar_Set("gl_fogenable", "0");
197 Cvar_Set("gl_fogdensity", "0.2");
198 Cvar_Set("gl_fogred", "0.3");
199 Cvar_Set("gl_foggreen", "0.3");
200 Cvar_Set("gl_fogblue", "0.3");
202 r_refdef.fog_density = r_refdef.fog_red = r_refdef.fog_green = r_refdef.fog_blue = 0.0f;
205 // FIXME: move this to client?
206 void FOG_registercvars(void)
211 if (gamemode == GAME_NEHAHRA)
213 Cvar_RegisterVariable (&gl_fogenable);
214 Cvar_RegisterVariable (&gl_fogdensity);
215 Cvar_RegisterVariable (&gl_fogred);
216 Cvar_RegisterVariable (&gl_foggreen);
217 Cvar_RegisterVariable (&gl_fogblue);
218 Cvar_RegisterVariable (&gl_fogstart);
219 Cvar_RegisterVariable (&gl_fogend);
222 r = (-1.0/256.0) * (FOGTABLEWIDTH * FOGTABLEWIDTH);
223 for (x = 0;x < FOGTABLEWIDTH;x++)
225 alpha = exp(r / ((double)x*(double)x));
226 if (x == FOGTABLEWIDTH - 1)
228 r_refdef.fogtable[x] = bound(0, alpha, 1);
232 static void R_BuildBlankTextures(void)
234 unsigned char data[4];
235 data[0] = 128; // normal X
236 data[1] = 128; // normal Y
237 data[2] = 255; // normal Z
238 data[3] = 128; // height
239 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
244 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
249 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
252 static void R_BuildNoTexture(void)
255 unsigned char pix[16][16][4];
256 // this makes a light grey/dark grey checkerboard texture
257 for (y = 0;y < 16;y++)
259 for (x = 0;x < 16;x++)
261 if ((y < 8) ^ (x < 8))
277 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_RGBA, TEXF_MIPMAP, NULL);
280 static void R_BuildWhiteCube(void)
282 unsigned char data[6*1*1*4];
283 data[ 0] = 255;data[ 1] = 255;data[ 2] = 255;data[ 3] = 255;
284 data[ 4] = 255;data[ 5] = 255;data[ 6] = 255;data[ 7] = 255;
285 data[ 8] = 255;data[ 9] = 255;data[10] = 255;data[11] = 255;
286 data[12] = 255;data[13] = 255;data[14] = 255;data[15] = 255;
287 data[16] = 255;data[17] = 255;data[18] = 255;data[19] = 255;
288 data[20] = 255;data[21] = 255;data[22] = 255;data[23] = 255;
289 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
292 static void R_BuildNormalizationCube(void)
296 vec_t s, t, intensity;
298 unsigned char data[6][NORMSIZE][NORMSIZE][4];
299 for (side = 0;side < 6;side++)
301 for (y = 0;y < NORMSIZE;y++)
303 for (x = 0;x < NORMSIZE;x++)
305 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
306 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
341 intensity = 127.0f / sqrt(DotProduct(v, v));
342 data[side][y][x][0] = (unsigned char)(128.0f + intensity * v[0]);
343 data[side][y][x][1] = (unsigned char)(128.0f + intensity * v[1]);
344 data[side][y][x][2] = (unsigned char)(128.0f + intensity * v[2]);
345 data[side][y][x][3] = 255;
349 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, &data[0][0][0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
352 static void R_BuildFogTexture(void)
357 unsigned char data1[FOGWIDTH][4];
358 //unsigned char data2[FOGWIDTH][4];
359 r = (-1.0/256.0) * (FOGWIDTH * FOGWIDTH);
360 for (x = 0;x < FOGWIDTH;x++)
362 alpha = exp(r / ((double)x*(double)x));
363 if (x == FOGWIDTH - 1)
365 b = (int)(256.0 * alpha);
366 b = bound(0, b, 255);
367 data1[x][0] = 255 - b;
368 data1[x][1] = 255 - b;
369 data1[x][2] = 255 - b;
376 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
377 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
380 static const char *builtinshaderstring =
381 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
382 "// written by Forest 'LordHavoc' Hale\n"
384 "// common definitions between vertex shader and fragment shader:\n"
386 "#ifdef __GLSL_CG_DATA_TYPES\n"
387 "#define myhalf half\n"
388 "#define myhvec2 hvec2\n"
389 "#define myhvec3 hvec3\n"
390 "#define myhvec4 hvec4\n"
392 "#define myhalf float\n"
393 "#define myhvec2 vec2\n"
394 "#define myhvec3 vec3\n"
395 "#define myhvec4 vec4\n"
398 "varying vec2 TexCoord;\n"
399 "varying vec2 TexCoordLightmap;\n"
401 "varying vec3 CubeVector;\n"
402 "varying vec3 LightVector;\n"
403 "varying vec3 EyeVector;\n"
405 "varying vec3 EyeVectorModelSpace;\n"
408 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
409 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
410 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
415 "// vertex shader specific:\n"
416 "#ifdef VERTEX_SHADER\n"
418 "uniform vec3 LightPosition;\n"
419 "uniform vec3 EyePosition;\n"
420 "uniform vec3 LightDir;\n"
422 "// TODO: get rid of tangentt (texcoord2) and use a crossproduct to regenerate it from tangents (texcoord1) and normal (texcoord3)\n"
426 " gl_FrontColor = gl_Color;\n"
427 " // copy the surface texcoord\n"
428 " TexCoord = vec2(gl_TextureMatrix[0] * gl_MultiTexCoord0);\n"
429 "#if !defined(MODE_LIGHTSOURCE) && !defined(MODE_LIGHTDIRECTION)\n"
430 " TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
433 "#ifdef MODE_LIGHTSOURCE\n"
434 " // transform vertex position into light attenuation/cubemap space\n"
435 " // (-1 to +1 across the light box)\n"
436 " CubeVector = vec3(gl_TextureMatrix[3] * gl_Vertex);\n"
438 " // transform unnormalized light direction into tangent space\n"
439 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
440 " // normalize it per pixel)\n"
441 " vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
442 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
443 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
444 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
447 "#ifdef MODE_LIGHTDIRECTION\n"
448 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
449 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
450 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
453 " // transform unnormalized eye direction into tangent space\n"
455 " vec3 EyeVectorModelSpace;\n"
457 " EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
458 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
459 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
460 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
462 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
463 " VectorS = gl_MultiTexCoord1.xyz;\n"
464 " VectorT = gl_MultiTexCoord2.xyz;\n"
465 " VectorR = gl_MultiTexCoord3.xyz;\n"
468 " // transform vertex to camera space, using ftransform to match non-VS\n"
470 " gl_Position = ftransform();\n"
473 "#endif // VERTEX_SHADER\n"
478 "// fragment shader specific:\n"
479 "#ifdef FRAGMENT_SHADER\n"
481 "uniform sampler2D Texture_Normal;\n"
482 "uniform sampler2D Texture_Color;\n"
483 "uniform sampler2D Texture_Gloss;\n"
484 "uniform samplerCube Texture_Cube;\n"
485 "uniform sampler2D Texture_FogMask;\n"
486 "uniform sampler2D Texture_Pants;\n"
487 "uniform sampler2D Texture_Shirt;\n"
488 "uniform sampler2D Texture_Lightmap;\n"
489 "uniform sampler2D Texture_Deluxemap;\n"
490 "uniform sampler2D Texture_Glow;\n"
492 "uniform myhvec3 LightColor;\n"
493 "uniform myhvec3 AmbientColor;\n"
494 "uniform myhvec3 DiffuseColor;\n"
495 "uniform myhvec3 SpecularColor;\n"
496 "uniform myhvec3 Color_Pants;\n"
497 "uniform myhvec3 Color_Shirt;\n"
498 "uniform myhvec3 FogColor;\n"
500 "uniform myhalf GlowScale;\n"
501 "uniform myhalf SceneBrightness;\n"
503 "uniform float OffsetMapping_Scale;\n"
504 "uniform float OffsetMapping_Bias;\n"
505 "uniform float FogRangeRecip;\n"
507 "uniform myhalf AmbientScale;\n"
508 "uniform myhalf DiffuseScale;\n"
509 "uniform myhalf SpecularScale;\n"
510 "uniform myhalf SpecularPower;\n"
514 " // apply offsetmapping\n"
515 "#ifdef USEOFFSETMAPPING\n"
516 " vec2 TexCoordOffset = TexCoord;\n"
517 "#define TexCoord TexCoordOffset\n"
519 " vec3 eyedir = vec3(normalize(EyeVector));\n"
520 " float depthbias = 1.0 - eyedir.z; // should this be a -?\n"
521 " depthbias = 1.0 - depthbias * depthbias;\n"
523 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
524 " // 14 sample relief mapping: linear search and then binary search\n"
525 " //vec3 OffsetVector = vec3(EyeVector.xy * (1.0 / EyeVector.z) * depthbias * OffsetMapping_Scale * vec2(-0.1, 0.1), -0.1);\n"
526 " //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-0.1, 0.1), -0.1);\n"
527 " vec3 OffsetVector = vec3(eyedir.xy * OffsetMapping_Scale * vec2(-0.1, 0.1), -0.1);\n"
528 " vec3 RT = vec3(TexCoord - OffsetVector.xy * 10.0, 1.0) + OffsetVector;\n"
529 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
530 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
531 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
532 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
533 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
534 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
535 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
536 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
537 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;OffsetVector *= 0.5;RT -= OffsetVector;\n"
538 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;OffsetVector *= 0.5;RT -= OffsetVector;\n"
539 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;OffsetVector *= 0.5;RT -= OffsetVector;\n"
540 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;OffsetVector *= 0.5;RT -= OffsetVector;\n"
541 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;OffsetVector *= 0.5;RT -= OffsetVector;\n"
542 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;OffsetVector *= 0.5;RT -= OffsetVector;\n"
543 " TexCoord = RT.xy;\n"
545 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
546 " //vec2 OffsetVector = vec2(EyeVector.xy * (1.0 / EyeVector.z) * depthbias) * OffsetMapping_Scale * vec2(-0.333, 0.333);\n"
547 " //vec2 OffsetVector = vec2(normalize(EyeVector.xy)) * OffsetMapping_Scale * vec2(-0.333, 0.333);\n"
548 " vec2 OffsetVector = vec2(eyedir.xy) * OffsetMapping_Scale * vec2(-0.333, 0.333);\n"
549 " //TexCoord += OffsetVector * 3.0;\n"
550 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
551 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
552 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
554 " // 10 sample offset mapping\n"
555 " //vec2 OffsetVector = vec2(EyeVector.xy * (1.0 / EyeVector.z) * depthbias) * OffsetMapping_Scale * vec2(-0.333, 0.333);\n"
556 " //vec2 OffsetVector = vec2(normalize(EyeVector.xy)) * OffsetMapping_Scale * vec2(-0.333, 0.333);\n"
557 " vec2 OffsetVector = vec2(eyedir.xy) * OffsetMapping_Scale * vec2(-0.1, 0.1);\n"
558 " //TexCoord += OffsetVector * 3.0;\n"
559 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
560 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
561 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
562 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
563 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
564 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
565 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
566 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
567 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
568 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
570 " // parallax mapping as described in the paper\n"
571 " // 'Parallax Mapping with Offset Limiting: A Per-Pixel Approximation of Uneven Surfaces' by Terry Welsh\n"
572 " // The paper provides code in the ARB fragment program assembly language\n"
573 " // I translated it to GLSL but may have done something wrong - SavageX\n"
574 " // LordHavoc: removed bias and simplified to one line\n"
575 " // LordHavoc: this is just a single sample offsetmapping...\n"
576 " TexCoordOffset += vec2(eyedir.x, -1.0 * eyedir.y) * OffsetMapping_Scale * texture2D(Texture_Normal, TexCoord).a;\n"
578 " // parallax mapping as described in the paper\n"
579 " // 'Parallax Mapping with Offset Limiting: A Per-Pixel Approximation of Uneven Surfaces' by Terry Welsh\n"
580 " // The paper provides code in the ARB fragment program assembly language\n"
581 " // I translated it to GLSL but may have done something wrong - SavageX\n"
582 " float height = texture2D(Texture_Normal, TexCoord).a;\n"
583 " height = (height - 0.5) * OffsetMapping_Scale; // bias and scale\n"
584 " TexCoordOffset += height * vec2(eyedir.x, -1.0 * eyedir.y);\n"
588 " // combine the diffuse textures (base, pants, shirt)\n"
589 " myhvec4 color = myhvec4(texture2D(Texture_Color, TexCoord));\n"
590 "#ifdef USECOLORMAPPING\n"
591 " color.rgb += myhvec3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhvec3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
597 "#ifdef MODE_LIGHTSOURCE\n"
600 " // get the surface normal and light normal\n"
601 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
602 " myhvec3 diffusenormal = myhvec3(normalize(LightVector));\n"
604 " // calculate directional shading\n"
605 " color.rgb *= AmbientScale + DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
606 "#ifdef USESPECULAR\n"
607 " myhvec3 specularnormal = normalize(diffusenormal + myhvec3(normalize(EyeVector)));\n"
608 " color.rgb += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
611 "#ifdef USECUBEFILTER\n"
612 " // apply light cubemap filter\n"
613 " //color.rgb *= normalize(CubeVector) * 0.5 + 0.5;//vec3(textureCube(Texture_Cube, CubeVector));\n"
614 " color.rgb *= myhvec3(textureCube(Texture_Cube, CubeVector));\n"
617 " // apply light color\n"
618 " color.rgb *= LightColor;\n"
620 " // apply attenuation\n"
622 " // the attenuation is (1-(x*x+y*y+z*z)) which gives a large bright\n"
623 " // center and sharp falloff at the edge, this is about the most efficient\n"
624 " // we can get away with as far as providing illumination.\n"
626 " // pow(1-(x*x+y*y+z*z), 4) is far more realistic but needs large lights to\n"
627 " // provide significant illumination, large = slow = pain.\n"
628 "// color.rgb *= myhalf(max(1.0 - dot(CubeVector, CubeVector), 0.0));\n"
629 " color.rgb *= myhalf(max(2.0 - 2.0 * length(CubeVector), 0.0) / (1 + dot(CubeVector, CubeVector)));\n"
634 "#elif defined(MODE_LIGHTDIRECTION)\n"
635 " // directional model lighting\n"
637 " // get the surface normal and light normal\n"
638 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
639 " myhvec3 diffusenormal = myhvec3(normalize(LightVector));\n"
641 " // calculate directional shading\n"
642 " color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
643 "#ifdef USESPECULAR\n"
644 " myhvec3 specularnormal = normalize(diffusenormal + myhvec3(normalize(EyeVector)));\n"
645 " color.rgb += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
651 "#elif defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
652 " // deluxemap lightmapping using light vectors in modelspace (evil q3map2)\n"
654 " // get the surface normal and light normal\n"
655 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
657 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
658 " myhvec3 diffusenormal_modelspace = myhvec3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - myhvec3(0.5);\n"
659 " myhvec3 diffusenormal = normalize(myhvec3(dot(diffusenormal_modelspace, myhvec3(VectorS)), dot(diffusenormal_modelspace, myhvec3(VectorT)), dot(diffusenormal_modelspace, myhvec3(VectorR))));\n"
661 " myhvec3 diffusenormal = normalize(myhvec3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - myhvec3(0.5));\n"
663 " // calculate directional shading\n"
664 " myhvec3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0)));\n"
665 "#ifdef USESPECULAR\n"
666 " myhvec3 specularnormal = myhvec3(normalize(diffusenormal + myhvec3(normalize(EyeVector))));\n"
667 " tempcolor += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
670 " // apply lightmap color\n"
671 " color.rgb = tempcolor * myhvec3(texture2D(Texture_Lightmap, TexCoordLightmap)) + color.rgb * AmbientScale;\n"
674 "#else // MODE none (lightmap)\n"
675 " // apply lightmap color\n"
676 " color.rgb *= myhvec3(texture2D(Texture_Lightmap, TexCoordLightmap)) * DiffuseScale + myhvec3(AmbientScale);\n"
679 " color *= myhvec4(gl_Color);\n"
682 " color.rgb += myhvec3(texture2D(Texture_Glow, TexCoord)) * GlowScale;\n"
687 " myhalf fog = myhalf(texture2D(Texture_FogMask, myhvec2(length(EyeVectorModelSpace)*FogRangeRecip, 0.0)).x);\n"
688 " color.rgb = color.rgb * fog + FogColor * (1.0 - fog);\n"
691 " color.rgb *= SceneBrightness;\n"
693 " gl_FragColor = vec4(color);\n"
696 "#endif // FRAGMENT_SHADER\n"
699 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
700 const char *permutationinfo[][2] =
702 {"#define MODE_LIGHTSOURCE\n", " lightsource"},
703 {"#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
704 {"#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
705 {"#define MODE_LIGHTDIRECTION\n", " lightdirection"},
706 {"#define USEGLOW\n", " glow"},
707 {"#define USEFOG\n", " fog"},
708 {"#define USECOLORMAPPING\n", " colormapping"},
709 {"#define USESPECULAR\n", " specular"},
710 {"#define USECUBEFILTER\n", " cubefilter"},
711 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
712 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
716 void R_GLSL_CompilePermutation(const char *filename, int permutation)
719 qboolean shaderfound;
720 r_glsl_permutation_t *p = r_glsl_permutations + (permutation & SHADERPERMUTATION_COUNTMASK);
721 int vertstrings_count;
722 int geomstrings_count;
723 int fragstrings_count;
725 const char *vertstrings_list[SHADERPERMUTATION_COUNT+1];
726 const char *geomstrings_list[SHADERPERMUTATION_COUNT+1];
727 const char *fragstrings_list[SHADERPERMUTATION_COUNT+1];
728 char permutationname[256];
733 vertstrings_list[0] = "#define VERTEX_SHADER\n";
734 geomstrings_list[0] = "#define GEOMETRY_SHADER\n";
735 fragstrings_list[0] = "#define FRAGMENT_SHADER\n";
736 vertstrings_count = 1;
737 geomstrings_count = 1;
738 fragstrings_count = 1;
739 permutationname[0] = 0;
740 for (i = 0;permutationinfo[i][0];i++)
742 if (permutation & (1<<i))
744 vertstrings_list[vertstrings_count++] = permutationinfo[i][0];
745 geomstrings_list[geomstrings_count++] = permutationinfo[i][0];
746 fragstrings_list[fragstrings_count++] = permutationinfo[i][0];
747 strlcat(permutationname, permutationinfo[i][1], sizeof(permutationname));
751 // keep line numbers correct
752 vertstrings_list[vertstrings_count++] = "\n";
753 geomstrings_list[geomstrings_count++] = "\n";
754 fragstrings_list[fragstrings_count++] = "\n";
757 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
761 Con_DPrintf("GLSL shader text for \"%s\" loaded from disk\n", filename);
762 vertstrings_list[vertstrings_count++] = shaderstring;
763 geomstrings_list[geomstrings_count++] = shaderstring;
764 fragstrings_list[fragstrings_count++] = shaderstring;
767 else if (!strcmp(filename, "glsl/default.glsl"))
769 Con_DPrintf("GLSL shader text for \"%s\" loaded from engine\n", filename);
770 vertstrings_list[vertstrings_count++] = builtinshaderstring;
771 geomstrings_list[geomstrings_count++] = builtinshaderstring;
772 fragstrings_list[fragstrings_count++] = builtinshaderstring;
775 // clear any lists that are not needed by this shader
776 if (!(permutation & SHADERPERMUTATION_USES_VERTEXSHADER))
777 vertstrings_count = 0;
778 if (!(permutation & SHADERPERMUTATION_USES_GEOMETRYSHADER))
779 geomstrings_count = 0;
780 if (!(permutation & SHADERPERMUTATION_USES_FRAGMENTSHADER))
781 fragstrings_count = 0;
782 // compile the shader program
783 if (shaderfound && vertstrings_count + geomstrings_count + fragstrings_count)
784 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
788 qglUseProgramObjectARB(p->program);CHECKGLERROR
789 // look up all the uniform variable names we care about, so we don't
790 // have to look them up every time we set them
791 p->loc_Texture_Normal = qglGetUniformLocationARB(p->program, "Texture_Normal");
792 p->loc_Texture_Color = qglGetUniformLocationARB(p->program, "Texture_Color");
793 p->loc_Texture_Gloss = qglGetUniformLocationARB(p->program, "Texture_Gloss");
794 p->loc_Texture_Cube = qglGetUniformLocationARB(p->program, "Texture_Cube");
795 p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
796 p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
797 p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
798 p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
799 p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
800 p->loc_Texture_Glow = qglGetUniformLocationARB(p->program, "Texture_Glow");
801 p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
802 p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
803 p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
804 p->loc_LightColor = qglGetUniformLocationARB(p->program, "LightColor");
805 p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants");
806 p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt");
807 p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip");
808 p->loc_AmbientScale = qglGetUniformLocationARB(p->program, "AmbientScale");
809 p->loc_DiffuseScale = qglGetUniformLocationARB(p->program, "DiffuseScale");
810 p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
811 p->loc_SpecularScale = qglGetUniformLocationARB(p->program, "SpecularScale");
812 p->loc_GlowScale = qglGetUniformLocationARB(p->program, "GlowScale");
813 p->loc_SceneBrightness = qglGetUniformLocationARB(p->program, "SceneBrightness");
814 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
815 p->loc_AmbientColor = qglGetUniformLocationARB(p->program, "AmbientColor");
816 p->loc_DiffuseColor = qglGetUniformLocationARB(p->program, "DiffuseColor");
817 p->loc_SpecularColor = qglGetUniformLocationARB(p->program, "SpecularColor");
818 p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
819 // initialize the samplers to refer to the texture units we use
820 if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal, 0);
821 if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color, 1);
822 if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss, 2);
823 if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube, 3);
824 if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask, 4);
825 if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants, 5);
826 if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt, 6);
827 if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap, 7);
828 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap, 8);
829 if (p->loc_Texture_Glow >= 0) qglUniform1iARB(p->loc_Texture_Glow, 9);
831 qglUseProgramObjectARB(0);CHECKGLERROR
834 Con_Printf("permutation%s failed for shader %s, some features may not work properly!\n", permutationname, "glsl/default.glsl");
836 Mem_Free(shaderstring);
839 void R_GLSL_Restart_f(void)
842 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
843 if (r_glsl_permutations[i].program)
844 GL_Backend_FreeProgram(r_glsl_permutations[i].program);
845 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
848 int R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting)
850 // select a permutation of the lighting shader appropriate to this
851 // combination of texture, entity, light source, and fogging, only use the
852 // minimum features necessary to avoid wasting rendering time in the
853 // fragment shader on features that are not being used
854 const char *shaderfilename = NULL;
856 float specularscale = rsurface_texture->specularscale;
857 r_glsl_permutation = NULL;
858 // TODO: implement geometry-shader based shadow volumes someday
859 if (r_shadow_rtlight)
862 shaderfilename = "glsl/default.glsl";
863 permutation = SHADERPERMUTATION_MODE_LIGHTSOURCE | SHADERPERMUTATION_USES_VERTEXSHADER | SHADERPERMUTATION_USES_FRAGMENTSHADER;
864 specularscale *= r_shadow_rtlight->specularscale;
865 if (r_shadow_rtlight->currentcubemap != r_texture_whitecube)
866 permutation |= SHADERPERMUTATION_CUBEFILTER;
867 if (specularscale > 0)
868 permutation |= SHADERPERMUTATION_SPECULAR;
869 if (r_refdef.fogenabled)
870 permutation |= SHADERPERMUTATION_FOG;
871 if (rsurface_texture->colormapping)
872 permutation |= SHADERPERMUTATION_COLORMAPPING;
873 if (r_glsl_offsetmapping.integer)
875 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
876 if (r_glsl_offsetmapping_reliefmapping.integer)
877 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
880 else if (rsurface_texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
882 // bright unshaded geometry
883 shaderfilename = "glsl/default.glsl";
884 permutation = SHADERPERMUTATION_USES_VERTEXSHADER | SHADERPERMUTATION_USES_FRAGMENTSHADER;
885 if (rsurface_texture->currentskinframe->glow)
886 permutation |= SHADERPERMUTATION_GLOW;
887 if (r_refdef.fogenabled)
888 permutation |= SHADERPERMUTATION_FOG;
889 if (rsurface_texture->colormapping)
890 permutation |= SHADERPERMUTATION_COLORMAPPING;
891 if (r_glsl_offsetmapping.integer)
893 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
894 if (r_glsl_offsetmapping_reliefmapping.integer)
895 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
898 else if (modellighting)
900 // directional model lighting
901 shaderfilename = "glsl/default.glsl";
902 permutation = SHADERPERMUTATION_USES_VERTEXSHADER | SHADERPERMUTATION_USES_FRAGMENTSHADER;
903 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTION;
904 if (rsurface_texture->currentskinframe->glow)
905 permutation |= SHADERPERMUTATION_GLOW;
906 if (specularscale > 0)
907 permutation |= SHADERPERMUTATION_SPECULAR;
908 if (r_refdef.fogenabled)
909 permutation |= SHADERPERMUTATION_FOG;
910 if (rsurface_texture->colormapping)
911 permutation |= SHADERPERMUTATION_COLORMAPPING;
912 if (r_glsl_offsetmapping.integer)
914 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
915 if (r_glsl_offsetmapping_reliefmapping.integer)
916 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
922 shaderfilename = "glsl/default.glsl";
923 permutation = SHADERPERMUTATION_USES_VERTEXSHADER | SHADERPERMUTATION_USES_FRAGMENTSHADER;
924 if (r_glsl_deluxemapping.integer >= 1 && rsurface_uselightmaptexture && r_refdef.worldmodel && r_refdef.worldmodel->brushq3.deluxemapping)
926 // deluxemapping (light direction texture)
927 if (rsurface_uselightmaptexture && r_refdef.worldmodel && r_refdef.worldmodel->brushq3.deluxemapping && r_refdef.worldmodel->brushq3.deluxemapping_modelspace)
928 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_MODELSPACE;
930 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
931 if (specularscale > 0)
932 permutation |= SHADERPERMUTATION_SPECULAR;
934 else if (r_glsl_deluxemapping.integer >= 2)
936 // fake deluxemapping (uniform light direction in tangentspace)
937 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
938 if (specularscale > 0)
939 permutation |= SHADERPERMUTATION_SPECULAR;
943 // ordinary lightmapping
946 if (rsurface_texture->currentskinframe->glow)
947 permutation |= SHADERPERMUTATION_GLOW;
948 if (r_refdef.fogenabled)
949 permutation |= SHADERPERMUTATION_FOG;
950 if (rsurface_texture->colormapping)
951 permutation |= SHADERPERMUTATION_COLORMAPPING;
952 if (r_glsl_offsetmapping.integer)
954 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
955 if (r_glsl_offsetmapping_reliefmapping.integer)
956 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
959 if (!r_glsl_permutations[permutation & SHADERPERMUTATION_COUNTMASK].program)
961 if (!r_glsl_permutations[permutation & SHADERPERMUTATION_COUNTMASK].compiled)
962 R_GLSL_CompilePermutation(shaderfilename, permutation);
963 if (!r_glsl_permutations[permutation & SHADERPERMUTATION_COUNTMASK].program)
965 // remove features until we find a valid permutation
967 for (i = SHADERPERMUTATION_COUNT-1;;i>>=1)
969 // reduce i more quickly whenever it would not remove any bits
973 if (!r_glsl_permutations[permutation & SHADERPERMUTATION_COUNTMASK].compiled)
974 R_GLSL_CompilePermutation(shaderfilename, permutation);
975 if (r_glsl_permutations[permutation & SHADERPERMUTATION_COUNTMASK].program)
978 return 0; // utterly failed
982 r_glsl_permutation = r_glsl_permutations + (permutation & SHADERPERMUTATION_COUNTMASK);
984 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
985 R_Mesh_TexMatrix(0, &rsurface_texture->currenttexmatrix);
986 if (permutation & SHADERPERMUTATION_MODE_LIGHTSOURCE)
988 if (r_glsl_permutation->loc_Texture_Cube >= 0 && r_shadow_rtlight) R_Mesh_TexBindCubeMap(3, R_GetTexture(r_shadow_rtlight->currentcubemap));
989 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, r_shadow_entitylightorigin[0], r_shadow_entitylightorigin[1], r_shadow_entitylightorigin[2]);
990 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
991 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_shadow_rtlight->ambientscale);
992 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_shadow_rtlight->diffusescale);
993 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, specularscale);
995 else if (permutation & SHADERPERMUTATION_MODE_LIGHTDIRECTION)
997 if (r_glsl_permutation->loc_AmbientColor >= 0)
998 qglUniform3fARB(r_glsl_permutation->loc_AmbientColor, rsurface_entity->modellight_ambient[0], rsurface_entity->modellight_ambient[1], rsurface_entity->modellight_ambient[2]);
999 if (r_glsl_permutation->loc_DiffuseColor >= 0)
1000 qglUniform3fARB(r_glsl_permutation->loc_DiffuseColor, rsurface_entity->modellight_diffuse[0], rsurface_entity->modellight_diffuse[1], rsurface_entity->modellight_diffuse[2]);
1001 if (r_glsl_permutation->loc_SpecularColor >= 0)
1002 qglUniform3fARB(r_glsl_permutation->loc_SpecularColor, rsurface_entity->modellight_diffuse[0] * rsurface_texture->specularscale, rsurface_entity->modellight_diffuse[1] * rsurface_texture->specularscale, rsurface_entity->modellight_diffuse[2] * rsurface_texture->specularscale);
1003 if (r_glsl_permutation->loc_LightDir >= 0)
1004 qglUniform3fARB(r_glsl_permutation->loc_LightDir, rsurface_entity->modellight_lightdir[0], rsurface_entity->modellight_lightdir[1], rsurface_entity->modellight_lightdir[2]);
1008 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_ambient.value * 2.0f / 128.0f);
1009 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_refdef.lightmapintensity * 2.0f);
1010 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, r_refdef.lightmapintensity * specularscale * 2.0f);
1012 if (r_glsl_permutation->loc_Texture_Normal >= 0) R_Mesh_TexBind(0, R_GetTexture(rsurface_texture->currentskinframe->nmap));
1013 if (r_glsl_permutation->loc_Texture_Color >= 0) R_Mesh_TexBind(1, R_GetTexture(rsurface_texture->basetexture));
1014 if (r_glsl_permutation->loc_Texture_Gloss >= 0) R_Mesh_TexBind(2, R_GetTexture(rsurface_texture->glosstexture));
1015 //if (r_glsl_permutation->loc_Texture_Cube >= 0 && permutation & SHADERPERMUTATION_MODE_LIGHTSOURCE) R_Mesh_TexBindCubeMap(3, R_GetTexture(r_shadow_rtlight->currentcubemap));
1016 if (r_glsl_permutation->loc_Texture_FogMask >= 0) R_Mesh_TexBind(4, R_GetTexture(r_texture_fogattenuation));
1017 if (r_glsl_permutation->loc_Texture_Pants >= 0) R_Mesh_TexBind(5, R_GetTexture(rsurface_texture->currentskinframe->pants));
1018 if (r_glsl_permutation->loc_Texture_Shirt >= 0) R_Mesh_TexBind(6, R_GetTexture(rsurface_texture->currentskinframe->shirt));
1019 //if (r_glsl_permutation->loc_Texture_Lightmap >= 0) R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
1020 //if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
1021 if (r_glsl_permutation->loc_Texture_Glow >= 0) R_Mesh_TexBind(9, R_GetTexture(rsurface_texture->currentskinframe->glow));
1022 if (r_glsl_permutation->loc_GlowScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_GlowScale, r_hdr_glowintensity.value);
1023 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_view.colorscale);
1024 if (r_glsl_permutation->loc_FogColor >= 0)
1026 // additive passes are only darkened by fog, not tinted
1027 if (r_shadow_rtlight || (rsurface_texture->currentmaterialflags & MATERIALFLAG_ADD))
1028 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
1030 qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
1032 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface_modelorg[0], rsurface_modelorg[1], rsurface_modelorg[2]);
1033 if (r_glsl_permutation->loc_Color_Pants >= 0)
1035 if (rsurface_texture->currentskinframe->pants)
1036 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface_entity->colormap_pantscolor[0], rsurface_entity->colormap_pantscolor[1], rsurface_entity->colormap_pantscolor[2]);
1038 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
1040 if (r_glsl_permutation->loc_Color_Shirt >= 0)
1042 if (rsurface_texture->currentskinframe->shirt)
1043 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface_entity->colormap_shirtcolor[0], rsurface_entity->colormap_shirtcolor[1], rsurface_entity->colormap_shirtcolor[2]);
1045 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
1047 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, r_refdef.fograngerecip);
1048 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface_texture->specularpower);
1049 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
1054 void R_SwitchSurfaceShader(int permutation)
1056 if (r_glsl_permutation != r_glsl_permutations + (permutation & SHADERPERMUTATION_COUNTMASK))
1058 r_glsl_permutation = r_glsl_permutations + (permutation & SHADERPERMUTATION_COUNTMASK);
1060 qglUseProgramObjectARB(r_glsl_permutation->program);
1065 void gl_main_start(void)
1067 r_main_texturepool = R_AllocTexturePool();
1068 R_BuildBlankTextures();
1070 if (gl_texturecubemap)
1073 R_BuildNormalizationCube();
1075 R_BuildFogTexture();
1076 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
1077 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
1078 memset(&r_svbsp, 0, sizeof (r_svbsp));
1081 void gl_main_shutdown(void)
1084 Mem_Free(r_svbsp.nodes);
1085 memset(&r_svbsp, 0, sizeof (r_svbsp));
1086 R_FreeTexturePool(&r_main_texturepool);
1087 r_texture_blanknormalmap = NULL;
1088 r_texture_white = NULL;
1089 r_texture_black = NULL;
1090 r_texture_whitecube = NULL;
1091 r_texture_normalizationcube = NULL;
1092 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
1096 extern void CL_ParseEntityLump(char *entitystring);
1097 void gl_main_newmap(void)
1099 // FIXME: move this code to client
1101 char *entities, entname[MAX_QPATH];
1104 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
1105 l = (int)strlen(entname) - 4;
1106 if (l >= 0 && !strcmp(entname + l, ".bsp"))
1108 memcpy(entname + l, ".ent", 5);
1109 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
1111 CL_ParseEntityLump(entities);
1116 if (cl.worldmodel->brush.entities)
1117 CL_ParseEntityLump(cl.worldmodel->brush.entities);
1121 void GL_Main_Init(void)
1123 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
1125 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
1126 FOG_registercvars(); // FIXME: move this fog stuff to client?
1127 Cvar_RegisterVariable(&r_nearclip);
1128 Cvar_RegisterVariable(&r_showsurfaces);
1129 Cvar_RegisterVariable(&r_showtris);
1130 Cvar_RegisterVariable(&r_shownormals);
1131 Cvar_RegisterVariable(&r_showlighting);
1132 Cvar_RegisterVariable(&r_showshadowvolumes);
1133 Cvar_RegisterVariable(&r_showcollisionbrushes);
1134 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
1135 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
1136 Cvar_RegisterVariable(&r_showdisabledepthtest);
1137 Cvar_RegisterVariable(&r_drawportals);
1138 Cvar_RegisterVariable(&r_drawentities);
1139 Cvar_RegisterVariable(&r_cullentities_trace);
1140 Cvar_RegisterVariable(&r_cullentities_trace_samples);
1141 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
1142 Cvar_RegisterVariable(&r_cullentities_trace_delay);
1143 Cvar_RegisterVariable(&r_drawviewmodel);
1144 Cvar_RegisterVariable(&r_speeds);
1145 Cvar_RegisterVariable(&r_fullbrights);
1146 Cvar_RegisterVariable(&r_wateralpha);
1147 Cvar_RegisterVariable(&r_dynamic);
1148 Cvar_RegisterVariable(&r_fullbright);
1149 Cvar_RegisterVariable(&r_shadows);
1150 Cvar_RegisterVariable(&r_shadows_throwdistance);
1151 Cvar_RegisterVariable(&r_q1bsp_skymasking);
1152 Cvar_RegisterVariable(&r_textureunits);
1153 Cvar_RegisterVariable(&r_glsl);
1154 Cvar_RegisterVariable(&r_glsl_offsetmapping);
1155 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
1156 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
1157 Cvar_RegisterVariable(&r_glsl_deluxemapping);
1158 Cvar_RegisterVariable(&r_lerpsprites);
1159 Cvar_RegisterVariable(&r_lerpmodels);
1160 Cvar_RegisterVariable(&r_waterscroll);
1161 Cvar_RegisterVariable(&r_bloom);
1162 Cvar_RegisterVariable(&r_bloom_colorscale);
1163 Cvar_RegisterVariable(&r_bloom_brighten);
1164 Cvar_RegisterVariable(&r_bloom_blur);
1165 Cvar_RegisterVariable(&r_bloom_resolution);
1166 Cvar_RegisterVariable(&r_bloom_colorexponent);
1167 Cvar_RegisterVariable(&r_bloom_colorsubtract);
1168 Cvar_RegisterVariable(&r_hdr);
1169 Cvar_RegisterVariable(&r_hdr_scenebrightness);
1170 Cvar_RegisterVariable(&r_hdr_glowintensity);
1171 Cvar_RegisterVariable(&r_hdr_range);
1172 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
1173 Cvar_RegisterVariable(&developer_texturelogging);
1174 Cvar_RegisterVariable(&gl_lightmaps);
1175 Cvar_RegisterVariable(&r_test);
1176 Cvar_RegisterVariable(&r_batchmode);
1177 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
1178 Cvar_SetValue("r_fullbrights", 0);
1179 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
1182 extern void R_Textures_Init(void);
1183 extern void GL_Draw_Init(void);
1184 extern void GL_Main_Init(void);
1185 extern void R_Shadow_Init(void);
1186 extern void R_Sky_Init(void);
1187 extern void GL_Surf_Init(void);
1188 extern void R_Light_Init(void);
1189 extern void R_Particles_Init(void);
1190 extern void R_Explosion_Init(void);
1191 extern void gl_backend_init(void);
1192 extern void Sbar_Init(void);
1193 extern void R_LightningBeams_Init(void);
1194 extern void Mod_RenderInit(void);
1196 void Render_Init(void)
1209 R_LightningBeams_Init();
1218 extern char *ENGINE_EXTENSIONS;
1221 VID_CheckExtensions();
1223 // LordHavoc: report supported extensions
1224 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
1226 // clear to black (loading plaque will be seen over this)
1228 qglClearColor(0,0,0,1);CHECKGLERROR
1229 qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
1232 int R_CullBox(const vec3_t mins, const vec3_t maxs)
1236 for (i = 0;i < 4;i++)
1238 p = r_view.frustum + i;
1243 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1247 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1251 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1255 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1259 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1263 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1267 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1271 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1279 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
1283 for (i = 0;i < numplanes;i++)
1290 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1294 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1298 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1302 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1306 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1310 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1314 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1318 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1326 //==================================================================================
1328 static void R_UpdateEntityLighting(entity_render_t *ent)
1330 vec3_t tempdiffusenormal;
1332 // fetch the lighting from the worldmodel data
1333 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));
1334 VectorClear(ent->modellight_diffuse);
1335 VectorClear(tempdiffusenormal);
1336 if ((ent->flags & RENDER_LIGHT) && r_refdef.worldmodel && r_refdef.worldmodel->brush.LightPoint)
1339 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
1340 r_refdef.worldmodel->brush.LightPoint(r_refdef.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
1343 VectorSet(ent->modellight_ambient, 1, 1, 1);
1345 // move the light direction into modelspace coordinates for lighting code
1346 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
1347 VectorNormalize(ent->modellight_lightdir);
1349 // scale ambient and directional light contributions according to rendering variables
1350 ent->modellight_ambient[0] *= ent->colormod[0] * r_refdef.lightmapintensity;
1351 ent->modellight_ambient[1] *= ent->colormod[1] * r_refdef.lightmapintensity;
1352 ent->modellight_ambient[2] *= ent->colormod[2] * r_refdef.lightmapintensity;
1353 ent->modellight_diffuse[0] *= ent->colormod[0] * r_refdef.lightmapintensity;
1354 ent->modellight_diffuse[1] *= ent->colormod[1] * r_refdef.lightmapintensity;
1355 ent->modellight_diffuse[2] *= ent->colormod[2] * r_refdef.lightmapintensity;
1358 static void R_View_UpdateEntityVisible (void)
1361 entity_render_t *ent;
1363 if (!r_drawentities.integer)
1366 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : (chase_active.integer ? 0 : RENDER_EXTERIORMODEL);
1367 if (r_refdef.worldmodel && r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs)
1369 // worldmodel can check visibility
1370 for (i = 0;i < r_refdef.numentities;i++)
1372 ent = r_refdef.entities[i];
1373 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));
1375 if(r_cullentities_trace.integer)
1377 for (i = 0;i < r_refdef.numentities;i++)
1379 ent = r_refdef.entities[i];
1380 if(r_viewcache.entityvisible[i] && !(ent->effects & EF_NODEPTHTEST) && !(ent->model && (ent->model->name[0] == '*')))
1382 if(Mod_CanSeeBox_Trace(r_cullentities_trace_samples.integer, r_cullentities_trace_enlarge.value, r_refdef.worldmodel, r_view.origin, ent->mins, ent->maxs))
1383 ent->last_trace_visibility = realtime;
1384 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
1385 r_viewcache.entityvisible[i] = 0;
1392 // no worldmodel or it can't check visibility
1393 for (i = 0;i < r_refdef.numentities;i++)
1395 ent = r_refdef.entities[i];
1396 r_viewcache.entityvisible[i] = !(ent->flags & renderimask) && !R_CullBox(ent->mins, ent->maxs);
1400 // update entity lighting (even on hidden entities for r_shadows)
1401 for (i = 0;i < r_refdef.numentities;i++)
1402 R_UpdateEntityLighting(r_refdef.entities[i]);
1405 // only used if skyrendermasked, and normally returns false
1406 int R_DrawBrushModelsSky (void)
1409 entity_render_t *ent;
1411 if (!r_drawentities.integer)
1415 for (i = 0;i < r_refdef.numentities;i++)
1417 if (!r_viewcache.entityvisible[i])
1419 ent = r_refdef.entities[i];
1420 if (!ent->model || !ent->model->DrawSky)
1422 ent->model->DrawSky(ent);
1428 void R_DrawNoModel(entity_render_t *ent);
1429 void R_DrawModels(void)
1432 entity_render_t *ent;
1434 if (!r_drawentities.integer)
1437 for (i = 0;i < r_refdef.numentities;i++)
1439 if (!r_viewcache.entityvisible[i])
1441 ent = r_refdef.entities[i];
1442 r_refdef.stats.entities++;
1443 if (ent->model && ent->model->Draw != NULL)
1444 ent->model->Draw(ent);
1450 static void R_View_SetFrustum(void)
1452 double slopex, slopey;
1454 // break apart the view matrix into vectors for various purposes
1455 Matrix4x4_ToVectors(&r_view.matrix, r_view.forward, r_view.left, r_view.up, r_view.origin);
1456 VectorNegate(r_view.left, r_view.right);
1459 r_view.frustum[0].normal[0] = 0 - 1.0 / r_view.frustum_x;
1460 r_view.frustum[0].normal[1] = 0 - 0;
1461 r_view.frustum[0].normal[2] = -1 - 0;
1462 r_view.frustum[1].normal[0] = 0 + 1.0 / r_view.frustum_x;
1463 r_view.frustum[1].normal[1] = 0 + 0;
1464 r_view.frustum[1].normal[2] = -1 + 0;
1465 r_view.frustum[2].normal[0] = 0 - 0;
1466 r_view.frustum[2].normal[1] = 0 - 1.0 / r_view.frustum_y;
1467 r_view.frustum[2].normal[2] = -1 - 0;
1468 r_view.frustum[3].normal[0] = 0 + 0;
1469 r_view.frustum[3].normal[1] = 0 + 1.0 / r_view.frustum_y;
1470 r_view.frustum[3].normal[2] = -1 + 0;
1474 zNear = r_refdef.nearclip;
1475 nudge = 1.0 - 1.0 / (1<<23);
1476 r_view.frustum[4].normal[0] = 0 - 0;
1477 r_view.frustum[4].normal[1] = 0 - 0;
1478 r_view.frustum[4].normal[2] = -1 - -nudge;
1479 r_view.frustum[4].dist = 0 - -2 * zNear * nudge;
1480 r_view.frustum[5].normal[0] = 0 + 0;
1481 r_view.frustum[5].normal[1] = 0 + 0;
1482 r_view.frustum[5].normal[2] = -1 + -nudge;
1483 r_view.frustum[5].dist = 0 + -2 * zNear * nudge;
1489 r_view.frustum[0].normal[0] = m[3] - m[0];
1490 r_view.frustum[0].normal[1] = m[7] - m[4];
1491 r_view.frustum[0].normal[2] = m[11] - m[8];
1492 r_view.frustum[0].dist = m[15] - m[12];
1494 r_view.frustum[1].normal[0] = m[3] + m[0];
1495 r_view.frustum[1].normal[1] = m[7] + m[4];
1496 r_view.frustum[1].normal[2] = m[11] + m[8];
1497 r_view.frustum[1].dist = m[15] + m[12];
1499 r_view.frustum[2].normal[0] = m[3] - m[1];
1500 r_view.frustum[2].normal[1] = m[7] - m[5];
1501 r_view.frustum[2].normal[2] = m[11] - m[9];
1502 r_view.frustum[2].dist = m[15] - m[13];
1504 r_view.frustum[3].normal[0] = m[3] + m[1];
1505 r_view.frustum[3].normal[1] = m[7] + m[5];
1506 r_view.frustum[3].normal[2] = m[11] + m[9];
1507 r_view.frustum[3].dist = m[15] + m[13];
1509 r_view.frustum[4].normal[0] = m[3] - m[2];
1510 r_view.frustum[4].normal[1] = m[7] - m[6];
1511 r_view.frustum[4].normal[2] = m[11] - m[10];
1512 r_view.frustum[4].dist = m[15] - m[14];
1514 r_view.frustum[5].normal[0] = m[3] + m[2];
1515 r_view.frustum[5].normal[1] = m[7] + m[6];
1516 r_view.frustum[5].normal[2] = m[11] + m[10];
1517 r_view.frustum[5].dist = m[15] + m[14];
1522 slopex = 1.0 / r_view.frustum_x;
1523 slopey = 1.0 / r_view.frustum_y;
1524 VectorMA(r_view.forward, -slopex, r_view.left, r_view.frustum[0].normal);
1525 VectorMA(r_view.forward, slopex, r_view.left, r_view.frustum[1].normal);
1526 VectorMA(r_view.forward, -slopey, r_view.up , r_view.frustum[2].normal);
1527 VectorMA(r_view.forward, slopey, r_view.up , r_view.frustum[3].normal);
1528 VectorCopy(r_view.forward, r_view.frustum[4].normal);
1529 VectorNormalize(r_view.frustum[0].normal);
1530 VectorNormalize(r_view.frustum[1].normal);
1531 VectorNormalize(r_view.frustum[2].normal);
1532 VectorNormalize(r_view.frustum[3].normal);
1533 r_view.frustum[0].dist = DotProduct (r_view.origin, r_view.frustum[0].normal);
1534 r_view.frustum[1].dist = DotProduct (r_view.origin, r_view.frustum[1].normal);
1535 r_view.frustum[2].dist = DotProduct (r_view.origin, r_view.frustum[2].normal);
1536 r_view.frustum[3].dist = DotProduct (r_view.origin, r_view.frustum[3].normal);
1537 r_view.frustum[4].dist = DotProduct (r_view.origin, r_view.frustum[4].normal) + r_refdef.nearclip;
1538 PlaneClassify(&r_view.frustum[0]);
1539 PlaneClassify(&r_view.frustum[1]);
1540 PlaneClassify(&r_view.frustum[2]);
1541 PlaneClassify(&r_view.frustum[3]);
1542 PlaneClassify(&r_view.frustum[4]);
1544 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
1545 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, -1024 * slopex, r_view.left, -1024 * slopey, r_view.up, r_view.frustumcorner[0]);
1546 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, 1024 * slopex, r_view.left, -1024 * slopey, r_view.up, r_view.frustumcorner[1]);
1547 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, -1024 * slopex, r_view.left, 1024 * slopey, r_view.up, r_view.frustumcorner[2]);
1548 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, 1024 * slopex, r_view.left, 1024 * slopey, r_view.up, r_view.frustumcorner[3]);
1550 // LordHavoc: note to all quake engine coders, Quake had a special case
1551 // for 90 degrees which assumed a square view (wrong), so I removed it,
1552 // Quake2 has it disabled as well.
1554 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
1555 //RotatePointAroundVector( r_view.frustum[0].normal, r_view.up, r_view.forward, -(90 - r_refdef.fov_x / 2));
1556 //r_view.frustum[0].dist = DotProduct (r_view.origin, frustum[0].normal);
1557 //PlaneClassify(&frustum[0]);
1559 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
1560 //RotatePointAroundVector( r_view.frustum[1].normal, r_view.up, r_view.forward, (90 - r_refdef.fov_x / 2));
1561 //r_view.frustum[1].dist = DotProduct (r_view.origin, frustum[1].normal);
1562 //PlaneClassify(&frustum[1]);
1564 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
1565 //RotatePointAroundVector( r_view.frustum[2].normal, r_view.left, r_view.forward, -(90 - r_refdef.fov_y / 2));
1566 //r_view.frustum[2].dist = DotProduct (r_view.origin, frustum[2].normal);
1567 //PlaneClassify(&frustum[2]);
1569 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
1570 //RotatePointAroundVector( r_view.frustum[3].normal, r_view.left, r_view.forward, (90 - r_refdef.fov_y / 2));
1571 //r_view.frustum[3].dist = DotProduct (r_view.origin, frustum[3].normal);
1572 //PlaneClassify(&frustum[3]);
1575 //VectorCopy(r_view.forward, r_view.frustum[4].normal);
1576 //r_view.frustum[4].dist = DotProduct (r_view.origin, frustum[4].normal) + r_nearclip.value;
1577 //PlaneClassify(&frustum[4]);
1580 void R_View_Update(void)
1582 R_View_SetFrustum();
1583 R_View_WorldVisibility();
1584 R_View_UpdateEntityVisible();
1587 void R_SetupView(const matrix4x4_t *matrix)
1589 if (r_refdef.rtworldshadows || r_refdef.rtdlightshadows)
1590 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_view.frustum_x, r_view.frustum_y, r_refdef.nearclip);
1592 GL_SetupView_Mode_Perspective(r_view.frustum_x, r_view.frustum_y, r_refdef.nearclip, r_refdef.farclip);
1594 GL_SetupView_Orientation_FromEntity(matrix);
1597 void R_ResetViewRendering2D(void)
1599 if (gl_support_fragment_shader)
1601 qglUseProgramObjectARB(0);CHECKGLERROR
1606 // GL is weird because it's bottom to top, r_view.y is top to bottom
1607 qglViewport(r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
1608 GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
1609 GL_Scissor(r_view.x, r_view.y, r_view.width, r_view.height);
1610 GL_Color(1, 1, 1, 1);
1611 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
1612 GL_BlendFunc(GL_ONE, GL_ZERO);
1613 GL_AlphaTest(false);
1614 GL_ScissorTest(false);
1615 GL_DepthMask(false);
1616 GL_DepthTest(false);
1617 R_Mesh_Matrix(&identitymatrix);
1618 R_Mesh_ResetTextureState();
1619 qglPolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR
1620 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
1621 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
1622 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
1623 qglStencilMask(~0);CHECKGLERROR
1624 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
1625 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
1626 GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
1629 void R_ResetViewRendering3D(void)
1631 if (gl_support_fragment_shader)
1633 qglUseProgramObjectARB(0);CHECKGLERROR
1638 // GL is weird because it's bottom to top, r_view.y is top to bottom
1639 qglViewport(r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
1640 R_SetupView(&r_view.matrix);
1641 GL_Scissor(r_view.x, r_view.y, r_view.width, r_view.height);
1642 GL_Color(1, 1, 1, 1);
1643 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
1644 GL_BlendFunc(GL_ONE, GL_ZERO);
1645 GL_AlphaTest(false);
1646 GL_ScissorTest(true);
1649 R_Mesh_Matrix(&identitymatrix);
1650 R_Mesh_ResetTextureState();
1651 qglPolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR
1652 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
1653 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
1654 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
1655 qglStencilMask(~0);CHECKGLERROR
1656 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
1657 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
1658 GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
1662 R_Bloom_SetupShader(
1664 "// written by Forest 'LordHavoc' Hale\n"
1666 "// common definitions between vertex shader and fragment shader:\n"
1668 "#ifdef __GLSL_CG_DATA_TYPES\n"
1669 "#define myhalf half\n"
1670 "#define myhvec2 hvec2\n"
1671 "#define myhvec3 hvec3\n"
1672 "#define myhvec4 hvec4\n"
1674 "#define myhalf float\n"
1675 "#define myhvec2 vec2\n"
1676 "#define myhvec3 vec3\n"
1677 "#define myhvec4 vec4\n"
1680 "varying vec2 ScreenTexCoord;\n"
1681 "varying vec2 BloomTexCoord;\n"
1686 "// vertex shader specific:\n"
1687 "#ifdef VERTEX_SHADER\n"
1691 " ScreenTexCoord = vec2(gl_MultiTexCoord0);\n"
1692 " BloomTexCoord = vec2(gl_MultiTexCoord1);\n"
1693 " // transform vertex to camera space, using ftransform to match non-VS\n"
1695 " gl_Position = ftransform();\n"
1698 "#endif // VERTEX_SHADER\n"
1703 "// fragment shader specific:\n"
1704 "#ifdef FRAGMENT_SHADER\n"
1709 " myhvec3 color = myhvec3(texture2D(Texture_Screen, ScreenTexCoord));\n"
1710 " for (x = -BLUR_X;x <= BLUR_X;x++)
1711 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
1712 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
1713 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
1714 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
1716 " gl_FragColor = vec4(color);\n"
1719 "#endif // FRAGMENT_SHADER\n"
1722 void R_RenderScene(void);
1724 void R_Bloom_StartFrame(void)
1726 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
1728 // set bloomwidth and bloomheight to the bloom resolution that will be
1729 // used (often less than the screen resolution for faster rendering)
1730 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_view.width);
1731 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_view.height / r_view.width;
1732 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_view.height);
1734 // calculate desired texture sizes
1735 if (gl_support_arb_texture_non_power_of_two)
1737 screentexturewidth = r_view.width;
1738 screentextureheight = r_view.height;
1739 bloomtexturewidth = r_bloomstate.bloomwidth;
1740 bloomtextureheight = r_bloomstate.bloomheight;
1744 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
1745 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
1746 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
1747 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
1752 screentexturewidth = screentextureheight = 0;
1754 else if (r_bloom.integer)
1759 screentexturewidth = screentextureheight = 0;
1760 bloomtexturewidth = bloomtextureheight = 0;
1763 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)
1765 // can't use bloom if the parameters are too weird
1766 // can't use bloom if the card does not support the texture size
1767 if (r_bloomstate.texture_screen)
1768 R_FreeTexture(r_bloomstate.texture_screen);
1769 if (r_bloomstate.texture_bloom)
1770 R_FreeTexture(r_bloomstate.texture_bloom);
1771 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
1775 r_bloomstate.enabled = true;
1776 r_bloomstate.hdr = r_hdr.integer != 0;
1778 // allocate textures as needed
1779 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
1781 if (r_bloomstate.texture_screen)
1782 R_FreeTexture(r_bloomstate.texture_screen);
1783 r_bloomstate.texture_screen = NULL;
1784 r_bloomstate.screentexturewidth = screentexturewidth;
1785 r_bloomstate.screentextureheight = screentextureheight;
1786 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
1787 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);
1789 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
1791 if (r_bloomstate.texture_bloom)
1792 R_FreeTexture(r_bloomstate.texture_bloom);
1793 r_bloomstate.texture_bloom = NULL;
1794 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
1795 r_bloomstate.bloomtextureheight = bloomtextureheight;
1796 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
1797 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);
1800 // set up a texcoord array for the full resolution screen image
1801 // (we have to keep this around to copy back during final render)
1802 r_bloomstate.screentexcoord2f[0] = 0;
1803 r_bloomstate.screentexcoord2f[1] = (float)r_view.height / (float)r_bloomstate.screentextureheight;
1804 r_bloomstate.screentexcoord2f[2] = (float)r_view.width / (float)r_bloomstate.screentexturewidth;
1805 r_bloomstate.screentexcoord2f[3] = (float)r_view.height / (float)r_bloomstate.screentextureheight;
1806 r_bloomstate.screentexcoord2f[4] = (float)r_view.width / (float)r_bloomstate.screentexturewidth;
1807 r_bloomstate.screentexcoord2f[5] = 0;
1808 r_bloomstate.screentexcoord2f[6] = 0;
1809 r_bloomstate.screentexcoord2f[7] = 0;
1811 // set up a texcoord array for the reduced resolution bloom image
1812 // (which will be additive blended over the screen image)
1813 r_bloomstate.bloomtexcoord2f[0] = 0;
1814 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
1815 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
1816 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
1817 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
1818 r_bloomstate.bloomtexcoord2f[5] = 0;
1819 r_bloomstate.bloomtexcoord2f[6] = 0;
1820 r_bloomstate.bloomtexcoord2f[7] = 0;
1823 void R_Bloom_CopyScreenTexture(float colorscale)
1825 r_refdef.stats.bloom++;
1827 R_ResetViewRendering2D();
1828 R_Mesh_VertexPointer(r_screenvertex3f);
1829 R_Mesh_ColorPointer(NULL);
1830 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f);
1831 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
1833 // copy view into the screen texture
1834 GL_ActiveTexture(0);
1836 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
1837 r_refdef.stats.bloom_copypixels += r_view.width * r_view.height;
1839 // now scale it down to the bloom texture size
1841 qglViewport(r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
1842 GL_BlendFunc(GL_ONE, GL_ZERO);
1843 GL_Color(colorscale, colorscale, colorscale, 1);
1844 // TODO: optimize with multitexture or GLSL
1845 R_Mesh_Draw(0, 4, 2, polygonelements);
1846 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
1848 // we now have a bloom image in the framebuffer
1849 // copy it into the bloom image texture for later processing
1850 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
1851 GL_ActiveTexture(0);
1853 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
1854 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
1857 void R_Bloom_CopyHDRTexture(void)
1859 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
1860 GL_ActiveTexture(0);
1862 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
1863 r_refdef.stats.bloom_copypixels += r_view.width * r_view.height;
1866 void R_Bloom_MakeTexture(void)
1869 float xoffset, yoffset, r, brighten;
1871 r_refdef.stats.bloom++;
1873 R_ResetViewRendering2D();
1874 R_Mesh_VertexPointer(r_screenvertex3f);
1875 R_Mesh_ColorPointer(NULL);
1877 // we have a bloom image in the framebuffer
1879 qglViewport(r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
1881 for (x = 1;x < r_bloom_colorexponent.value;)
1884 r = bound(0, r_bloom_colorexponent.value / x, 1);
1885 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
1886 GL_Color(r, r, r, 1);
1887 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
1888 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f);
1889 R_Mesh_Draw(0, 4, 2, polygonelements);
1890 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
1892 // copy the vertically blurred bloom view to a texture
1893 GL_ActiveTexture(0);
1895 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
1896 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
1899 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
1900 brighten = r_bloom_brighten.value;
1902 brighten *= r_hdr_range.value;
1903 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
1904 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f);
1906 for (dir = 0;dir < 2;dir++)
1908 // blend on at multiple vertical offsets to achieve a vertical blur
1909 // TODO: do offset blends using GLSL
1910 GL_BlendFunc(GL_ONE, GL_ZERO);
1911 for (x = -range;x <= range;x++)
1913 if (!dir){xoffset = 0;yoffset = x;}
1914 else {xoffset = x;yoffset = 0;}
1915 xoffset /= (float)r_bloomstate.bloomtexturewidth;
1916 yoffset /= (float)r_bloomstate.bloomtextureheight;
1917 // compute a texcoord array with the specified x and y offset
1918 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
1919 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
1920 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
1921 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
1922 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
1923 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
1924 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
1925 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
1926 // this r value looks like a 'dot' particle, fading sharply to
1927 // black at the edges
1928 // (probably not realistic but looks good enough)
1929 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
1930 //r = (dir ? 1.0f : brighten)/(range*2+1);
1931 r = (dir ? 1.0f : brighten)/(range*2+1)*(1 - x*x/(float)(range*range));
1932 GL_Color(r, r, r, 1);
1933 R_Mesh_Draw(0, 4, 2, polygonelements);
1934 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
1935 GL_BlendFunc(GL_ONE, GL_ONE);
1938 // copy the vertically blurred bloom view to a texture
1939 GL_ActiveTexture(0);
1941 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
1942 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
1945 // apply subtract last
1946 // (just like it would be in a GLSL shader)
1947 if (r_bloom_colorsubtract.value > 0 && gl_support_ext_blend_subtract)
1949 GL_BlendFunc(GL_ONE, GL_ZERO);
1950 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
1951 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f);
1952 GL_Color(1, 1, 1, 1);
1953 R_Mesh_Draw(0, 4, 2, polygonelements);
1954 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
1956 GL_BlendFunc(GL_ONE, GL_ONE);
1957 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
1958 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
1959 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f);
1960 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
1961 R_Mesh_Draw(0, 4, 2, polygonelements);
1962 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
1963 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
1965 // copy the darkened bloom view to a texture
1966 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
1967 GL_ActiveTexture(0);
1969 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
1970 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
1974 void R_HDR_RenderBloomTexture(void)
1976 int oldwidth, oldheight;
1978 oldwidth = r_view.width;
1979 oldheight = r_view.height;
1980 r_view.width = r_bloomstate.bloomwidth;
1981 r_view.height = r_bloomstate.bloomheight;
1983 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
1984 // TODO: add exposure compensation features
1985 // TODO: add fp16 framebuffer support
1987 r_view.colorscale = r_bloom_colorscale.value * r_hdr_scenebrightness.value;
1989 r_view.colorscale /= r_hdr_range.value;
1992 R_ResetViewRendering2D();
1994 R_Bloom_CopyHDRTexture();
1995 R_Bloom_MakeTexture();
1997 R_ResetViewRendering3D();
2000 if (r_timereport_active)
2001 R_TimeReport("clear");
2004 // restore the view settings
2005 r_view.width = oldwidth;
2006 r_view.height = oldheight;
2009 static void R_BlendView(void)
2011 if (r_bloomstate.enabled && r_bloomstate.hdr)
2013 // render high dynamic range bloom effect
2014 // the bloom texture was made earlier this render, so we just need to
2015 // blend it onto the screen...
2016 R_ResetViewRendering2D();
2017 R_Mesh_VertexPointer(r_screenvertex3f);
2018 R_Mesh_ColorPointer(NULL);
2019 GL_Color(1, 1, 1, 1);
2020 GL_BlendFunc(GL_ONE, GL_ONE);
2021 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2022 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f);
2023 R_Mesh_Draw(0, 4, 2, polygonelements);
2024 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
2026 else if (r_bloomstate.enabled)
2028 // render simple bloom effect
2029 // copy the screen and shrink it and darken it for the bloom process
2030 R_Bloom_CopyScreenTexture(r_bloom_colorscale.value);
2031 // make the bloom texture
2032 R_Bloom_MakeTexture();
2033 // put the original screen image back in place and blend the bloom
2035 R_ResetViewRendering2D();
2036 R_Mesh_VertexPointer(r_screenvertex3f);
2037 R_Mesh_ColorPointer(NULL);
2038 GL_Color(1, 1, 1, 1);
2039 GL_BlendFunc(GL_ONE, GL_ZERO);
2040 // do both in one pass if possible
2041 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2042 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f);
2043 if (r_textureunits.integer >= 2 && gl_combine.integer)
2045 R_Mesh_TexCombine(1, GL_ADD, GL_ADD, 1, 1);
2046 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_screen));
2047 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.screentexcoord2f);
2051 R_Mesh_Draw(0, 4, 2, polygonelements);
2052 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
2053 // now blend on the bloom texture
2054 GL_BlendFunc(GL_ONE, GL_ONE);
2055 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
2056 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f);
2058 R_Mesh_Draw(0, 4, 2, polygonelements);
2059 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
2061 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
2063 // apply a color tint to the whole view
2064 R_ResetViewRendering2D();
2065 R_Mesh_VertexPointer(r_screenvertex3f);
2066 R_Mesh_ColorPointer(NULL);
2067 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2068 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
2069 R_Mesh_Draw(0, 4, 2, polygonelements);
2073 void R_RenderScene(void);
2075 matrix4x4_t r_waterscrollmatrix;
2077 void R_UpdateVariables(void)
2081 r_refdef.farclip = 4096;
2082 if (r_refdef.worldmodel)
2083 r_refdef.farclip += VectorDistance(r_refdef.worldmodel->normalmins, r_refdef.worldmodel->normalmaxs);
2084 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
2086 r_refdef.polygonfactor = 0;
2087 r_refdef.polygonoffset = 0;
2088 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_shadow_polygonfactor.value;
2089 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_shadow_polygonoffset.value;
2091 r_refdef.rtworld = r_shadow_realtime_world.integer;
2092 r_refdef.rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
2093 r_refdef.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
2094 r_refdef.rtdlightshadows = r_refdef.rtdlight && (r_refdef.rtworld ? r_shadow_realtime_world_dlightshadows.integer : r_shadow_realtime_dlight_shadows.integer) && gl_stencil;
2095 r_refdef.lightmapintensity = r_refdef.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
2096 if (r_showsurfaces.integer)
2098 r_refdef.rtworld = false;
2099 r_refdef.rtworldshadows = false;
2100 r_refdef.rtdlight = false;
2101 r_refdef.rtdlightshadows = false;
2102 r_refdef.lightmapintensity = 0;
2105 if (gamemode == GAME_NEHAHRA)
2107 if (gl_fogenable.integer)
2109 r_refdef.oldgl_fogenable = true;
2110 r_refdef.fog_density = gl_fogdensity.value;
2111 r_refdef.fog_red = gl_fogred.value;
2112 r_refdef.fog_green = gl_foggreen.value;
2113 r_refdef.fog_blue = gl_fogblue.value;
2115 else if (r_refdef.oldgl_fogenable)
2117 r_refdef.oldgl_fogenable = false;
2118 r_refdef.fog_density = 0;
2119 r_refdef.fog_red = 0;
2120 r_refdef.fog_green = 0;
2121 r_refdef.fog_blue = 0;
2124 if (r_refdef.fog_density)
2126 r_refdef.fogcolor[0] = bound(0.0f, r_refdef.fog_red , 1.0f);
2127 r_refdef.fogcolor[1] = bound(0.0f, r_refdef.fog_green, 1.0f);
2128 r_refdef.fogcolor[2] = bound(0.0f, r_refdef.fog_blue , 1.0f);
2130 if (r_refdef.fog_density)
2132 r_refdef.fogenabled = true;
2133 // this is the point where the fog reaches 0.9986 alpha, which we
2134 // consider a good enough cutoff point for the texture
2135 // (0.9986 * 256 == 255.6)
2136 r_refdef.fogrange = 400 / r_refdef.fog_density;
2137 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
2138 r_refdef.fogtabledistmultiplier = FOGTABLEWIDTH * r_refdef.fograngerecip;
2139 // fog color was already set
2142 r_refdef.fogenabled = false;
2150 void R_RenderView(void)
2152 if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
2153 return; //Host_Error ("R_RenderView: NULL worldmodel");
2155 R_Shadow_UpdateWorldLightSelection();
2158 if (r_timereport_active)
2159 R_TimeReport("setup");
2162 if (r_timereport_active)
2163 R_TimeReport("visibility");
2165 R_ResetViewRendering3D();
2168 if (r_timereport_active)
2169 R_TimeReport("clear");
2171 R_Bloom_StartFrame();
2173 // this produces a bloom texture to be used in R_BlendView() later
2175 R_HDR_RenderBloomTexture();
2177 r_view.colorscale = r_hdr_scenebrightness.value;
2181 if (r_timereport_active)
2182 R_TimeReport("blendview");
2184 GL_Scissor(0, 0, vid.width, vid.height);
2185 GL_ScissorTest(false);
2189 extern void R_DrawLightningBeams (void);
2190 extern void VM_CL_AddPolygonsToMeshQueue (void);
2191 extern void R_DrawPortals (void);
2192 void R_RenderScene(void)
2194 // don't let sound skip if going slow
2195 if (r_refdef.extraupdate)
2198 R_ResetViewRendering3D();
2200 R_MeshQueue_BeginScene();
2204 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);
2206 if (cl.csqc_vidvars.drawworld)
2208 // don't let sound skip if going slow
2209 if (r_refdef.extraupdate)
2212 if (r_refdef.worldmodel && r_refdef.worldmodel->DrawSky)
2214 r_refdef.worldmodel->DrawSky(r_refdef.worldentity);
2215 if (r_timereport_active)
2216 R_TimeReport("worldsky");
2219 if (R_DrawBrushModelsSky() && r_timereport_active)
2220 R_TimeReport("bmodelsky");
2222 if (r_refdef.worldmodel && r_refdef.worldmodel->Draw)
2224 r_refdef.worldmodel->Draw(r_refdef.worldentity);
2225 if (r_timereport_active)
2226 R_TimeReport("world");
2230 // don't let sound skip if going slow
2231 if (r_refdef.extraupdate)
2235 if (r_timereport_active)
2236 R_TimeReport("models");
2238 // don't let sound skip if going slow
2239 if (r_refdef.extraupdate)
2242 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
2244 R_DrawModelShadows();
2246 R_ResetViewRendering3D();
2248 // don't let sound skip if going slow
2249 if (r_refdef.extraupdate)
2253 R_ShadowVolumeLighting(false);
2254 if (r_timereport_active)
2255 R_TimeReport("rtlights");
2257 // don't let sound skip if going slow
2258 if (r_refdef.extraupdate)
2261 if (cl.csqc_vidvars.drawworld)
2263 R_DrawLightningBeams();
2264 if (r_timereport_active)
2265 R_TimeReport("lightning");
2268 if (r_timereport_active)
2269 R_TimeReport("particles");
2272 if (r_timereport_active)
2273 R_TimeReport("explosions");
2276 if (gl_support_fragment_shader)
2278 qglUseProgramObjectARB(0);CHECKGLERROR
2280 VM_CL_AddPolygonsToMeshQueue();
2282 if (r_drawportals.integer)
2285 if (r_timereport_active)
2286 R_TimeReport("portals");
2289 if (gl_support_fragment_shader)
2291 qglUseProgramObjectARB(0);CHECKGLERROR
2293 R_MeshQueue_RenderTransparent();
2294 if (r_timereport_active)
2295 R_TimeReport("drawtrans");
2297 if (gl_support_fragment_shader)
2299 qglUseProgramObjectARB(0);CHECKGLERROR
2302 if (cl.csqc_vidvars.drawworld)
2305 if (r_timereport_active)
2306 R_TimeReport("coronas");
2309 // don't let sound skip if going slow
2310 if (r_refdef.extraupdate)
2313 R_ResetViewRendering2D();
2317 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
2320 float *v, *c, f1, f2, diff[3], vertex3f[8*3], color4f[8*4];
2321 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2322 GL_DepthMask(false);
2324 R_Mesh_Matrix(&identitymatrix);
2326 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2];
2327 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
2328 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
2329 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
2330 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
2331 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
2332 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
2333 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
2334 R_FillColors(color, 8, cr, cg, cb, ca);
2335 if (r_refdef.fogenabled)
2337 for (i = 0, v = vertex, c = color;i < 8;i++, v += 4, c += 4)
2339 f2 = VERTEXFOGTABLE(VectorDistance(v, r_view.origin));
2341 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
2342 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
2343 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
2346 R_Mesh_VertexPointer(vertex3f);
2347 R_Mesh_ColorPointer(color);
2348 R_Mesh_ResetTextureState();
2353 int nomodelelements[24] =
2365 float nomodelvertex3f[6*3] =
2375 float nomodelcolor4f[6*4] =
2377 0.0f, 0.0f, 0.5f, 1.0f,
2378 0.0f, 0.0f, 0.5f, 1.0f,
2379 0.0f, 0.5f, 0.0f, 1.0f,
2380 0.0f, 0.5f, 0.0f, 1.0f,
2381 0.5f, 0.0f, 0.0f, 1.0f,
2382 0.5f, 0.0f, 0.0f, 1.0f
2385 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
2390 // this is only called once per entity so numsurfaces is always 1, and
2391 // surfacelist is always {0}, so this code does not handle batches
2392 R_Mesh_Matrix(&ent->matrix);
2394 if (ent->flags & EF_ADDITIVE)
2396 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2397 GL_DepthMask(false);
2399 else if (ent->alpha < 1)
2401 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2402 GL_DepthMask(false);
2406 GL_BlendFunc(GL_ONE, GL_ZERO);
2409 GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
2410 GL_CullFace((ent->effects & EF_DOUBLESIDED) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
2411 R_Mesh_VertexPointer(nomodelvertex3f);
2412 if (r_refdef.fogenabled)
2415 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
2416 R_Mesh_ColorPointer(color4f);
2417 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
2418 f2 = VERTEXFOGTABLE(VectorDistance(org, r_view.origin));
2420 for (i = 0, c = color4f;i < 6;i++, c += 4)
2422 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
2423 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
2424 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
2428 else if (ent->alpha != 1)
2430 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
2431 R_Mesh_ColorPointer(color4f);
2432 for (i = 0, c = color4f;i < 6;i++, c += 4)
2436 R_Mesh_ColorPointer(nomodelcolor4f);
2437 R_Mesh_ResetTextureState();
2438 R_Mesh_Draw(0, 6, 8, nomodelelements);
2441 void R_DrawNoModel(entity_render_t *ent)
2444 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
2445 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
2446 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, r_shadow_rtlight);
2448 // R_DrawNoModelCallback(ent, 0);
2451 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
2453 vec3_t right1, right2, diff, normal;
2455 VectorSubtract (org2, org1, normal);
2457 // calculate 'right' vector for start
2458 VectorSubtract (r_view.origin, org1, diff);
2459 CrossProduct (normal, diff, right1);
2460 VectorNormalize (right1);
2462 // calculate 'right' vector for end
2463 VectorSubtract (r_view.origin, org2, diff);
2464 CrossProduct (normal, diff, right2);
2465 VectorNormalize (right2);
2467 vert[ 0] = org1[0] + width * right1[0];
2468 vert[ 1] = org1[1] + width * right1[1];
2469 vert[ 2] = org1[2] + width * right1[2];
2470 vert[ 3] = org1[0] - width * right1[0];
2471 vert[ 4] = org1[1] - width * right1[1];
2472 vert[ 5] = org1[2] - width * right1[2];
2473 vert[ 6] = org2[0] - width * right2[0];
2474 vert[ 7] = org2[1] - width * right2[1];
2475 vert[ 8] = org2[2] - width * right2[2];
2476 vert[ 9] = org2[0] + width * right2[0];
2477 vert[10] = org2[1] + width * right2[1];
2478 vert[11] = org2[2] + width * right2[2];
2481 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
2483 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)
2485 float fog = 0.0f, ifog;
2488 if (r_refdef.fogenabled)
2489 fog = VERTEXFOGTABLE(VectorDistance(origin, r_view.origin));
2492 R_Mesh_Matrix(&identitymatrix);
2493 GL_BlendFunc(blendfunc1, blendfunc2);
2494 GL_DepthMask(false);
2495 GL_DepthTest(!depthdisable);
2497 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
2498 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
2499 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
2500 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
2501 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
2502 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
2503 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
2504 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
2505 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
2506 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
2507 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
2508 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
2510 R_Mesh_VertexPointer(vertex3f);
2511 R_Mesh_ColorPointer(NULL);
2512 R_Mesh_ResetTextureState();
2513 R_Mesh_TexBind(0, R_GetTexture(texture));
2514 R_Mesh_TexCoordPointer(0, 2, spritetexcoord2f);
2515 // FIXME: fixed function path can't properly handle r_view.colorscale > 1
2516 GL_Color(cr * ifog * r_view.colorscale, cg * ifog * r_view.colorscale, cb * ifog * r_view.colorscale, ca);
2517 R_Mesh_Draw(0, 4, 2, polygonelements);
2519 if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
2521 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
2522 GL_BlendFunc(blendfunc1, GL_ONE);
2523 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);
2524 R_Mesh_Draw(0, 4, 2, polygonelements);
2528 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
2533 VectorSet(v, x, y, z);
2534 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
2535 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
2537 if (i == mesh->numvertices)
2539 if (mesh->numvertices < mesh->maxvertices)
2541 VectorCopy(v, vertex3f);
2542 mesh->numvertices++;
2544 return mesh->numvertices;
2550 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
2554 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
2555 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
2556 e = mesh->element3i + mesh->numtriangles * 3;
2557 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
2559 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
2560 if (mesh->numtriangles < mesh->maxtriangles)
2565 mesh->numtriangles++;
2567 element[1] = element[2];
2571 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
2575 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
2576 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
2577 e = mesh->element3i + mesh->numtriangles * 3;
2578 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
2580 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
2581 if (mesh->numtriangles < mesh->maxtriangles)
2586 mesh->numtriangles++;
2588 element[1] = element[2];
2592 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
2593 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
2595 int planenum, planenum2;
2598 mplane_t *plane, *plane2;
2600 double temppoints[2][256*3];
2601 // figure out how large a bounding box we need to properly compute this brush
2603 for (w = 0;w < numplanes;w++)
2604 maxdist = max(maxdist, planes[w].dist);
2605 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
2606 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
2607 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
2611 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
2612 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
2614 if (planenum2 == planenum)
2616 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);
2619 if (tempnumpoints < 3)
2621 // generate elements forming a triangle fan for this polygon
2622 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
2626 static void R_DrawCollisionBrush(const colbrushf_t *brush)
2629 R_Mesh_VertexPointer(brush->points->v);
2630 i = (int)(((size_t)brush) / sizeof(colbrushf_t));
2631 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);
2632 GL_LockArrays(0, brush->numpoints);
2633 R_Mesh_Draw(0, brush->numpoints, brush->numtriangles, brush->elements);
2634 GL_LockArrays(0, 0);
2637 static void R_DrawCollisionSurface(const entity_render_t *ent, const msurface_t *surface)
2640 if (!surface->num_collisiontriangles)
2642 R_Mesh_VertexPointer(surface->data_collisionvertex3f);
2643 i = (int)(((size_t)surface) / sizeof(msurface_t));
2644 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);
2645 GL_LockArrays(0, surface->num_collisionvertices);
2646 R_Mesh_Draw(0, surface->num_collisionvertices, surface->num_collisiontriangles, surface->data_collisionelement3i);
2647 GL_LockArrays(0, 0);
2650 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)
2652 texturelayer_t *layer;
2653 layer = t->currentlayers + t->currentnumlayers++;
2655 layer->depthmask = depthmask;
2656 layer->blendfunc1 = blendfunc1;
2657 layer->blendfunc2 = blendfunc2;
2658 layer->texture = texture;
2659 layer->texmatrix = *matrix;
2660 layer->color[0] = r * r_view.colorscale;
2661 layer->color[1] = g * r_view.colorscale;
2662 layer->color[2] = b * r_view.colorscale;
2663 layer->color[3] = a;
2666 void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
2668 model_t *model = ent->model;
2670 // switch to an alternate material if this is a q1bsp animated material
2672 texture_t *texture = t;
2673 int s = ent->skinnum;
2674 if ((unsigned int)s >= (unsigned int)model->numskins)
2676 if (model->skinscenes)
2678 if (model->skinscenes[s].framecount > 1)
2679 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
2681 s = model->skinscenes[s].firstframe;
2684 t = t + s * model->num_surfaces;
2687 // use an alternate animation if the entity's frame is not 0,
2688 // and only if the texture has an alternate animation
2689 if (ent->frame != 0 && t->anim_total[1])
2690 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.time * 5.0f) % t->anim_total[1]) : 0];
2692 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.time * 5.0f) % t->anim_total[0]) : 0];
2694 texture->currentframe = t;
2697 // pick a new currentskinframe if the material is animated
2698 if (t->numskinframes >= 2)
2699 t->currentskinframe = t->skinframes + ((int)(t->skinframerate * (cl.time - ent->frame2time)) % t->numskinframes);
2700 if (t->backgroundnumskinframes >= 2)
2701 t->backgroundcurrentskinframe = t->backgroundskinframes + ((int)(t->backgroundskinframerate * (cl.time - ent->frame2time)) % t->backgroundnumskinframes);
2703 t->currentmaterialflags = t->basematerialflags;
2704 t->currentalpha = ent->alpha;
2705 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
2706 t->currentalpha *= r_wateralpha.value;
2707 if (!(ent->flags & RENDER_LIGHT))
2708 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
2709 if (ent->effects & EF_ADDITIVE)
2710 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_TRANSPARENT | MATERIALFLAG_NOSHADOW;
2711 else if (t->currentalpha < 1)
2712 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_TRANSPARENT | MATERIALFLAG_NOSHADOW;
2713 if (ent->effects & EF_DOUBLESIDED)
2714 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
2715 if (ent->effects & EF_NODEPTHTEST)
2716 t->currentmaterialflags |= MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_NOSHADOW;
2717 if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
2718 t->currenttexmatrix = r_waterscrollmatrix;
2720 t->currenttexmatrix = identitymatrix;
2721 if (t->backgroundnumskinframes && !(t->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
2722 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
2724 t->colormapping = VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f);
2725 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
2726 t->glosstexture = r_texture_white;
2727 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
2728 t->backgroundglosstexture = r_texture_white;
2729 t->specularpower = r_shadow_glossexponent.value;
2730 t->specularscale = 0;
2731 if (r_shadow_gloss.integer > 0)
2733 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
2735 if (r_shadow_glossintensity.value > 0)
2737 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_black;
2738 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_black;
2739 t->specularscale = r_shadow_glossintensity.value;
2742 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
2743 t->specularscale = r_shadow_gloss2intensity.value;
2746 t->currentnumlayers = 0;
2747 if (!(t->currentmaterialflags & MATERIALFLAG_NODRAW))
2749 if (gl_lightmaps.integer)
2750 R_Texture_AddLayer(t, true, GL_ONE, GL_ZERO, TEXTURELAYERTYPE_LITTEXTURE, r_texture_white, &identitymatrix, 1, 1, 1, 1);
2751 else if (!(t->currentmaterialflags & MATERIALFLAG_SKY))
2753 int blendfunc1, blendfunc2, depthmask;
2754 if (t->currentmaterialflags & MATERIALFLAG_ADD)
2756 blendfunc1 = GL_SRC_ALPHA;
2757 blendfunc2 = GL_ONE;
2759 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
2761 blendfunc1 = GL_SRC_ALPHA;
2762 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
2764 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
2766 blendfunc1 = t->customblendfunc[0];
2767 blendfunc2 = t->customblendfunc[1];
2771 blendfunc1 = GL_ONE;
2772 blendfunc2 = GL_ZERO;
2774 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
2775 if (t->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL))
2777 rtexture_t *currentbasetexture;
2779 if (r_refdef.fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED))
2780 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
2781 currentbasetexture = (VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) < (1.0f / 1048576.0f) && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
2782 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2784 // fullbright is not affected by r_refdef.lightmapintensity
2785 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
2786 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
2787 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);
2788 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
2789 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);
2795 // q3bsp has no lightmap updates, so the lightstylevalue that
2796 // would normally be baked into the lightmap must be
2797 // applied to the color
2798 if (ent->model->type == mod_brushq3)
2799 colorscale *= r_refdef.lightstylevalue[0] * (1.0f / 256.0f);
2800 colorscale *= r_refdef.lightmapintensity;
2801 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);
2802 if (r_ambient.value >= (1.0f/64.0f))
2803 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);
2804 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
2806 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);
2807 if (r_ambient.value >= (1.0f/64.0f))
2808 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);
2810 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
2812 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);
2813 if (r_ambient.value >= (1.0f/64.0f))
2814 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);
2817 if (t->currentskinframe->glow != NULL)
2818 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);
2819 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
2821 // if this is opaque use alpha blend which will darken the earlier
2824 // if this is an alpha blended material, all the earlier passes
2825 // were darkened by fog already, so we only need to add the fog
2826 // color ontop through the fog mask texture
2828 // if this is an additive blended material, all the earlier passes
2829 // were darkened by fog already, and we should not add fog color
2830 // (because the background was not darkened, there is no fog color
2831 // that was lost behind it).
2832 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);
2839 void R_UpdateAllTextureInfo(entity_render_t *ent)
2843 for (i = 0;i < ent->model->num_textures;i++)
2844 R_UpdateTextureInfo(ent, ent->model->data_textures + i);
2847 int rsurface_array_size = 0;
2848 float *rsurface_array_modelvertex3f = NULL;
2849 float *rsurface_array_modelsvector3f = NULL;
2850 float *rsurface_array_modeltvector3f = NULL;
2851 float *rsurface_array_modelnormal3f = NULL;
2852 float *rsurface_array_deformedvertex3f = NULL;
2853 float *rsurface_array_deformedsvector3f = NULL;
2854 float *rsurface_array_deformedtvector3f = NULL;
2855 float *rsurface_array_deformednormal3f = NULL;
2856 float *rsurface_array_color4f = NULL;
2857 float *rsurface_array_texcoord3f = NULL;
2859 void R_Mesh_ResizeArrays(int newvertices)
2862 if (rsurface_array_size >= newvertices)
2864 if (rsurface_array_modelvertex3f)
2865 Mem_Free(rsurface_array_modelvertex3f);
2866 rsurface_array_size = (newvertices + 1023) & ~1023;
2867 base = (float *)Mem_Alloc(r_main_mempool, rsurface_array_size * sizeof(float[31]));
2868 rsurface_array_modelvertex3f = base + rsurface_array_size * 0;
2869 rsurface_array_modelsvector3f = base + rsurface_array_size * 3;
2870 rsurface_array_modeltvector3f = base + rsurface_array_size * 6;
2871 rsurface_array_modelnormal3f = base + rsurface_array_size * 9;
2872 rsurface_array_deformedvertex3f = base + rsurface_array_size * 12;
2873 rsurface_array_deformedsvector3f = base + rsurface_array_size * 15;
2874 rsurface_array_deformedtvector3f = base + rsurface_array_size * 18;
2875 rsurface_array_deformednormal3f = base + rsurface_array_size * 21;
2876 rsurface_array_texcoord3f = base + rsurface_array_size * 24;
2877 rsurface_array_color4f = base + rsurface_array_size * 27;
2880 float *rsurface_modelvertex3f;
2881 float *rsurface_modelsvector3f;
2882 float *rsurface_modeltvector3f;
2883 float *rsurface_modelnormal3f;
2884 float *rsurface_vertex3f;
2885 float *rsurface_svector3f;
2886 float *rsurface_tvector3f;
2887 float *rsurface_normal3f;
2888 float *rsurface_lightmapcolor4f;
2889 vec3_t rsurface_modelorg;
2890 qboolean rsurface_generatedvertex;
2891 const entity_render_t *rsurface_entity;
2892 const model_t *rsurface_model;
2893 texture_t *rsurface_texture;
2894 qboolean rsurface_uselightmaptexture;
2895 rsurfmode_t rsurface_mode;
2896 int rsurface_lightmode; // 0 = lightmap or fullbright, 1 = color array from q3bsp, 2 = vertex shaded model
2898 void RSurf_CleanUp(void)
2901 if (rsurface_mode == RSURFMODE_GLSL)
2903 qglUseProgramObjectARB(0);CHECKGLERROR
2905 GL_AlphaTest(false);
2906 rsurface_mode = RSURFMODE_NONE;
2907 rsurface_uselightmaptexture = false;
2908 rsurface_texture = NULL;
2911 void RSurf_ActiveWorldEntity(void)
2914 rsurface_entity = r_refdef.worldentity;
2915 rsurface_model = r_refdef.worldmodel;
2916 if (rsurface_array_size < rsurface_model->surfmesh.num_vertices)
2917 R_Mesh_ResizeArrays(rsurface_model->surfmesh.num_vertices);
2918 R_Mesh_Matrix(&identitymatrix);
2919 VectorCopy(r_view.origin, rsurface_modelorg);
2920 rsurface_modelvertex3f = rsurface_model->surfmesh.data_vertex3f;
2921 rsurface_modelsvector3f = rsurface_model->surfmesh.data_svector3f;
2922 rsurface_modeltvector3f = rsurface_model->surfmesh.data_tvector3f;
2923 rsurface_modelnormal3f = rsurface_model->surfmesh.data_normal3f;
2924 rsurface_generatedvertex = false;
2925 rsurface_vertex3f = rsurface_modelvertex3f;
2926 rsurface_svector3f = rsurface_modelsvector3f;
2927 rsurface_tvector3f = rsurface_modeltvector3f;
2928 rsurface_normal3f = rsurface_modelnormal3f;
2931 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
2934 rsurface_entity = ent;
2935 rsurface_model = ent->model;
2936 if (rsurface_array_size < rsurface_model->surfmesh.num_vertices)
2937 R_Mesh_ResizeArrays(rsurface_model->surfmesh.num_vertices);
2938 R_Mesh_Matrix(&ent->matrix);
2939 Matrix4x4_Transform(&ent->inversematrix, r_view.origin, rsurface_modelorg);
2940 if (rsurface_model->surfmesh.isanimated && (rsurface_entity->frameblend[0].lerp != 1 || rsurface_entity->frameblend[0].frame != 0))
2944 rsurface_modelvertex3f = rsurface_array_modelvertex3f;
2945 rsurface_modelsvector3f = rsurface_array_modelsvector3f;
2946 rsurface_modeltvector3f = rsurface_array_modeltvector3f;
2947 rsurface_modelnormal3f = rsurface_array_modelnormal3f;
2948 Mod_Alias_GetMesh_Vertices(rsurface_model, rsurface_entity->frameblend, rsurface_array_modelvertex3f, rsurface_array_modelnormal3f, rsurface_array_modelsvector3f, rsurface_array_modeltvector3f);
2950 else if (wantnormals)
2952 rsurface_modelvertex3f = rsurface_array_modelvertex3f;
2953 rsurface_modelsvector3f = NULL;
2954 rsurface_modeltvector3f = NULL;
2955 rsurface_modelnormal3f = rsurface_array_modelnormal3f;
2956 Mod_Alias_GetMesh_Vertices(rsurface_model, rsurface_entity->frameblend, rsurface_array_modelvertex3f, rsurface_array_modelnormal3f, NULL, NULL);
2960 rsurface_modelvertex3f = rsurface_array_modelvertex3f;
2961 rsurface_modelsvector3f = NULL;
2962 rsurface_modeltvector3f = NULL;
2963 rsurface_modelnormal3f = NULL;
2964 Mod_Alias_GetMesh_Vertices(rsurface_model, rsurface_entity->frameblend, rsurface_array_modelvertex3f, NULL, NULL, NULL);
2966 rsurface_generatedvertex = true;
2970 rsurface_modelvertex3f = rsurface_model->surfmesh.data_vertex3f;
2971 rsurface_modelsvector3f = rsurface_model->surfmesh.data_svector3f;
2972 rsurface_modeltvector3f = rsurface_model->surfmesh.data_tvector3f;
2973 rsurface_modelnormal3f = rsurface_model->surfmesh.data_normal3f;
2974 rsurface_generatedvertex = false;
2976 rsurface_vertex3f = rsurface_modelvertex3f;
2977 rsurface_svector3f = rsurface_modelsvector3f;
2978 rsurface_tvector3f = rsurface_modeltvector3f;
2979 rsurface_normal3f = rsurface_modelnormal3f;
2982 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, msurface_t **texturesurfacelist)
2984 // 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
2985 if (rsurface_generatedvertex)
2987 if (rsurface_texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
2988 generatetangents = true;
2989 if (generatetangents)
2990 generatenormals = true;
2991 if (generatenormals && !rsurface_modelnormal3f)
2993 rsurface_normal3f = rsurface_modelnormal3f = rsurface_array_modelnormal3f;
2994 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);
2996 if (generatetangents && !rsurface_modelsvector3f)
2998 rsurface_svector3f = rsurface_modelsvector3f = rsurface_array_modelsvector3f;
2999 rsurface_tvector3f = rsurface_modeltvector3f = rsurface_array_modeltvector3f;
3000 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);
3003 // 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)
3004 if (rsurface_texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
3006 int texturesurfaceindex;
3007 float center[3], forward[3], right[3], up[3], v[4][3];
3008 matrix4x4_t matrix1, imatrix1;
3009 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_view.forward, forward);
3010 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_view.right, right);
3011 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_view.up, up);
3012 // make deformed versions of only the model vertices used by the specified surfaces
3013 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3016 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3017 // a single autosprite surface can contain multiple sprites...
3018 for (j = 0;j < surface->num_vertices - 3;j += 4)
3020 VectorClear(center);
3021 for (i = 0;i < 4;i++)
3022 VectorAdd(center, (rsurface_modelvertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
3023 VectorScale(center, 0.25f, center);
3024 if (rsurface_texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE2)
3026 forward[0] = rsurface_modelorg[0] - center[0];
3027 forward[1] = rsurface_modelorg[1] - center[1];
3029 VectorNormalize(forward);
3030 right[0] = forward[1];
3031 right[1] = -forward[0];
3033 VectorSet(up, 0, 0, 1);
3035 // FIXME: calculate vectors from triangle edges instead of using texture vectors as an easy way out?
3036 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);
3037 Matrix4x4_Invert_Simple(&imatrix1, &matrix1);
3038 for (i = 0;i < 4;i++)
3039 Matrix4x4_Transform(&imatrix1, (rsurface_modelvertex3f + 3 * surface->num_firstvertex) + (j+i)*3, v[i]);
3040 for (i = 0;i < 4;i++)
3041 VectorMAMAMAM(1, center, v[i][0], forward, v[i][1], right, v[i][2], up, rsurface_array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
3043 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);
3044 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);
3046 rsurface_vertex3f = rsurface_array_deformedvertex3f;
3047 rsurface_svector3f = rsurface_array_deformedsvector3f;
3048 rsurface_tvector3f = rsurface_array_deformedtvector3f;
3049 rsurface_normal3f = rsurface_array_deformednormal3f;
3053 rsurface_vertex3f = rsurface_modelvertex3f;
3054 rsurface_svector3f = rsurface_modelsvector3f;
3055 rsurface_tvector3f = rsurface_modeltvector3f;
3056 rsurface_normal3f = rsurface_modelnormal3f;
3058 R_Mesh_VertexPointer(rsurface_vertex3f);
3061 void RSurf_DrawBatch_Simple(int texturenumsurfaces, msurface_t **texturesurfacelist)
3064 const msurface_t *surface = texturesurfacelist[0];
3065 const msurface_t *surface2;
3070 // TODO: lock all array ranges before render, rather than on each surface
3071 if (texturenumsurfaces == 1)
3073 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
3074 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
3076 else if (r_batchmode.integer == 2)
3078 #define MAXBATCHTRIANGLES 4096
3079 int batchtriangles = 0;
3080 int batchelements[MAXBATCHTRIANGLES*3];
3081 for (i = 0;i < texturenumsurfaces;i = j)
3083 surface = texturesurfacelist[i];
3085 if (surface->num_triangles > MAXBATCHTRIANGLES)
3087 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
3090 memcpy(batchelements, rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
3091 batchtriangles = surface->num_triangles;
3092 firstvertex = surface->num_firstvertex;
3093 endvertex = surface->num_firstvertex + surface->num_vertices;
3094 for (;j < texturenumsurfaces;j++)
3096 surface2 = texturesurfacelist[j];
3097 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
3099 memcpy(batchelements + batchtriangles * 3, rsurface_model->surfmesh.data_element3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
3100 batchtriangles += surface2->num_triangles;
3101 firstvertex = min(firstvertex, surface2->num_firstvertex);
3102 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
3104 surface2 = texturesurfacelist[j-1];
3105 numvertices = endvertex - firstvertex;
3106 R_Mesh_Draw(firstvertex, numvertices, batchtriangles, batchelements);
3109 else if (r_batchmode.integer == 1)
3111 for (i = 0;i < texturenumsurfaces;i = j)
3113 surface = texturesurfacelist[i];
3114 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
3115 if (texturesurfacelist[j] != surface2)
3117 surface2 = texturesurfacelist[j-1];
3118 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
3119 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
3120 GL_LockArrays(surface->num_firstvertex, numvertices);
3121 R_Mesh_Draw(surface->num_firstvertex, numvertices, numtriangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
3126 for (i = 0;i < texturenumsurfaces;i++)
3128 surface = texturesurfacelist[i];
3129 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
3130 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
3135 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit)
3139 const msurface_t *surface = texturesurfacelist[0];
3140 const msurface_t *surface2;
3145 // TODO: lock all array ranges before render, rather than on each surface
3146 if (texturenumsurfaces == 1)
3148 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
3149 if (deluxemaptexunit >= 0)
3150 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
3151 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
3152 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
3154 else if (r_batchmode.integer == 2)
3156 #define MAXBATCHTRIANGLES 4096
3157 int batchtriangles = 0;
3158 int batchelements[MAXBATCHTRIANGLES*3];
3159 for (i = 0;i < texturenumsurfaces;i = j)
3161 surface = texturesurfacelist[i];
3162 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
3163 if (deluxemaptexunit >= 0)
3164 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
3166 if (surface->num_triangles > MAXBATCHTRIANGLES)
3168 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
3171 memcpy(batchelements, rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
3172 batchtriangles = surface->num_triangles;
3173 firstvertex = surface->num_firstvertex;
3174 endvertex = surface->num_firstvertex + surface->num_vertices;
3175 for (;j < texturenumsurfaces;j++)
3177 surface2 = texturesurfacelist[j];
3178 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
3180 memcpy(batchelements + batchtriangles * 3, rsurface_model->surfmesh.data_element3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
3181 batchtriangles += surface2->num_triangles;
3182 firstvertex = min(firstvertex, surface2->num_firstvertex);
3183 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
3185 surface2 = texturesurfacelist[j-1];
3186 numvertices = endvertex - firstvertex;
3187 R_Mesh_Draw(firstvertex, numvertices, batchtriangles, batchelements);
3190 else if (r_batchmode.integer == 1)
3193 Con_Printf("%s batch sizes ignoring lightmap:", rsurface_texture->name);
3194 for (i = 0;i < texturenumsurfaces;i = j)
3196 surface = texturesurfacelist[i];
3197 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
3198 if (texturesurfacelist[j] != surface2)
3200 Con_Printf(" %i", j - i);
3203 Con_Printf("%s batch sizes honoring lightmap:", rsurface_texture->name);
3205 for (i = 0;i < texturenumsurfaces;i = j)
3207 surface = texturesurfacelist[i];
3208 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
3209 if (deluxemaptexunit >= 0)
3210 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
3211 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
3212 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
3215 Con_Printf(" %i", j - i);
3217 surface2 = texturesurfacelist[j-1];
3218 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
3219 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
3220 GL_LockArrays(surface->num_firstvertex, numvertices);
3221 R_Mesh_Draw(surface->num_firstvertex, numvertices, numtriangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
3229 for (i = 0;i < texturenumsurfaces;i++)
3231 surface = texturesurfacelist[i];
3232 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
3233 if (deluxemaptexunit >= 0)
3234 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
3235 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
3236 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
3241 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
3244 int texturesurfaceindex;
3245 if (r_showsurfaces.integer == 2)
3247 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3249 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3250 for (j = 0;j < surface->num_triangles;j++)
3252 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_view.colorscale;
3253 GL_Color(f, f, f, 1);
3254 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, 1, (rsurface_model->surfmesh.data_element3i + 3 * (j + surface->num_firsttriangle)));
3260 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3262 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3263 int k = (int)(((size_t)surface) / sizeof(msurface_t));
3264 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);
3265 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
3266 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
3271 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, msurface_t **texturesurfacelist)
3273 int texturesurfaceindex;
3277 if (rsurface_lightmapcolor4f)
3279 // generate color arrays for the surfaces in this list
3280 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3282 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3283 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)
3285 f = 1 - VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
3295 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3297 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3298 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)
3300 f = 1 - VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
3308 rsurface_lightmapcolor4f = rsurface_array_color4f;
3311 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a)
3313 int texturesurfaceindex;
3316 if (!rsurface_lightmapcolor4f)
3318 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3320 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3321 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)
3329 rsurface_lightmapcolor4f = rsurface_array_color4f;
3332 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
3335 rsurface_lightmapcolor4f = NULL;
3336 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
3337 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
3338 R_Mesh_ColorPointer(rsurface_lightmapcolor4f);
3339 GL_Color(r, g, b, a);
3340 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 0, -1);
3343 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
3345 // TODO: optimize applyfog && applycolor case
3346 // just apply fog if necessary, and tint the fog color array if necessary
3347 rsurface_lightmapcolor4f = NULL;
3348 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
3349 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
3350 R_Mesh_ColorPointer(rsurface_lightmapcolor4f);
3351 GL_Color(r, g, b, a);
3352 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3355 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
3357 int texturesurfaceindex;
3361 if (texturesurfacelist[0]->lightmapinfo && texturesurfacelist[0]->lightmapinfo->stainsamples)
3363 // generate color arrays for the surfaces in this list
3364 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3366 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3367 for (i = 0, c = rsurface_array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
3369 if (surface->lightmapinfo->samples)
3371 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface_model->surfmesh.data_lightmapoffsets + surface->num_firstvertex)[i];
3372 float scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
3373 VectorScale(lm, scale, c);
3374 if (surface->lightmapinfo->styles[1] != 255)
3376 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
3378 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
3379 VectorMA(c, scale, lm, c);
3380 if (surface->lightmapinfo->styles[2] != 255)
3383 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
3384 VectorMA(c, scale, lm, c);
3385 if (surface->lightmapinfo->styles[3] != 255)
3388 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
3389 VectorMA(c, scale, lm, c);
3399 rsurface_lightmapcolor4f = rsurface_array_color4f;
3402 rsurface_lightmapcolor4f = rsurface_model->surfmesh.data_lightmapcolor4f;
3403 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
3404 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
3405 R_Mesh_ColorPointer(rsurface_lightmapcolor4f);
3406 GL_Color(r, g, b, a);
3407 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3410 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
3412 int texturesurfaceindex;
3416 vec3_t ambientcolor;
3417 vec3_t diffusecolor;
3421 VectorCopy(rsurface_entity->modellight_lightdir, lightdir);
3422 ambientcolor[0] = rsurface_entity->modellight_ambient[0] * r * 0.5f;
3423 ambientcolor[1] = rsurface_entity->modellight_ambient[1] * g * 0.5f;
3424 ambientcolor[2] = rsurface_entity->modellight_ambient[2] * b * 0.5f;
3425 diffusecolor[0] = rsurface_entity->modellight_diffuse[0] * r * 0.5f;
3426 diffusecolor[1] = rsurface_entity->modellight_diffuse[1] * g * 0.5f;
3427 diffusecolor[2] = rsurface_entity->modellight_diffuse[2] * b * 0.5f;
3428 if (VectorLength2(diffusecolor) > 0)
3430 // generate color arrays for the surfaces in this list
3431 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3433 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3434 int numverts = surface->num_vertices;
3435 v = rsurface_vertex3f + 3 * surface->num_firstvertex;
3436 c2 = rsurface_normal3f + 3 * surface->num_firstvertex;
3437 c = rsurface_array_color4f + 4 * surface->num_firstvertex;
3438 // q3-style directional shading
3439 for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
3441 if ((f = DotProduct(c2, lightdir)) > 0)
3442 VectorMA(ambientcolor, f, diffusecolor, c);
3444 VectorCopy(ambientcolor, c);
3453 rsurface_lightmapcolor4f = rsurface_array_color4f;
3457 r = ambientcolor[0];
3458 g = ambientcolor[1];
3459 b = ambientcolor[2];
3460 rsurface_lightmapcolor4f = NULL;
3462 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
3463 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
3464 R_Mesh_ColorPointer(rsurface_lightmapcolor4f);
3465 GL_Color(r, g, b, a);
3466 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3469 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
3471 GL_DepthTest(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
3472 GL_CullFace((rsurface_texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
3473 if (rsurface_mode != RSURFMODE_SHOWSURFACES)
3475 rsurface_mode = RSURFMODE_SHOWSURFACES;
3477 GL_BlendFunc(GL_ONE, GL_ZERO);
3478 R_Mesh_ColorPointer(NULL);
3479 R_Mesh_ResetTextureState();
3481 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
3482 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
3485 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, msurface_t **texturesurfacelist)
3487 // transparent sky would be ridiculous
3488 if ((rsurface_texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
3490 if (rsurface_mode != RSURFMODE_SKY)
3492 if (rsurface_mode == RSURFMODE_GLSL)
3494 qglUseProgramObjectARB(0);CHECKGLERROR
3496 rsurface_mode = RSURFMODE_SKY;
3500 skyrendernow = false;
3502 // restore entity matrix
3503 R_Mesh_Matrix(&rsurface_entity->matrix);
3505 GL_DepthTest(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
3506 GL_CullFace((rsurface_texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
3508 // LordHavoc: HalfLife maps have freaky skypolys so don't use
3509 // skymasking on them, and Quake3 never did sky masking (unlike
3510 // software Quake and software Quake2), so disable the sky masking
3511 // in Quake3 maps as it causes problems with q3map2 sky tricks,
3512 // and skymasking also looks very bad when noclipping outside the
3513 // level, so don't use it then either.
3514 if (rsurface_model->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_viewcache.world_novis)
3516 GL_Color(r_refdef.fogcolor[0] * r_view.colorscale, r_refdef.fogcolor[1] * r_view.colorscale, r_refdef.fogcolor[2] * r_view.colorscale, 1);
3517 R_Mesh_ColorPointer(NULL);
3518 R_Mesh_ResetTextureState();
3519 if (skyrendermasked)
3521 // depth-only (masking)
3522 GL_ColorMask(0,0,0,0);
3523 // just to make sure that braindead drivers don't draw
3524 // anything despite that colormask...
3525 GL_BlendFunc(GL_ZERO, GL_ONE);
3530 GL_BlendFunc(GL_ONE, GL_ZERO);
3532 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
3533 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3534 if (skyrendermasked)
3535 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
3539 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, msurface_t **texturesurfacelist)
3541 if (rsurface_mode != RSURFMODE_GLSL)
3543 rsurface_mode = RSURFMODE_GLSL;
3544 R_Mesh_ResetTextureState();
3547 R_SetupSurfaceShader(vec3_origin, rsurface_lightmode == 2);
3548 if (!r_glsl_permutation)
3551 if (rsurface_lightmode == 2)
3552 RSurf_PrepareVerticesForBatch(true, r_glsl_permutation->loc_Texture_Normal, texturenumsurfaces, texturesurfacelist);
3554 RSurf_PrepareVerticesForBatch(r_glsl_permutation->loc_Texture_Normal, r_glsl_permutation->loc_Texture_Normal, texturenumsurfaces, texturesurfacelist);
3555 R_Mesh_TexCoordPointer(0, 2, rsurface_model->surfmesh.data_texcoordtexture2f);
3556 R_Mesh_TexCoordPointer(1, 3, rsurface_svector3f);
3557 R_Mesh_TexCoordPointer(2, 3, rsurface_tvector3f);
3558 R_Mesh_TexCoordPointer(3, 3, rsurface_normal3f);
3559 R_Mesh_TexCoordPointer(4, 2, rsurface_model->surfmesh.data_texcoordlightmap2f);
3561 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
3563 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
3564 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
3565 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
3566 R_Mesh_ColorPointer(NULL);
3568 else if (rsurface_uselightmaptexture)
3570 R_Mesh_TexBind(7, R_GetTexture(texturesurfacelist[0]->lightmaptexture));
3571 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
3572 R_Mesh_TexBind(8, R_GetTexture(texturesurfacelist[0]->deluxemaptexture));
3573 R_Mesh_ColorPointer(NULL);
3577 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
3578 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
3579 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
3580 R_Mesh_ColorPointer(rsurface_model->surfmesh.data_lightmapcolor4f);
3583 if (rsurface_uselightmaptexture && !(rsurface_texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
3584 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 7, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? 8 : -1);
3586 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3587 if (rsurface_texture->backgroundnumskinframes && !(rsurface_texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
3592 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, msurface_t **texturesurfacelist)
3594 // OpenGL 1.3 path - anything not completely ancient
3595 int texturesurfaceindex;
3596 qboolean applycolor;
3600 const texturelayer_t *layer;
3601 if (rsurface_mode != RSURFMODE_MULTIPASS)
3602 rsurface_mode = RSURFMODE_MULTIPASS;
3603 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
3604 for (layerindex = 0, layer = rsurface_texture->currentlayers;layerindex < rsurface_texture->currentnumlayers;layerindex++, layer++)
3607 int layertexrgbscale;
3608 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
3610 if (layerindex == 0)
3614 GL_AlphaTest(false);
3615 qglDepthFunc(GL_EQUAL);CHECKGLERROR
3618 GL_DepthMask(layer->depthmask);
3619 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
3620 if ((layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2) && (gl_combine.integer || layer->depthmask))
3622 layertexrgbscale = 4;
3623 VectorScale(layer->color, 0.25f, layercolor);
3625 else if ((layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1) && (gl_combine.integer || layer->depthmask))
3627 layertexrgbscale = 2;
3628 VectorScale(layer->color, 0.5f, layercolor);
3632 layertexrgbscale = 1;
3633 VectorScale(layer->color, 1.0f, layercolor);
3635 layercolor[3] = layer->color[3];
3636 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
3637 R_Mesh_ColorPointer(NULL);
3638 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
3639 switch (layer->type)
3641 case TEXTURELAYERTYPE_LITTEXTURE:
3642 memset(&m, 0, sizeof(m));
3643 m.tex[0] = R_GetTexture(r_texture_white);
3644 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordlightmap2f;
3645 m.tex[1] = R_GetTexture(layer->texture);
3646 m.texmatrix[1] = layer->texmatrix;
3647 m.texrgbscale[1] = layertexrgbscale;
3648 m.pointer_texcoord[1] = rsurface_model->surfmesh.data_texcoordtexture2f;
3649 R_Mesh_TextureState(&m);
3650 if (rsurface_lightmode == 2)
3651 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
3652 else if (rsurface_uselightmaptexture)
3653 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
3655 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
3657 case TEXTURELAYERTYPE_TEXTURE:
3658 memset(&m, 0, sizeof(m));
3659 m.tex[0] = R_GetTexture(layer->texture);
3660 m.texmatrix[0] = layer->texmatrix;
3661 m.texrgbscale[0] = layertexrgbscale;
3662 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3663 R_Mesh_TextureState(&m);
3664 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
3666 case TEXTURELAYERTYPE_FOG:
3667 memset(&m, 0, sizeof(m));
3668 m.texrgbscale[0] = layertexrgbscale;
3671 m.tex[0] = R_GetTexture(layer->texture);
3672 m.texmatrix[0] = layer->texmatrix;
3673 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3675 R_Mesh_TextureState(&m);
3676 // generate a color array for the fog pass
3677 R_Mesh_ColorPointer(rsurface_array_color4f);
3678 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3682 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3683 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)
3685 f = VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
3686 c[0] = layercolor[0];
3687 c[1] = layercolor[1];
3688 c[2] = layercolor[2];
3689 c[3] = f * layercolor[3];
3692 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3695 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
3697 GL_LockArrays(0, 0);
3700 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
3702 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3703 GL_AlphaTest(false);
3707 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, msurface_t **texturesurfacelist)
3709 // OpenGL 1.1 - crusty old voodoo path
3710 int texturesurfaceindex;
3714 const texturelayer_t *layer;
3715 if (rsurface_mode != RSURFMODE_MULTIPASS)
3716 rsurface_mode = RSURFMODE_MULTIPASS;
3717 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
3718 for (layerindex = 0, layer = rsurface_texture->currentlayers;layerindex < rsurface_texture->currentnumlayers;layerindex++, layer++)
3720 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
3722 if (layerindex == 0)
3726 GL_AlphaTest(false);
3727 qglDepthFunc(GL_EQUAL);CHECKGLERROR
3730 GL_DepthMask(layer->depthmask);
3731 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
3732 R_Mesh_ColorPointer(NULL);
3733 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
3734 switch (layer->type)
3736 case TEXTURELAYERTYPE_LITTEXTURE:
3737 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
3739 // two-pass lit texture with 2x rgbscale
3740 // first the lightmap pass
3741 memset(&m, 0, sizeof(m));
3742 m.tex[0] = R_GetTexture(r_texture_white);
3743 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordlightmap2f;
3744 R_Mesh_TextureState(&m);
3745 if (rsurface_lightmode == 2)
3746 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
3747 else if (rsurface_uselightmaptexture)
3748 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
3750 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
3751 GL_LockArrays(0, 0);
3752 // then apply the texture to it
3753 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
3754 memset(&m, 0, sizeof(m));
3755 m.tex[0] = R_GetTexture(layer->texture);
3756 m.texmatrix[0] = layer->texmatrix;
3757 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3758 R_Mesh_TextureState(&m);
3759 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);
3763 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
3764 memset(&m, 0, sizeof(m));
3765 m.tex[0] = R_GetTexture(layer->texture);
3766 m.texmatrix[0] = layer->texmatrix;
3767 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3768 R_Mesh_TextureState(&m);
3769 if (rsurface_lightmode == 2)
3770 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);
3772 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);
3775 case TEXTURELAYERTYPE_TEXTURE:
3776 // singletexture unlit texture with transparency support
3777 memset(&m, 0, sizeof(m));
3778 m.tex[0] = R_GetTexture(layer->texture);
3779 m.texmatrix[0] = layer->texmatrix;
3780 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3781 R_Mesh_TextureState(&m);
3782 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);
3784 case TEXTURELAYERTYPE_FOG:
3785 // singletexture fogging
3786 R_Mesh_ColorPointer(rsurface_array_color4f);
3789 memset(&m, 0, sizeof(m));
3790 m.tex[0] = R_GetTexture(layer->texture);
3791 m.texmatrix[0] = layer->texmatrix;
3792 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3793 R_Mesh_TextureState(&m);
3796 R_Mesh_ResetTextureState();
3797 // generate a color array for the fog pass
3798 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3802 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3803 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)
3805 f = VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
3806 c[0] = layer->color[0];
3807 c[1] = layer->color[1];
3808 c[2] = layer->color[2];
3809 c[3] = f * layer->color[3];
3812 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3815 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
3817 GL_LockArrays(0, 0);
3820 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
3822 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3823 GL_AlphaTest(false);
3827 static void R_DrawTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist)
3829 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_NODRAW)
3831 r_shadow_rtlight = NULL;
3832 r_refdef.stats.entities_surfaces += texturenumsurfaces;
3834 if (r_showsurfaces.integer)
3835 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
3836 else if (rsurface_texture->currentmaterialflags & MATERIALFLAG_SKY)
3837 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
3838 else if (rsurface_texture->currentnumlayers)
3840 GL_DepthTest(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
3841 GL_CullFace((rsurface_texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
3842 GL_BlendFunc(rsurface_texture->currentlayers[0].blendfunc1, rsurface_texture->currentlayers[0].blendfunc2);
3843 GL_DepthMask(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_BLENDED));
3844 GL_Color(rsurface_entity->colormod[0], rsurface_entity->colormod[1], rsurface_entity->colormod[2], rsurface_texture->currentalpha);
3845 GL_AlphaTest((rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
3846 // FIXME: identify models using a better check than rsurface_model->brush.shadowmesh
3847 rsurface_lightmode = ((rsurface_texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT) || rsurface_model->brush.shadowmesh) ? 0 : 2;
3848 if (r_glsl.integer && gl_support_fragment_shader)
3849 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist);
3850 else if (gl_combine.integer && r_textureunits.integer >= 2)
3851 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist);
3853 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist);
3856 GL_LockArrays(0, 0);
3859 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
3862 int texturenumsurfaces, endsurface;
3864 msurface_t *surface;
3865 msurface_t *texturesurfacelist[1024];
3867 // if the model is static it doesn't matter what value we give for
3868 // wantnormals and wanttangents, so this logic uses only rules applicable
3869 // to a model, knowing that they are meaningless otherwise
3870 if (ent == r_refdef.worldentity)
3871 RSurf_ActiveWorldEntity();
3872 else if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
3873 RSurf_ActiveModelEntity(ent, false, false);
3875 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
3877 for (i = 0;i < numsurfaces;i = j)
3880 surface = rsurface_model->data_surfaces + surfacelist[i];
3881 texture = surface->texture;
3882 rsurface_texture = texture->currentframe;
3883 rsurface_uselightmaptexture = surface->lightmaptexture != NULL;
3884 // scan ahead until we find a different texture
3885 endsurface = min(i + 1024, numsurfaces);
3886 texturenumsurfaces = 0;
3887 texturesurfacelist[texturenumsurfaces++] = surface;
3888 for (;j < endsurface;j++)
3890 surface = rsurface_model->data_surfaces + surfacelist[j];
3891 if (texture != surface->texture || rsurface_uselightmaptexture != (surface->lightmaptexture != NULL))
3893 texturesurfacelist[texturenumsurfaces++] = surface;
3895 // render the range of surfaces
3896 R_DrawTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
3902 void R_QueueSurfaceList(int numsurfaces, msurface_t **surfacelist, int flagsmask)
3905 vec3_t tempcenter, center;
3907 // break the surface list down into batches by texture and use of lightmapping
3908 for (i = 0;i < numsurfaces;i = j)
3911 // texture is the base texture pointer, rsurface_texture is the
3912 // current frame/skin the texture is directing us to use (for example
3913 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
3914 // use skin 1 instead)
3915 texture = surfacelist[i]->texture;
3916 rsurface_texture = texture->currentframe;
3917 rsurface_uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
3918 if (!(rsurface_texture->currentmaterialflags & flagsmask))
3920 // if this texture is not the kind we want, skip ahead to the next one
3921 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
3925 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_BLENDED)
3927 // transparent surfaces get pushed off into the transparent queue
3928 const msurface_t *surface = surfacelist[i];
3929 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
3930 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
3931 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
3932 Matrix4x4_Transform(&rsurface_entity->matrix, tempcenter, center);
3933 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);
3937 // simply scan ahead until we find a different texture or lightmap state
3938 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface_uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
3940 // render the range of surfaces
3941 R_DrawTextureSurfaceList(j - i, surfacelist + i);
3946 void R_DrawCollisionBrushes(entity_render_t *ent)
3950 msurface_t *surface;
3951 model_t *model = ent->model;
3952 if (!model->brush.num_brushes)
3955 R_Mesh_ColorPointer(NULL);
3956 R_Mesh_ResetTextureState();
3957 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
3958 GL_DepthMask(false);
3959 GL_DepthTest(!r_showdisabledepthtest.integer);
3960 qglPolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);CHECKGLERROR
3961 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
3962 if (brush->colbrushf && brush->colbrushf->numtriangles)
3963 R_DrawCollisionBrush(brush->colbrushf);
3964 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
3965 if (surface->num_collisiontriangles)
3966 R_DrawCollisionSurface(ent, surface);
3967 qglPolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR
3970 void R_DrawTrianglesAndNormals(entity_render_t *ent, qboolean drawtris, qboolean drawnormals, int flagsmask)
3973 const int *elements;
3974 msurface_t *surface;
3975 model_t *model = ent->model;
3978 GL_DepthTest(!r_showdisabledepthtest.integer);
3980 GL_BlendFunc(GL_ONE, GL_ZERO);
3981 R_Mesh_ColorPointer(NULL);
3982 R_Mesh_ResetTextureState();
3983 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
3985 if (ent == r_refdef.worldentity && !r_viewcache.world_surfacevisible[j])
3987 rsurface_texture = surface->texture->currentframe;
3988 if ((rsurface_texture->currentmaterialflags & flagsmask) && surface->num_triangles)
3990 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
3993 if (!rsurface_texture->currentlayers->depthmask)
3994 GL_Color(r_showtris.value * r_view.colorscale, 0, 0, 1);
3995 else if (ent == r_refdef.worldentity)
3996 GL_Color(r_showtris.value * r_view.colorscale, r_showtris.value * r_view.colorscale, r_showtris.value * r_view.colorscale, 1);
3998 GL_Color(0, r_showtris.value * r_view.colorscale, 0, 1);
3999 elements = (ent->model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
4002 for (k = 0;k < surface->num_triangles;k++, elements += 3)
4004 qglArrayElement(elements[0]);qglArrayElement(elements[1]);
4005 qglArrayElement(elements[1]);qglArrayElement(elements[2]);
4006 qglArrayElement(elements[2]);qglArrayElement(elements[0]);
4013 GL_Color(r_shownormals.value * r_view.colorscale, 0, 0, 1);
4015 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
4017 VectorCopy(rsurface_vertex3f + l * 3, v);
4018 qglVertex3f(v[0], v[1], v[2]);
4019 VectorMA(v, 8, rsurface_svector3f + l * 3, v);
4020 qglVertex3f(v[0], v[1], v[2]);
4024 GL_Color(0, 0, r_shownormals.value * r_view.colorscale, 1);
4026 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
4028 VectorCopy(rsurface_vertex3f + l * 3, v);
4029 qglVertex3f(v[0], v[1], v[2]);
4030 VectorMA(v, 8, rsurface_tvector3f + l * 3, v);
4031 qglVertex3f(v[0], v[1], v[2]);
4035 GL_Color(0, r_shownormals.value * r_view.colorscale, 0, 1);
4037 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
4039 VectorCopy(rsurface_vertex3f + l * 3, v);
4040 qglVertex3f(v[0], v[1], v[2]);
4041 VectorMA(v, 8, rsurface_normal3f + l * 3, v);
4042 qglVertex3f(v[0], v[1], v[2]);
4049 rsurface_texture = NULL;
4052 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
4053 void R_DrawWorldSurfaces(qboolean skysurfaces)
4055 int i, j, endj, f, flagsmask;
4056 int counttriangles = 0;
4057 msurface_t *surface, **surfacechain;
4059 model_t *model = r_refdef.worldmodel;
4060 const int maxsurfacelist = 1024;
4061 int numsurfacelist = 0;
4062 msurface_t *surfacelist[1024];
4066 RSurf_ActiveWorldEntity();
4068 // update light styles
4069 if (!skysurfaces && model->brushq1.light_styleupdatechains)
4071 for (i = 0;i < model->brushq1.light_styles;i++)
4073 if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
4075 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
4076 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
4077 for (;(surface = *surfacechain);surfacechain++)
4078 surface->cached_dlight = true;
4083 R_UpdateAllTextureInfo(r_refdef.worldentity);
4084 flagsmask = skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL);
4087 rsurface_uselightmaptexture = false;
4088 rsurface_texture = NULL;
4090 j = model->firstmodelsurface;
4091 endj = j + model->nummodelsurfaces;
4094 // quickly skip over non-visible surfaces
4095 for (;j < endj && !r_viewcache.world_surfacevisible[j];j++)
4097 // quickly iterate over visible surfaces
4098 for (;j < endj && r_viewcache.world_surfacevisible[j];j++)
4100 // process this surface
4101 surface = model->data_surfaces + j;
4102 // if this surface fits the criteria, add it to the list
4103 if (surface->num_triangles)
4105 // if lightmap parameters changed, rebuild lightmap texture
4106 if (surface->cached_dlight)
4107 R_BuildLightMap(r_refdef.worldentity, surface);
4108 // add face to draw list
4109 surfacelist[numsurfacelist++] = surface;
4110 counttriangles += surface->num_triangles;
4111 if (numsurfacelist >= maxsurfacelist)
4113 R_QueueSurfaceList(numsurfacelist, surfacelist, flagsmask);
4120 R_QueueSurfaceList(numsurfacelist, surfacelist, flagsmask);
4121 r_refdef.stats.entities_triangles += counttriangles;
4124 if (r_showcollisionbrushes.integer && !skysurfaces)
4125 R_DrawCollisionBrushes(r_refdef.worldentity);
4127 if (r_showtris.integer || r_shownormals.integer)
4128 R_DrawTrianglesAndNormals(r_refdef.worldentity, r_showtris.integer, r_shownormals.integer, flagsmask);
4131 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces)
4133 int i, f, flagsmask;
4134 int counttriangles = 0;
4135 msurface_t *surface, *endsurface, **surfacechain;
4137 model_t *model = ent->model;
4138 const int maxsurfacelist = 1024;
4139 int numsurfacelist = 0;
4140 msurface_t *surfacelist[1024];
4144 // if the model is static it doesn't matter what value we give for
4145 // wantnormals and wanttangents, so this logic uses only rules applicable
4146 // to a model, knowing that they are meaningless otherwise
4147 if (ent == r_refdef.worldentity)
4148 RSurf_ActiveWorldEntity();
4149 else if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
4150 RSurf_ActiveModelEntity(ent, false, false);
4152 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
4154 // update light styles
4155 if (!skysurfaces && model->brushq1.light_styleupdatechains)
4157 for (i = 0;i < model->brushq1.light_styles;i++)
4159 if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
4161 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
4162 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
4163 for (;(surface = *surfacechain);surfacechain++)
4164 surface->cached_dlight = true;
4169 R_UpdateAllTextureInfo(ent);
4170 flagsmask = skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL);
4173 rsurface_uselightmaptexture = false;
4174 rsurface_texture = NULL;
4176 surface = model->data_surfaces + model->firstmodelsurface;
4177 endsurface = surface + model->nummodelsurfaces;
4178 for (;surface < endsurface;surface++)
4180 // if this surface fits the criteria, add it to the list
4181 if (surface->num_triangles)
4183 // if lightmap parameters changed, rebuild lightmap texture
4184 if (surface->cached_dlight)
4185 R_BuildLightMap(ent, surface);
4186 // add face to draw list
4187 surfacelist[numsurfacelist++] = surface;
4188 counttriangles += surface->num_triangles;
4189 if (numsurfacelist >= maxsurfacelist)
4191 R_QueueSurfaceList(numsurfacelist, surfacelist, flagsmask);
4197 R_QueueSurfaceList(numsurfacelist, surfacelist, flagsmask);
4198 r_refdef.stats.entities_triangles += counttriangles;
4201 if (r_showcollisionbrushes.integer && !skysurfaces)
4202 R_DrawCollisionBrushes(ent);
4204 if (r_showtris.integer || r_shownormals.integer)
4205 R_DrawTrianglesAndNormals(ent, r_showtris.integer, r_shownormals.integer, flagsmask);