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.
27 mempool_t *r_main_mempool;
28 rtexturepool_t *r_main_texturepool;
35 r_viewcache_t r_viewcache;
37 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
38 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%, 10 = 100%)"};
39 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)"};
40 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
41 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
42 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"};
43 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"};
44 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
45 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"};
46 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"};
47 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"};
48 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
49 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
50 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
51 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
52 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling"};
53 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
54 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
55 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
56 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
57 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
58 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
59 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
60 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this)"};
61 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
62 cvar_t r_q1bsp_skymasking = {0, "r_qb1sp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
64 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
65 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
66 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
67 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
68 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
69 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
70 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
72 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)"};
74 cvar_t r_glsl = {CVAR_SAVE, "r_glsl", "1", "enables use of OpenGL 2.0 pixel shaders for lighting"};
75 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
76 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
77 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
78 cvar_t r_glsl_deluxemapping = {CVAR_SAVE, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"};
80 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1", "enables animation smoothing on sprites (requires r_lerpmodels 1)"};
81 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
82 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
84 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
85 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
86 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
87 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
88 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
89 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
90 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
92 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
93 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
94 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
95 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)"};
97 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"};
99 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"};
101 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
103 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
104 cvar_t r_batchmode = {0, "r_batchmode", "1", "selects method of rendering multiple surfaces with one driver call (values are 0, 1, 2, etc...)"};
106 typedef struct r_glsl_bloomshader_s
109 int loc_Texture_Bloom;
111 r_glsl_bloomshader_t;
113 static struct r_bloomstate_s
118 int bloomwidth, bloomheight;
120 int screentexturewidth, screentextureheight;
121 rtexture_t *texture_screen;
123 int bloomtexturewidth, bloomtextureheight;
124 rtexture_t *texture_bloom;
126 r_glsl_bloomshader_t *shader;
128 // arrays for rendering the screen passes
129 float screentexcoord2f[8];
130 float bloomtexcoord2f[8];
131 float offsettexcoord2f[8];
135 // shadow volume bsp struct with automatically growing nodes buffer
138 rtexture_t *r_texture_blanknormalmap;
139 rtexture_t *r_texture_white;
140 rtexture_t *r_texture_black;
141 rtexture_t *r_texture_notexture;
142 rtexture_t *r_texture_whitecube;
143 rtexture_t *r_texture_normalizationcube;
144 rtexture_t *r_texture_fogattenuation;
145 //rtexture_t *r_texture_fogintensity;
147 // information about each possible shader permutation
148 r_glsl_permutation_t r_glsl_permutations[SHADERPERMUTATION_MAX];
149 // currently selected permutation
150 r_glsl_permutation_t *r_glsl_permutation;
152 // vertex coordinates for a quad that covers the screen exactly
153 const static float r_screenvertex3f[12] =
161 extern void R_DrawModelShadows(void);
163 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
166 for (i = 0;i < verts;i++)
177 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
180 for (i = 0;i < verts;i++)
190 // FIXME: move this to client?
193 if (gamemode == GAME_NEHAHRA)
195 Cvar_Set("gl_fogenable", "0");
196 Cvar_Set("gl_fogdensity", "0.2");
197 Cvar_Set("gl_fogred", "0.3");
198 Cvar_Set("gl_foggreen", "0.3");
199 Cvar_Set("gl_fogblue", "0.3");
201 r_refdef.fog_density = r_refdef.fog_red = r_refdef.fog_green = r_refdef.fog_blue = 0.0f;
204 float FogPoint_World(const vec3_t p)
206 int fogmasktableindex = (int)(VectorDistance((p), r_view.origin) * r_refdef.fogmasktabledistmultiplier);
207 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
210 float FogPoint_Model(const vec3_t p)
212 int fogmasktableindex = (int)(VectorDistance((p), rsurface_modelorg) * r_refdef.fogmasktabledistmultiplier);
213 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
216 static void R_BuildBlankTextures(void)
218 unsigned char data[4];
219 data[0] = 128; // normal X
220 data[1] = 128; // normal Y
221 data[2] = 255; // normal Z
222 data[3] = 128; // height
223 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
228 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
233 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
236 static void R_BuildNoTexture(void)
239 unsigned char pix[16][16][4];
240 // this makes a light grey/dark grey checkerboard texture
241 for (y = 0;y < 16;y++)
243 for (x = 0;x < 16;x++)
245 if ((y < 8) ^ (x < 8))
261 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_RGBA, TEXF_MIPMAP, NULL);
264 static void R_BuildWhiteCube(void)
266 unsigned char data[6*1*1*4];
267 data[ 0] = 255;data[ 1] = 255;data[ 2] = 255;data[ 3] = 255;
268 data[ 4] = 255;data[ 5] = 255;data[ 6] = 255;data[ 7] = 255;
269 data[ 8] = 255;data[ 9] = 255;data[10] = 255;data[11] = 255;
270 data[12] = 255;data[13] = 255;data[14] = 255;data[15] = 255;
271 data[16] = 255;data[17] = 255;data[18] = 255;data[19] = 255;
272 data[20] = 255;data[21] = 255;data[22] = 255;data[23] = 255;
273 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
276 static void R_BuildNormalizationCube(void)
280 vec_t s, t, intensity;
282 unsigned char data[6][NORMSIZE][NORMSIZE][4];
283 for (side = 0;side < 6;side++)
285 for (y = 0;y < NORMSIZE;y++)
287 for (x = 0;x < NORMSIZE;x++)
289 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
290 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
325 intensity = 127.0f / sqrt(DotProduct(v, v));
326 data[side][y][x][0] = (unsigned char)(128.0f + intensity * v[0]);
327 data[side][y][x][1] = (unsigned char)(128.0f + intensity * v[1]);
328 data[side][y][x][2] = (unsigned char)(128.0f + intensity * v[2]);
329 data[side][y][x][3] = 255;
333 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, &data[0][0][0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
336 static void R_BuildFogTexture(void)
340 unsigned char data1[FOGWIDTH][4];
341 //unsigned char data2[FOGWIDTH][4];
342 for (x = 0;x < FOGWIDTH;x++)
344 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
349 //data2[x][0] = 255 - b;
350 //data2[x][1] = 255 - b;
351 //data2[x][2] = 255 - b;
354 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
355 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
358 static const char *builtinshaderstring =
359 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
360 "// written by Forest 'LordHavoc' Hale\n"
362 "// common definitions between vertex shader and fragment shader:\n"
364 "#ifdef __GLSL_CG_DATA_TYPES\n"
365 "#define myhalf half\n"
366 "#define myhvec2 hvec2\n"
367 "#define myhvec3 hvec3\n"
368 "#define myhvec4 hvec4\n"
370 "#define myhalf float\n"
371 "#define myhvec2 vec2\n"
372 "#define myhvec3 vec3\n"
373 "#define myhvec4 vec4\n"
376 "varying vec2 TexCoord;\n"
377 "varying vec2 TexCoordLightmap;\n"
379 "varying vec3 CubeVector;\n"
380 "varying vec3 LightVector;\n"
381 "varying vec3 EyeVector;\n"
383 "varying vec3 EyeVectorModelSpace;\n"
386 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
387 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
388 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
393 "// vertex shader specific:\n"
394 "#ifdef VERTEX_SHADER\n"
396 "uniform vec3 LightPosition;\n"
397 "uniform vec3 EyePosition;\n"
398 "uniform vec3 LightDir;\n"
400 "// TODO: get rid of tangentt (texcoord2) and use a crossproduct to regenerate it from tangents (texcoord1) and normal (texcoord3)\n"
404 " gl_FrontColor = gl_Color;\n"
405 " // copy the surface texcoord\n"
406 " TexCoord = vec2(gl_TextureMatrix[0] * gl_MultiTexCoord0);\n"
407 "#if !defined(MODE_LIGHTSOURCE) && !defined(MODE_LIGHTDIRECTION)\n"
408 " TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
411 "#ifdef MODE_LIGHTSOURCE\n"
412 " // transform vertex position into light attenuation/cubemap space\n"
413 " // (-1 to +1 across the light box)\n"
414 " CubeVector = vec3(gl_TextureMatrix[3] * gl_Vertex);\n"
416 " // transform unnormalized light direction into tangent space\n"
417 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
418 " // normalize it per pixel)\n"
419 " vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
420 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
421 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
422 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
425 "#ifdef MODE_LIGHTDIRECTION\n"
426 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
427 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
428 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
431 " // transform unnormalized eye direction into tangent space\n"
433 " vec3 EyeVectorModelSpace;\n"
435 " EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
436 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
437 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
438 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
440 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
441 " VectorS = gl_MultiTexCoord1.xyz;\n"
442 " VectorT = gl_MultiTexCoord2.xyz;\n"
443 " VectorR = gl_MultiTexCoord3.xyz;\n"
446 " // transform vertex to camera space, using ftransform to match non-VS\n"
448 " gl_Position = ftransform();\n"
451 "#endif // VERTEX_SHADER\n"
456 "// fragment shader specific:\n"
457 "#ifdef FRAGMENT_SHADER\n"
459 "// 11 textures, we can only use up to 16 on DX9-class hardware\n"
460 "uniform sampler2D Texture_Normal;\n"
461 "uniform sampler2D Texture_Color;\n"
462 "uniform sampler2D Texture_Gloss;\n"
463 "uniform samplerCube Texture_Cube;\n"
464 "uniform sampler2D Texture_Attenuation;\n"
465 "uniform sampler2D Texture_FogMask;\n"
466 "uniform sampler2D Texture_Pants;\n"
467 "uniform sampler2D Texture_Shirt;\n"
468 "uniform sampler2D Texture_Lightmap;\n"
469 "uniform sampler2D Texture_Deluxemap;\n"
470 "uniform sampler2D Texture_Glow;\n"
472 "uniform myhvec3 LightColor;\n"
473 "uniform myhvec3 AmbientColor;\n"
474 "uniform myhvec3 DiffuseColor;\n"
475 "uniform myhvec3 SpecularColor;\n"
476 "uniform myhvec3 Color_Pants;\n"
477 "uniform myhvec3 Color_Shirt;\n"
478 "uniform myhvec3 FogColor;\n"
480 "uniform myhalf GlowScale;\n"
481 "uniform myhalf SceneBrightness;\n"
483 "uniform float OffsetMapping_Scale;\n"
484 "uniform float OffsetMapping_Bias;\n"
485 "uniform float FogRangeRecip;\n"
487 "uniform myhalf AmbientScale;\n"
488 "uniform myhalf DiffuseScale;\n"
489 "uniform myhalf SpecularScale;\n"
490 "uniform myhalf SpecularPower;\n"
492 "#ifdef USEOFFSETMAPPING\n"
493 "vec2 OffsetMapping(vec2 TexCoord)\n"
495 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
496 " // 14 sample relief mapping: linear search and then binary search\n"
497 " // this basically steps forward a small amount repeatedly until it finds\n"
498 " // itself inside solid, then jitters forward and back using decreasing\n"
499 " // amounts to find the impact\n"
500 " //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
501 " //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
502 " vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
503 " vec3 RT = vec3(TexCoord, 1);\n"
504 " OffsetVector *= 0.1;\n"
505 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
506 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
507 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
508 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
509 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
510 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
511 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
512 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
513 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
514 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) - 0.5);\n"
515 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5 - 0.25);\n"
516 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25 - 0.125);\n"
517 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125 - 0.0625);\n"
518 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
521 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
522 " // this basically moves forward the full distance, and then backs up based\n"
523 " // on height of samples\n"
524 " //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
525 " //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
526 " vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
527 " TexCoord += OffsetVector;\n"
528 " OffsetVector *= 0.333;\n"
529 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
530 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
531 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
532 " return TexCoord;\n"
539 "#ifdef USEOFFSETMAPPING\n"
540 " // apply offsetmapping\n"
541 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
542 "#define TexCoord TexCoordOffset\n"
545 " // combine the diffuse textures (base, pants, shirt)\n"
546 " myhvec4 color = myhvec4(texture2D(Texture_Color, TexCoord));\n"
547 "#ifdef USECOLORMAPPING\n"
548 " color.rgb += myhvec3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhvec3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
554 "#ifdef MODE_LIGHTSOURCE\n"
557 " // calculate surface normal, light normal, and specular normal\n"
558 " // compute color intensity for the two textures (colormap and glossmap)\n"
559 " // scale by light color and attenuation as efficiently as possible\n"
560 " // (do as much scalar math as possible rather than vector math)\n"
561 "#ifdef USESPECULAR\n"
562 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
563 " myhvec3 diffusenormal = myhvec3(normalize(LightVector));\n"
564 " myhvec3 specularnormal = normalize(diffusenormal + myhvec3(normalize(EyeVector)));\n"
566 " // calculate directional shading\n"
567 " color.rgb = LightColor * myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0))) * (color.rgb * (AmbientScale + DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0))) + (SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower)) * myhvec3(texture2D(Texture_Gloss, TexCoord)));\n"
569 "#ifdef USEDIFFUSE\n"
570 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
571 " myhvec3 diffusenormal = myhvec3(normalize(LightVector));\n"
573 " // calculate directional shading\n"
574 " color.rgb = color.rgb * LightColor * (myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0))) * (AmbientScale + DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0))));\n"
576 " // calculate directionless shading\n"
577 " color.rgb = color.rgb * LightColor * myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
581 "#ifdef USECUBEFILTER\n"
582 " // apply light cubemap filter\n"
583 " //color.rgb *= normalize(CubeVector) * 0.5 + 0.5;//vec3(textureCube(Texture_Cube, CubeVector));\n"
584 " color.rgb *= myhvec3(textureCube(Texture_Cube, CubeVector));\n"
590 "#elif defined(MODE_LIGHTDIRECTION)\n"
591 " // directional model lighting\n"
593 " // get the surface normal and light normal\n"
594 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
595 " myhvec3 diffusenormal = myhvec3(normalize(LightVector));\n"
597 " // calculate directional shading\n"
598 " color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
599 "#ifdef USESPECULAR\n"
600 " myhvec3 specularnormal = normalize(diffusenormal + myhvec3(normalize(EyeVector)));\n"
601 " color.rgb += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
607 "#elif defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
608 " // deluxemap lightmapping using light vectors in modelspace (evil q3map2)\n"
610 " // get the surface normal and light normal\n"
611 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
613 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
614 " myhvec3 diffusenormal_modelspace = myhvec3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - myhvec3(0.5);\n"
615 " myhvec3 diffusenormal = normalize(myhvec3(dot(diffusenormal_modelspace, myhvec3(VectorS)), dot(diffusenormal_modelspace, myhvec3(VectorT)), dot(diffusenormal_modelspace, myhvec3(VectorR))));\n"
617 " myhvec3 diffusenormal = normalize(myhvec3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - myhvec3(0.5));\n"
619 " // calculate directional shading\n"
620 " myhvec3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0)));\n"
621 "#ifdef USESPECULAR\n"
622 " myhvec3 specularnormal = myhvec3(normalize(diffusenormal + myhvec3(normalize(EyeVector))));\n"
623 " tempcolor += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
626 " // apply lightmap color\n"
627 " color.rgb = tempcolor * myhvec3(texture2D(Texture_Lightmap, TexCoordLightmap)) + color.rgb * AmbientScale;\n"
630 "#else // MODE none (lightmap)\n"
631 " // apply lightmap color\n"
632 " color.rgb *= myhvec3(texture2D(Texture_Lightmap, TexCoordLightmap)) * DiffuseScale + myhvec3(AmbientScale);\n"
635 " color *= myhvec4(gl_Color);\n"
638 " color.rgb += myhvec3(texture2D(Texture_Glow, TexCoord)) * GlowScale;\n"
643 " color.rgb = mix(FogColor, color.rgb, myhalf(texture2D(Texture_FogMask, myhvec2(length(EyeVectorModelSpace)*FogRangeRecip, 0.0))));\n"
646 " color.rgb *= SceneBrightness;\n"
648 " gl_FragColor = vec4(color);\n"
651 "#endif // FRAGMENT_SHADER\n"
654 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
655 const char *permutationinfo[][2] =
657 {"#define MODE_LIGHTSOURCE\n", " lightsource"},
658 {"#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
659 {"#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
660 {"#define MODE_LIGHTDIRECTION\n", " lightdirection"},
661 {"#define USEGLOW\n", " glow"},
662 {"#define USEFOG\n", " fog"},
663 {"#define USECOLORMAPPING\n", " colormapping"},
664 {"#define USEDIFFUSE\n", " diffuse"},
665 {"#define USESPECULAR\n", " specular"},
666 {"#define USECUBEFILTER\n", " cubefilter"},
667 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
668 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
672 void R_GLSL_CompilePermutation(const char *filename, int permutation)
675 qboolean shaderfound;
676 r_glsl_permutation_t *p = r_glsl_permutations + (permutation & SHADERPERMUTATION_MASK);
677 int vertstrings_count;
678 int geomstrings_count;
679 int fragstrings_count;
681 const char *vertstrings_list[32+1];
682 const char *geomstrings_list[32+1];
683 const char *fragstrings_list[32+1];
684 char permutationname[256];
689 vertstrings_list[0] = "#define VERTEX_SHADER\n";
690 geomstrings_list[0] = "#define GEOMETRY_SHADER\n";
691 fragstrings_list[0] = "#define FRAGMENT_SHADER\n";
692 vertstrings_count = 1;
693 geomstrings_count = 1;
694 fragstrings_count = 1;
695 permutationname[0] = 0;
696 for (i = 0;permutationinfo[i][0];i++)
698 if (permutation & (1<<i))
700 vertstrings_list[vertstrings_count++] = permutationinfo[i][0];
701 geomstrings_list[geomstrings_count++] = permutationinfo[i][0];
702 fragstrings_list[fragstrings_count++] = permutationinfo[i][0];
703 strlcat(permutationname, permutationinfo[i][1], sizeof(permutationname));
707 // keep line numbers correct
708 vertstrings_list[vertstrings_count++] = "\n";
709 geomstrings_list[geomstrings_count++] = "\n";
710 fragstrings_list[fragstrings_count++] = "\n";
713 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
717 Con_DPrintf("GLSL shader text for \"%s\" loaded from disk\n", filename);
718 vertstrings_list[vertstrings_count++] = shaderstring;
719 geomstrings_list[geomstrings_count++] = shaderstring;
720 fragstrings_list[fragstrings_count++] = shaderstring;
723 else if (!strcmp(filename, "glsl/default.glsl"))
725 Con_DPrintf("GLSL shader text for \"%s\" loaded from engine\n", filename);
726 vertstrings_list[vertstrings_count++] = builtinshaderstring;
727 geomstrings_list[geomstrings_count++] = builtinshaderstring;
728 fragstrings_list[fragstrings_count++] = builtinshaderstring;
731 // clear any lists that are not needed by this shader
732 if (!(permutation & SHADERPERMUTATION_USES_VERTEXSHADER))
733 vertstrings_count = 0;
734 if (!(permutation & SHADERPERMUTATION_USES_GEOMETRYSHADER))
735 geomstrings_count = 0;
736 if (!(permutation & SHADERPERMUTATION_USES_FRAGMENTSHADER))
737 fragstrings_count = 0;
738 // compile the shader program
739 if (shaderfound && vertstrings_count + geomstrings_count + fragstrings_count)
740 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
744 qglUseProgramObjectARB(p->program);CHECKGLERROR
745 // look up all the uniform variable names we care about, so we don't
746 // have to look them up every time we set them
747 p->loc_Texture_Normal = qglGetUniformLocationARB(p->program, "Texture_Normal");
748 p->loc_Texture_Color = qglGetUniformLocationARB(p->program, "Texture_Color");
749 p->loc_Texture_Gloss = qglGetUniformLocationARB(p->program, "Texture_Gloss");
750 p->loc_Texture_Cube = qglGetUniformLocationARB(p->program, "Texture_Cube");
751 p->loc_Texture_Attenuation = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
752 p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
753 p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
754 p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
755 p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
756 p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
757 p->loc_Texture_Glow = qglGetUniformLocationARB(p->program, "Texture_Glow");
758 p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
759 p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
760 p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
761 p->loc_LightColor = qglGetUniformLocationARB(p->program, "LightColor");
762 p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants");
763 p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt");
764 p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip");
765 p->loc_AmbientScale = qglGetUniformLocationARB(p->program, "AmbientScale");
766 p->loc_DiffuseScale = qglGetUniformLocationARB(p->program, "DiffuseScale");
767 p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
768 p->loc_SpecularScale = qglGetUniformLocationARB(p->program, "SpecularScale");
769 p->loc_GlowScale = qglGetUniformLocationARB(p->program, "GlowScale");
770 p->loc_SceneBrightness = qglGetUniformLocationARB(p->program, "SceneBrightness");
771 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
772 p->loc_AmbientColor = qglGetUniformLocationARB(p->program, "AmbientColor");
773 p->loc_DiffuseColor = qglGetUniformLocationARB(p->program, "DiffuseColor");
774 p->loc_SpecularColor = qglGetUniformLocationARB(p->program, "SpecularColor");
775 p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
776 // initialize the samplers to refer to the texture units we use
777 if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal, 0);
778 if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color, 1);
779 if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss, 2);
780 if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube, 3);
781 if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask, 4);
782 if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants, 5);
783 if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt, 6);
784 if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap, 7);
785 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap, 8);
786 if (p->loc_Texture_Glow >= 0) qglUniform1iARB(p->loc_Texture_Glow, 9);
787 if (p->loc_Texture_Attenuation >= 0) qglUniform1iARB(p->loc_Texture_Attenuation, 10);
789 qglUseProgramObjectARB(0);CHECKGLERROR
792 Con_Printf("permutation%s failed for shader %s, some features may not work properly!\n", permutationname, "glsl/default.glsl");
794 Mem_Free(shaderstring);
797 void R_GLSL_Restart_f(void)
800 for (i = 0;i < SHADERPERMUTATION_MAX;i++)
801 if (r_glsl_permutations[i].program)
802 GL_Backend_FreeProgram(r_glsl_permutations[i].program);
803 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
806 extern rtexture_t *r_shadow_attenuationgradienttexture;
807 extern rtexture_t *r_shadow_attenuation2dtexture;
808 extern rtexture_t *r_shadow_attenuation3dtexture;
809 int R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale)
811 // select a permutation of the lighting shader appropriate to this
812 // combination of texture, entity, light source, and fogging, only use the
813 // minimum features necessary to avoid wasting rendering time in the
814 // fragment shader on features that are not being used
815 const char *shaderfilename = NULL;
816 unsigned int permutation = 0;
817 r_glsl_permutation = NULL;
818 // TODO: implement geometry-shader based shadow volumes someday
819 if (r_shadow_rtlight)
822 shaderfilename = "glsl/default.glsl";
823 permutation = SHADERPERMUTATION_MODE_LIGHTSOURCE | SHADERPERMUTATION_USES_VERTEXSHADER | SHADERPERMUTATION_USES_FRAGMENTSHADER;
824 if (r_shadow_rtlight->currentcubemap != r_texture_whitecube)
825 permutation |= SHADERPERMUTATION_CUBEFILTER;
826 if (diffusescale > 0)
827 permutation |= SHADERPERMUTATION_DIFFUSE;
828 if (specularscale > 0)
829 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
830 if (r_refdef.fogenabled)
831 permutation |= SHADERPERMUTATION_FOG;
832 if (rsurface_texture->colormapping)
833 permutation |= SHADERPERMUTATION_COLORMAPPING;
834 if (r_glsl_offsetmapping.integer)
836 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
837 if (r_glsl_offsetmapping_reliefmapping.integer)
838 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
841 else if (rsurface_texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
843 // bright unshaded geometry
844 shaderfilename = "glsl/default.glsl";
845 permutation = SHADERPERMUTATION_USES_VERTEXSHADER | SHADERPERMUTATION_USES_FRAGMENTSHADER;
846 if (rsurface_texture->currentskinframe->glow)
847 permutation |= SHADERPERMUTATION_GLOW;
848 if (r_refdef.fogenabled)
849 permutation |= SHADERPERMUTATION_FOG;
850 if (rsurface_texture->colormapping)
851 permutation |= SHADERPERMUTATION_COLORMAPPING;
852 if (r_glsl_offsetmapping.integer)
854 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
855 if (r_glsl_offsetmapping_reliefmapping.integer)
856 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
859 else if (modellighting)
861 // directional model lighting
862 shaderfilename = "glsl/default.glsl";
863 permutation = SHADERPERMUTATION_USES_VERTEXSHADER | SHADERPERMUTATION_USES_FRAGMENTSHADER;
864 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTION;
865 if (rsurface_texture->currentskinframe->glow)
866 permutation |= SHADERPERMUTATION_GLOW;
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;
883 shaderfilename = "glsl/default.glsl";
884 permutation = SHADERPERMUTATION_USES_VERTEXSHADER | SHADERPERMUTATION_USES_FRAGMENTSHADER;
885 if (r_glsl_deluxemapping.integer >= 1 && rsurface_lightmaptexture && r_refdef.worldmodel && r_refdef.worldmodel->brushq3.deluxemapping)
887 // deluxemapping (light direction texture)
888 if (rsurface_lightmaptexture && r_refdef.worldmodel && r_refdef.worldmodel->brushq3.deluxemapping && r_refdef.worldmodel->brushq3.deluxemapping_modelspace)
889 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_MODELSPACE;
891 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
892 if (specularscale > 0)
893 permutation |= SHADERPERMUTATION_SPECULAR;
895 else if (r_glsl_deluxemapping.integer >= 2)
897 // fake deluxemapping (uniform light direction in tangentspace)
898 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
899 if (specularscale > 0)
900 permutation |= SHADERPERMUTATION_SPECULAR;
904 // ordinary lightmapping
907 if (rsurface_texture->currentskinframe->glow)
908 permutation |= SHADERPERMUTATION_GLOW;
909 if (r_refdef.fogenabled)
910 permutation |= SHADERPERMUTATION_FOG;
911 if (rsurface_texture->colormapping)
912 permutation |= SHADERPERMUTATION_COLORMAPPING;
913 if (r_glsl_offsetmapping.integer)
915 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
916 if (r_glsl_offsetmapping_reliefmapping.integer)
917 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
920 if (!r_glsl_permutations[permutation & SHADERPERMUTATION_MASK].program)
922 if (!r_glsl_permutations[permutation & SHADERPERMUTATION_MASK].compiled)
923 R_GLSL_CompilePermutation(shaderfilename, permutation);
924 if (!r_glsl_permutations[permutation & SHADERPERMUTATION_MASK].program)
926 // remove features until we find a valid permutation
928 for (i = SHADERPERMUTATION_MASK;;i>>=1)
931 return 0; // utterly failed
932 // reduce i more quickly whenever it would not remove any bits
936 if (!r_glsl_permutations[permutation & SHADERPERMUTATION_MASK].compiled)
937 R_GLSL_CompilePermutation(shaderfilename, permutation);
938 if (r_glsl_permutations[permutation & SHADERPERMUTATION_MASK].program)
943 r_glsl_permutation = r_glsl_permutations + (permutation & SHADERPERMUTATION_MASK);
945 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
946 R_Mesh_TexMatrix(0, &rsurface_texture->currenttexmatrix);
947 if (permutation & SHADERPERMUTATION_MODE_LIGHTSOURCE)
949 if (r_glsl_permutation->loc_Texture_Cube >= 0 && r_shadow_rtlight) R_Mesh_TexBindCubeMap(3, R_GetTexture(r_shadow_rtlight->currentcubemap));
950 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]);
951 if (permutation & SHADERPERMUTATION_DIFFUSE)
953 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
954 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, ambientscale);
955 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, diffusescale);
956 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, specularscale);
960 // ambient only is simpler
961 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0] * ambientscale, lightcolorbase[1] * ambientscale, lightcolorbase[2] * ambientscale);
962 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, 1);
963 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, 0);
964 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, 0);
967 else if (permutation & SHADERPERMUTATION_MODE_LIGHTDIRECTION)
969 if (r_glsl_permutation->loc_AmbientColor >= 0)
970 qglUniform3fARB(r_glsl_permutation->loc_AmbientColor, rsurface_entity->modellight_ambient[0] * ambientscale, rsurface_entity->modellight_ambient[1] * ambientscale, rsurface_entity->modellight_ambient[2] * ambientscale);
971 if (r_glsl_permutation->loc_DiffuseColor >= 0)
972 qglUniform3fARB(r_glsl_permutation->loc_DiffuseColor, rsurface_entity->modellight_diffuse[0] * diffusescale, rsurface_entity->modellight_diffuse[1] * diffusescale, rsurface_entity->modellight_diffuse[2] * diffusescale);
973 if (r_glsl_permutation->loc_SpecularColor >= 0)
974 qglUniform3fARB(r_glsl_permutation->loc_SpecularColor, rsurface_entity->modellight_diffuse[0] * specularscale, rsurface_entity->modellight_diffuse[1] * specularscale, rsurface_entity->modellight_diffuse[2] * specularscale);
975 if (r_glsl_permutation->loc_LightDir >= 0)
976 qglUniform3fARB(r_glsl_permutation->loc_LightDir, rsurface_entity->modellight_lightdir[0], rsurface_entity->modellight_lightdir[1], rsurface_entity->modellight_lightdir[2]);
980 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_ambient.value * 2.0f / 128.0f);
981 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_refdef.lightmapintensity * 2.0f);
982 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, r_refdef.lightmapintensity * specularscale * 2.0f);
984 if (r_glsl_permutation->loc_Texture_Normal >= 0) R_Mesh_TexBind(0, R_GetTexture(rsurface_texture->currentskinframe->nmap));
985 if (r_glsl_permutation->loc_Texture_Color >= 0) R_Mesh_TexBind(1, R_GetTexture(rsurface_texture->basetexture));
986 if (r_glsl_permutation->loc_Texture_Gloss >= 0) R_Mesh_TexBind(2, R_GetTexture(rsurface_texture->glosstexture));
987 //if (r_glsl_permutation->loc_Texture_Cube >= 0 && permutation & SHADERPERMUTATION_MODE_LIGHTSOURCE) R_Mesh_TexBindCubeMap(3, R_GetTexture(r_shadow_rtlight->currentcubemap));
988 if (r_glsl_permutation->loc_Texture_Attenuation >= 0) R_Mesh_TexBind(10, R_GetTexture(r_shadow_attenuationgradienttexture));
989 if (r_glsl_permutation->loc_Texture_FogMask >= 0) R_Mesh_TexBind(4, R_GetTexture(r_texture_fogattenuation));
990 if (r_glsl_permutation->loc_Texture_Pants >= 0) R_Mesh_TexBind(5, R_GetTexture(rsurface_texture->currentskinframe->pants));
991 if (r_glsl_permutation->loc_Texture_Shirt >= 0) R_Mesh_TexBind(6, R_GetTexture(rsurface_texture->currentskinframe->shirt));
992 //if (r_glsl_permutation->loc_Texture_Lightmap >= 0) R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
993 //if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
994 if (r_glsl_permutation->loc_Texture_Glow >= 0) R_Mesh_TexBind(9, R_GetTexture(rsurface_texture->currentskinframe->glow));
995 if (r_glsl_permutation->loc_GlowScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_GlowScale, r_hdr_glowintensity.value);
996 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_view.colorscale);
997 if (r_glsl_permutation->loc_FogColor >= 0)
999 // additive passes are only darkened by fog, not tinted
1000 if (r_shadow_rtlight || (rsurface_texture->currentmaterialflags & MATERIALFLAG_ADD))
1001 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
1003 qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
1005 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface_modelorg[0], rsurface_modelorg[1], rsurface_modelorg[2]);
1006 if (r_glsl_permutation->loc_Color_Pants >= 0)
1008 if (rsurface_texture->currentskinframe->pants)
1009 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface_entity->colormap_pantscolor[0], rsurface_entity->colormap_pantscolor[1], rsurface_entity->colormap_pantscolor[2]);
1011 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
1013 if (r_glsl_permutation->loc_Color_Shirt >= 0)
1015 if (rsurface_texture->currentskinframe->shirt)
1016 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface_entity->colormap_shirtcolor[0], rsurface_entity->colormap_shirtcolor[1], rsurface_entity->colormap_shirtcolor[2]);
1018 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
1020 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, r_refdef.fograngerecip);
1021 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface_texture->specularpower);
1022 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
1027 void R_SwitchSurfaceShader(int permutation)
1029 if (r_glsl_permutation != r_glsl_permutations + (permutation & SHADERPERMUTATION_MASK))
1031 r_glsl_permutation = r_glsl_permutations + (permutation & SHADERPERMUTATION_MASK);
1033 qglUseProgramObjectARB(r_glsl_permutation->program);
1038 #define SKINFRAME_HASH 1024
1042 int loadsequence; // incremented each level change
1043 memexpandablearray_t array;
1044 skinframe_t *hash[SKINFRAME_HASH];
1048 void R_SkinFrame_PrepareForPurge(void)
1050 r_skinframe.loadsequence++;
1051 // wrap it without hitting zero
1052 if (r_skinframe.loadsequence >= 200)
1053 r_skinframe.loadsequence = 1;
1056 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
1058 // mark the skinframe as used for the purging code
1059 skinframe->loadsequence = r_skinframe.loadsequence;
1062 void R_SkinFrame_Purge(void)
1066 for (i = 0;i < SKINFRAME_HASH;i++)
1068 for (s = r_skinframe.hash[i];s;s = s->next)
1070 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
1072 if (s->base == r_texture_notexture) s->base = NULL;
1073 if (s->nmap == r_texture_blanknormalmap)s->nmap = NULL;
1074 if (s->merged == s->base) s->merged = NULL;
1075 if (s->stain ) R_FreeTexture(s->stain );s->stain = NULL;
1076 if (s->merged) R_FreeTexture(s->merged);s->merged = NULL;
1077 if (s->base ) R_FreeTexture(s->base );s->base = NULL;
1078 if (s->pants ) R_FreeTexture(s->pants );s->pants = NULL;
1079 if (s->shirt ) R_FreeTexture(s->shirt );s->shirt = NULL;
1080 if (s->nmap ) R_FreeTexture(s->nmap );s->nmap = NULL;
1081 if (s->gloss ) R_FreeTexture(s->gloss );s->gloss = NULL;
1082 if (s->glow ) R_FreeTexture(s->glow );s->glow = NULL;
1083 if (s->fog ) R_FreeTexture(s->fog );s->fog = NULL;
1084 s->loadsequence = 0;
1090 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
1094 char basename[MAX_QPATH];
1096 Image_StripImageExtension(name, basename, sizeof(basename));
1098 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
1099 for (item = r_skinframe.hash[hashindex];item;item = item->next)
1100 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
1106 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
1107 memset(item, 0, sizeof(*item));
1108 strlcpy(item->basename, basename, sizeof(item->basename));
1109 item->textureflags = textureflags;
1110 item->comparewidth = comparewidth;
1111 item->compareheight = compareheight;
1112 item->comparecrc = comparecrc;
1113 item->next = r_skinframe.hash[hashindex];
1114 r_skinframe.hash[hashindex] = item;
1116 R_SkinFrame_MarkUsed(item);
1120 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags)
1122 // FIXME: it should be possible to disable loading various layers using
1123 // cvars, to prevent wasted loading time and memory usage if the user does
1125 qboolean loadnormalmap = true;
1126 qboolean loadgloss = true;
1127 qboolean loadpantsandshirt = true;
1128 qboolean loadglow = true;
1130 unsigned char *pixels;
1131 unsigned char *bumppixels;
1132 unsigned char *basepixels = NULL;
1133 int basepixels_width;
1134 int basepixels_height;
1135 skinframe_t *skinframe;
1137 if (cls.state == ca_dedicated)
1140 // return an existing skinframe if already loaded
1141 // if loading of the first image fails, don't make a new skinframe as it
1142 // would cause all future lookups of this to be missing
1143 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
1144 if (skinframe && skinframe->base)
1147 basepixels = loadimagepixels(name, false, 0, 0);
1148 if (basepixels == NULL)
1151 // we've got some pixels to store, so really allocate this new texture now
1153 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
1154 skinframe->stain = NULL;
1155 skinframe->merged = NULL;
1156 skinframe->base = r_texture_notexture;
1157 skinframe->pants = NULL;
1158 skinframe->shirt = NULL;
1159 skinframe->nmap = r_texture_blanknormalmap;
1160 skinframe->gloss = NULL;
1161 skinframe->glow = NULL;
1162 skinframe->fog = NULL;
1164 basepixels_width = image_width;
1165 basepixels_height = image_height;
1166 skinframe->base = R_LoadTexture2D (r_main_texturepool, skinframe->basename, basepixels_width, basepixels_height, basepixels, TEXTYPE_RGBA, skinframe->textureflags, NULL);
1168 if (textureflags & TEXF_ALPHA)
1170 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
1171 if (basepixels[j] < 255)
1173 if (j < basepixels_width * basepixels_height * 4)
1175 // has transparent pixels
1176 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
1177 for (j = 0;j < image_width * image_height * 4;j += 4)
1182 pixels[j+3] = basepixels[j+3];
1184 skinframe->fog = R_LoadTexture2D (r_main_texturepool, va("%s_mask", skinframe->basename), image_width, image_height, pixels, TEXTYPE_RGBA, skinframe->textureflags, NULL);
1189 // _norm is the name used by tenebrae and has been adopted as standard
1192 if ((pixels = loadimagepixels(va("%s_norm", skinframe->basename), false, 0, 0)) != NULL)
1194 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_RGBA, skinframe->textureflags, NULL);
1198 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixels(va("%s_bump", skinframe->basename), false, 0, 0)) != NULL)
1200 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
1201 Image_HeightmapToNormalmap(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
1202 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_RGBA, skinframe->textureflags, NULL);
1204 Mem_Free(bumppixels);
1206 else if (r_shadow_bumpscale_basetexture.value > 0)
1208 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
1209 Image_HeightmapToNormalmap(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
1210 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), basepixels_width, basepixels_height, pixels, TEXTYPE_RGBA, skinframe->textureflags, NULL);
1214 // _luma is supported for tenebrae compatibility
1215 // (I think it's a very stupid name, but oh well)
1216 // _glow is the preferred name
1217 if (loadglow && ((pixels = loadimagepixels(va("%s_glow", skinframe->basename), false, 0, 0)) != NULL || (pixels = loadimagepixels(va("%s_luma", skinframe->basename), false, 0, 0)) != NULL)) {skinframe->glow = R_LoadTexture2D (r_main_texturepool, va("%s_glow", skinframe->basename), image_width, image_height, pixels, TEXTYPE_RGBA, skinframe->textureflags, NULL);Mem_Free(pixels);pixels = NULL;}
1218 if (loadgloss && (pixels = loadimagepixels(va("%s_gloss", skinframe->basename), false, 0, 0)) != NULL) {skinframe->gloss = R_LoadTexture2D (r_main_texturepool, va("%s_gloss", skinframe->basename), image_width, image_height, pixels, TEXTYPE_RGBA, skinframe->textureflags, NULL);Mem_Free(pixels);pixels = NULL;}
1219 if (loadpantsandshirt && (pixels = loadimagepixels(va("%s_pants", skinframe->basename), false, 0, 0)) != NULL) {skinframe->pants = R_LoadTexture2D (r_main_texturepool, va("%s_pants", skinframe->basename), image_width, image_height, pixels, TEXTYPE_RGBA, skinframe->textureflags, NULL);Mem_Free(pixels);pixels = NULL;}
1220 if (loadpantsandshirt && (pixels = loadimagepixels(va("%s_shirt", skinframe->basename), false, 0, 0)) != NULL) {skinframe->shirt = R_LoadTexture2D (r_main_texturepool, va("%s_shirt", skinframe->basename), image_width, image_height, pixels, TEXTYPE_RGBA, skinframe->textureflags, NULL);Mem_Free(pixels);pixels = NULL;}
1223 Mem_Free(basepixels);
1228 static rtexture_t *R_SkinFrame_TextureForSkinLayer(const unsigned char *in, int width, int height, const char *name, const unsigned int *palette, int textureflags, qboolean force)
1233 for (i = 0;i < width*height;i++)
1234 if (((unsigned char *)&palette[in[i]])[3] > 0)
1236 if (i == width*height)
1239 return R_LoadTexture2D (r_main_texturepool, name, width, height, in, TEXTYPE_PALETTE, textureflags, palette);
1242 skinframe_t *R_SkinFrame_LoadInternal(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height, int bitsperpixel, const unsigned int *palette, const unsigned int *alphapalette)
1245 unsigned char *temp1, *temp2;
1246 skinframe_t *skinframe;
1248 if (cls.state == ca_dedicated)
1251 // if already loaded just return it, otherwise make a new skinframe
1252 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*bitsperpixel/8) : 0, true);
1253 if (skinframe && skinframe->base)
1256 skinframe->stain = NULL;
1257 skinframe->merged = NULL;
1258 skinframe->base = r_texture_notexture;
1259 skinframe->pants = NULL;
1260 skinframe->shirt = NULL;
1261 skinframe->nmap = r_texture_blanknormalmap;
1262 skinframe->gloss = NULL;
1263 skinframe->glow = NULL;
1264 skinframe->fog = NULL;
1266 // if no data was provided, then clearly the caller wanted to get a blank skinframe
1270 if (bitsperpixel == 32)
1272 if (r_shadow_bumpscale_basetexture.value > 0)
1274 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
1275 temp2 = temp1 + width * height * 4;
1276 Image_HeightmapToNormalmap(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
1277 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_RGBA, textureflags | TEXF_ALPHA, NULL);
1280 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_RGBA, textureflags, NULL);
1281 if (textureflags & TEXF_ALPHA)
1283 for (i = 3;i < width * height * 4;i += 4)
1284 if (skindata[i] < 255)
1286 if (i < width * height * 4)
1288 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
1289 memcpy(fogpixels, skindata, width * height * 4);
1290 for (i = 0;i < width * height * 4;i += 4)
1291 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
1292 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_RGBA, textureflags, NULL);
1293 Mem_Free(fogpixels);
1297 else if (bitsperpixel == 8)
1299 if (r_shadow_bumpscale_basetexture.value > 0)
1301 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
1302 temp2 = temp1 + width * height * 4;
1303 if (bitsperpixel == 32)
1304 Image_HeightmapToNormalmap(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
1307 // use either a custom palette or the quake palette
1308 Image_Copy8bitRGBA(skindata, temp1, width * height, palette ? palette : palette_complete);
1309 Image_HeightmapToNormalmap(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
1311 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_RGBA, textureflags | TEXF_ALPHA, NULL);
1314 // use either a custom palette, or the quake palette
1315 skinframe->base = skinframe->merged = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_merged", skinframe->basename), palette ? palette : (loadglowtexture ? palette_nofullbrights : ((textureflags & TEXF_ALPHA) ? palette_transparent : palette_complete)), textureflags, true); // all
1316 if (!palette && loadglowtexture)
1317 skinframe->glow = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_glow", skinframe->basename), palette_onlyfullbrights, textureflags, false); // glow
1318 if (!palette && loadpantsandshirt)
1320 skinframe->pants = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_pants", skinframe->basename), palette_pantsaswhite, textureflags, false); // pants
1321 skinframe->shirt = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_shirt", skinframe->basename), palette_shirtaswhite, textureflags, false); // shirt
1323 if (skinframe->pants || skinframe->shirt)
1324 skinframe->base = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_nospecial", skinframe->basename),loadglowtexture ? palette_nocolormapnofullbrights : palette_nocolormap, textureflags, false); // no special colors
1325 if (textureflags & TEXF_ALPHA)
1327 // if not using a custom alphapalette, use the quake one
1329 alphapalette = palette_alpha;
1330 for (i = 0;i < width * height;i++)
1331 if (((unsigned char *)alphapalette)[skindata[i]*4+3] < 255)
1333 if (i < width * height)
1334 skinframe->fog = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_fog", skinframe->basename), alphapalette, textureflags, true); // fog mask
1341 skinframe_t *R_SkinFrame_LoadMissing(void)
1343 skinframe_t *skinframe;
1345 if (cls.state == ca_dedicated)
1348 skinframe = R_SkinFrame_Find("missing", TEXF_PRECACHE, 0, 0, 0, true);
1349 skinframe->stain = NULL;
1350 skinframe->merged = NULL;
1351 skinframe->base = r_texture_notexture;
1352 skinframe->pants = NULL;
1353 skinframe->shirt = NULL;
1354 skinframe->nmap = r_texture_blanknormalmap;
1355 skinframe->gloss = NULL;
1356 skinframe->glow = NULL;
1357 skinframe->fog = NULL;
1362 void gl_main_start(void)
1367 r = (-1.0/256.0) * (FOGMASKTABLEWIDTH * FOGMASKTABLEWIDTH);
1368 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
1370 alpha = 1 - exp(r / ((double)x*(double)x));
1371 if (x == FOGMASKTABLEWIDTH - 1)
1373 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
1376 // set up r_skinframe loading system for textures
1377 memset(&r_skinframe, 0, sizeof(r_skinframe));
1378 r_skinframe.loadsequence = 1;
1379 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
1381 r_main_texturepool = R_AllocTexturePool();
1382 R_BuildBlankTextures();
1384 if (gl_texturecubemap)
1387 R_BuildNormalizationCube();
1389 R_BuildFogTexture();
1390 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
1391 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
1392 memset(&r_svbsp, 0, sizeof (r_svbsp));
1395 void gl_main_shutdown(void)
1397 // clear out the r_skinframe state
1398 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
1399 memset(&r_skinframe, 0, sizeof(r_skinframe));
1402 Mem_Free(r_svbsp.nodes);
1403 memset(&r_svbsp, 0, sizeof (r_svbsp));
1404 R_FreeTexturePool(&r_main_texturepool);
1405 r_texture_blanknormalmap = NULL;
1406 r_texture_white = NULL;
1407 r_texture_black = NULL;
1408 r_texture_whitecube = NULL;
1409 r_texture_normalizationcube = NULL;
1410 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
1414 extern void CL_ParseEntityLump(char *entitystring);
1415 void gl_main_newmap(void)
1417 // FIXME: move this code to client
1419 char *entities, entname[MAX_QPATH];
1422 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
1423 l = (int)strlen(entname) - 4;
1424 if (l >= 0 && !strcmp(entname + l, ".bsp"))
1426 memcpy(entname + l, ".ent", 5);
1427 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
1429 CL_ParseEntityLump(entities);
1434 if (cl.worldmodel->brush.entities)
1435 CL_ParseEntityLump(cl.worldmodel->brush.entities);
1439 void GL_Main_Init(void)
1441 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
1443 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
1444 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
1445 if (gamemode == GAME_NEHAHRA)
1447 Cvar_RegisterVariable (&gl_fogenable);
1448 Cvar_RegisterVariable (&gl_fogdensity);
1449 Cvar_RegisterVariable (&gl_fogred);
1450 Cvar_RegisterVariable (&gl_foggreen);
1451 Cvar_RegisterVariable (&gl_fogblue);
1452 Cvar_RegisterVariable (&gl_fogstart);
1453 Cvar_RegisterVariable (&gl_fogend);
1455 Cvar_RegisterVariable(&r_nearclip);
1456 Cvar_RegisterVariable(&r_showbboxes);
1457 Cvar_RegisterVariable(&r_showsurfaces);
1458 Cvar_RegisterVariable(&r_showtris);
1459 Cvar_RegisterVariable(&r_shownormals);
1460 Cvar_RegisterVariable(&r_showlighting);
1461 Cvar_RegisterVariable(&r_showshadowvolumes);
1462 Cvar_RegisterVariable(&r_showcollisionbrushes);
1463 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
1464 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
1465 Cvar_RegisterVariable(&r_showdisabledepthtest);
1466 Cvar_RegisterVariable(&r_drawportals);
1467 Cvar_RegisterVariable(&r_drawentities);
1468 Cvar_RegisterVariable(&r_cullentities_trace);
1469 Cvar_RegisterVariable(&r_cullentities_trace_samples);
1470 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
1471 Cvar_RegisterVariable(&r_cullentities_trace_delay);
1472 Cvar_RegisterVariable(&r_drawviewmodel);
1473 Cvar_RegisterVariable(&r_speeds);
1474 Cvar_RegisterVariable(&r_fullbrights);
1475 Cvar_RegisterVariable(&r_wateralpha);
1476 Cvar_RegisterVariable(&r_dynamic);
1477 Cvar_RegisterVariable(&r_fullbright);
1478 Cvar_RegisterVariable(&r_shadows);
1479 Cvar_RegisterVariable(&r_shadows_throwdistance);
1480 Cvar_RegisterVariable(&r_q1bsp_skymasking);
1481 Cvar_RegisterVariable(&r_textureunits);
1482 Cvar_RegisterVariable(&r_glsl);
1483 Cvar_RegisterVariable(&r_glsl_offsetmapping);
1484 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
1485 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
1486 Cvar_RegisterVariable(&r_glsl_deluxemapping);
1487 Cvar_RegisterVariable(&r_lerpsprites);
1488 Cvar_RegisterVariable(&r_lerpmodels);
1489 Cvar_RegisterVariable(&r_waterscroll);
1490 Cvar_RegisterVariable(&r_bloom);
1491 Cvar_RegisterVariable(&r_bloom_colorscale);
1492 Cvar_RegisterVariable(&r_bloom_brighten);
1493 Cvar_RegisterVariable(&r_bloom_blur);
1494 Cvar_RegisterVariable(&r_bloom_resolution);
1495 Cvar_RegisterVariable(&r_bloom_colorexponent);
1496 Cvar_RegisterVariable(&r_bloom_colorsubtract);
1497 Cvar_RegisterVariable(&r_hdr);
1498 Cvar_RegisterVariable(&r_hdr_scenebrightness);
1499 Cvar_RegisterVariable(&r_hdr_glowintensity);
1500 Cvar_RegisterVariable(&r_hdr_range);
1501 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
1502 Cvar_RegisterVariable(&developer_texturelogging);
1503 Cvar_RegisterVariable(&gl_lightmaps);
1504 Cvar_RegisterVariable(&r_test);
1505 Cvar_RegisterVariable(&r_batchmode);
1506 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
1507 Cvar_SetValue("r_fullbrights", 0);
1508 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
1511 extern void R_Textures_Init(void);
1512 extern void GL_Draw_Init(void);
1513 extern void GL_Main_Init(void);
1514 extern void R_Shadow_Init(void);
1515 extern void R_Sky_Init(void);
1516 extern void GL_Surf_Init(void);
1517 extern void R_Light_Init(void);
1518 extern void R_Particles_Init(void);
1519 extern void R_Explosion_Init(void);
1520 extern void gl_backend_init(void);
1521 extern void Sbar_Init(void);
1522 extern void R_LightningBeams_Init(void);
1523 extern void Mod_RenderInit(void);
1525 void Render_Init(void)
1538 R_LightningBeams_Init();
1547 extern char *ENGINE_EXTENSIONS;
1550 VID_CheckExtensions();
1552 // LordHavoc: report supported extensions
1553 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
1555 // clear to black (loading plaque will be seen over this)
1557 qglClearColor(0,0,0,1);CHECKGLERROR
1558 qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
1561 int R_CullBox(const vec3_t mins, const vec3_t maxs)
1565 for (i = 0;i < 4;i++)
1567 p = r_view.frustum + i;
1572 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1576 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1580 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1584 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1588 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1592 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1596 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1600 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1608 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
1612 for (i = 0;i < numplanes;i++)
1619 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1623 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1627 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1631 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1635 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1639 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1643 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1647 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1655 //==================================================================================
1657 static void R_UpdateEntityLighting(entity_render_t *ent)
1659 vec3_t tempdiffusenormal;
1661 // fetch the lighting from the worldmodel data
1662 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));
1663 VectorClear(ent->modellight_diffuse);
1664 VectorClear(tempdiffusenormal);
1665 if ((ent->flags & RENDER_LIGHT) && r_refdef.worldmodel && r_refdef.worldmodel->brush.LightPoint)
1668 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
1669 r_refdef.worldmodel->brush.LightPoint(r_refdef.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
1672 VectorSet(ent->modellight_ambient, 1, 1, 1);
1674 // move the light direction into modelspace coordinates for lighting code
1675 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
1676 VectorNormalize(ent->modellight_lightdir);
1678 // scale ambient and directional light contributions according to rendering variables
1679 ent->modellight_ambient[0] *= ent->colormod[0] * r_refdef.lightmapintensity;
1680 ent->modellight_ambient[1] *= ent->colormod[1] * r_refdef.lightmapintensity;
1681 ent->modellight_ambient[2] *= ent->colormod[2] * r_refdef.lightmapintensity;
1682 ent->modellight_diffuse[0] *= ent->colormod[0] * r_refdef.lightmapintensity;
1683 ent->modellight_diffuse[1] *= ent->colormod[1] * r_refdef.lightmapintensity;
1684 ent->modellight_diffuse[2] *= ent->colormod[2] * r_refdef.lightmapintensity;
1687 static void R_View_UpdateEntityVisible (void)
1690 entity_render_t *ent;
1692 if (!r_drawentities.integer)
1695 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : (chase_active.integer ? 0 : RENDER_EXTERIORMODEL);
1696 if (r_refdef.worldmodel && r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs)
1698 // worldmodel can check visibility
1699 for (i = 0;i < r_refdef.numentities;i++)
1701 ent = r_refdef.entities[i];
1702 r_viewcache.entityvisible[i] = !(ent->flags & renderimask) && !R_CullBox(ent->mins, ent->maxs) && ((ent->effects & EF_NODEPTHTEST) || (ent->flags & RENDER_VIEWMODEL) || r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs(r_refdef.worldmodel, r_viewcache.world_leafvisible, ent->mins, ent->maxs));
1704 if(r_cullentities_trace.integer)
1706 for (i = 0;i < r_refdef.numentities;i++)
1708 ent = r_refdef.entities[i];
1709 if(r_viewcache.entityvisible[i] && !(ent->effects & EF_NODEPTHTEST) && !(ent->flags & RENDER_VIEWMODEL) && !(ent->model && (ent->model->name[0] == '*')))
1711 if(Mod_CanSeeBox_Trace(r_cullentities_trace_samples.integer, r_cullentities_trace_enlarge.value, r_refdef.worldmodel, r_view.origin, ent->mins, ent->maxs))
1712 ent->last_trace_visibility = realtime;
1713 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
1714 r_viewcache.entityvisible[i] = 0;
1721 // no worldmodel or it can't check visibility
1722 for (i = 0;i < r_refdef.numentities;i++)
1724 ent = r_refdef.entities[i];
1725 r_viewcache.entityvisible[i] = !(ent->flags & renderimask) && !R_CullBox(ent->mins, ent->maxs);
1729 // update entity lighting (even on hidden entities for r_shadows)
1730 for (i = 0;i < r_refdef.numentities;i++)
1731 R_UpdateEntityLighting(r_refdef.entities[i]);
1734 // only used if skyrendermasked, and normally returns false
1735 int R_DrawBrushModelsSky (void)
1738 entity_render_t *ent;
1740 if (!r_drawentities.integer)
1744 for (i = 0;i < r_refdef.numentities;i++)
1746 if (!r_viewcache.entityvisible[i])
1748 ent = r_refdef.entities[i];
1749 if (!ent->model || !ent->model->DrawSky)
1751 ent->model->DrawSky(ent);
1757 void R_DrawNoModel(entity_render_t *ent);
1758 void R_DrawModels(void)
1761 entity_render_t *ent;
1763 if (!r_drawentities.integer)
1766 for (i = 0;i < r_refdef.numentities;i++)
1768 if (!r_viewcache.entityvisible[i])
1770 ent = r_refdef.entities[i];
1771 r_refdef.stats.entities++;
1772 if (ent->model && ent->model->Draw != NULL)
1773 ent->model->Draw(ent);
1779 static void R_View_SetFrustum(void)
1781 double slopex, slopey;
1783 // break apart the view matrix into vectors for various purposes
1784 Matrix4x4_ToVectors(&r_view.matrix, r_view.forward, r_view.left, r_view.up, r_view.origin);
1785 VectorNegate(r_view.left, r_view.right);
1788 r_view.frustum[0].normal[0] = 0 - 1.0 / r_view.frustum_x;
1789 r_view.frustum[0].normal[1] = 0 - 0;
1790 r_view.frustum[0].normal[2] = -1 - 0;
1791 r_view.frustum[1].normal[0] = 0 + 1.0 / r_view.frustum_x;
1792 r_view.frustum[1].normal[1] = 0 + 0;
1793 r_view.frustum[1].normal[2] = -1 + 0;
1794 r_view.frustum[2].normal[0] = 0 - 0;
1795 r_view.frustum[2].normal[1] = 0 - 1.0 / r_view.frustum_y;
1796 r_view.frustum[2].normal[2] = -1 - 0;
1797 r_view.frustum[3].normal[0] = 0 + 0;
1798 r_view.frustum[3].normal[1] = 0 + 1.0 / r_view.frustum_y;
1799 r_view.frustum[3].normal[2] = -1 + 0;
1803 zNear = r_refdef.nearclip;
1804 nudge = 1.0 - 1.0 / (1<<23);
1805 r_view.frustum[4].normal[0] = 0 - 0;
1806 r_view.frustum[4].normal[1] = 0 - 0;
1807 r_view.frustum[4].normal[2] = -1 - -nudge;
1808 r_view.frustum[4].dist = 0 - -2 * zNear * nudge;
1809 r_view.frustum[5].normal[0] = 0 + 0;
1810 r_view.frustum[5].normal[1] = 0 + 0;
1811 r_view.frustum[5].normal[2] = -1 + -nudge;
1812 r_view.frustum[5].dist = 0 + -2 * zNear * nudge;
1818 r_view.frustum[0].normal[0] = m[3] - m[0];
1819 r_view.frustum[0].normal[1] = m[7] - m[4];
1820 r_view.frustum[0].normal[2] = m[11] - m[8];
1821 r_view.frustum[0].dist = m[15] - m[12];
1823 r_view.frustum[1].normal[0] = m[3] + m[0];
1824 r_view.frustum[1].normal[1] = m[7] + m[4];
1825 r_view.frustum[1].normal[2] = m[11] + m[8];
1826 r_view.frustum[1].dist = m[15] + m[12];
1828 r_view.frustum[2].normal[0] = m[3] - m[1];
1829 r_view.frustum[2].normal[1] = m[7] - m[5];
1830 r_view.frustum[2].normal[2] = m[11] - m[9];
1831 r_view.frustum[2].dist = m[15] - m[13];
1833 r_view.frustum[3].normal[0] = m[3] + m[1];
1834 r_view.frustum[3].normal[1] = m[7] + m[5];
1835 r_view.frustum[3].normal[2] = m[11] + m[9];
1836 r_view.frustum[3].dist = m[15] + m[13];
1838 r_view.frustum[4].normal[0] = m[3] - m[2];
1839 r_view.frustum[4].normal[1] = m[7] - m[6];
1840 r_view.frustum[4].normal[2] = m[11] - m[10];
1841 r_view.frustum[4].dist = m[15] - m[14];
1843 r_view.frustum[5].normal[0] = m[3] + m[2];
1844 r_view.frustum[5].normal[1] = m[7] + m[6];
1845 r_view.frustum[5].normal[2] = m[11] + m[10];
1846 r_view.frustum[5].dist = m[15] + m[14];
1851 slopex = 1.0 / r_view.frustum_x;
1852 slopey = 1.0 / r_view.frustum_y;
1853 VectorMA(r_view.forward, -slopex, r_view.left, r_view.frustum[0].normal);
1854 VectorMA(r_view.forward, slopex, r_view.left, r_view.frustum[1].normal);
1855 VectorMA(r_view.forward, -slopey, r_view.up , r_view.frustum[2].normal);
1856 VectorMA(r_view.forward, slopey, r_view.up , r_view.frustum[3].normal);
1857 VectorCopy(r_view.forward, r_view.frustum[4].normal);
1858 VectorNormalize(r_view.frustum[0].normal);
1859 VectorNormalize(r_view.frustum[1].normal);
1860 VectorNormalize(r_view.frustum[2].normal);
1861 VectorNormalize(r_view.frustum[3].normal);
1862 r_view.frustum[0].dist = DotProduct (r_view.origin, r_view.frustum[0].normal);
1863 r_view.frustum[1].dist = DotProduct (r_view.origin, r_view.frustum[1].normal);
1864 r_view.frustum[2].dist = DotProduct (r_view.origin, r_view.frustum[2].normal);
1865 r_view.frustum[3].dist = DotProduct (r_view.origin, r_view.frustum[3].normal);
1866 r_view.frustum[4].dist = DotProduct (r_view.origin, r_view.frustum[4].normal) + r_refdef.nearclip;
1867 PlaneClassify(&r_view.frustum[0]);
1868 PlaneClassify(&r_view.frustum[1]);
1869 PlaneClassify(&r_view.frustum[2]);
1870 PlaneClassify(&r_view.frustum[3]);
1871 PlaneClassify(&r_view.frustum[4]);
1873 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
1874 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, -1024 * slopex, r_view.left, -1024 * slopey, r_view.up, r_view.frustumcorner[0]);
1875 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, 1024 * slopex, r_view.left, -1024 * slopey, r_view.up, r_view.frustumcorner[1]);
1876 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, -1024 * slopex, r_view.left, 1024 * slopey, r_view.up, r_view.frustumcorner[2]);
1877 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, 1024 * slopex, r_view.left, 1024 * slopey, r_view.up, r_view.frustumcorner[3]);
1879 // LordHavoc: note to all quake engine coders, Quake had a special case
1880 // for 90 degrees which assumed a square view (wrong), so I removed it,
1881 // Quake2 has it disabled as well.
1883 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
1884 //RotatePointAroundVector( r_view.frustum[0].normal, r_view.up, r_view.forward, -(90 - r_refdef.fov_x / 2));
1885 //r_view.frustum[0].dist = DotProduct (r_view.origin, frustum[0].normal);
1886 //PlaneClassify(&frustum[0]);
1888 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
1889 //RotatePointAroundVector( r_view.frustum[1].normal, r_view.up, r_view.forward, (90 - r_refdef.fov_x / 2));
1890 //r_view.frustum[1].dist = DotProduct (r_view.origin, frustum[1].normal);
1891 //PlaneClassify(&frustum[1]);
1893 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
1894 //RotatePointAroundVector( r_view.frustum[2].normal, r_view.left, r_view.forward, -(90 - r_refdef.fov_y / 2));
1895 //r_view.frustum[2].dist = DotProduct (r_view.origin, frustum[2].normal);
1896 //PlaneClassify(&frustum[2]);
1898 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
1899 //RotatePointAroundVector( r_view.frustum[3].normal, r_view.left, r_view.forward, (90 - r_refdef.fov_y / 2));
1900 //r_view.frustum[3].dist = DotProduct (r_view.origin, frustum[3].normal);
1901 //PlaneClassify(&frustum[3]);
1904 //VectorCopy(r_view.forward, r_view.frustum[4].normal);
1905 //r_view.frustum[4].dist = DotProduct (r_view.origin, frustum[4].normal) + r_nearclip.value;
1906 //PlaneClassify(&frustum[4]);
1909 void R_View_Update(void)
1911 R_View_SetFrustum();
1912 R_View_WorldVisibility();
1913 R_View_UpdateEntityVisible();
1916 void R_SetupView(const matrix4x4_t *matrix)
1918 if (r_refdef.rtworldshadows || r_refdef.rtdlightshadows)
1919 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_view.frustum_x, r_view.frustum_y, r_refdef.nearclip);
1921 GL_SetupView_Mode_Perspective(r_view.frustum_x, r_view.frustum_y, r_refdef.nearclip, r_refdef.farclip);
1923 GL_SetupView_Orientation_FromEntity(matrix);
1926 void R_ResetViewRendering2D(void)
1928 if (gl_support_fragment_shader)
1930 qglUseProgramObjectARB(0);CHECKGLERROR
1935 // GL is weird because it's bottom to top, r_view.y is top to bottom
1936 qglViewport(r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
1937 GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
1938 GL_Scissor(r_view.x, r_view.y, r_view.width, r_view.height);
1939 GL_Color(1, 1, 1, 1);
1940 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
1941 GL_BlendFunc(GL_ONE, GL_ZERO);
1942 GL_AlphaTest(false);
1943 GL_ScissorTest(false);
1944 GL_DepthMask(false);
1945 GL_DepthRange(0, 1);
1946 GL_DepthTest(false);
1947 R_Mesh_Matrix(&identitymatrix);
1948 R_Mesh_ResetTextureState();
1949 qglPolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR
1950 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
1951 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
1952 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
1953 qglStencilMask(~0);CHECKGLERROR
1954 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
1955 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
1956 GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
1959 void R_ResetViewRendering3D(void)
1961 if (gl_support_fragment_shader)
1963 qglUseProgramObjectARB(0);CHECKGLERROR
1968 // GL is weird because it's bottom to top, r_view.y is top to bottom
1969 qglViewport(r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
1970 R_SetupView(&r_view.matrix);
1971 GL_Scissor(r_view.x, r_view.y, r_view.width, r_view.height);
1972 GL_Color(1, 1, 1, 1);
1973 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
1974 GL_BlendFunc(GL_ONE, GL_ZERO);
1975 GL_AlphaTest(false);
1976 GL_ScissorTest(true);
1978 GL_DepthRange(0, 1);
1980 R_Mesh_Matrix(&identitymatrix);
1981 R_Mesh_ResetTextureState();
1982 qglPolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR
1983 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
1984 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
1985 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
1986 qglStencilMask(~0);CHECKGLERROR
1987 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
1988 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
1989 GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
1993 R_Bloom_SetupShader(
1995 "// written by Forest 'LordHavoc' Hale\n"
1997 "// common definitions between vertex shader and fragment shader:\n"
1999 "#ifdef __GLSL_CG_DATA_TYPES\n"
2000 "#define myhalf half\n"
2001 "#define myhvec2 hvec2\n"
2002 "#define myhvec3 hvec3\n"
2003 "#define myhvec4 hvec4\n"
2005 "#define myhalf float\n"
2006 "#define myhvec2 vec2\n"
2007 "#define myhvec3 vec3\n"
2008 "#define myhvec4 vec4\n"
2011 "varying vec2 ScreenTexCoord;\n"
2012 "varying vec2 BloomTexCoord;\n"
2017 "// vertex shader specific:\n"
2018 "#ifdef VERTEX_SHADER\n"
2022 " ScreenTexCoord = vec2(gl_MultiTexCoord0);\n"
2023 " BloomTexCoord = vec2(gl_MultiTexCoord1);\n"
2024 " // transform vertex to camera space, using ftransform to match non-VS\n"
2026 " gl_Position = ftransform();\n"
2029 "#endif // VERTEX_SHADER\n"
2034 "// fragment shader specific:\n"
2035 "#ifdef FRAGMENT_SHADER\n"
2040 " myhvec3 color = myhvec3(texture2D(Texture_Screen, ScreenTexCoord));\n"
2041 " for (x = -BLUR_X;x <= BLUR_X;x++)
2042 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2043 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2044 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2045 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2047 " gl_FragColor = vec4(color);\n"
2050 "#endif // FRAGMENT_SHADER\n"
2053 void R_RenderScene(void);
2055 void R_Bloom_StartFrame(void)
2057 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
2059 // set bloomwidth and bloomheight to the bloom resolution that will be
2060 // used (often less than the screen resolution for faster rendering)
2061 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_view.width);
2062 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_view.height / r_view.width;
2063 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_view.height);
2065 // calculate desired texture sizes
2066 if (gl_support_arb_texture_non_power_of_two)
2068 screentexturewidth = r_view.width;
2069 screentextureheight = r_view.height;
2070 bloomtexturewidth = r_bloomstate.bloomwidth;
2071 bloomtextureheight = r_bloomstate.bloomheight;
2075 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
2076 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
2077 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
2078 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
2083 screentexturewidth = screentextureheight = 0;
2085 else if (r_bloom.integer)
2090 screentexturewidth = screentextureheight = 0;
2091 bloomtexturewidth = bloomtextureheight = 0;
2094 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)
2096 // can't use bloom if the parameters are too weird
2097 // can't use bloom if the card does not support the texture size
2098 if (r_bloomstate.texture_screen)
2099 R_FreeTexture(r_bloomstate.texture_screen);
2100 if (r_bloomstate.texture_bloom)
2101 R_FreeTexture(r_bloomstate.texture_bloom);
2102 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
2106 r_bloomstate.enabled = true;
2107 r_bloomstate.hdr = r_hdr.integer != 0;
2109 // allocate textures as needed
2110 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
2112 if (r_bloomstate.texture_screen)
2113 R_FreeTexture(r_bloomstate.texture_screen);
2114 r_bloomstate.texture_screen = NULL;
2115 r_bloomstate.screentexturewidth = screentexturewidth;
2116 r_bloomstate.screentextureheight = screentextureheight;
2117 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
2118 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);
2120 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
2122 if (r_bloomstate.texture_bloom)
2123 R_FreeTexture(r_bloomstate.texture_bloom);
2124 r_bloomstate.texture_bloom = NULL;
2125 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
2126 r_bloomstate.bloomtextureheight = bloomtextureheight;
2127 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
2128 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);
2131 // set up a texcoord array for the full resolution screen image
2132 // (we have to keep this around to copy back during final render)
2133 r_bloomstate.screentexcoord2f[0] = 0;
2134 r_bloomstate.screentexcoord2f[1] = (float)r_view.height / (float)r_bloomstate.screentextureheight;
2135 r_bloomstate.screentexcoord2f[2] = (float)r_view.width / (float)r_bloomstate.screentexturewidth;
2136 r_bloomstate.screentexcoord2f[3] = (float)r_view.height / (float)r_bloomstate.screentextureheight;
2137 r_bloomstate.screentexcoord2f[4] = (float)r_view.width / (float)r_bloomstate.screentexturewidth;
2138 r_bloomstate.screentexcoord2f[5] = 0;
2139 r_bloomstate.screentexcoord2f[6] = 0;
2140 r_bloomstate.screentexcoord2f[7] = 0;
2142 // set up a texcoord array for the reduced resolution bloom image
2143 // (which will be additive blended over the screen image)
2144 r_bloomstate.bloomtexcoord2f[0] = 0;
2145 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
2146 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
2147 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
2148 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
2149 r_bloomstate.bloomtexcoord2f[5] = 0;
2150 r_bloomstate.bloomtexcoord2f[6] = 0;
2151 r_bloomstate.bloomtexcoord2f[7] = 0;
2154 void R_Bloom_CopyScreenTexture(float colorscale)
2156 r_refdef.stats.bloom++;
2158 R_ResetViewRendering2D();
2159 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
2160 R_Mesh_ColorPointer(NULL, 0, 0);
2161 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
2162 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
2164 // copy view into the screen texture
2165 GL_ActiveTexture(0);
2167 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
2168 r_refdef.stats.bloom_copypixels += r_view.width * r_view.height;
2170 // now scale it down to the bloom texture size
2172 qglViewport(r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
2173 GL_BlendFunc(GL_ONE, GL_ZERO);
2174 GL_Color(colorscale, colorscale, colorscale, 1);
2175 // TODO: optimize with multitexture or GLSL
2176 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2177 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2179 // we now have a bloom image in the framebuffer
2180 // copy it into the bloom image texture for later processing
2181 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2182 GL_ActiveTexture(0);
2184 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
2185 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2188 void R_Bloom_CopyHDRTexture(void)
2190 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2191 GL_ActiveTexture(0);
2193 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
2194 r_refdef.stats.bloom_copypixels += r_view.width * r_view.height;
2197 void R_Bloom_MakeTexture(void)
2200 float xoffset, yoffset, r, brighten;
2202 r_refdef.stats.bloom++;
2204 R_ResetViewRendering2D();
2205 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
2206 R_Mesh_ColorPointer(NULL, 0, 0);
2208 // we have a bloom image in the framebuffer
2210 qglViewport(r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
2212 for (x = 1;x < r_bloom_colorexponent.value;)
2215 r = bound(0, r_bloom_colorexponent.value / x, 1);
2216 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
2217 GL_Color(r, r, r, 1);
2218 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2219 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
2220 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2221 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2223 // copy the vertically blurred bloom view to a texture
2224 GL_ActiveTexture(0);
2226 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
2227 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2230 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
2231 brighten = r_bloom_brighten.value;
2233 brighten *= r_hdr_range.value;
2234 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2235 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
2237 for (dir = 0;dir < 2;dir++)
2239 // blend on at multiple vertical offsets to achieve a vertical blur
2240 // TODO: do offset blends using GLSL
2241 GL_BlendFunc(GL_ONE, GL_ZERO);
2242 for (x = -range;x <= range;x++)
2244 if (!dir){xoffset = 0;yoffset = x;}
2245 else {xoffset = x;yoffset = 0;}
2246 xoffset /= (float)r_bloomstate.bloomtexturewidth;
2247 yoffset /= (float)r_bloomstate.bloomtextureheight;
2248 // compute a texcoord array with the specified x and y offset
2249 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
2250 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
2251 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
2252 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
2253 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
2254 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
2255 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
2256 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
2257 // this r value looks like a 'dot' particle, fading sharply to
2258 // black at the edges
2259 // (probably not realistic but looks good enough)
2260 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
2261 //r = (dir ? 1.0f : brighten)/(range*2+1);
2262 r = (dir ? 1.0f : brighten)/(range*2+1)*(1 - x*x/(float)(range*range));
2263 GL_Color(r, r, r, 1);
2264 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2265 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2266 GL_BlendFunc(GL_ONE, GL_ONE);
2269 // copy the vertically blurred bloom view to a texture
2270 GL_ActiveTexture(0);
2272 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
2273 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2276 // apply subtract last
2277 // (just like it would be in a GLSL shader)
2278 if (r_bloom_colorsubtract.value > 0 && gl_support_ext_blend_subtract)
2280 GL_BlendFunc(GL_ONE, GL_ZERO);
2281 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2282 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
2283 GL_Color(1, 1, 1, 1);
2284 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2285 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2287 GL_BlendFunc(GL_ONE, GL_ONE);
2288 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
2289 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2290 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
2291 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
2292 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2293 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2294 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
2296 // copy the darkened bloom view to a texture
2297 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2298 GL_ActiveTexture(0);
2300 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
2301 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2305 void R_HDR_RenderBloomTexture(void)
2307 int oldwidth, oldheight;
2309 oldwidth = r_view.width;
2310 oldheight = r_view.height;
2311 r_view.width = r_bloomstate.bloomwidth;
2312 r_view.height = r_bloomstate.bloomheight;
2314 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
2315 // TODO: add exposure compensation features
2316 // TODO: add fp16 framebuffer support
2318 r_view.colorscale = r_bloom_colorscale.value * r_hdr_scenebrightness.value;
2320 r_view.colorscale /= r_hdr_range.value;
2323 R_ResetViewRendering2D();
2325 R_Bloom_CopyHDRTexture();
2326 R_Bloom_MakeTexture();
2328 R_ResetViewRendering3D();
2331 if (r_timereport_active)
2332 R_TimeReport("clear");
2335 // restore the view settings
2336 r_view.width = oldwidth;
2337 r_view.height = oldheight;
2340 static void R_BlendView(void)
2342 if (r_bloomstate.enabled && r_bloomstate.hdr)
2344 // render high dynamic range bloom effect
2345 // the bloom texture was made earlier this render, so we just need to
2346 // blend it onto the screen...
2347 R_ResetViewRendering2D();
2348 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
2349 R_Mesh_ColorPointer(NULL, 0, 0);
2350 GL_Color(1, 1, 1, 1);
2351 GL_BlendFunc(GL_ONE, GL_ONE);
2352 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2353 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
2354 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2355 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
2357 else if (r_bloomstate.enabled)
2359 // render simple bloom effect
2360 // copy the screen and shrink it and darken it for the bloom process
2361 R_Bloom_CopyScreenTexture(r_bloom_colorscale.value);
2362 // make the bloom texture
2363 R_Bloom_MakeTexture();
2364 // put the original screen image back in place and blend the bloom
2366 R_ResetViewRendering2D();
2367 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
2368 R_Mesh_ColorPointer(NULL, 0, 0);
2369 GL_Color(1, 1, 1, 1);
2370 GL_BlendFunc(GL_ONE, GL_ZERO);
2371 // do both in one pass if possible
2372 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2373 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
2374 if (r_textureunits.integer >= 2 && gl_combine.integer)
2376 R_Mesh_TexCombine(1, GL_ADD, GL_ADD, 1, 1);
2377 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_screen));
2378 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.screentexcoord2f, 0, 0);
2382 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2383 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
2384 // now blend on the bloom texture
2385 GL_BlendFunc(GL_ONE, GL_ONE);
2386 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
2387 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
2389 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2390 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
2392 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
2394 // apply a color tint to the whole view
2395 R_ResetViewRendering2D();
2396 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
2397 R_Mesh_ColorPointer(NULL, 0, 0);
2398 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2399 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
2400 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2404 void R_RenderScene(void);
2406 matrix4x4_t r_waterscrollmatrix;
2408 void R_UpdateVariables(void)
2412 r_refdef.farclip = 4096;
2413 if (r_refdef.worldmodel)
2414 r_refdef.farclip += VectorDistance(r_refdef.worldmodel->normalmins, r_refdef.worldmodel->normalmaxs);
2415 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
2417 r_refdef.polygonfactor = 0;
2418 r_refdef.polygonoffset = 0;
2419 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_shadow_polygonfactor.value;
2420 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_shadow_polygonoffset.value;
2422 r_refdef.rtworld = r_shadow_realtime_world.integer;
2423 r_refdef.rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
2424 r_refdef.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
2425 r_refdef.rtdlightshadows = r_refdef.rtdlight && (r_refdef.rtworld ? r_shadow_realtime_world_dlightshadows.integer : r_shadow_realtime_dlight_shadows.integer) && gl_stencil;
2426 r_refdef.lightmapintensity = r_refdef.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
2427 if (r_showsurfaces.integer)
2429 r_refdef.rtworld = false;
2430 r_refdef.rtworldshadows = false;
2431 r_refdef.rtdlight = false;
2432 r_refdef.rtdlightshadows = false;
2433 r_refdef.lightmapintensity = 0;
2436 if (gamemode == GAME_NEHAHRA)
2438 if (gl_fogenable.integer)
2440 r_refdef.oldgl_fogenable = true;
2441 r_refdef.fog_density = gl_fogdensity.value;
2442 r_refdef.fog_red = gl_fogred.value;
2443 r_refdef.fog_green = gl_foggreen.value;
2444 r_refdef.fog_blue = gl_fogblue.value;
2446 else if (r_refdef.oldgl_fogenable)
2448 r_refdef.oldgl_fogenable = false;
2449 r_refdef.fog_density = 0;
2450 r_refdef.fog_red = 0;
2451 r_refdef.fog_green = 0;
2452 r_refdef.fog_blue = 0;
2455 if (r_refdef.fog_density)
2457 r_refdef.fogcolor[0] = bound(0.0f, r_refdef.fog_red , 1.0f);
2458 r_refdef.fogcolor[1] = bound(0.0f, r_refdef.fog_green, 1.0f);
2459 r_refdef.fogcolor[2] = bound(0.0f, r_refdef.fog_blue , 1.0f);
2461 if (r_refdef.fog_density)
2463 r_refdef.fogenabled = true;
2464 // this is the point where the fog reaches 0.9986 alpha, which we
2465 // consider a good enough cutoff point for the texture
2466 // (0.9986 * 256 == 255.6)
2467 r_refdef.fogrange = 400 / r_refdef.fog_density;
2468 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
2469 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
2470 // fog color was already set
2473 r_refdef.fogenabled = false;
2481 void R_RenderView(void)
2483 if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
2484 return; //Host_Error ("R_RenderView: NULL worldmodel");
2486 R_Shadow_UpdateWorldLightSelection();
2489 if (r_timereport_active)
2490 R_TimeReport("setup");
2493 if (r_timereport_active)
2494 R_TimeReport("visibility");
2496 R_ResetViewRendering3D();
2499 if (r_timereport_active)
2500 R_TimeReport("clear");
2502 R_Bloom_StartFrame();
2504 // this produces a bloom texture to be used in R_BlendView() later
2506 R_HDR_RenderBloomTexture();
2508 r_view.colorscale = r_hdr_scenebrightness.value;
2512 if (r_timereport_active)
2513 R_TimeReport("blendview");
2515 GL_Scissor(0, 0, vid.width, vid.height);
2516 GL_ScissorTest(false);
2520 extern void R_DrawLightningBeams (void);
2521 extern void VM_CL_AddPolygonsToMeshQueue (void);
2522 extern void R_DrawPortals (void);
2523 extern cvar_t cl_locs_show;
2524 static void R_DrawLocs(void);
2525 static void R_DrawEntityBBoxes(void);
2526 void R_RenderScene(void)
2528 // don't let sound skip if going slow
2529 if (r_refdef.extraupdate)
2532 R_ResetViewRendering3D();
2534 R_MeshQueue_BeginScene();
2538 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);
2540 if (cl.csqc_vidvars.drawworld)
2542 // don't let sound skip if going slow
2543 if (r_refdef.extraupdate)
2546 if (r_refdef.worldmodel && r_refdef.worldmodel->DrawSky)
2548 r_refdef.worldmodel->DrawSky(r_refdef.worldentity);
2549 if (r_timereport_active)
2550 R_TimeReport("worldsky");
2553 if (R_DrawBrushModelsSky() && r_timereport_active)
2554 R_TimeReport("bmodelsky");
2556 if (r_refdef.worldmodel && r_refdef.worldmodel->Draw)
2558 r_refdef.worldmodel->Draw(r_refdef.worldentity);
2559 if (r_timereport_active)
2560 R_TimeReport("world");
2564 // don't let sound skip if going slow
2565 if (r_refdef.extraupdate)
2569 if (r_timereport_active)
2570 R_TimeReport("models");
2572 // don't let sound skip if going slow
2573 if (r_refdef.extraupdate)
2576 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
2578 R_DrawModelShadows();
2580 R_ResetViewRendering3D();
2582 // don't let sound skip if going slow
2583 if (r_refdef.extraupdate)
2587 R_ShadowVolumeLighting(false);
2588 if (r_timereport_active)
2589 R_TimeReport("rtlights");
2591 // don't let sound skip if going slow
2592 if (r_refdef.extraupdate)
2595 if (cl.csqc_vidvars.drawworld)
2597 R_DrawLightningBeams();
2598 if (r_timereport_active)
2599 R_TimeReport("lightning");
2602 if (r_timereport_active)
2603 R_TimeReport("particles");
2606 if (r_timereport_active)
2607 R_TimeReport("explosions");
2610 if (gl_support_fragment_shader)
2612 qglUseProgramObjectARB(0);CHECKGLERROR
2614 VM_CL_AddPolygonsToMeshQueue();
2616 if (cl_locs_show.integer)
2619 if (r_timereport_active)
2620 R_TimeReport("showlocs");
2623 if (r_drawportals.integer)
2626 if (r_timereport_active)
2627 R_TimeReport("portals");
2630 if (r_showbboxes.value > 0)
2632 R_DrawEntityBBoxes();
2633 if (r_timereport_active)
2634 R_TimeReport("bboxes");
2637 if (gl_support_fragment_shader)
2639 qglUseProgramObjectARB(0);CHECKGLERROR
2641 R_MeshQueue_RenderTransparent();
2642 if (r_timereport_active)
2643 R_TimeReport("drawtrans");
2645 if (gl_support_fragment_shader)
2647 qglUseProgramObjectARB(0);CHECKGLERROR
2650 if (cl.csqc_vidvars.drawworld)
2653 if (r_timereport_active)
2654 R_TimeReport("coronas");
2657 // don't let sound skip if going slow
2658 if (r_refdef.extraupdate)
2661 R_ResetViewRendering2D();
2664 static const int bboxelements[36] =
2674 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
2677 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
2678 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2679 GL_DepthMask(false);
2680 GL_DepthRange(0, 1);
2681 R_Mesh_Matrix(&identitymatrix);
2682 R_Mesh_ResetTextureState();
2684 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
2685 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
2686 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
2687 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
2688 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
2689 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
2690 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
2691 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
2692 R_FillColors(color4f, 8, cr, cg, cb, ca);
2693 if (r_refdef.fogenabled)
2695 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
2697 f1 = FogPoint_World(v);
2699 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
2700 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
2701 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
2704 R_Mesh_VertexPointer(vertex3f, 0, 0);
2705 R_Mesh_ColorPointer(color4f, 0, 0);
2706 R_Mesh_ResetTextureState();
2707 R_Mesh_Draw(0, 8, 12, bboxelements, 0, 0);
2710 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
2714 prvm_edict_t *edict;
2715 // this function draws bounding boxes of server entities
2719 for (i = 0;i < numsurfaces;i++)
2721 edict = PRVM_EDICT_NUM(surfacelist[i]);
2722 switch ((int)edict->fields.server->solid)
2724 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
2725 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
2726 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
2727 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
2728 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
2729 default: Vector4Set(color, 0, 0, 0, 0.50);break;
2731 color[3] *= r_showbboxes.value;
2732 color[3] = bound(0, color[3], 1);
2733 GL_DepthTest(!r_showdisabledepthtest.integer);
2734 GL_CullFace(GL_BACK);
2735 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
2740 static void R_DrawEntityBBoxes(void)
2743 prvm_edict_t *edict;
2745 // this function draws bounding boxes of server entities
2749 for (i = 0;i < prog->num_edicts;i++)
2751 edict = PRVM_EDICT_NUM(i);
2752 if (edict->priv.server->free)
2754 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
2755 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
2760 int nomodelelements[24] =
2772 float nomodelvertex3f[6*3] =
2782 float nomodelcolor4f[6*4] =
2784 0.0f, 0.0f, 0.5f, 1.0f,
2785 0.0f, 0.0f, 0.5f, 1.0f,
2786 0.0f, 0.5f, 0.0f, 1.0f,
2787 0.0f, 0.5f, 0.0f, 1.0f,
2788 0.5f, 0.0f, 0.0f, 1.0f,
2789 0.5f, 0.0f, 0.0f, 1.0f
2792 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
2797 // this is only called once per entity so numsurfaces is always 1, and
2798 // surfacelist is always {0}, so this code does not handle batches
2799 R_Mesh_Matrix(&ent->matrix);
2801 if (ent->flags & EF_ADDITIVE)
2803 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2804 GL_DepthMask(false);
2806 else if (ent->alpha < 1)
2808 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2809 GL_DepthMask(false);
2813 GL_BlendFunc(GL_ONE, GL_ZERO);
2816 GL_DepthRange(0, (ent->flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
2817 GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
2818 GL_CullFace((ent->effects & EF_DOUBLESIDED) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
2819 R_Mesh_VertexPointer(nomodelvertex3f, 0, 0);
2820 if (r_refdef.fogenabled)
2823 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
2824 R_Mesh_ColorPointer(color4f, 0, 0);
2825 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
2826 f1 = FogPoint_World(org);
2828 for (i = 0, c = color4f;i < 6;i++, c += 4)
2830 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
2831 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
2832 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
2836 else if (ent->alpha != 1)
2838 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
2839 R_Mesh_ColorPointer(color4f, 0, 0);
2840 for (i = 0, c = color4f;i < 6;i++, c += 4)
2844 R_Mesh_ColorPointer(nomodelcolor4f, 0, 0);
2845 R_Mesh_ResetTextureState();
2846 R_Mesh_Draw(0, 6, 8, nomodelelements, 0, 0);
2849 void R_DrawNoModel(entity_render_t *ent)
2852 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
2853 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
2854 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, r_shadow_rtlight);
2856 // R_DrawNoModelCallback(ent, 0);
2859 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
2861 vec3_t right1, right2, diff, normal;
2863 VectorSubtract (org2, org1, normal);
2865 // calculate 'right' vector for start
2866 VectorSubtract (r_view.origin, org1, diff);
2867 CrossProduct (normal, diff, right1);
2868 VectorNormalize (right1);
2870 // calculate 'right' vector for end
2871 VectorSubtract (r_view.origin, org2, diff);
2872 CrossProduct (normal, diff, right2);
2873 VectorNormalize (right2);
2875 vert[ 0] = org1[0] + width * right1[0];
2876 vert[ 1] = org1[1] + width * right1[1];
2877 vert[ 2] = org1[2] + width * right1[2];
2878 vert[ 3] = org1[0] - width * right1[0];
2879 vert[ 4] = org1[1] - width * right1[1];
2880 vert[ 5] = org1[2] - width * right1[2];
2881 vert[ 6] = org2[0] - width * right2[0];
2882 vert[ 7] = org2[1] - width * right2[1];
2883 vert[ 8] = org2[2] - width * right2[2];
2884 vert[ 9] = org2[0] + width * right2[0];
2885 vert[10] = org2[1] + width * right2[1];
2886 vert[11] = org2[2] + width * right2[2];
2889 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
2891 void R_DrawSprite(int blendfunc1, int blendfunc2, rtexture_t *texture, rtexture_t *fogtexture, qboolean depthdisable, qboolean depthshort, 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)
2896 if (r_refdef.fogenabled)
2897 fog = FogPoint_World(origin);
2899 R_Mesh_Matrix(&identitymatrix);
2900 GL_BlendFunc(blendfunc1, blendfunc2);
2901 GL_DepthMask(false);
2902 GL_DepthRange(0, depthshort ? 0.0625 : 1);
2903 GL_DepthTest(!depthdisable);
2905 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
2906 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
2907 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
2908 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
2909 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
2910 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
2911 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
2912 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
2913 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
2914 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
2915 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
2916 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
2918 R_Mesh_VertexPointer(vertex3f, 0, 0);
2919 R_Mesh_ColorPointer(NULL, 0, 0);
2920 R_Mesh_ResetTextureState();
2921 R_Mesh_TexBind(0, R_GetTexture(texture));
2922 R_Mesh_TexCoordPointer(0, 2, spritetexcoord2f, 0, 0);
2923 // FIXME: fixed function path can't properly handle r_view.colorscale > 1
2924 GL_Color(cr * fog * r_view.colorscale, cg * fog * r_view.colorscale, cb * fog * r_view.colorscale, ca);
2925 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2927 if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
2929 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
2930 GL_BlendFunc(blendfunc1, GL_ONE);
2932 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);
2933 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2937 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
2942 VectorSet(v, x, y, z);
2943 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
2944 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
2946 if (i == mesh->numvertices)
2948 if (mesh->numvertices < mesh->maxvertices)
2950 VectorCopy(v, vertex3f);
2951 mesh->numvertices++;
2953 return mesh->numvertices;
2959 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
2963 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
2964 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
2965 e = mesh->element3i + mesh->numtriangles * 3;
2966 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
2968 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
2969 if (mesh->numtriangles < mesh->maxtriangles)
2974 mesh->numtriangles++;
2976 element[1] = element[2];
2980 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
2984 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
2985 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
2986 e = mesh->element3i + mesh->numtriangles * 3;
2987 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
2989 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
2990 if (mesh->numtriangles < mesh->maxtriangles)
2995 mesh->numtriangles++;
2997 element[1] = element[2];
3001 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
3002 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
3004 int planenum, planenum2;
3007 mplane_t *plane, *plane2;
3009 double temppoints[2][256*3];
3010 // figure out how large a bounding box we need to properly compute this brush
3012 for (w = 0;w < numplanes;w++)
3013 maxdist = max(maxdist, planes[w].dist);
3014 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
3015 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
3016 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
3020 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
3021 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
3023 if (planenum2 == planenum)
3025 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);
3028 if (tempnumpoints < 3)
3030 // generate elements forming a triangle fan for this polygon
3031 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
3035 static void R_DrawCollisionBrush(const colbrushf_t *brush)
3038 R_Mesh_VertexPointer(brush->points->v, 0, 0);
3039 i = (int)(((size_t)brush) / sizeof(colbrushf_t));
3040 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);
3041 GL_LockArrays(0, brush->numpoints);
3042 R_Mesh_Draw(0, brush->numpoints, brush->numtriangles, brush->elements, 0, 0);
3043 GL_LockArrays(0, 0);
3046 static void R_DrawCollisionSurface(const entity_render_t *ent, const msurface_t *surface)
3049 if (!surface->num_collisiontriangles)
3051 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
3052 i = (int)(((size_t)surface) / sizeof(msurface_t));
3053 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);
3054 GL_LockArrays(0, surface->num_collisionvertices);
3055 R_Mesh_Draw(0, surface->num_collisionvertices, surface->num_collisiontriangles, surface->data_collisionelement3i, 0, 0);
3056 GL_LockArrays(0, 0);
3059 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)
3061 texturelayer_t *layer;
3062 layer = t->currentlayers + t->currentnumlayers++;
3064 layer->depthmask = depthmask;
3065 layer->blendfunc1 = blendfunc1;
3066 layer->blendfunc2 = blendfunc2;
3067 layer->texture = texture;
3068 layer->texmatrix = *matrix;
3069 layer->color[0] = r * r_view.colorscale;
3070 layer->color[1] = g * r_view.colorscale;
3071 layer->color[2] = b * r_view.colorscale;
3072 layer->color[3] = a;
3075 void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
3077 model_t *model = ent->model;
3079 // switch to an alternate material if this is a q1bsp animated material
3081 texture_t *texture = t;
3082 int s = ent->skinnum;
3083 if ((unsigned int)s >= (unsigned int)model->numskins)
3085 if (model->skinscenes)
3087 if (model->skinscenes[s].framecount > 1)
3088 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
3090 s = model->skinscenes[s].firstframe;
3093 t = t + s * model->num_surfaces;
3096 // use an alternate animation if the entity's frame is not 0,
3097 // and only if the texture has an alternate animation
3098 if (ent->frame != 0 && t->anim_total[1])
3099 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.time * 5.0f) % t->anim_total[1]) : 0];
3101 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.time * 5.0f) % t->anim_total[0]) : 0];
3103 texture->currentframe = t;
3106 // pick a new currentskinframe if the material is animated
3107 if (t->numskinframes >= 2)
3108 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->frame2time)) % t->numskinframes];
3109 if (t->backgroundnumskinframes >= 2)
3110 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - ent->frame2time)) % t->backgroundnumskinframes];
3112 t->currentmaterialflags = t->basematerialflags;
3113 t->currentalpha = ent->alpha;
3114 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
3115 t->currentalpha *= r_wateralpha.value;
3116 if (!(ent->flags & RENDER_LIGHT))
3117 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
3118 if (ent->effects & EF_ADDITIVE)
3119 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
3120 else if (t->currentalpha < 1)
3121 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
3122 if (ent->effects & EF_DOUBLESIDED)
3123 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
3124 if (ent->effects & EF_NODEPTHTEST)
3125 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
3126 if (ent->flags & RENDER_VIEWMODEL)
3127 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
3128 if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
3129 t->currenttexmatrix = r_waterscrollmatrix;
3131 t->currenttexmatrix = identitymatrix;
3132 if (t->backgroundnumskinframes && !(t->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED))
3133 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
3135 t->colormapping = VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f);
3136 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
3137 t->glosstexture = r_texture_white;
3138 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
3139 t->backgroundglosstexture = r_texture_white;
3140 t->specularpower = r_shadow_glossexponent.value;
3141 // TODO: store reference values for these in the texture?
3142 t->specularscale = 0;
3143 if (r_shadow_gloss.integer > 0)
3145 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
3147 if (r_shadow_glossintensity.value > 0)
3149 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_black;
3150 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_black;
3151 t->specularscale = r_shadow_glossintensity.value;
3154 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
3155 t->specularscale = r_shadow_gloss2intensity.value;
3158 t->currentnumlayers = 0;
3159 if (!(t->currentmaterialflags & MATERIALFLAG_NODRAW))
3161 if (gl_lightmaps.integer)
3162 R_Texture_AddLayer(t, true, GL_ONE, GL_ZERO, TEXTURELAYERTYPE_LITTEXTURE, r_texture_white, &identitymatrix, 1, 1, 1, 1);
3163 else if (!(t->currentmaterialflags & MATERIALFLAG_SKY))
3165 int blendfunc1, blendfunc2, depthmask;
3166 if (t->currentmaterialflags & MATERIALFLAG_ADD)
3168 blendfunc1 = GL_SRC_ALPHA;
3169 blendfunc2 = GL_ONE;
3171 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
3173 blendfunc1 = GL_SRC_ALPHA;
3174 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
3176 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
3178 blendfunc1 = t->customblendfunc[0];
3179 blendfunc2 = t->customblendfunc[1];
3183 blendfunc1 = GL_ONE;
3184 blendfunc2 = GL_ZERO;
3186 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
3187 if (t->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL))
3189 rtexture_t *currentbasetexture;
3191 if (r_refdef.fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED))
3192 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
3193 currentbasetexture = (VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) < (1.0f / 1048576.0f) && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
3194 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
3196 // fullbright is not affected by r_refdef.lightmapintensity
3197 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
3198 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
3199 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);
3200 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
3201 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);
3207 // q3bsp has no lightmap updates, so the lightstylevalue that
3208 // would normally be baked into the lightmap must be
3209 // applied to the color
3210 if (ent->model->type == mod_brushq3)
3211 colorscale *= r_refdef.lightstylevalue[0] * (1.0f / 256.0f);
3212 colorscale *= r_refdef.lightmapintensity;
3213 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);
3214 if (r_ambient.value >= (1.0f/64.0f))
3215 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);
3216 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
3218 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);
3219 if (r_ambient.value >= (1.0f/64.0f))
3220 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);
3222 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
3224 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);
3225 if (r_ambient.value >= (1.0f/64.0f))
3226 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);
3229 if (t->currentskinframe->glow != NULL)
3230 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);
3231 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
3233 // if this is opaque use alpha blend which will darken the earlier
3236 // if this is an alpha blended material, all the earlier passes
3237 // were darkened by fog already, so we only need to add the fog
3238 // color ontop through the fog mask texture
3240 // if this is an additive blended material, all the earlier passes
3241 // were darkened by fog already, and we should not add fog color
3242 // (because the background was not darkened, there is no fog color
3243 // that was lost behind it).
3244 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);
3251 void R_UpdateAllTextureInfo(entity_render_t *ent)
3255 for (i = 0;i < ent->model->num_textures;i++)
3256 R_UpdateTextureInfo(ent, ent->model->data_textures + i);
3259 int rsurface_array_size = 0;
3260 float *rsurface_array_modelvertex3f = NULL;
3261 float *rsurface_array_modelsvector3f = NULL;
3262 float *rsurface_array_modeltvector3f = NULL;
3263 float *rsurface_array_modelnormal3f = NULL;
3264 float *rsurface_array_deformedvertex3f = NULL;
3265 float *rsurface_array_deformedsvector3f = NULL;
3266 float *rsurface_array_deformedtvector3f = NULL;
3267 float *rsurface_array_deformednormal3f = NULL;
3268 float *rsurface_array_color4f = NULL;
3269 float *rsurface_array_texcoord3f = NULL;
3271 void R_Mesh_ResizeArrays(int newvertices)
3274 if (rsurface_array_size >= newvertices)
3276 if (rsurface_array_modelvertex3f)
3277 Mem_Free(rsurface_array_modelvertex3f);
3278 rsurface_array_size = (newvertices + 1023) & ~1023;
3279 base = (float *)Mem_Alloc(r_main_mempool, rsurface_array_size * sizeof(float[31]));
3280 rsurface_array_modelvertex3f = base + rsurface_array_size * 0;
3281 rsurface_array_modelsvector3f = base + rsurface_array_size * 3;
3282 rsurface_array_modeltvector3f = base + rsurface_array_size * 6;
3283 rsurface_array_modelnormal3f = base + rsurface_array_size * 9;
3284 rsurface_array_deformedvertex3f = base + rsurface_array_size * 12;
3285 rsurface_array_deformedsvector3f = base + rsurface_array_size * 15;
3286 rsurface_array_deformedtvector3f = base + rsurface_array_size * 18;
3287 rsurface_array_deformednormal3f = base + rsurface_array_size * 21;
3288 rsurface_array_texcoord3f = base + rsurface_array_size * 24;
3289 rsurface_array_color4f = base + rsurface_array_size * 27;
3292 float *rsurface_modelvertex3f;
3293 int rsurface_modelvertex3f_bufferobject;
3294 size_t rsurface_modelvertex3f_bufferoffset;
3295 float *rsurface_modelsvector3f;
3296 int rsurface_modelsvector3f_bufferobject;
3297 size_t rsurface_modelsvector3f_bufferoffset;
3298 float *rsurface_modeltvector3f;
3299 int rsurface_modeltvector3f_bufferobject;
3300 size_t rsurface_modeltvector3f_bufferoffset;
3301 float *rsurface_modelnormal3f;
3302 int rsurface_modelnormal3f_bufferobject;
3303 size_t rsurface_modelnormal3f_bufferoffset;
3304 float *rsurface_vertex3f;
3305 int rsurface_vertex3f_bufferobject;
3306 size_t rsurface_vertex3f_bufferoffset;
3307 float *rsurface_svector3f;
3308 int rsurface_svector3f_bufferobject;
3309 size_t rsurface_svector3f_bufferoffset;
3310 float *rsurface_tvector3f;
3311 int rsurface_tvector3f_bufferobject;
3312 size_t rsurface_tvector3f_bufferoffset;
3313 float *rsurface_normal3f;
3314 int rsurface_normal3f_bufferobject;
3315 size_t rsurface_normal3f_bufferoffset;
3316 float *rsurface_lightmapcolor4f;
3317 int rsurface_lightmapcolor4f_bufferobject;
3318 size_t rsurface_lightmapcolor4f_bufferoffset;
3319 vec3_t rsurface_modelorg;
3320 qboolean rsurface_generatedvertex;
3321 const entity_render_t *rsurface_entity;
3322 const model_t *rsurface_model;
3323 texture_t *rsurface_texture;
3324 rtexture_t *rsurface_lightmaptexture;
3325 rtexture_t *rsurface_deluxemaptexture;
3326 rsurfmode_t rsurface_mode;
3327 int rsurface_lightmode; // 0 = lightmap or fullbright, 1 = color array from q3bsp, 2 = vertex shaded model
3329 void RSurf_CleanUp(void)
3332 if (rsurface_mode == RSURFMODE_GLSL)
3334 qglUseProgramObjectARB(0);CHECKGLERROR
3336 GL_AlphaTest(false);
3337 rsurface_mode = RSURFMODE_NONE;
3338 rsurface_lightmaptexture = NULL;
3339 rsurface_deluxemaptexture = NULL;
3340 rsurface_texture = NULL;
3343 void RSurf_ActiveWorldEntity(void)
3346 rsurface_entity = r_refdef.worldentity;
3347 rsurface_model = r_refdef.worldmodel;
3348 if (rsurface_array_size < rsurface_model->surfmesh.num_vertices)
3349 R_Mesh_ResizeArrays(rsurface_model->surfmesh.num_vertices);
3350 R_Mesh_Matrix(&identitymatrix);
3351 VectorCopy(r_view.origin, rsurface_modelorg);
3352 rsurface_modelvertex3f = rsurface_model->surfmesh.data_vertex3f;
3353 rsurface_modelvertex3f_bufferobject = rsurface_model->surfmesh.vbo;
3354 rsurface_modelvertex3f_bufferoffset = rsurface_model->surfmesh.vbooffset_vertex3f;
3355 rsurface_modelsvector3f = rsurface_model->surfmesh.data_svector3f;
3356 rsurface_modelsvector3f_bufferobject = rsurface_model->surfmesh.vbo;
3357 rsurface_modelsvector3f_bufferoffset = rsurface_model->surfmesh.vbooffset_svector3f;
3358 rsurface_modeltvector3f = rsurface_model->surfmesh.data_tvector3f;
3359 rsurface_modeltvector3f_bufferobject = rsurface_model->surfmesh.vbo;
3360 rsurface_modeltvector3f_bufferoffset = rsurface_model->surfmesh.vbooffset_tvector3f;
3361 rsurface_modelnormal3f = rsurface_model->surfmesh.data_normal3f;
3362 rsurface_modelnormal3f_bufferobject = rsurface_model->surfmesh.vbo;
3363 rsurface_modelnormal3f_bufferoffset = rsurface_model->surfmesh.vbooffset_normal3f;
3364 rsurface_generatedvertex = false;
3365 rsurface_vertex3f = rsurface_modelvertex3f;
3366 rsurface_vertex3f_bufferobject = rsurface_modelvertex3f_bufferobject;
3367 rsurface_vertex3f_bufferoffset = rsurface_modelvertex3f_bufferoffset;
3368 rsurface_svector3f = rsurface_modelsvector3f;
3369 rsurface_svector3f_bufferobject = rsurface_modelsvector3f_bufferobject;
3370 rsurface_svector3f_bufferoffset = rsurface_modelsvector3f_bufferoffset;
3371 rsurface_tvector3f = rsurface_modeltvector3f;
3372 rsurface_tvector3f_bufferobject = rsurface_modeltvector3f_bufferobject;
3373 rsurface_tvector3f_bufferoffset = rsurface_modeltvector3f_bufferoffset;
3374 rsurface_normal3f = rsurface_modelnormal3f;
3375 rsurface_normal3f_bufferobject = rsurface_modelnormal3f_bufferobject;
3376 rsurface_normal3f_bufferoffset = rsurface_modelnormal3f_bufferoffset;
3379 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
3382 rsurface_entity = ent;
3383 rsurface_model = ent->model;
3384 if (rsurface_array_size < rsurface_model->surfmesh.num_vertices)
3385 R_Mesh_ResizeArrays(rsurface_model->surfmesh.num_vertices);
3386 R_Mesh_Matrix(&ent->matrix);
3387 Matrix4x4_Transform(&ent->inversematrix, r_view.origin, rsurface_modelorg);
3388 if (rsurface_model->surfmesh.isanimated && (rsurface_entity->frameblend[0].lerp != 1 || rsurface_entity->frameblend[0].frame != 0))
3392 rsurface_modelvertex3f = rsurface_array_modelvertex3f;
3393 rsurface_modelsvector3f = rsurface_array_modelsvector3f;
3394 rsurface_modeltvector3f = rsurface_array_modeltvector3f;
3395 rsurface_modelnormal3f = rsurface_array_modelnormal3f;
3396 Mod_Alias_GetMesh_Vertices(rsurface_model, rsurface_entity->frameblend, rsurface_array_modelvertex3f, rsurface_array_modelnormal3f, rsurface_array_modelsvector3f, rsurface_array_modeltvector3f);
3398 else if (wantnormals)
3400 rsurface_modelvertex3f = rsurface_array_modelvertex3f;
3401 rsurface_modelsvector3f = NULL;
3402 rsurface_modeltvector3f = NULL;
3403 rsurface_modelnormal3f = rsurface_array_modelnormal3f;
3404 Mod_Alias_GetMesh_Vertices(rsurface_model, rsurface_entity->frameblend, rsurface_array_modelvertex3f, rsurface_array_modelnormal3f, NULL, NULL);
3408 rsurface_modelvertex3f = rsurface_array_modelvertex3f;
3409 rsurface_modelsvector3f = NULL;
3410 rsurface_modeltvector3f = NULL;
3411 rsurface_modelnormal3f = NULL;
3412 Mod_Alias_GetMesh_Vertices(rsurface_model, rsurface_entity->frameblend, rsurface_array_modelvertex3f, NULL, NULL, NULL);
3414 rsurface_modelvertex3f_bufferobject = 0;
3415 rsurface_modelvertex3f_bufferoffset = 0;
3416 rsurface_modelsvector3f_bufferobject = 0;
3417 rsurface_modelsvector3f_bufferoffset = 0;
3418 rsurface_modeltvector3f_bufferobject = 0;
3419 rsurface_modeltvector3f_bufferoffset = 0;
3420 rsurface_modelnormal3f_bufferobject = 0;
3421 rsurface_modelnormal3f_bufferoffset = 0;
3422 rsurface_generatedvertex = true;
3426 rsurface_modelvertex3f = rsurface_model->surfmesh.data_vertex3f;
3427 rsurface_modelvertex3f_bufferobject = rsurface_model->surfmesh.vbo;
3428 rsurface_modelvertex3f_bufferoffset = rsurface_model->surfmesh.vbooffset_vertex3f;
3429 rsurface_modelsvector3f = rsurface_model->surfmesh.data_svector3f;
3430 rsurface_modelsvector3f_bufferobject = rsurface_model->surfmesh.vbo;
3431 rsurface_modelsvector3f_bufferoffset = rsurface_model->surfmesh.vbooffset_svector3f;
3432 rsurface_modeltvector3f = rsurface_model->surfmesh.data_tvector3f;
3433 rsurface_modeltvector3f_bufferobject = rsurface_model->surfmesh.vbo;
3434 rsurface_modeltvector3f_bufferoffset = rsurface_model->surfmesh.vbooffset_tvector3f;
3435 rsurface_modelnormal3f = rsurface_model->surfmesh.data_normal3f;
3436 rsurface_modelnormal3f_bufferobject = rsurface_model->surfmesh.vbo;
3437 rsurface_modelnormal3f_bufferoffset = rsurface_model->surfmesh.vbooffset_normal3f;
3438 rsurface_generatedvertex = false;
3440 rsurface_vertex3f = rsurface_modelvertex3f;
3441 rsurface_vertex3f_bufferobject = rsurface_modelvertex3f_bufferobject;
3442 rsurface_vertex3f_bufferoffset = rsurface_modelvertex3f_bufferoffset;
3443 rsurface_svector3f = rsurface_modelsvector3f;
3444 rsurface_svector3f_bufferobject = rsurface_modelsvector3f_bufferobject;
3445 rsurface_svector3f_bufferoffset = rsurface_modelsvector3f_bufferoffset;
3446 rsurface_tvector3f = rsurface_modeltvector3f;
3447 rsurface_tvector3f_bufferobject = rsurface_modeltvector3f_bufferobject;
3448 rsurface_tvector3f_bufferoffset = rsurface_modeltvector3f_bufferoffset;
3449 rsurface_normal3f = rsurface_modelnormal3f;
3450 rsurface_normal3f_bufferobject = rsurface_modelnormal3f_bufferobject;
3451 rsurface_normal3f_bufferoffset = rsurface_modelnormal3f_bufferoffset;
3454 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, msurface_t **texturesurfacelist)
3456 // 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
3457 if (rsurface_generatedvertex)
3459 if (rsurface_texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
3460 generatetangents = true;
3461 if (generatetangents)
3462 generatenormals = true;
3463 if (generatenormals && !rsurface_modelnormal3f)
3465 rsurface_normal3f = rsurface_modelnormal3f = rsurface_array_modelnormal3f;
3466 rsurface_normal3f_bufferobject = rsurface_modelnormal3f_bufferobject = 0;
3467 rsurface_normal3f_bufferoffset = rsurface_modelnormal3f_bufferoffset = 0;
3468 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);
3470 if (generatetangents && !rsurface_modelsvector3f)
3472 rsurface_svector3f = rsurface_modelsvector3f = rsurface_array_modelsvector3f;
3473 rsurface_svector3f_bufferobject = rsurface_modelsvector3f_bufferobject = 0;
3474 rsurface_svector3f_bufferoffset = rsurface_modelsvector3f_bufferoffset = 0;
3475 rsurface_tvector3f = rsurface_modeltvector3f = rsurface_array_modeltvector3f;
3476 rsurface_tvector3f_bufferobject = rsurface_modeltvector3f_bufferobject = 0;
3477 rsurface_tvector3f_bufferoffset = rsurface_modeltvector3f_bufferoffset = 0;
3478 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);
3481 // 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)
3482 if (rsurface_texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
3484 int texturesurfaceindex;
3485 float center[3], forward[3], right[3], up[3], v[4][3];
3486 matrix4x4_t matrix1, imatrix1;
3487 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_view.forward, forward);
3488 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_view.right, right);
3489 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_view.up, up);
3490 // make deformed versions of only the model vertices used by the specified surfaces
3491 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3494 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3495 // a single autosprite surface can contain multiple sprites...
3496 for (j = 0;j < surface->num_vertices - 3;j += 4)
3498 VectorClear(center);
3499 for (i = 0;i < 4;i++)
3500 VectorAdd(center, (rsurface_modelvertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
3501 VectorScale(center, 0.25f, center);
3502 if (rsurface_texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE2)
3504 forward[0] = rsurface_modelorg[0] - center[0];
3505 forward[1] = rsurface_modelorg[1] - center[1];
3507 VectorNormalize(forward);
3508 right[0] = forward[1];
3509 right[1] = -forward[0];
3511 VectorSet(up, 0, 0, 1);
3513 // FIXME: calculate vectors from triangle edges instead of using texture vectors as an easy way out?
3514 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);
3515 Matrix4x4_Invert_Simple(&imatrix1, &matrix1);
3516 for (i = 0;i < 4;i++)
3517 Matrix4x4_Transform(&imatrix1, (rsurface_modelvertex3f + 3 * surface->num_firstvertex) + (j+i)*3, v[i]);
3518 for (i = 0;i < 4;i++)
3519 VectorMAMAMAM(1, center, v[i][0], forward, v[i][1], right, v[i][2], up, rsurface_array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
3521 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);
3522 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);
3524 rsurface_vertex3f = rsurface_array_deformedvertex3f;
3525 rsurface_vertex3f_bufferobject = 0;
3526 rsurface_vertex3f_bufferoffset = 0;
3527 rsurface_svector3f = rsurface_array_deformedsvector3f;
3528 rsurface_svector3f_bufferobject = 0;
3529 rsurface_svector3f_bufferoffset = 0;
3530 rsurface_tvector3f = rsurface_array_deformedtvector3f;
3531 rsurface_tvector3f_bufferobject = 0;
3532 rsurface_tvector3f_bufferoffset = 0;
3533 rsurface_normal3f = rsurface_array_deformednormal3f;
3534 rsurface_normal3f_bufferobject = 0;
3535 rsurface_normal3f_bufferoffset = 0;
3539 rsurface_vertex3f = rsurface_modelvertex3f;
3540 rsurface_vertex3f_bufferobject = rsurface_modelvertex3f_bufferobject;
3541 rsurface_vertex3f_bufferoffset = rsurface_modelvertex3f_bufferoffset;
3542 rsurface_svector3f = rsurface_modelsvector3f;
3543 rsurface_svector3f_bufferobject = rsurface_modelsvector3f_bufferobject;
3544 rsurface_svector3f_bufferoffset = rsurface_modelsvector3f_bufferoffset;
3545 rsurface_tvector3f = rsurface_modeltvector3f;
3546 rsurface_tvector3f_bufferobject = rsurface_modeltvector3f_bufferobject;
3547 rsurface_tvector3f_bufferoffset = rsurface_modeltvector3f_bufferoffset;
3548 rsurface_normal3f = rsurface_modelnormal3f;
3549 rsurface_normal3f_bufferobject = rsurface_modelnormal3f_bufferobject;
3550 rsurface_normal3f_bufferoffset = rsurface_modelnormal3f_bufferoffset;
3552 R_Mesh_VertexPointer(rsurface_vertex3f, rsurface_vertex3f_bufferobject, rsurface_vertex3f_bufferoffset);
3555 void RSurf_DrawBatch_Simple(int texturenumsurfaces, msurface_t **texturesurfacelist)
3558 const msurface_t *surface = texturesurfacelist[0];
3559 const msurface_t *surface2;
3564 // TODO: lock all array ranges before render, rather than on each surface
3565 if (texturenumsurfaces == 1)
3567 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
3568 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle), rsurface_model->surfmesh.ebo, (sizeof(int[3]) * surface->num_firsttriangle));
3570 else if (r_batchmode.integer == 2)
3572 #define MAXBATCHTRIANGLES 4096
3573 int batchtriangles = 0;
3574 int batchelements[MAXBATCHTRIANGLES*3];
3575 for (i = 0;i < texturenumsurfaces;i = j)
3577 surface = texturesurfacelist[i];
3579 if (surface->num_triangles > MAXBATCHTRIANGLES)
3581 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle), rsurface_model->surfmesh.ebo, (sizeof(int[3]) * surface->num_firsttriangle));
3584 memcpy(batchelements, rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
3585 batchtriangles = surface->num_triangles;
3586 firstvertex = surface->num_firstvertex;
3587 endvertex = surface->num_firstvertex + surface->num_vertices;
3588 for (;j < texturenumsurfaces;j++)
3590 surface2 = texturesurfacelist[j];
3591 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
3593 memcpy(batchelements + batchtriangles * 3, rsurface_model->surfmesh.data_element3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
3594 batchtriangles += surface2->num_triangles;
3595 firstvertex = min(firstvertex, surface2->num_firstvertex);
3596 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
3598 surface2 = texturesurfacelist[j-1];
3599 numvertices = endvertex - firstvertex;
3600 R_Mesh_Draw(firstvertex, numvertices, batchtriangles, batchelements, 0, 0);
3603 else if (r_batchmode.integer == 1)
3605 for (i = 0;i < texturenumsurfaces;i = j)
3607 surface = texturesurfacelist[i];
3608 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
3609 if (texturesurfacelist[j] != surface2)
3611 surface2 = texturesurfacelist[j-1];
3612 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
3613 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
3614 GL_LockArrays(surface->num_firstvertex, numvertices);
3615 R_Mesh_Draw(surface->num_firstvertex, numvertices, numtriangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle), rsurface_model->surfmesh.ebo, (sizeof(int[3]) * surface->num_firsttriangle));
3620 for (i = 0;i < texturenumsurfaces;i++)
3622 surface = texturesurfacelist[i];
3623 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
3624 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle), rsurface_model->surfmesh.ebo, (sizeof(int[3]) * surface->num_firsttriangle));
3629 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
3632 int texturesurfaceindex;
3633 if (r_showsurfaces.integer == 2)
3635 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3637 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3638 for (j = 0;j < surface->num_triangles;j++)
3640 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_view.colorscale;
3641 GL_Color(f, f, f, 1);
3642 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, 1, (rsurface_model->surfmesh.data_element3i + 3 * (j + surface->num_firsttriangle)), rsurface_model->surfmesh.ebo, (sizeof(int[3]) * (j + surface->num_firsttriangle)));
3648 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3650 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3651 int k = (int)(((size_t)surface) / sizeof(msurface_t));
3652 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);
3653 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
3654 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle), rsurface_model->surfmesh.ebo, (sizeof(int[3]) * surface->num_firsttriangle));
3659 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, msurface_t **texturesurfacelist)
3661 int texturesurfaceindex;
3665 if (rsurface_lightmapcolor4f)
3667 // generate color arrays for the surfaces in this list
3668 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3670 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3671 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)
3673 f = FogPoint_Model(v);
3683 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3685 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3686 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)
3688 f = FogPoint_Model(v);
3696 rsurface_lightmapcolor4f = rsurface_array_color4f;
3697 rsurface_lightmapcolor4f_bufferobject = 0;
3698 rsurface_lightmapcolor4f_bufferoffset = 0;
3701 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a)
3703 int texturesurfaceindex;
3706 if (!rsurface_lightmapcolor4f)
3708 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3710 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3711 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)
3719 rsurface_lightmapcolor4f = rsurface_array_color4f;
3720 rsurface_lightmapcolor4f_bufferobject = 0;
3721 rsurface_lightmapcolor4f_bufferoffset = 0;
3724 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
3727 rsurface_lightmapcolor4f = NULL;
3728 rsurface_lightmapcolor4f_bufferobject = 0;
3729 rsurface_lightmapcolor4f_bufferoffset = 0;
3730 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
3731 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
3732 R_Mesh_ColorPointer(rsurface_lightmapcolor4f, rsurface_lightmapcolor4f_bufferobject, rsurface_lightmapcolor4f_bufferoffset);
3733 GL_Color(r, g, b, a);
3734 R_Mesh_TexBind(0, R_GetTexture(rsurface_lightmaptexture));
3735 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3738 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
3740 // TODO: optimize applyfog && applycolor case
3741 // just apply fog if necessary, and tint the fog color array if necessary
3742 rsurface_lightmapcolor4f = NULL;
3743 rsurface_lightmapcolor4f_bufferobject = 0;
3744 rsurface_lightmapcolor4f_bufferoffset = 0;
3745 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
3746 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
3747 R_Mesh_ColorPointer(rsurface_lightmapcolor4f, rsurface_lightmapcolor4f_bufferobject, rsurface_lightmapcolor4f_bufferoffset);
3748 GL_Color(r, g, b, a);
3749 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3752 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
3754 int texturesurfaceindex;
3758 if (texturesurfacelist[0]->lightmapinfo && texturesurfacelist[0]->lightmapinfo->stainsamples)
3760 // generate color arrays for the surfaces in this list
3761 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3763 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3764 for (i = 0, c = rsurface_array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
3766 if (surface->lightmapinfo->samples)
3768 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface_model->surfmesh.data_lightmapoffsets + surface->num_firstvertex)[i];
3769 float scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
3770 VectorScale(lm, scale, c);
3771 if (surface->lightmapinfo->styles[1] != 255)
3773 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
3775 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
3776 VectorMA(c, scale, lm, c);
3777 if (surface->lightmapinfo->styles[2] != 255)
3780 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
3781 VectorMA(c, scale, lm, c);
3782 if (surface->lightmapinfo->styles[3] != 255)
3785 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
3786 VectorMA(c, scale, lm, c);
3796 rsurface_lightmapcolor4f = rsurface_array_color4f;
3797 rsurface_lightmapcolor4f_bufferobject = 0;
3798 rsurface_lightmapcolor4f_bufferoffset = 0;
3802 rsurface_lightmapcolor4f = rsurface_model->surfmesh.data_lightmapcolor4f;
3803 rsurface_lightmapcolor4f_bufferobject = rsurface_model->surfmesh.vbo;
3804 rsurface_lightmapcolor4f_bufferoffset = rsurface_model->surfmesh.vbooffset_lightmapcolor4f;
3806 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
3807 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
3808 R_Mesh_ColorPointer(rsurface_lightmapcolor4f, rsurface_lightmapcolor4f_bufferobject, rsurface_lightmapcolor4f_bufferoffset);
3809 GL_Color(r, g, b, a);
3810 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3813 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
3815 int texturesurfaceindex;
3819 vec3_t ambientcolor;
3820 vec3_t diffusecolor;
3824 VectorCopy(rsurface_entity->modellight_lightdir, lightdir);
3825 ambientcolor[0] = rsurface_entity->modellight_ambient[0] * r * 0.5f;
3826 ambientcolor[1] = rsurface_entity->modellight_ambient[1] * g * 0.5f;
3827 ambientcolor[2] = rsurface_entity->modellight_ambient[2] * b * 0.5f;
3828 diffusecolor[0] = rsurface_entity->modellight_diffuse[0] * r * 0.5f;
3829 diffusecolor[1] = rsurface_entity->modellight_diffuse[1] * g * 0.5f;
3830 diffusecolor[2] = rsurface_entity->modellight_diffuse[2] * b * 0.5f;
3831 if (VectorLength2(diffusecolor) > 0)
3833 // generate color arrays for the surfaces in this list
3834 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3836 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3837 int numverts = surface->num_vertices;
3838 v = rsurface_vertex3f + 3 * surface->num_firstvertex;
3839 c2 = rsurface_normal3f + 3 * surface->num_firstvertex;
3840 c = rsurface_array_color4f + 4 * surface->num_firstvertex;
3841 // q3-style directional shading
3842 for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
3844 if ((f = DotProduct(c2, lightdir)) > 0)
3845 VectorMA(ambientcolor, f, diffusecolor, c);
3847 VectorCopy(ambientcolor, c);
3856 rsurface_lightmapcolor4f = rsurface_array_color4f;
3857 rsurface_lightmapcolor4f_bufferobject = 0;
3858 rsurface_lightmapcolor4f_bufferoffset = 0;
3862 r = ambientcolor[0];
3863 g = ambientcolor[1];
3864 b = ambientcolor[2];
3865 rsurface_lightmapcolor4f = NULL;
3866 rsurface_lightmapcolor4f_bufferobject = 0;
3867 rsurface_lightmapcolor4f_bufferoffset = 0;
3869 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
3870 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
3871 R_Mesh_ColorPointer(rsurface_lightmapcolor4f, rsurface_lightmapcolor4f_bufferobject, rsurface_lightmapcolor4f_bufferoffset);
3872 GL_Color(r, g, b, a);
3873 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3876 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
3878 GL_DepthRange(0, (rsurface_texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
3879 GL_DepthTest(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
3880 GL_CullFace((rsurface_texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
3881 if (rsurface_mode != RSURFMODE_SHOWSURFACES)
3883 rsurface_mode = RSURFMODE_SHOWSURFACES;
3885 GL_BlendFunc(GL_ONE, GL_ZERO);
3886 R_Mesh_ColorPointer(NULL, 0, 0);
3887 R_Mesh_ResetTextureState();
3889 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
3890 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
3893 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, msurface_t **texturesurfacelist)
3895 // transparent sky would be ridiculous
3896 if ((rsurface_texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED))
3898 if (rsurface_mode != RSURFMODE_SKY)
3900 if (rsurface_mode == RSURFMODE_GLSL)
3902 qglUseProgramObjectARB(0);CHECKGLERROR
3904 rsurface_mode = RSURFMODE_SKY;
3908 skyrendernow = false;
3910 // restore entity matrix
3911 R_Mesh_Matrix(&rsurface_entity->matrix);
3913 GL_DepthRange(0, (rsurface_texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
3914 GL_DepthTest(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
3915 GL_CullFace((rsurface_texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
3917 // LordHavoc: HalfLife maps have freaky skypolys so don't use
3918 // skymasking on them, and Quake3 never did sky masking (unlike
3919 // software Quake and software Quake2), so disable the sky masking
3920 // in Quake3 maps as it causes problems with q3map2 sky tricks,
3921 // and skymasking also looks very bad when noclipping outside the
3922 // level, so don't use it then either.
3923 if (rsurface_model->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_viewcache.world_novis)
3925 GL_Color(r_refdef.fogcolor[0] * r_view.colorscale, r_refdef.fogcolor[1] * r_view.colorscale, r_refdef.fogcolor[2] * r_view.colorscale, 1);
3926 R_Mesh_ColorPointer(NULL, 0, 0);
3927 R_Mesh_ResetTextureState();
3928 if (skyrendermasked)
3930 // depth-only (masking)
3931 GL_ColorMask(0,0,0,0);
3932 // just to make sure that braindead drivers don't draw
3933 // anything despite that colormask...
3934 GL_BlendFunc(GL_ZERO, GL_ONE);
3939 GL_BlendFunc(GL_ONE, GL_ZERO);
3941 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
3942 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3943 if (skyrendermasked)
3944 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
3948 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, msurface_t **texturesurfacelist)
3950 if (rsurface_mode != RSURFMODE_GLSL)
3952 rsurface_mode = RSURFMODE_GLSL;
3953 R_Mesh_ResetTextureState();
3956 R_SetupSurfaceShader(vec3_origin, rsurface_lightmode == 2, 1, 1, rsurface_texture->specularscale);
3957 if (!r_glsl_permutation)
3960 if (rsurface_lightmode == 2)
3961 RSurf_PrepareVerticesForBatch(true, r_glsl_permutation->loc_Texture_Normal, texturenumsurfaces, texturesurfacelist);
3963 RSurf_PrepareVerticesForBatch(r_glsl_permutation->loc_Texture_Normal, r_glsl_permutation->loc_Texture_Normal, texturenumsurfaces, texturesurfacelist);
3964 R_Mesh_TexCoordPointer(0, 2, rsurface_model->surfmesh.data_texcoordtexture2f, rsurface_model->surfmesh.vbo, rsurface_model->surfmesh.vbooffset_texcoordtexture2f);
3965 R_Mesh_TexCoordPointer(1, 3, rsurface_svector3f, rsurface_svector3f_bufferobject, rsurface_svector3f_bufferoffset);
3966 R_Mesh_TexCoordPointer(2, 3, rsurface_tvector3f, rsurface_tvector3f_bufferobject, rsurface_tvector3f_bufferoffset);
3967 R_Mesh_TexCoordPointer(3, 3, rsurface_normal3f, rsurface_normal3f_bufferobject, rsurface_normal3f_bufferoffset);
3968 R_Mesh_TexCoordPointer(4, 2, rsurface_model->surfmesh.data_texcoordlightmap2f, rsurface_model->surfmesh.vbo, rsurface_model->surfmesh.vbooffset_texcoordlightmap2f);
3970 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
3972 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
3973 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
3974 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
3975 R_Mesh_ColorPointer(NULL, 0, 0);
3977 else if (rsurface_lightmaptexture)
3979 R_Mesh_TexBind(7, R_GetTexture(rsurface_lightmaptexture));
3980 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
3981 R_Mesh_TexBind(8, R_GetTexture(rsurface_deluxemaptexture));
3982 R_Mesh_ColorPointer(NULL, 0, 0);
3986 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
3987 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
3988 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
3989 R_Mesh_ColorPointer(rsurface_model->surfmesh.data_lightmapcolor4f, rsurface_model->surfmesh.vbo, rsurface_model->surfmesh.vbooffset_lightmapcolor4f);
3992 if (rsurface_lightmaptexture && !(rsurface_texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
3994 R_Mesh_TexBind(7, R_GetTexture(rsurface_lightmaptexture));
3995 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
3996 R_Mesh_TexBind(8, R_GetTexture(rsurface_deluxemaptexture));
3998 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3999 if (rsurface_texture->backgroundnumskinframes && !(rsurface_texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED))
4004 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, msurface_t **texturesurfacelist)
4006 // OpenGL 1.3 path - anything not completely ancient
4007 int texturesurfaceindex;
4008 qboolean applycolor;
4012 const texturelayer_t *layer;
4013 if (rsurface_mode != RSURFMODE_MULTIPASS)
4014 rsurface_mode = RSURFMODE_MULTIPASS;
4015 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
4016 for (layerindex = 0, layer = rsurface_texture->currentlayers;layerindex < rsurface_texture->currentnumlayers;layerindex++, layer++)
4019 int layertexrgbscale;
4020 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
4022 if (layerindex == 0)
4026 GL_AlphaTest(false);
4027 qglDepthFunc(GL_EQUAL);CHECKGLERROR
4030 GL_DepthMask(layer->depthmask);
4031 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
4032 if ((layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2) && (gl_combine.integer || layer->depthmask))
4034 layertexrgbscale = 4;
4035 VectorScale(layer->color, 0.25f, layercolor);
4037 else if ((layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1) && (gl_combine.integer || layer->depthmask))
4039 layertexrgbscale = 2;
4040 VectorScale(layer->color, 0.5f, layercolor);
4044 layertexrgbscale = 1;
4045 VectorScale(layer->color, 1.0f, layercolor);
4047 layercolor[3] = layer->color[3];
4048 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
4049 R_Mesh_ColorPointer(NULL, 0, 0);
4050 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
4051 switch (layer->type)
4053 case TEXTURELAYERTYPE_LITTEXTURE:
4054 memset(&m, 0, sizeof(m));
4055 m.tex[0] = R_GetTexture(r_texture_white);
4056 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordlightmap2f;
4057 m.pointer_texcoord_bufferobject[0] = rsurface_model->surfmesh.vbo;
4058 m.pointer_texcoord_bufferoffset[0] = rsurface_model->surfmesh.vbooffset_texcoordlightmap2f;
4059 m.tex[1] = R_GetTexture(layer->texture);
4060 m.texmatrix[1] = layer->texmatrix;
4061 m.texrgbscale[1] = layertexrgbscale;
4062 m.pointer_texcoord[1] = rsurface_model->surfmesh.data_texcoordtexture2f;
4063 m.pointer_texcoord_bufferobject[1] = rsurface_model->surfmesh.vbo;
4064 m.pointer_texcoord_bufferoffset[1] = rsurface_model->surfmesh.vbooffset_texcoordtexture2f;
4065 R_Mesh_TextureState(&m);
4066 if (rsurface_lightmode == 2)
4067 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
4068 else if (rsurface_lightmaptexture)
4069 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
4071 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
4073 case TEXTURELAYERTYPE_TEXTURE:
4074 memset(&m, 0, sizeof(m));
4075 m.tex[0] = R_GetTexture(layer->texture);
4076 m.texmatrix[0] = layer->texmatrix;
4077 m.texrgbscale[0] = layertexrgbscale;
4078 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
4079 m.pointer_texcoord_bufferobject[0] = rsurface_model->surfmesh.vbo;
4080 m.pointer_texcoord_bufferoffset[0] = rsurface_model->surfmesh.vbooffset_texcoordtexture2f;
4081 R_Mesh_TextureState(&m);
4082 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
4084 case TEXTURELAYERTYPE_FOG:
4085 memset(&m, 0, sizeof(m));
4086 m.texrgbscale[0] = layertexrgbscale;
4089 m.tex[0] = R_GetTexture(layer->texture);
4090 m.texmatrix[0] = layer->texmatrix;
4091 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
4092 m.pointer_texcoord_bufferobject[0] = rsurface_model->surfmesh.vbo;
4093 m.pointer_texcoord_bufferoffset[0] = rsurface_model->surfmesh.vbooffset_texcoordtexture2f;
4095 R_Mesh_TextureState(&m);
4096 // generate a color array for the fog pass
4097 R_Mesh_ColorPointer(rsurface_array_color4f, 0, 0);
4098 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4102 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4103 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)
4105 f = 1 - FogPoint_Model(v);
4106 c[0] = layercolor[0];
4107 c[1] = layercolor[1];
4108 c[2] = layercolor[2];
4109 c[3] = f * layercolor[3];
4112 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
4115 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
4117 GL_LockArrays(0, 0);
4120 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
4122 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
4123 GL_AlphaTest(false);
4127 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, msurface_t **texturesurfacelist)
4129 // OpenGL 1.1 - crusty old voodoo path
4130 int texturesurfaceindex;
4134 const texturelayer_t *layer;
4135 if (rsurface_mode != RSURFMODE_MULTIPASS)
4136 rsurface_mode = RSURFMODE_MULTIPASS;
4137 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
4138 for (layerindex = 0, layer = rsurface_texture->currentlayers;layerindex < rsurface_texture->currentnumlayers;layerindex++, layer++)
4140 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
4142 if (layerindex == 0)
4146 GL_AlphaTest(false);
4147 qglDepthFunc(GL_EQUAL);CHECKGLERROR
4150 GL_DepthMask(layer->depthmask);
4151 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
4152 R_Mesh_ColorPointer(NULL, 0, 0);
4153 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
4154 switch (layer->type)
4156 case TEXTURELAYERTYPE_LITTEXTURE:
4157 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
4159 // two-pass lit texture with 2x rgbscale
4160 // first the lightmap pass
4161 memset(&m, 0, sizeof(m));
4162 m.tex[0] = R_GetTexture(r_texture_white);
4163 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordlightmap2f;
4164 m.pointer_texcoord_bufferobject[0] = rsurface_model->surfmesh.vbo;
4165 m.pointer_texcoord_bufferoffset[0] = rsurface_model->surfmesh.vbooffset_texcoordlightmap2f;
4166 R_Mesh_TextureState(&m);
4167 if (rsurface_lightmode == 2)
4168 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
4169 else if (rsurface_lightmaptexture)
4170 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
4172 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
4173 GL_LockArrays(0, 0);
4174 // then apply the texture to it
4175 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
4176 memset(&m, 0, sizeof(m));
4177 m.tex[0] = R_GetTexture(layer->texture);
4178 m.texmatrix[0] = layer->texmatrix;
4179 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
4180 m.pointer_texcoord_bufferobject[0] = rsurface_model->surfmesh.vbo;
4181 m.pointer_texcoord_bufferoffset[0] = rsurface_model->surfmesh.vbooffset_texcoordtexture2f;
4182 R_Mesh_TextureState(&m);
4183 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);
4187 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
4188 memset(&m, 0, sizeof(m));
4189 m.tex[0] = R_GetTexture(layer->texture);
4190 m.texmatrix[0] = layer->texmatrix;
4191 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
4192 m.pointer_texcoord_bufferobject[0] = rsurface_model->surfmesh.vbo;
4193 m.pointer_texcoord_bufferoffset[0] = rsurface_model->surfmesh.vbooffset_texcoordtexture2f;
4194 R_Mesh_TextureState(&m);
4195 if (rsurface_lightmode == 2)
4196 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);
4198 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);
4201 case TEXTURELAYERTYPE_TEXTURE:
4202 // singletexture unlit texture with transparency support
4203 memset(&m, 0, sizeof(m));
4204 m.tex[0] = R_GetTexture(layer->texture);
4205 m.texmatrix[0] = layer->texmatrix;
4206 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
4207 m.pointer_texcoord_bufferobject[0] = rsurface_model->surfmesh.vbo;
4208 m.pointer_texcoord_bufferoffset[0] = rsurface_model->surfmesh.vbooffset_texcoordtexture2f;
4209 R_Mesh_TextureState(&m);
4210 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);
4212 case TEXTURELAYERTYPE_FOG:
4213 // singletexture fogging
4214 R_Mesh_ColorPointer(rsurface_array_color4f, 0, 0);
4217 memset(&m, 0, sizeof(m));
4218 m.tex[0] = R_GetTexture(layer->texture);
4219 m.texmatrix[0] = layer->texmatrix;
4220 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
4221 m.pointer_texcoord_bufferobject[0] = rsurface_model->surfmesh.vbo;
4222 m.pointer_texcoord_bufferoffset[0] = rsurface_model->surfmesh.vbooffset_texcoordtexture2f;
4223 R_Mesh_TextureState(&m);
4226 R_Mesh_ResetTextureState();
4227 // generate a color array for the fog pass
4228 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4232 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4233 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)
4235 f = 1 - FogPoint_Model(v);
4236 c[0] = layer->color[0];
4237 c[1] = layer->color[1];
4238 c[2] = layer->color[2];
4239 c[3] = f * layer->color[3];
4242 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
4245 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
4247 GL_LockArrays(0, 0);
4250 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
4252 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
4253 GL_AlphaTest(false);
4257 static void R_DrawTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist)
4259 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_NODRAW)
4261 r_shadow_rtlight = NULL;
4262 r_refdef.stats.entities_surfaces += texturenumsurfaces;
4264 if (r_showsurfaces.integer)
4265 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
4266 else if (rsurface_texture->currentmaterialflags & MATERIALFLAG_SKY)
4267 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
4268 else if (rsurface_texture->currentnumlayers)
4270 GL_DepthRange(0, (rsurface_texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
4271 GL_DepthTest(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
4272 GL_CullFace((rsurface_texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
4273 GL_BlendFunc(rsurface_texture->currentlayers[0].blendfunc1, rsurface_texture->currentlayers[0].blendfunc2);
4274 GL_DepthMask(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_BLENDED));
4275 GL_Color(rsurface_entity->colormod[0], rsurface_entity->colormod[1], rsurface_entity->colormod[2], rsurface_texture->currentalpha);
4276 GL_AlphaTest((rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4277 // FIXME: identify models using a better check than rsurface_model->brush.shadowmesh
4278 rsurface_lightmode = ((rsurface_texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT) || rsurface_model->brush.shadowmesh) ? 0 : 2;
4279 if (r_glsl.integer && gl_support_fragment_shader)
4280 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist);
4281 else if (gl_combine.integer && r_textureunits.integer >= 2)
4282 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist);
4284 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist);
4287 GL_LockArrays(0, 0);
4290 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
4293 int texturenumsurfaces, endsurface;
4295 msurface_t *surface;
4296 msurface_t *texturesurfacelist[1024];
4298 // if the model is static it doesn't matter what value we give for
4299 // wantnormals and wanttangents, so this logic uses only rules applicable
4300 // to a model, knowing that they are meaningless otherwise
4301 if (ent == r_refdef.worldentity)
4302 RSurf_ActiveWorldEntity();
4303 else if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
4304 RSurf_ActiveModelEntity(ent, false, false);
4306 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
4308 for (i = 0;i < numsurfaces;i = j)
4311 surface = rsurface_model->data_surfaces + surfacelist[i];
4312 texture = surface->texture;
4313 R_UpdateTextureInfo(ent, texture);
4314 rsurface_texture = texture->currentframe;
4315 rsurface_lightmaptexture = surface->lightmaptexture;
4316 rsurface_deluxemaptexture = surface->deluxemaptexture;
4317 // scan ahead until we find a different texture
4318 endsurface = min(i + 1024, numsurfaces);
4319 texturenumsurfaces = 0;
4320 texturesurfacelist[texturenumsurfaces++] = surface;
4321 for (;j < endsurface;j++)
4323 surface = rsurface_model->data_surfaces + surfacelist[j];
4324 if (texture != surface->texture || rsurface_lightmaptexture != surface->lightmaptexture)
4326 texturesurfacelist[texturenumsurfaces++] = surface;
4328 // render the range of surfaces
4329 R_DrawTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
4335 void R_QueueSurfaceList(int numsurfaces, msurface_t **surfacelist, int flagsmask)
4338 vec3_t tempcenter, center;
4340 // break the surface list down into batches by texture and use of lightmapping
4341 for (i = 0;i < numsurfaces;i = j)
4344 // texture is the base texture pointer, rsurface_texture is the
4345 // current frame/skin the texture is directing us to use (for example
4346 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
4347 // use skin 1 instead)
4348 texture = surfacelist[i]->texture;
4349 rsurface_texture = texture->currentframe;
4350 rsurface_lightmaptexture = surfacelist[i]->lightmaptexture;
4351 rsurface_deluxemaptexture = surfacelist[i]->deluxemaptexture;
4352 if (!(rsurface_texture->currentmaterialflags & flagsmask))
4354 // if this texture is not the kind we want, skip ahead to the next one
4355 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
4359 if (rsurface_texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
4361 // transparent surfaces get pushed off into the transparent queue
4362 const msurface_t *surface = surfacelist[i];
4363 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
4364 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
4365 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
4366 Matrix4x4_Transform(&rsurface_entity->matrix, tempcenter, center);
4367 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);
4371 // simply scan ahead until we find a different texture or lightmap state
4372 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface_lightmaptexture == surfacelist[j]->lightmaptexture;j++)
4374 // render the range of surfaces
4375 R_DrawTextureSurfaceList(j - i, surfacelist + i);
4380 float locboxvertex3f[6*4*3] =
4382 1,0,1, 1,0,0, 1,1,0, 1,1,1,
4383 0,1,1, 0,1,0, 0,0,0, 0,0,1,
4384 1,1,1, 1,1,0, 0,1,0, 0,1,1,
4385 0,0,1, 0,0,0, 1,0,0, 1,0,1,
4386 0,0,1, 1,0,1, 1,1,1, 0,1,1,
4387 1,0,0, 0,0,0, 0,1,0, 1,1,0
4390 int locboxelement3i[6*2*3] =
4400 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
4403 cl_locnode_t *loc = (cl_locnode_t *)ent;
4405 float vertex3f[6*4*3];
4407 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4408 GL_DepthMask(false);
4409 GL_DepthRange(0, 1);
4411 GL_CullFace(GL_NONE);
4412 R_Mesh_Matrix(&identitymatrix);
4414 R_Mesh_VertexPointer(vertex3f, 0, 0);
4415 R_Mesh_ColorPointer(NULL, 0, 0);
4416 R_Mesh_ResetTextureState();
4419 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_view.colorscale,
4420 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_view.colorscale,
4421 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_view.colorscale,
4422 surfacelist[0] < 0 ? 0.5f : 0.125f);
4424 if (VectorCompare(loc->mins, loc->maxs))
4426 VectorSet(size, 2, 2, 2);
4427 VectorMA(loc->mins, -0.5f, size, mins);
4431 VectorCopy(loc->mins, mins);
4432 VectorSubtract(loc->maxs, loc->mins, size);
4435 for (i = 0;i < 6*4*3;)
4436 for (j = 0;j < 3;j++, i++)
4437 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
4439 R_Mesh_Draw(0, 6*4, 6*2, locboxelement3i, 0, 0);
4442 void R_DrawLocs(void)
4445 cl_locnode_t *loc, *nearestloc;
4447 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
4448 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
4450 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
4451 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
4455 void R_DrawCollisionBrushes(entity_render_t *ent)
4459 msurface_t *surface;
4460 model_t *model = ent->model;
4461 if (!model->brush.num_brushes)
4464 R_Mesh_ColorPointer(NULL, 0, 0);
4465 R_Mesh_ResetTextureState();
4466 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
4467 GL_DepthMask(false);
4468 GL_DepthRange(0, 1);
4469 GL_DepthTest(!r_showdisabledepthtest.integer);
4470 qglPolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);CHECKGLERROR
4471 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
4472 if (brush->colbrushf && brush->colbrushf->numtriangles)
4473 R_DrawCollisionBrush(brush->colbrushf);
4474 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
4475 if (surface->num_collisiontriangles)
4476 R_DrawCollisionSurface(ent, surface);
4477 qglPolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR
4480 void R_DrawTrianglesAndNormals(entity_render_t *ent, qboolean drawtris, qboolean drawnormals, int flagsmask)
4483 const int *elements;
4484 msurface_t *surface;
4485 model_t *model = ent->model;
4488 GL_DepthRange(0, 1);
4489 GL_DepthTest(!r_showdisabledepthtest.integer);
4491 GL_BlendFunc(GL_ONE, GL_ZERO);
4492 R_Mesh_ColorPointer(NULL, 0, 0);
4493 R_Mesh_ResetTextureState();
4494 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
4496 if (ent == r_refdef.worldentity && !r_viewcache.world_surfacevisible[j])
4498 rsurface_texture = surface->texture->currentframe;
4499 if ((rsurface_texture->currentmaterialflags & flagsmask) && surface->num_triangles)
4501 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
4504 if (!rsurface_texture->currentlayers->depthmask)
4505 GL_Color(r_showtris.value * r_view.colorscale, 0, 0, 1);
4506 else if (ent == r_refdef.worldentity)
4507 GL_Color(r_showtris.value * r_view.colorscale, r_showtris.value * r_view.colorscale, r_showtris.value * r_view.colorscale, 1);
4509 GL_Color(0, r_showtris.value * r_view.colorscale, 0, 1);
4510 elements = (ent->model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
4513 for (k = 0;k < surface->num_triangles;k++, elements += 3)
4515 #define GLVERTEXELEMENT(n) qglVertex3f(rsurface_vertex3f[elements[n]*3+0], rsurface_vertex3f[elements[n]*3+1], rsurface_vertex3f[elements[n]*3+2])
4516 GLVERTEXELEMENT(0);GLVERTEXELEMENT(1);
4517 GLVERTEXELEMENT(1);GLVERTEXELEMENT(2);
4518 GLVERTEXELEMENT(2);GLVERTEXELEMENT(0);
4525 GL_Color(r_shownormals.value * r_view.colorscale, 0, 0, 1);
4527 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
4529 VectorCopy(rsurface_vertex3f + l * 3, v);
4530 qglVertex3f(v[0], v[1], v[2]);
4531 VectorMA(v, 8, rsurface_svector3f + l * 3, v);
4532 qglVertex3f(v[0], v[1], v[2]);
4536 GL_Color(0, 0, r_shownormals.value * r_view.colorscale, 1);
4538 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
4540 VectorCopy(rsurface_vertex3f + l * 3, v);
4541 qglVertex3f(v[0], v[1], v[2]);
4542 VectorMA(v, 8, rsurface_tvector3f + l * 3, v);
4543 qglVertex3f(v[0], v[1], v[2]);
4547 GL_Color(0, r_shownormals.value * r_view.colorscale, 0, 1);
4549 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
4551 VectorCopy(rsurface_vertex3f + l * 3, v);
4552 qglVertex3f(v[0], v[1], v[2]);
4553 VectorMA(v, 8, rsurface_normal3f + l * 3, v);
4554 qglVertex3f(v[0], v[1], v[2]);
4561 rsurface_texture = NULL;
4564 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
4565 void R_DrawWorldSurfaces(qboolean skysurfaces)
4567 int i, j, endj, f, flagsmask;
4568 int counttriangles = 0;
4569 msurface_t *surface, **surfacechain;
4571 model_t *model = r_refdef.worldmodel;
4572 const int maxsurfacelist = 1024;
4573 int numsurfacelist = 0;
4574 msurface_t *surfacelist[1024];
4578 RSurf_ActiveWorldEntity();
4580 // update light styles
4581 if (!skysurfaces && model->brushq1.light_styleupdatechains)
4583 for (i = 0;i < model->brushq1.light_styles;i++)
4585 if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
4587 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
4588 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
4589 for (;(surface = *surfacechain);surfacechain++)
4590 surface->cached_dlight = true;
4595 R_UpdateAllTextureInfo(r_refdef.worldentity);
4596 flagsmask = skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL);
4599 rsurface_lightmaptexture = NULL;
4600 rsurface_deluxemaptexture = NULL;
4601 rsurface_texture = NULL;
4603 j = model->firstmodelsurface;
4604 endj = j + model->nummodelsurfaces;
4607 // quickly skip over non-visible surfaces
4608 for (;j < endj && !r_viewcache.world_surfacevisible[j];j++)
4610 // quickly iterate over visible surfaces
4611 for (;j < endj && r_viewcache.world_surfacevisible[j];j++)
4613 // process this surface
4614 surface = model->data_surfaces + j;
4615 // if this surface fits the criteria, add it to the list
4616 if (surface->num_triangles)
4618 // if lightmap parameters changed, rebuild lightmap texture
4619 if (surface->cached_dlight)
4620 R_BuildLightMap(r_refdef.worldentity, surface);
4621 // add face to draw list
4622 surfacelist[numsurfacelist++] = surface;
4623 counttriangles += surface->num_triangles;
4624 if (numsurfacelist >= maxsurfacelist)
4626 R_QueueSurfaceList(numsurfacelist, surfacelist, flagsmask);
4633 R_QueueSurfaceList(numsurfacelist, surfacelist, flagsmask);
4634 r_refdef.stats.entities_triangles += counttriangles;
4637 if (r_showcollisionbrushes.integer && !skysurfaces)
4638 R_DrawCollisionBrushes(r_refdef.worldentity);
4640 if (r_showtris.integer || r_shownormals.integer)
4641 R_DrawTrianglesAndNormals(r_refdef.worldentity, r_showtris.integer, r_shownormals.integer, flagsmask);
4644 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces)
4646 int i, f, flagsmask;
4647 int counttriangles = 0;
4648 msurface_t *surface, *endsurface, **surfacechain;
4650 model_t *model = ent->model;
4651 const int maxsurfacelist = 1024;
4652 int numsurfacelist = 0;
4653 msurface_t *surfacelist[1024];
4657 // if the model is static it doesn't matter what value we give for
4658 // wantnormals and wanttangents, so this logic uses only rules applicable
4659 // to a model, knowing that they are meaningless otherwise
4660 if (ent == r_refdef.worldentity)
4661 RSurf_ActiveWorldEntity();
4662 else if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
4663 RSurf_ActiveModelEntity(ent, false, false);
4665 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
4667 // update light styles
4668 if (!skysurfaces && model->brushq1.light_styleupdatechains)
4670 for (i = 0;i < model->brushq1.light_styles;i++)
4672 if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
4674 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
4675 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
4676 for (;(surface = *surfacechain);surfacechain++)
4677 surface->cached_dlight = true;
4682 R_UpdateAllTextureInfo(ent);
4683 flagsmask = skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL);
4686 rsurface_lightmaptexture = NULL;
4687 rsurface_deluxemaptexture = NULL;
4688 rsurface_texture = NULL;
4690 surface = model->data_surfaces + model->firstmodelsurface;
4691 endsurface = surface + model->nummodelsurfaces;
4692 for (;surface < endsurface;surface++)
4694 // if this surface fits the criteria, add it to the list
4695 if (surface->num_triangles)
4697 // if lightmap parameters changed, rebuild lightmap texture
4698 if (surface->cached_dlight)
4699 R_BuildLightMap(ent, surface);
4700 // add face to draw list
4701 surfacelist[numsurfacelist++] = surface;
4702 counttriangles += surface->num_triangles;
4703 if (numsurfacelist >= maxsurfacelist)
4705 R_QueueSurfaceList(numsurfacelist, surfacelist, flagsmask);
4711 R_QueueSurfaceList(numsurfacelist, surfacelist, flagsmask);
4712 r_refdef.stats.entities_triangles += counttriangles;
4715 if (r_showcollisionbrushes.integer && !skysurfaces)
4716 R_DrawCollisionBrushes(ent);
4718 if (r_showtris.integer || r_shownormals.integer)
4719 R_DrawTrianglesAndNormals(ent, r_showtris.integer, r_shownormals.integer, flagsmask);