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)
1060 // mark the skinframe as used for the purging code
1061 skinframe->loadsequence = r_skinframe.loadsequence;
1064 void R_SkinFrame_Purge(void)
1068 for (i = 0;i < SKINFRAME_HASH;i++)
1070 for (s = r_skinframe.hash[i];s;s = s->next)
1072 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
1074 if (s->base == r_texture_notexture) s->base = NULL;
1075 if (s->nmap == r_texture_blanknormalmap)s->nmap = NULL;
1076 if (s->merged == s->base) s->merged = NULL;
1077 if (s->stain ) R_FreeTexture(s->stain );s->stain = NULL;
1078 if (s->merged) R_FreeTexture(s->merged);s->merged = NULL;
1079 if (s->base ) R_FreeTexture(s->base );s->base = NULL;
1080 if (s->pants ) R_FreeTexture(s->pants );s->pants = NULL;
1081 if (s->shirt ) R_FreeTexture(s->shirt );s->shirt = NULL;
1082 if (s->nmap ) R_FreeTexture(s->nmap );s->nmap = NULL;
1083 if (s->gloss ) R_FreeTexture(s->gloss );s->gloss = NULL;
1084 if (s->glow ) R_FreeTexture(s->glow );s->glow = NULL;
1085 if (s->fog ) R_FreeTexture(s->fog );s->fog = NULL;
1086 s->loadsequence = 0;
1092 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
1096 char basename[MAX_QPATH];
1098 Image_StripImageExtension(name, basename, sizeof(basename));
1100 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
1101 for (item = r_skinframe.hash[hashindex];item;item = item->next)
1102 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
1108 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
1109 memset(item, 0, sizeof(*item));
1110 strlcpy(item->basename, basename, sizeof(item->basename));
1111 item->textureflags = textureflags;
1112 item->comparewidth = comparewidth;
1113 item->compareheight = compareheight;
1114 item->comparecrc = comparecrc;
1115 item->next = r_skinframe.hash[hashindex];
1116 r_skinframe.hash[hashindex] = item;
1118 R_SkinFrame_MarkUsed(item);
1122 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags)
1124 // FIXME: it should be possible to disable loading various layers using
1125 // cvars, to prevent wasted loading time and memory usage if the user does
1127 qboolean loadnormalmap = true;
1128 qboolean loadgloss = true;
1129 qboolean loadpantsandshirt = true;
1130 qboolean loadglow = true;
1132 unsigned char *pixels;
1133 unsigned char *bumppixels;
1134 unsigned char *basepixels = NULL;
1135 int basepixels_width;
1136 int basepixels_height;
1137 skinframe_t *skinframe;
1139 if (cls.state == ca_dedicated)
1142 // return an existing skinframe if already loaded
1143 // if loading of the first image fails, don't make a new skinframe as it
1144 // would cause all future lookups of this to be missing
1145 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
1146 if (skinframe && skinframe->base)
1149 basepixels = loadimagepixels(name, false, 0, 0);
1150 if (basepixels == NULL)
1153 // we've got some pixels to store, so really allocate this new texture now
1155 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
1156 skinframe->stain = NULL;
1157 skinframe->merged = NULL;
1158 skinframe->base = r_texture_notexture;
1159 skinframe->pants = NULL;
1160 skinframe->shirt = NULL;
1161 skinframe->nmap = r_texture_blanknormalmap;
1162 skinframe->gloss = NULL;
1163 skinframe->glow = NULL;
1164 skinframe->fog = NULL;
1166 basepixels_width = image_width;
1167 basepixels_height = image_height;
1168 skinframe->base = R_LoadTexture2D (r_main_texturepool, skinframe->basename, basepixels_width, basepixels_height, basepixels, TEXTYPE_RGBA, skinframe->textureflags, NULL);
1170 if (textureflags & TEXF_ALPHA)
1172 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
1173 if (basepixels[j] < 255)
1175 if (j < basepixels_width * basepixels_height * 4)
1177 // has transparent pixels
1178 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
1179 for (j = 0;j < image_width * image_height * 4;j += 4)
1184 pixels[j+3] = basepixels[j+3];
1186 skinframe->fog = R_LoadTexture2D (r_main_texturepool, va("%s_mask", skinframe->basename), image_width, image_height, pixels, TEXTYPE_RGBA, skinframe->textureflags, NULL);
1191 // _norm is the name used by tenebrae and has been adopted as standard
1194 if ((pixels = loadimagepixels(va("%s_norm", skinframe->basename), false, 0, 0)) != NULL)
1196 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_RGBA, skinframe->textureflags, NULL);
1200 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixels(va("%s_bump", skinframe->basename), false, 0, 0)) != NULL)
1202 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
1203 Image_HeightmapToNormalmap(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
1204 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_RGBA, skinframe->textureflags, NULL);
1206 Mem_Free(bumppixels);
1208 else if (r_shadow_bumpscale_basetexture.value > 0)
1210 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
1211 Image_HeightmapToNormalmap(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
1212 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), basepixels_width, basepixels_height, pixels, TEXTYPE_RGBA, skinframe->textureflags, NULL);
1216 // _luma is supported for tenebrae compatibility
1217 // (I think it's a very stupid name, but oh well)
1218 // _glow is the preferred name
1219 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;}
1220 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;}
1221 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;}
1222 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;}
1225 Mem_Free(basepixels);
1230 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)
1235 for (i = 0;i < width*height;i++)
1236 if (((unsigned char *)&palette[in[i]])[3] > 0)
1238 if (i == width*height)
1241 return R_LoadTexture2D (r_main_texturepool, name, width, height, in, TEXTYPE_PALETTE, textureflags, palette);
1244 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)
1247 unsigned char *temp1, *temp2;
1248 skinframe_t *skinframe;
1250 if (cls.state == ca_dedicated)
1253 // if already loaded just return it, otherwise make a new skinframe
1254 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*bitsperpixel/8) : 0, true);
1255 if (skinframe && skinframe->base)
1258 skinframe->stain = NULL;
1259 skinframe->merged = NULL;
1260 skinframe->base = r_texture_notexture;
1261 skinframe->pants = NULL;
1262 skinframe->shirt = NULL;
1263 skinframe->nmap = r_texture_blanknormalmap;
1264 skinframe->gloss = NULL;
1265 skinframe->glow = NULL;
1266 skinframe->fog = NULL;
1268 // if no data was provided, then clearly the caller wanted to get a blank skinframe
1272 if (bitsperpixel == 32)
1274 if (r_shadow_bumpscale_basetexture.value > 0)
1276 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
1277 temp2 = temp1 + width * height * 4;
1278 Image_HeightmapToNormalmap(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
1279 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_RGBA, textureflags | TEXF_ALPHA, NULL);
1282 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_RGBA, textureflags, NULL);
1283 if (textureflags & TEXF_ALPHA)
1285 for (i = 3;i < width * height * 4;i += 4)
1286 if (skindata[i] < 255)
1288 if (i < width * height * 4)
1290 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
1291 memcpy(fogpixels, skindata, width * height * 4);
1292 for (i = 0;i < width * height * 4;i += 4)
1293 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
1294 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_RGBA, textureflags, NULL);
1295 Mem_Free(fogpixels);
1299 else if (bitsperpixel == 8)
1301 if (r_shadow_bumpscale_basetexture.value > 0)
1303 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
1304 temp2 = temp1 + width * height * 4;
1305 if (bitsperpixel == 32)
1306 Image_HeightmapToNormalmap(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
1309 // use either a custom palette or the quake palette
1310 Image_Copy8bitRGBA(skindata, temp1, width * height, palette ? palette : palette_complete);
1311 Image_HeightmapToNormalmap(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
1313 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_RGBA, textureflags | TEXF_ALPHA, NULL);
1316 // use either a custom palette, or the quake palette
1317 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
1318 if (!palette && loadglowtexture)
1319 skinframe->glow = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_glow", skinframe->basename), palette_onlyfullbrights, textureflags, false); // glow
1320 if (!palette && loadpantsandshirt)
1322 skinframe->pants = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_pants", skinframe->basename), palette_pantsaswhite, textureflags, false); // pants
1323 skinframe->shirt = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_shirt", skinframe->basename), palette_shirtaswhite, textureflags, false); // shirt
1325 if (skinframe->pants || skinframe->shirt)
1326 skinframe->base = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_nospecial", skinframe->basename),loadglowtexture ? palette_nocolormapnofullbrights : palette_nocolormap, textureflags, false); // no special colors
1327 if (textureflags & TEXF_ALPHA)
1329 // if not using a custom alphapalette, use the quake one
1331 alphapalette = palette_alpha;
1332 for (i = 0;i < width * height;i++)
1333 if (((unsigned char *)alphapalette)[skindata[i]*4+3] < 255)
1335 if (i < width * height)
1336 skinframe->fog = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_fog", skinframe->basename), alphapalette, textureflags, true); // fog mask
1343 skinframe_t *R_SkinFrame_LoadMissing(void)
1345 skinframe_t *skinframe;
1347 if (cls.state == ca_dedicated)
1350 skinframe = R_SkinFrame_Find("missing", TEXF_PRECACHE, 0, 0, 0, true);
1351 skinframe->stain = NULL;
1352 skinframe->merged = NULL;
1353 skinframe->base = r_texture_notexture;
1354 skinframe->pants = NULL;
1355 skinframe->shirt = NULL;
1356 skinframe->nmap = r_texture_blanknormalmap;
1357 skinframe->gloss = NULL;
1358 skinframe->glow = NULL;
1359 skinframe->fog = NULL;
1364 void gl_main_start(void)
1369 r = (-1.0/256.0) * (FOGMASKTABLEWIDTH * FOGMASKTABLEWIDTH);
1370 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
1372 alpha = 1 - exp(r / ((double)x*(double)x));
1373 if (x == FOGMASKTABLEWIDTH - 1)
1375 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
1378 // set up r_skinframe loading system for textures
1379 memset(&r_skinframe, 0, sizeof(r_skinframe));
1380 r_skinframe.loadsequence = 1;
1381 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
1383 r_main_texturepool = R_AllocTexturePool();
1384 R_BuildBlankTextures();
1386 if (gl_texturecubemap)
1389 R_BuildNormalizationCube();
1391 R_BuildFogTexture();
1392 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
1393 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
1394 memset(&r_svbsp, 0, sizeof (r_svbsp));
1397 void gl_main_shutdown(void)
1399 // clear out the r_skinframe state
1400 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
1401 memset(&r_skinframe, 0, sizeof(r_skinframe));
1404 Mem_Free(r_svbsp.nodes);
1405 memset(&r_svbsp, 0, sizeof (r_svbsp));
1406 R_FreeTexturePool(&r_main_texturepool);
1407 r_texture_blanknormalmap = NULL;
1408 r_texture_white = NULL;
1409 r_texture_black = NULL;
1410 r_texture_whitecube = NULL;
1411 r_texture_normalizationcube = NULL;
1412 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
1416 extern void CL_ParseEntityLump(char *entitystring);
1417 void gl_main_newmap(void)
1419 // FIXME: move this code to client
1421 char *entities, entname[MAX_QPATH];
1424 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
1425 l = (int)strlen(entname) - 4;
1426 if (l >= 0 && !strcmp(entname + l, ".bsp"))
1428 memcpy(entname + l, ".ent", 5);
1429 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
1431 CL_ParseEntityLump(entities);
1436 if (cl.worldmodel->brush.entities)
1437 CL_ParseEntityLump(cl.worldmodel->brush.entities);
1441 void GL_Main_Init(void)
1443 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
1445 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
1446 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
1447 if (gamemode == GAME_NEHAHRA)
1449 Cvar_RegisterVariable (&gl_fogenable);
1450 Cvar_RegisterVariable (&gl_fogdensity);
1451 Cvar_RegisterVariable (&gl_fogred);
1452 Cvar_RegisterVariable (&gl_foggreen);
1453 Cvar_RegisterVariable (&gl_fogblue);
1454 Cvar_RegisterVariable (&gl_fogstart);
1455 Cvar_RegisterVariable (&gl_fogend);
1457 Cvar_RegisterVariable(&r_nearclip);
1458 Cvar_RegisterVariable(&r_showbboxes);
1459 Cvar_RegisterVariable(&r_showsurfaces);
1460 Cvar_RegisterVariable(&r_showtris);
1461 Cvar_RegisterVariable(&r_shownormals);
1462 Cvar_RegisterVariable(&r_showlighting);
1463 Cvar_RegisterVariable(&r_showshadowvolumes);
1464 Cvar_RegisterVariable(&r_showcollisionbrushes);
1465 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
1466 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
1467 Cvar_RegisterVariable(&r_showdisabledepthtest);
1468 Cvar_RegisterVariable(&r_drawportals);
1469 Cvar_RegisterVariable(&r_drawentities);
1470 Cvar_RegisterVariable(&r_cullentities_trace);
1471 Cvar_RegisterVariable(&r_cullentities_trace_samples);
1472 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
1473 Cvar_RegisterVariable(&r_cullentities_trace_delay);
1474 Cvar_RegisterVariable(&r_drawviewmodel);
1475 Cvar_RegisterVariable(&r_speeds);
1476 Cvar_RegisterVariable(&r_fullbrights);
1477 Cvar_RegisterVariable(&r_wateralpha);
1478 Cvar_RegisterVariable(&r_dynamic);
1479 Cvar_RegisterVariable(&r_fullbright);
1480 Cvar_RegisterVariable(&r_shadows);
1481 Cvar_RegisterVariable(&r_shadows_throwdistance);
1482 Cvar_RegisterVariable(&r_q1bsp_skymasking);
1483 Cvar_RegisterVariable(&r_textureunits);
1484 Cvar_RegisterVariable(&r_glsl);
1485 Cvar_RegisterVariable(&r_glsl_offsetmapping);
1486 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
1487 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
1488 Cvar_RegisterVariable(&r_glsl_deluxemapping);
1489 Cvar_RegisterVariable(&r_lerpsprites);
1490 Cvar_RegisterVariable(&r_lerpmodels);
1491 Cvar_RegisterVariable(&r_waterscroll);
1492 Cvar_RegisterVariable(&r_bloom);
1493 Cvar_RegisterVariable(&r_bloom_colorscale);
1494 Cvar_RegisterVariable(&r_bloom_brighten);
1495 Cvar_RegisterVariable(&r_bloom_blur);
1496 Cvar_RegisterVariable(&r_bloom_resolution);
1497 Cvar_RegisterVariable(&r_bloom_colorexponent);
1498 Cvar_RegisterVariable(&r_bloom_colorsubtract);
1499 Cvar_RegisterVariable(&r_hdr);
1500 Cvar_RegisterVariable(&r_hdr_scenebrightness);
1501 Cvar_RegisterVariable(&r_hdr_glowintensity);
1502 Cvar_RegisterVariable(&r_hdr_range);
1503 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
1504 Cvar_RegisterVariable(&developer_texturelogging);
1505 Cvar_RegisterVariable(&gl_lightmaps);
1506 Cvar_RegisterVariable(&r_test);
1507 Cvar_RegisterVariable(&r_batchmode);
1508 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
1509 Cvar_SetValue("r_fullbrights", 0);
1510 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
1513 extern void R_Textures_Init(void);
1514 extern void GL_Draw_Init(void);
1515 extern void GL_Main_Init(void);
1516 extern void R_Shadow_Init(void);
1517 extern void R_Sky_Init(void);
1518 extern void GL_Surf_Init(void);
1519 extern void R_Light_Init(void);
1520 extern void R_Particles_Init(void);
1521 extern void R_Explosion_Init(void);
1522 extern void gl_backend_init(void);
1523 extern void Sbar_Init(void);
1524 extern void R_LightningBeams_Init(void);
1525 extern void Mod_RenderInit(void);
1527 void Render_Init(void)
1540 R_LightningBeams_Init();
1549 extern char *ENGINE_EXTENSIONS;
1552 VID_CheckExtensions();
1554 // LordHavoc: report supported extensions
1555 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
1557 // clear to black (loading plaque will be seen over this)
1559 qglClearColor(0,0,0,1);CHECKGLERROR
1560 qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
1563 int R_CullBox(const vec3_t mins, const vec3_t maxs)
1567 for (i = 0;i < 4;i++)
1569 p = r_view.frustum + i;
1574 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1578 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1582 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1586 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1590 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1594 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1598 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1602 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1610 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
1614 for (i = 0;i < numplanes;i++)
1621 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1625 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1629 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1633 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1637 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1641 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1645 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1649 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1657 //==================================================================================
1659 static void R_UpdateEntityLighting(entity_render_t *ent)
1661 vec3_t tempdiffusenormal;
1663 // fetch the lighting from the worldmodel data
1664 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));
1665 VectorClear(ent->modellight_diffuse);
1666 VectorClear(tempdiffusenormal);
1667 if ((ent->flags & RENDER_LIGHT) && r_refdef.worldmodel && r_refdef.worldmodel->brush.LightPoint)
1670 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
1671 r_refdef.worldmodel->brush.LightPoint(r_refdef.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
1674 VectorSet(ent->modellight_ambient, 1, 1, 1);
1676 // move the light direction into modelspace coordinates for lighting code
1677 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
1678 VectorNormalize(ent->modellight_lightdir);
1680 // scale ambient and directional light contributions according to rendering variables
1681 ent->modellight_ambient[0] *= ent->colormod[0] * r_refdef.lightmapintensity;
1682 ent->modellight_ambient[1] *= ent->colormod[1] * r_refdef.lightmapintensity;
1683 ent->modellight_ambient[2] *= ent->colormod[2] * r_refdef.lightmapintensity;
1684 ent->modellight_diffuse[0] *= ent->colormod[0] * r_refdef.lightmapintensity;
1685 ent->modellight_diffuse[1] *= ent->colormod[1] * r_refdef.lightmapintensity;
1686 ent->modellight_diffuse[2] *= ent->colormod[2] * r_refdef.lightmapintensity;
1689 static void R_View_UpdateEntityVisible (void)
1692 entity_render_t *ent;
1694 if (!r_drawentities.integer)
1697 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : (chase_active.integer ? 0 : RENDER_EXTERIORMODEL);
1698 if (r_refdef.worldmodel && r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs)
1700 // worldmodel can check visibility
1701 for (i = 0;i < r_refdef.numentities;i++)
1703 ent = r_refdef.entities[i];
1704 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));
1706 if(r_cullentities_trace.integer)
1708 for (i = 0;i < r_refdef.numentities;i++)
1710 ent = r_refdef.entities[i];
1711 if(r_viewcache.entityvisible[i] && !(ent->effects & EF_NODEPTHTEST) && !(ent->flags & RENDER_VIEWMODEL) && !(ent->model && (ent->model->name[0] == '*')))
1713 if(Mod_CanSeeBox_Trace(r_cullentities_trace_samples.integer, r_cullentities_trace_enlarge.value, r_refdef.worldmodel, r_view.origin, ent->mins, ent->maxs))
1714 ent->last_trace_visibility = realtime;
1715 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
1716 r_viewcache.entityvisible[i] = 0;
1723 // no worldmodel or it can't check visibility
1724 for (i = 0;i < r_refdef.numentities;i++)
1726 ent = r_refdef.entities[i];
1727 r_viewcache.entityvisible[i] = !(ent->flags & renderimask) && !R_CullBox(ent->mins, ent->maxs);
1731 // update entity lighting (even on hidden entities for r_shadows)
1732 for (i = 0;i < r_refdef.numentities;i++)
1733 R_UpdateEntityLighting(r_refdef.entities[i]);
1736 // only used if skyrendermasked, and normally returns false
1737 int R_DrawBrushModelsSky (void)
1740 entity_render_t *ent;
1742 if (!r_drawentities.integer)
1746 for (i = 0;i < r_refdef.numentities;i++)
1748 if (!r_viewcache.entityvisible[i])
1750 ent = r_refdef.entities[i];
1751 if (!ent->model || !ent->model->DrawSky)
1753 ent->model->DrawSky(ent);
1759 void R_DrawNoModel(entity_render_t *ent);
1760 void R_DrawModels(void)
1763 entity_render_t *ent;
1765 if (!r_drawentities.integer)
1768 for (i = 0;i < r_refdef.numentities;i++)
1770 if (!r_viewcache.entityvisible[i])
1772 ent = r_refdef.entities[i];
1773 r_refdef.stats.entities++;
1774 if (ent->model && ent->model->Draw != NULL)
1775 ent->model->Draw(ent);
1781 static void R_View_SetFrustum(void)
1783 double slopex, slopey;
1785 // break apart the view matrix into vectors for various purposes
1786 Matrix4x4_ToVectors(&r_view.matrix, r_view.forward, r_view.left, r_view.up, r_view.origin);
1787 VectorNegate(r_view.left, r_view.right);
1790 r_view.frustum[0].normal[0] = 0 - 1.0 / r_view.frustum_x;
1791 r_view.frustum[0].normal[1] = 0 - 0;
1792 r_view.frustum[0].normal[2] = -1 - 0;
1793 r_view.frustum[1].normal[0] = 0 + 1.0 / r_view.frustum_x;
1794 r_view.frustum[1].normal[1] = 0 + 0;
1795 r_view.frustum[1].normal[2] = -1 + 0;
1796 r_view.frustum[2].normal[0] = 0 - 0;
1797 r_view.frustum[2].normal[1] = 0 - 1.0 / r_view.frustum_y;
1798 r_view.frustum[2].normal[2] = -1 - 0;
1799 r_view.frustum[3].normal[0] = 0 + 0;
1800 r_view.frustum[3].normal[1] = 0 + 1.0 / r_view.frustum_y;
1801 r_view.frustum[3].normal[2] = -1 + 0;
1805 zNear = r_refdef.nearclip;
1806 nudge = 1.0 - 1.0 / (1<<23);
1807 r_view.frustum[4].normal[0] = 0 - 0;
1808 r_view.frustum[4].normal[1] = 0 - 0;
1809 r_view.frustum[4].normal[2] = -1 - -nudge;
1810 r_view.frustum[4].dist = 0 - -2 * zNear * nudge;
1811 r_view.frustum[5].normal[0] = 0 + 0;
1812 r_view.frustum[5].normal[1] = 0 + 0;
1813 r_view.frustum[5].normal[2] = -1 + -nudge;
1814 r_view.frustum[5].dist = 0 + -2 * zNear * nudge;
1820 r_view.frustum[0].normal[0] = m[3] - m[0];
1821 r_view.frustum[0].normal[1] = m[7] - m[4];
1822 r_view.frustum[0].normal[2] = m[11] - m[8];
1823 r_view.frustum[0].dist = m[15] - m[12];
1825 r_view.frustum[1].normal[0] = m[3] + m[0];
1826 r_view.frustum[1].normal[1] = m[7] + m[4];
1827 r_view.frustum[1].normal[2] = m[11] + m[8];
1828 r_view.frustum[1].dist = m[15] + m[12];
1830 r_view.frustum[2].normal[0] = m[3] - m[1];
1831 r_view.frustum[2].normal[1] = m[7] - m[5];
1832 r_view.frustum[2].normal[2] = m[11] - m[9];
1833 r_view.frustum[2].dist = m[15] - m[13];
1835 r_view.frustum[3].normal[0] = m[3] + m[1];
1836 r_view.frustum[3].normal[1] = m[7] + m[5];
1837 r_view.frustum[3].normal[2] = m[11] + m[9];
1838 r_view.frustum[3].dist = m[15] + m[13];
1840 r_view.frustum[4].normal[0] = m[3] - m[2];
1841 r_view.frustum[4].normal[1] = m[7] - m[6];
1842 r_view.frustum[4].normal[2] = m[11] - m[10];
1843 r_view.frustum[4].dist = m[15] - m[14];
1845 r_view.frustum[5].normal[0] = m[3] + m[2];
1846 r_view.frustum[5].normal[1] = m[7] + m[6];
1847 r_view.frustum[5].normal[2] = m[11] + m[10];
1848 r_view.frustum[5].dist = m[15] + m[14];
1853 slopex = 1.0 / r_view.frustum_x;
1854 slopey = 1.0 / r_view.frustum_y;
1855 VectorMA(r_view.forward, -slopex, r_view.left, r_view.frustum[0].normal);
1856 VectorMA(r_view.forward, slopex, r_view.left, r_view.frustum[1].normal);
1857 VectorMA(r_view.forward, -slopey, r_view.up , r_view.frustum[2].normal);
1858 VectorMA(r_view.forward, slopey, r_view.up , r_view.frustum[3].normal);
1859 VectorCopy(r_view.forward, r_view.frustum[4].normal);
1860 VectorNormalize(r_view.frustum[0].normal);
1861 VectorNormalize(r_view.frustum[1].normal);
1862 VectorNormalize(r_view.frustum[2].normal);
1863 VectorNormalize(r_view.frustum[3].normal);
1864 r_view.frustum[0].dist = DotProduct (r_view.origin, r_view.frustum[0].normal);
1865 r_view.frustum[1].dist = DotProduct (r_view.origin, r_view.frustum[1].normal);
1866 r_view.frustum[2].dist = DotProduct (r_view.origin, r_view.frustum[2].normal);
1867 r_view.frustum[3].dist = DotProduct (r_view.origin, r_view.frustum[3].normal);
1868 r_view.frustum[4].dist = DotProduct (r_view.origin, r_view.frustum[4].normal) + r_refdef.nearclip;
1869 PlaneClassify(&r_view.frustum[0]);
1870 PlaneClassify(&r_view.frustum[1]);
1871 PlaneClassify(&r_view.frustum[2]);
1872 PlaneClassify(&r_view.frustum[3]);
1873 PlaneClassify(&r_view.frustum[4]);
1875 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
1876 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, -1024 * slopex, r_view.left, -1024 * slopey, r_view.up, r_view.frustumcorner[0]);
1877 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, 1024 * slopex, r_view.left, -1024 * slopey, r_view.up, r_view.frustumcorner[1]);
1878 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, -1024 * slopex, r_view.left, 1024 * slopey, r_view.up, r_view.frustumcorner[2]);
1879 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, 1024 * slopex, r_view.left, 1024 * slopey, r_view.up, r_view.frustumcorner[3]);
1881 // LordHavoc: note to all quake engine coders, Quake had a special case
1882 // for 90 degrees which assumed a square view (wrong), so I removed it,
1883 // Quake2 has it disabled as well.
1885 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
1886 //RotatePointAroundVector( r_view.frustum[0].normal, r_view.up, r_view.forward, -(90 - r_refdef.fov_x / 2));
1887 //r_view.frustum[0].dist = DotProduct (r_view.origin, frustum[0].normal);
1888 //PlaneClassify(&frustum[0]);
1890 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
1891 //RotatePointAroundVector( r_view.frustum[1].normal, r_view.up, r_view.forward, (90 - r_refdef.fov_x / 2));
1892 //r_view.frustum[1].dist = DotProduct (r_view.origin, frustum[1].normal);
1893 //PlaneClassify(&frustum[1]);
1895 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
1896 //RotatePointAroundVector( r_view.frustum[2].normal, r_view.left, r_view.forward, -(90 - r_refdef.fov_y / 2));
1897 //r_view.frustum[2].dist = DotProduct (r_view.origin, frustum[2].normal);
1898 //PlaneClassify(&frustum[2]);
1900 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
1901 //RotatePointAroundVector( r_view.frustum[3].normal, r_view.left, r_view.forward, (90 - r_refdef.fov_y / 2));
1902 //r_view.frustum[3].dist = DotProduct (r_view.origin, frustum[3].normal);
1903 //PlaneClassify(&frustum[3]);
1906 //VectorCopy(r_view.forward, r_view.frustum[4].normal);
1907 //r_view.frustum[4].dist = DotProduct (r_view.origin, frustum[4].normal) + r_nearclip.value;
1908 //PlaneClassify(&frustum[4]);
1911 void R_View_Update(void)
1913 R_View_SetFrustum();
1914 R_View_WorldVisibility();
1915 R_View_UpdateEntityVisible();
1918 void R_SetupView(const matrix4x4_t *matrix)
1920 if (r_refdef.rtworldshadows || r_refdef.rtdlightshadows)
1921 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_view.frustum_x, r_view.frustum_y, r_refdef.nearclip);
1923 GL_SetupView_Mode_Perspective(r_view.frustum_x, r_view.frustum_y, r_refdef.nearclip, r_refdef.farclip);
1925 GL_SetupView_Orientation_FromEntity(matrix);
1928 void R_ResetViewRendering2D(void)
1930 if (gl_support_fragment_shader)
1932 qglUseProgramObjectARB(0);CHECKGLERROR
1937 // GL is weird because it's bottom to top, r_view.y is top to bottom
1938 qglViewport(r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
1939 GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
1940 GL_Scissor(r_view.x, r_view.y, r_view.width, r_view.height);
1941 GL_Color(1, 1, 1, 1);
1942 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
1943 GL_BlendFunc(GL_ONE, GL_ZERO);
1944 GL_AlphaTest(false);
1945 GL_ScissorTest(false);
1946 GL_DepthMask(false);
1947 GL_DepthRange(0, 1);
1948 GL_DepthTest(false);
1949 R_Mesh_Matrix(&identitymatrix);
1950 R_Mesh_ResetTextureState();
1951 qglPolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR
1952 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
1953 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
1954 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
1955 qglStencilMask(~0);CHECKGLERROR
1956 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
1957 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
1958 GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
1961 void R_ResetViewRendering3D(void)
1963 if (gl_support_fragment_shader)
1965 qglUseProgramObjectARB(0);CHECKGLERROR
1970 // GL is weird because it's bottom to top, r_view.y is top to bottom
1971 qglViewport(r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
1972 R_SetupView(&r_view.matrix);
1973 GL_Scissor(r_view.x, r_view.y, r_view.width, r_view.height);
1974 GL_Color(1, 1, 1, 1);
1975 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
1976 GL_BlendFunc(GL_ONE, GL_ZERO);
1977 GL_AlphaTest(false);
1978 GL_ScissorTest(true);
1980 GL_DepthRange(0, 1);
1982 R_Mesh_Matrix(&identitymatrix);
1983 R_Mesh_ResetTextureState();
1984 qglPolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR
1985 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
1986 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
1987 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
1988 qglStencilMask(~0);CHECKGLERROR
1989 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
1990 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
1991 GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
1995 R_Bloom_SetupShader(
1997 "// written by Forest 'LordHavoc' Hale\n"
1999 "// common definitions between vertex shader and fragment shader:\n"
2001 "#ifdef __GLSL_CG_DATA_TYPES\n"
2002 "#define myhalf half\n"
2003 "#define myhvec2 hvec2\n"
2004 "#define myhvec3 hvec3\n"
2005 "#define myhvec4 hvec4\n"
2007 "#define myhalf float\n"
2008 "#define myhvec2 vec2\n"
2009 "#define myhvec3 vec3\n"
2010 "#define myhvec4 vec4\n"
2013 "varying vec2 ScreenTexCoord;\n"
2014 "varying vec2 BloomTexCoord;\n"
2019 "// vertex shader specific:\n"
2020 "#ifdef VERTEX_SHADER\n"
2024 " ScreenTexCoord = vec2(gl_MultiTexCoord0);\n"
2025 " BloomTexCoord = vec2(gl_MultiTexCoord1);\n"
2026 " // transform vertex to camera space, using ftransform to match non-VS\n"
2028 " gl_Position = ftransform();\n"
2031 "#endif // VERTEX_SHADER\n"
2036 "// fragment shader specific:\n"
2037 "#ifdef FRAGMENT_SHADER\n"
2042 " myhvec3 color = myhvec3(texture2D(Texture_Screen, ScreenTexCoord));\n"
2043 " for (x = -BLUR_X;x <= BLUR_X;x++)
2044 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2045 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2046 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2047 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2049 " gl_FragColor = vec4(color);\n"
2052 "#endif // FRAGMENT_SHADER\n"
2055 void R_RenderScene(void);
2057 void R_Bloom_StartFrame(void)
2059 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
2061 // set bloomwidth and bloomheight to the bloom resolution that will be
2062 // used (often less than the screen resolution for faster rendering)
2063 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_view.width);
2064 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_view.height / r_view.width;
2065 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_view.height);
2067 // calculate desired texture sizes
2068 if (gl_support_arb_texture_non_power_of_two)
2070 screentexturewidth = r_view.width;
2071 screentextureheight = r_view.height;
2072 bloomtexturewidth = r_bloomstate.bloomwidth;
2073 bloomtextureheight = r_bloomstate.bloomheight;
2077 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
2078 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
2079 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
2080 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
2085 screentexturewidth = screentextureheight = 0;
2087 else if (r_bloom.integer)
2092 screentexturewidth = screentextureheight = 0;
2093 bloomtexturewidth = bloomtextureheight = 0;
2096 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)
2098 // can't use bloom if the parameters are too weird
2099 // can't use bloom if the card does not support the texture size
2100 if (r_bloomstate.texture_screen)
2101 R_FreeTexture(r_bloomstate.texture_screen);
2102 if (r_bloomstate.texture_bloom)
2103 R_FreeTexture(r_bloomstate.texture_bloom);
2104 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
2108 r_bloomstate.enabled = true;
2109 r_bloomstate.hdr = r_hdr.integer != 0;
2111 // allocate textures as needed
2112 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
2114 if (r_bloomstate.texture_screen)
2115 R_FreeTexture(r_bloomstate.texture_screen);
2116 r_bloomstate.texture_screen = NULL;
2117 r_bloomstate.screentexturewidth = screentexturewidth;
2118 r_bloomstate.screentextureheight = screentextureheight;
2119 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
2120 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);
2122 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
2124 if (r_bloomstate.texture_bloom)
2125 R_FreeTexture(r_bloomstate.texture_bloom);
2126 r_bloomstate.texture_bloom = NULL;
2127 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
2128 r_bloomstate.bloomtextureheight = bloomtextureheight;
2129 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
2130 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);
2133 // set up a texcoord array for the full resolution screen image
2134 // (we have to keep this around to copy back during final render)
2135 r_bloomstate.screentexcoord2f[0] = 0;
2136 r_bloomstate.screentexcoord2f[1] = (float)r_view.height / (float)r_bloomstate.screentextureheight;
2137 r_bloomstate.screentexcoord2f[2] = (float)r_view.width / (float)r_bloomstate.screentexturewidth;
2138 r_bloomstate.screentexcoord2f[3] = (float)r_view.height / (float)r_bloomstate.screentextureheight;
2139 r_bloomstate.screentexcoord2f[4] = (float)r_view.width / (float)r_bloomstate.screentexturewidth;
2140 r_bloomstate.screentexcoord2f[5] = 0;
2141 r_bloomstate.screentexcoord2f[6] = 0;
2142 r_bloomstate.screentexcoord2f[7] = 0;
2144 // set up a texcoord array for the reduced resolution bloom image
2145 // (which will be additive blended over the screen image)
2146 r_bloomstate.bloomtexcoord2f[0] = 0;
2147 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
2148 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
2149 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
2150 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
2151 r_bloomstate.bloomtexcoord2f[5] = 0;
2152 r_bloomstate.bloomtexcoord2f[6] = 0;
2153 r_bloomstate.bloomtexcoord2f[7] = 0;
2156 void R_Bloom_CopyScreenTexture(float colorscale)
2158 r_refdef.stats.bloom++;
2160 R_ResetViewRendering2D();
2161 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
2162 R_Mesh_ColorPointer(NULL, 0, 0);
2163 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
2164 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
2166 // copy view into the screen texture
2167 GL_ActiveTexture(0);
2169 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
2170 r_refdef.stats.bloom_copypixels += r_view.width * r_view.height;
2172 // now scale it down to the bloom texture size
2174 qglViewport(r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
2175 GL_BlendFunc(GL_ONE, GL_ZERO);
2176 GL_Color(colorscale, colorscale, colorscale, 1);
2177 // TODO: optimize with multitexture or GLSL
2178 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2179 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2181 // we now have a bloom image in the framebuffer
2182 // copy it into the bloom image texture for later processing
2183 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2184 GL_ActiveTexture(0);
2186 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
2187 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2190 void R_Bloom_CopyHDRTexture(void)
2192 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2193 GL_ActiveTexture(0);
2195 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
2196 r_refdef.stats.bloom_copypixels += r_view.width * r_view.height;
2199 void R_Bloom_MakeTexture(void)
2202 float xoffset, yoffset, r, brighten;
2204 r_refdef.stats.bloom++;
2206 R_ResetViewRendering2D();
2207 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
2208 R_Mesh_ColorPointer(NULL, 0, 0);
2210 // we have a bloom image in the framebuffer
2212 qglViewport(r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
2214 for (x = 1;x < r_bloom_colorexponent.value;)
2217 r = bound(0, r_bloom_colorexponent.value / x, 1);
2218 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
2219 GL_Color(r, r, r, 1);
2220 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2221 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
2222 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2223 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2225 // copy the vertically blurred bloom view to a texture
2226 GL_ActiveTexture(0);
2228 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
2229 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2232 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
2233 brighten = r_bloom_brighten.value;
2235 brighten *= r_hdr_range.value;
2236 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2237 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
2239 for (dir = 0;dir < 2;dir++)
2241 // blend on at multiple vertical offsets to achieve a vertical blur
2242 // TODO: do offset blends using GLSL
2243 GL_BlendFunc(GL_ONE, GL_ZERO);
2244 for (x = -range;x <= range;x++)
2246 if (!dir){xoffset = 0;yoffset = x;}
2247 else {xoffset = x;yoffset = 0;}
2248 xoffset /= (float)r_bloomstate.bloomtexturewidth;
2249 yoffset /= (float)r_bloomstate.bloomtextureheight;
2250 // compute a texcoord array with the specified x and y offset
2251 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
2252 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
2253 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
2254 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
2255 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
2256 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
2257 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
2258 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
2259 // this r value looks like a 'dot' particle, fading sharply to
2260 // black at the edges
2261 // (probably not realistic but looks good enough)
2262 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
2263 //r = (dir ? 1.0f : brighten)/(range*2+1);
2264 r = (dir ? 1.0f : brighten)/(range*2+1)*(1 - x*x/(float)(range*range));
2265 GL_Color(r, r, r, 1);
2266 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2267 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2268 GL_BlendFunc(GL_ONE, GL_ONE);
2271 // copy the vertically blurred bloom view to a texture
2272 GL_ActiveTexture(0);
2274 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
2275 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2278 // apply subtract last
2279 // (just like it would be in a GLSL shader)
2280 if (r_bloom_colorsubtract.value > 0 && gl_support_ext_blend_subtract)
2282 GL_BlendFunc(GL_ONE, GL_ZERO);
2283 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2284 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
2285 GL_Color(1, 1, 1, 1);
2286 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2287 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2289 GL_BlendFunc(GL_ONE, GL_ONE);
2290 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
2291 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2292 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
2293 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
2294 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2295 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2296 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
2298 // copy the darkened bloom view to a texture
2299 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2300 GL_ActiveTexture(0);
2302 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
2303 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2307 void R_HDR_RenderBloomTexture(void)
2309 int oldwidth, oldheight;
2311 oldwidth = r_view.width;
2312 oldheight = r_view.height;
2313 r_view.width = r_bloomstate.bloomwidth;
2314 r_view.height = r_bloomstate.bloomheight;
2316 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
2317 // TODO: add exposure compensation features
2318 // TODO: add fp16 framebuffer support
2320 r_view.colorscale = r_bloom_colorscale.value * r_hdr_scenebrightness.value;
2322 r_view.colorscale /= r_hdr_range.value;
2325 R_ResetViewRendering2D();
2327 R_Bloom_CopyHDRTexture();
2328 R_Bloom_MakeTexture();
2330 R_ResetViewRendering3D();
2333 if (r_timereport_active)
2334 R_TimeReport("clear");
2337 // restore the view settings
2338 r_view.width = oldwidth;
2339 r_view.height = oldheight;
2342 static void R_BlendView(void)
2344 if (r_bloomstate.enabled && r_bloomstate.hdr)
2346 // render high dynamic range bloom effect
2347 // the bloom texture was made earlier this render, so we just need to
2348 // blend it onto the screen...
2349 R_ResetViewRendering2D();
2350 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
2351 R_Mesh_ColorPointer(NULL, 0, 0);
2352 GL_Color(1, 1, 1, 1);
2353 GL_BlendFunc(GL_ONE, GL_ONE);
2354 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2355 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
2356 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2357 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
2359 else if (r_bloomstate.enabled)
2361 // render simple bloom effect
2362 // copy the screen and shrink it and darken it for the bloom process
2363 R_Bloom_CopyScreenTexture(r_bloom_colorscale.value);
2364 // make the bloom texture
2365 R_Bloom_MakeTexture();
2366 // put the original screen image back in place and blend the bloom
2368 R_ResetViewRendering2D();
2369 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
2370 R_Mesh_ColorPointer(NULL, 0, 0);
2371 GL_Color(1, 1, 1, 1);
2372 GL_BlendFunc(GL_ONE, GL_ZERO);
2373 // do both in one pass if possible
2374 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2375 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
2376 if (r_textureunits.integer >= 2 && gl_combine.integer)
2378 R_Mesh_TexCombine(1, GL_ADD, GL_ADD, 1, 1);
2379 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_screen));
2380 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.screentexcoord2f, 0, 0);
2384 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2385 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
2386 // now blend on the bloom texture
2387 GL_BlendFunc(GL_ONE, GL_ONE);
2388 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
2389 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
2391 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2392 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
2394 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
2396 // apply a color tint to the whole view
2397 R_ResetViewRendering2D();
2398 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
2399 R_Mesh_ColorPointer(NULL, 0, 0);
2400 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2401 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
2402 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2406 void R_RenderScene(void);
2408 matrix4x4_t r_waterscrollmatrix;
2410 void R_UpdateVariables(void)
2414 r_refdef.farclip = 4096;
2415 if (r_refdef.worldmodel)
2416 r_refdef.farclip += VectorDistance(r_refdef.worldmodel->normalmins, r_refdef.worldmodel->normalmaxs);
2417 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
2419 r_refdef.polygonfactor = 0;
2420 r_refdef.polygonoffset = 0;
2421 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_shadow_polygonfactor.value;
2422 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_shadow_polygonoffset.value;
2424 r_refdef.rtworld = r_shadow_realtime_world.integer;
2425 r_refdef.rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
2426 r_refdef.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
2427 r_refdef.rtdlightshadows = r_refdef.rtdlight && (r_refdef.rtworld ? r_shadow_realtime_world_dlightshadows.integer : r_shadow_realtime_dlight_shadows.integer) && gl_stencil;
2428 r_refdef.lightmapintensity = r_refdef.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
2429 if (r_showsurfaces.integer)
2431 r_refdef.rtworld = false;
2432 r_refdef.rtworldshadows = false;
2433 r_refdef.rtdlight = false;
2434 r_refdef.rtdlightshadows = false;
2435 r_refdef.lightmapintensity = 0;
2438 if (gamemode == GAME_NEHAHRA)
2440 if (gl_fogenable.integer)
2442 r_refdef.oldgl_fogenable = true;
2443 r_refdef.fog_density = gl_fogdensity.value;
2444 r_refdef.fog_red = gl_fogred.value;
2445 r_refdef.fog_green = gl_foggreen.value;
2446 r_refdef.fog_blue = gl_fogblue.value;
2448 else if (r_refdef.oldgl_fogenable)
2450 r_refdef.oldgl_fogenable = false;
2451 r_refdef.fog_density = 0;
2452 r_refdef.fog_red = 0;
2453 r_refdef.fog_green = 0;
2454 r_refdef.fog_blue = 0;
2457 if (r_refdef.fog_density)
2459 r_refdef.fogcolor[0] = bound(0.0f, r_refdef.fog_red , 1.0f);
2460 r_refdef.fogcolor[1] = bound(0.0f, r_refdef.fog_green, 1.0f);
2461 r_refdef.fogcolor[2] = bound(0.0f, r_refdef.fog_blue , 1.0f);
2463 if (r_refdef.fog_density)
2465 r_refdef.fogenabled = true;
2466 // this is the point where the fog reaches 0.9986 alpha, which we
2467 // consider a good enough cutoff point for the texture
2468 // (0.9986 * 256 == 255.6)
2469 r_refdef.fogrange = 400 / r_refdef.fog_density;
2470 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
2471 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
2472 // fog color was already set
2475 r_refdef.fogenabled = false;
2483 void R_RenderView(void)
2485 if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
2486 return; //Host_Error ("R_RenderView: NULL worldmodel");
2488 R_Shadow_UpdateWorldLightSelection();
2491 if (r_timereport_active)
2492 R_TimeReport("setup");
2495 if (r_timereport_active)
2496 R_TimeReport("visibility");
2498 R_ResetViewRendering3D();
2501 if (r_timereport_active)
2502 R_TimeReport("clear");
2504 R_Bloom_StartFrame();
2506 // this produces a bloom texture to be used in R_BlendView() later
2508 R_HDR_RenderBloomTexture();
2510 r_view.colorscale = r_hdr_scenebrightness.value;
2514 if (r_timereport_active)
2515 R_TimeReport("blendview");
2517 GL_Scissor(0, 0, vid.width, vid.height);
2518 GL_ScissorTest(false);
2522 extern void R_DrawLightningBeams (void);
2523 extern void VM_CL_AddPolygonsToMeshQueue (void);
2524 extern void R_DrawPortals (void);
2525 extern cvar_t cl_locs_show;
2526 static void R_DrawLocs(void);
2527 static void R_DrawEntityBBoxes(void);
2528 void R_RenderScene(void)
2530 // don't let sound skip if going slow
2531 if (r_refdef.extraupdate)
2534 R_ResetViewRendering3D();
2536 R_MeshQueue_BeginScene();
2540 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);
2542 if (cl.csqc_vidvars.drawworld)
2544 // don't let sound skip if going slow
2545 if (r_refdef.extraupdate)
2548 if (r_refdef.worldmodel && r_refdef.worldmodel->DrawSky)
2550 r_refdef.worldmodel->DrawSky(r_refdef.worldentity);
2551 if (r_timereport_active)
2552 R_TimeReport("worldsky");
2555 if (R_DrawBrushModelsSky() && r_timereport_active)
2556 R_TimeReport("bmodelsky");
2558 if (r_refdef.worldmodel && r_refdef.worldmodel->Draw)
2560 r_refdef.worldmodel->Draw(r_refdef.worldentity);
2561 if (r_timereport_active)
2562 R_TimeReport("world");
2566 // don't let sound skip if going slow
2567 if (r_refdef.extraupdate)
2571 if (r_timereport_active)
2572 R_TimeReport("models");
2574 // don't let sound skip if going slow
2575 if (r_refdef.extraupdate)
2578 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
2580 R_DrawModelShadows();
2582 R_ResetViewRendering3D();
2584 // don't let sound skip if going slow
2585 if (r_refdef.extraupdate)
2589 R_ShadowVolumeLighting(false);
2590 if (r_timereport_active)
2591 R_TimeReport("rtlights");
2593 // don't let sound skip if going slow
2594 if (r_refdef.extraupdate)
2597 if (cl.csqc_vidvars.drawworld)
2599 R_DrawLightningBeams();
2600 if (r_timereport_active)
2601 R_TimeReport("lightning");
2604 if (r_timereport_active)
2605 R_TimeReport("particles");
2608 if (r_timereport_active)
2609 R_TimeReport("explosions");
2612 if (gl_support_fragment_shader)
2614 qglUseProgramObjectARB(0);CHECKGLERROR
2616 VM_CL_AddPolygonsToMeshQueue();
2618 if (cl_locs_show.integer)
2621 if (r_timereport_active)
2622 R_TimeReport("showlocs");
2625 if (r_drawportals.integer)
2628 if (r_timereport_active)
2629 R_TimeReport("portals");
2632 if (r_showbboxes.value > 0)
2634 R_DrawEntityBBoxes();
2635 if (r_timereport_active)
2636 R_TimeReport("bboxes");
2639 if (gl_support_fragment_shader)
2641 qglUseProgramObjectARB(0);CHECKGLERROR
2643 R_MeshQueue_RenderTransparent();
2644 if (r_timereport_active)
2645 R_TimeReport("drawtrans");
2647 if (gl_support_fragment_shader)
2649 qglUseProgramObjectARB(0);CHECKGLERROR
2652 if (cl.csqc_vidvars.drawworld)
2655 if (r_timereport_active)
2656 R_TimeReport("coronas");
2659 // don't let sound skip if going slow
2660 if (r_refdef.extraupdate)
2663 R_ResetViewRendering2D();
2666 static const int bboxelements[36] =
2676 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
2679 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
2680 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2681 GL_DepthMask(false);
2682 GL_DepthRange(0, 1);
2683 R_Mesh_Matrix(&identitymatrix);
2684 R_Mesh_ResetTextureState();
2686 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
2687 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
2688 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
2689 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
2690 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
2691 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
2692 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
2693 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
2694 R_FillColors(color4f, 8, cr, cg, cb, ca);
2695 if (r_refdef.fogenabled)
2697 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
2699 f1 = FogPoint_World(v);
2701 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
2702 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
2703 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
2706 R_Mesh_VertexPointer(vertex3f, 0, 0);
2707 R_Mesh_ColorPointer(color4f, 0, 0);
2708 R_Mesh_ResetTextureState();
2709 R_Mesh_Draw(0, 8, 12, bboxelements, 0, 0);
2712 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
2716 prvm_edict_t *edict;
2717 // this function draws bounding boxes of server entities
2721 for (i = 0;i < numsurfaces;i++)
2723 edict = PRVM_EDICT_NUM(surfacelist[i]);
2724 switch ((int)edict->fields.server->solid)
2726 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
2727 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
2728 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
2729 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
2730 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
2731 default: Vector4Set(color, 0, 0, 0, 0.50);break;
2733 color[3] *= r_showbboxes.value;
2734 color[3] = bound(0, color[3], 1);
2735 GL_DepthTest(!r_showdisabledepthtest.integer);
2736 GL_CullFace(GL_BACK);
2737 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
2742 static void R_DrawEntityBBoxes(void)
2745 prvm_edict_t *edict;
2747 // this function draws bounding boxes of server entities
2751 for (i = 0;i < prog->num_edicts;i++)
2753 edict = PRVM_EDICT_NUM(i);
2754 if (edict->priv.server->free)
2756 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
2757 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
2762 int nomodelelements[24] =
2774 float nomodelvertex3f[6*3] =
2784 float nomodelcolor4f[6*4] =
2786 0.0f, 0.0f, 0.5f, 1.0f,
2787 0.0f, 0.0f, 0.5f, 1.0f,
2788 0.0f, 0.5f, 0.0f, 1.0f,
2789 0.0f, 0.5f, 0.0f, 1.0f,
2790 0.5f, 0.0f, 0.0f, 1.0f,
2791 0.5f, 0.0f, 0.0f, 1.0f
2794 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
2799 // this is only called once per entity so numsurfaces is always 1, and
2800 // surfacelist is always {0}, so this code does not handle batches
2801 R_Mesh_Matrix(&ent->matrix);
2803 if (ent->flags & EF_ADDITIVE)
2805 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2806 GL_DepthMask(false);
2808 else if (ent->alpha < 1)
2810 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2811 GL_DepthMask(false);
2815 GL_BlendFunc(GL_ONE, GL_ZERO);
2818 GL_DepthRange(0, (ent->flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
2819 GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
2820 GL_CullFace((ent->effects & EF_DOUBLESIDED) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
2821 R_Mesh_VertexPointer(nomodelvertex3f, 0, 0);
2822 if (r_refdef.fogenabled)
2825 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
2826 R_Mesh_ColorPointer(color4f, 0, 0);
2827 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
2828 f1 = FogPoint_World(org);
2830 for (i = 0, c = color4f;i < 6;i++, c += 4)
2832 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
2833 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
2834 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
2838 else if (ent->alpha != 1)
2840 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
2841 R_Mesh_ColorPointer(color4f, 0, 0);
2842 for (i = 0, c = color4f;i < 6;i++, c += 4)
2846 R_Mesh_ColorPointer(nomodelcolor4f, 0, 0);
2847 R_Mesh_ResetTextureState();
2848 R_Mesh_Draw(0, 6, 8, nomodelelements, 0, 0);
2851 void R_DrawNoModel(entity_render_t *ent)
2854 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
2855 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
2856 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, r_shadow_rtlight);
2858 // R_DrawNoModelCallback(ent, 0);
2861 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
2863 vec3_t right1, right2, diff, normal;
2865 VectorSubtract (org2, org1, normal);
2867 // calculate 'right' vector for start
2868 VectorSubtract (r_view.origin, org1, diff);
2869 CrossProduct (normal, diff, right1);
2870 VectorNormalize (right1);
2872 // calculate 'right' vector for end
2873 VectorSubtract (r_view.origin, org2, diff);
2874 CrossProduct (normal, diff, right2);
2875 VectorNormalize (right2);
2877 vert[ 0] = org1[0] + width * right1[0];
2878 vert[ 1] = org1[1] + width * right1[1];
2879 vert[ 2] = org1[2] + width * right1[2];
2880 vert[ 3] = org1[0] - width * right1[0];
2881 vert[ 4] = org1[1] - width * right1[1];
2882 vert[ 5] = org1[2] - width * right1[2];
2883 vert[ 6] = org2[0] - width * right2[0];
2884 vert[ 7] = org2[1] - width * right2[1];
2885 vert[ 8] = org2[2] - width * right2[2];
2886 vert[ 9] = org2[0] + width * right2[0];
2887 vert[10] = org2[1] + width * right2[1];
2888 vert[11] = org2[2] + width * right2[2];
2891 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
2893 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)
2898 if (r_refdef.fogenabled)
2899 fog = FogPoint_World(origin);
2901 R_Mesh_Matrix(&identitymatrix);
2902 GL_BlendFunc(blendfunc1, blendfunc2);
2903 GL_DepthMask(false);
2904 GL_DepthRange(0, depthshort ? 0.0625 : 1);
2905 GL_DepthTest(!depthdisable);
2907 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
2908 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
2909 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
2910 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
2911 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
2912 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
2913 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
2914 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
2915 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
2916 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
2917 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
2918 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
2920 R_Mesh_VertexPointer(vertex3f, 0, 0);
2921 R_Mesh_ColorPointer(NULL, 0, 0);
2922 R_Mesh_ResetTextureState();
2923 R_Mesh_TexBind(0, R_GetTexture(texture));
2924 R_Mesh_TexCoordPointer(0, 2, spritetexcoord2f, 0, 0);
2925 // FIXME: fixed function path can't properly handle r_view.colorscale > 1
2926 GL_Color(cr * fog * r_view.colorscale, cg * fog * r_view.colorscale, cb * fog * r_view.colorscale, ca);
2927 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2929 if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
2931 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
2932 GL_BlendFunc(blendfunc1, GL_ONE);
2934 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);
2935 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2939 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
2944 VectorSet(v, x, y, z);
2945 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
2946 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
2948 if (i == mesh->numvertices)
2950 if (mesh->numvertices < mesh->maxvertices)
2952 VectorCopy(v, vertex3f);
2953 mesh->numvertices++;
2955 return mesh->numvertices;
2961 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
2965 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
2966 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
2967 e = mesh->element3i + mesh->numtriangles * 3;
2968 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
2970 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
2971 if (mesh->numtriangles < mesh->maxtriangles)
2976 mesh->numtriangles++;
2978 element[1] = element[2];
2982 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
2986 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
2987 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
2988 e = mesh->element3i + mesh->numtriangles * 3;
2989 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
2991 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
2992 if (mesh->numtriangles < mesh->maxtriangles)
2997 mesh->numtriangles++;
2999 element[1] = element[2];
3003 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
3004 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
3006 int planenum, planenum2;
3009 mplane_t *plane, *plane2;
3011 double temppoints[2][256*3];
3012 // figure out how large a bounding box we need to properly compute this brush
3014 for (w = 0;w < numplanes;w++)
3015 maxdist = max(maxdist, planes[w].dist);
3016 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
3017 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
3018 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
3022 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
3023 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
3025 if (planenum2 == planenum)
3027 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);
3030 if (tempnumpoints < 3)
3032 // generate elements forming a triangle fan for this polygon
3033 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
3037 static void R_DrawCollisionBrush(const colbrushf_t *brush)
3040 R_Mesh_VertexPointer(brush->points->v, 0, 0);
3041 i = (int)(((size_t)brush) / sizeof(colbrushf_t));
3042 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);
3043 GL_LockArrays(0, brush->numpoints);
3044 R_Mesh_Draw(0, brush->numpoints, brush->numtriangles, brush->elements, 0, 0);
3045 GL_LockArrays(0, 0);
3048 static void R_DrawCollisionSurface(const entity_render_t *ent, const msurface_t *surface)
3051 if (!surface->num_collisiontriangles)
3053 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
3054 i = (int)(((size_t)surface) / sizeof(msurface_t));
3055 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);
3056 GL_LockArrays(0, surface->num_collisionvertices);
3057 R_Mesh_Draw(0, surface->num_collisionvertices, surface->num_collisiontriangles, surface->data_collisionelement3i, 0, 0);
3058 GL_LockArrays(0, 0);
3061 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)
3063 texturelayer_t *layer;
3064 layer = t->currentlayers + t->currentnumlayers++;
3066 layer->depthmask = depthmask;
3067 layer->blendfunc1 = blendfunc1;
3068 layer->blendfunc2 = blendfunc2;
3069 layer->texture = texture;
3070 layer->texmatrix = *matrix;
3071 layer->color[0] = r * r_view.colorscale;
3072 layer->color[1] = g * r_view.colorscale;
3073 layer->color[2] = b * r_view.colorscale;
3074 layer->color[3] = a;
3077 void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
3079 model_t *model = ent->model;
3081 // switch to an alternate material if this is a q1bsp animated material
3083 texture_t *texture = t;
3084 int s = ent->skinnum;
3085 if ((unsigned int)s >= (unsigned int)model->numskins)
3087 if (model->skinscenes)
3089 if (model->skinscenes[s].framecount > 1)
3090 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
3092 s = model->skinscenes[s].firstframe;
3095 t = t + s * model->num_surfaces;
3098 // use an alternate animation if the entity's frame is not 0,
3099 // and only if the texture has an alternate animation
3100 if (ent->frame != 0 && t->anim_total[1])
3101 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.time * 5.0f) % t->anim_total[1]) : 0];
3103 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.time * 5.0f) % t->anim_total[0]) : 0];
3105 texture->currentframe = t;
3108 // pick a new currentskinframe if the material is animated
3109 if (t->numskinframes >= 2)
3110 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->frame2time)) % t->numskinframes];
3111 if (t->backgroundnumskinframes >= 2)
3112 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - ent->frame2time)) % t->backgroundnumskinframes];
3114 t->currentmaterialflags = t->basematerialflags;
3115 t->currentalpha = ent->alpha;
3116 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
3117 t->currentalpha *= r_wateralpha.value;
3118 if (!(ent->flags & RENDER_LIGHT))
3119 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
3120 if (ent->effects & EF_ADDITIVE)
3121 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
3122 else if (t->currentalpha < 1)
3123 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
3124 if (ent->effects & EF_DOUBLESIDED)
3125 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
3126 if (ent->effects & EF_NODEPTHTEST)
3127 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
3128 if (ent->flags & RENDER_VIEWMODEL)
3129 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
3130 if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
3131 t->currenttexmatrix = r_waterscrollmatrix;
3133 t->currenttexmatrix = identitymatrix;
3134 if (t->backgroundnumskinframes && !(t->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED))
3135 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
3137 t->colormapping = VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f);
3138 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
3139 t->glosstexture = r_texture_white;
3140 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
3141 t->backgroundglosstexture = r_texture_white;
3142 t->specularpower = r_shadow_glossexponent.value;
3143 // TODO: store reference values for these in the texture?
3144 t->specularscale = 0;
3145 if (r_shadow_gloss.integer > 0)
3147 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
3149 if (r_shadow_glossintensity.value > 0)
3151 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_black;
3152 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_black;
3153 t->specularscale = r_shadow_glossintensity.value;
3156 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
3157 t->specularscale = r_shadow_gloss2intensity.value;
3160 t->currentnumlayers = 0;
3161 if (!(t->currentmaterialflags & MATERIALFLAG_NODRAW))
3163 if (gl_lightmaps.integer)
3164 R_Texture_AddLayer(t, true, GL_ONE, GL_ZERO, TEXTURELAYERTYPE_LITTEXTURE, r_texture_white, &identitymatrix, 1, 1, 1, 1);
3165 else if (!(t->currentmaterialflags & MATERIALFLAG_SKY))
3167 int blendfunc1, blendfunc2, depthmask;
3168 if (t->currentmaterialflags & MATERIALFLAG_ADD)
3170 blendfunc1 = GL_SRC_ALPHA;
3171 blendfunc2 = GL_ONE;
3173 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
3175 blendfunc1 = GL_SRC_ALPHA;
3176 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
3178 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
3180 blendfunc1 = t->customblendfunc[0];
3181 blendfunc2 = t->customblendfunc[1];
3185 blendfunc1 = GL_ONE;
3186 blendfunc2 = GL_ZERO;
3188 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
3189 if (t->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL))
3191 rtexture_t *currentbasetexture;
3193 if (r_refdef.fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED))
3194 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
3195 currentbasetexture = (VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) < (1.0f / 1048576.0f) && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
3196 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
3198 // fullbright is not affected by r_refdef.lightmapintensity
3199 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
3200 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
3201 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);
3202 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
3203 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);
3209 // q3bsp has no lightmap updates, so the lightstylevalue that
3210 // would normally be baked into the lightmap must be
3211 // applied to the color
3212 if (ent->model->type == mod_brushq3)
3213 colorscale *= r_refdef.lightstylevalue[0] * (1.0f / 256.0f);
3214 colorscale *= r_refdef.lightmapintensity;
3215 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);
3216 if (r_ambient.value >= (1.0f/64.0f))
3217 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);
3218 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
3220 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);
3221 if (r_ambient.value >= (1.0f/64.0f))
3222 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);
3224 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
3226 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);
3227 if (r_ambient.value >= (1.0f/64.0f))
3228 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);
3231 if (t->currentskinframe->glow != NULL)
3232 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);
3233 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
3235 // if this is opaque use alpha blend which will darken the earlier
3238 // if this is an alpha blended material, all the earlier passes
3239 // were darkened by fog already, so we only need to add the fog
3240 // color ontop through the fog mask texture
3242 // if this is an additive blended material, all the earlier passes
3243 // were darkened by fog already, and we should not add fog color
3244 // (because the background was not darkened, there is no fog color
3245 // that was lost behind it).
3246 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);
3253 void R_UpdateAllTextureInfo(entity_render_t *ent)
3257 for (i = 0;i < ent->model->num_texturesperskin;i++)
3258 R_UpdateTextureInfo(ent, ent->model->data_textures + i);
3261 int rsurface_array_size = 0;
3262 float *rsurface_array_modelvertex3f = NULL;
3263 float *rsurface_array_modelsvector3f = NULL;
3264 float *rsurface_array_modeltvector3f = NULL;
3265 float *rsurface_array_modelnormal3f = NULL;
3266 float *rsurface_array_deformedvertex3f = NULL;
3267 float *rsurface_array_deformedsvector3f = NULL;
3268 float *rsurface_array_deformedtvector3f = NULL;
3269 float *rsurface_array_deformednormal3f = NULL;
3270 float *rsurface_array_color4f = NULL;
3271 float *rsurface_array_texcoord3f = NULL;
3273 void R_Mesh_ResizeArrays(int newvertices)
3276 if (rsurface_array_size >= newvertices)
3278 if (rsurface_array_modelvertex3f)
3279 Mem_Free(rsurface_array_modelvertex3f);
3280 rsurface_array_size = (newvertices + 1023) & ~1023;
3281 base = (float *)Mem_Alloc(r_main_mempool, rsurface_array_size * sizeof(float[31]));
3282 rsurface_array_modelvertex3f = base + rsurface_array_size * 0;
3283 rsurface_array_modelsvector3f = base + rsurface_array_size * 3;
3284 rsurface_array_modeltvector3f = base + rsurface_array_size * 6;
3285 rsurface_array_modelnormal3f = base + rsurface_array_size * 9;
3286 rsurface_array_deformedvertex3f = base + rsurface_array_size * 12;
3287 rsurface_array_deformedsvector3f = base + rsurface_array_size * 15;
3288 rsurface_array_deformedtvector3f = base + rsurface_array_size * 18;
3289 rsurface_array_deformednormal3f = base + rsurface_array_size * 21;
3290 rsurface_array_texcoord3f = base + rsurface_array_size * 24;
3291 rsurface_array_color4f = base + rsurface_array_size * 27;
3294 float *rsurface_modelvertex3f;
3295 int rsurface_modelvertex3f_bufferobject;
3296 size_t rsurface_modelvertex3f_bufferoffset;
3297 float *rsurface_modelsvector3f;
3298 int rsurface_modelsvector3f_bufferobject;
3299 size_t rsurface_modelsvector3f_bufferoffset;
3300 float *rsurface_modeltvector3f;
3301 int rsurface_modeltvector3f_bufferobject;
3302 size_t rsurface_modeltvector3f_bufferoffset;
3303 float *rsurface_modelnormal3f;
3304 int rsurface_modelnormal3f_bufferobject;
3305 size_t rsurface_modelnormal3f_bufferoffset;
3306 float *rsurface_vertex3f;
3307 int rsurface_vertex3f_bufferobject;
3308 size_t rsurface_vertex3f_bufferoffset;
3309 float *rsurface_svector3f;
3310 int rsurface_svector3f_bufferobject;
3311 size_t rsurface_svector3f_bufferoffset;
3312 float *rsurface_tvector3f;
3313 int rsurface_tvector3f_bufferobject;
3314 size_t rsurface_tvector3f_bufferoffset;
3315 float *rsurface_normal3f;
3316 int rsurface_normal3f_bufferobject;
3317 size_t rsurface_normal3f_bufferoffset;
3318 float *rsurface_lightmapcolor4f;
3319 int rsurface_lightmapcolor4f_bufferobject;
3320 size_t rsurface_lightmapcolor4f_bufferoffset;
3321 vec3_t rsurface_modelorg;
3322 qboolean rsurface_generatedvertex;
3323 const entity_render_t *rsurface_entity;
3324 const model_t *rsurface_model;
3325 texture_t *rsurface_texture;
3326 rtexture_t *rsurface_lightmaptexture;
3327 rtexture_t *rsurface_deluxemaptexture;
3328 rsurfmode_t rsurface_mode;
3329 int rsurface_lightmode; // 0 = lightmap or fullbright, 1 = color array from q3bsp, 2 = vertex shaded model
3331 void RSurf_CleanUp(void)
3334 if (rsurface_mode == RSURFMODE_GLSL)
3336 qglUseProgramObjectARB(0);CHECKGLERROR
3338 GL_AlphaTest(false);
3339 rsurface_mode = RSURFMODE_NONE;
3340 rsurface_lightmaptexture = NULL;
3341 rsurface_deluxemaptexture = NULL;
3342 rsurface_texture = NULL;
3345 void RSurf_ActiveWorldEntity(void)
3348 rsurface_entity = r_refdef.worldentity;
3349 rsurface_model = r_refdef.worldmodel;
3350 if (rsurface_array_size < rsurface_model->surfmesh.num_vertices)
3351 R_Mesh_ResizeArrays(rsurface_model->surfmesh.num_vertices);
3352 R_Mesh_Matrix(&identitymatrix);
3353 VectorCopy(r_view.origin, rsurface_modelorg);
3354 rsurface_modelvertex3f = rsurface_model->surfmesh.data_vertex3f;
3355 rsurface_modelvertex3f_bufferobject = rsurface_model->surfmesh.vbo;
3356 rsurface_modelvertex3f_bufferoffset = rsurface_model->surfmesh.vbooffset_vertex3f;
3357 rsurface_modelsvector3f = rsurface_model->surfmesh.data_svector3f;
3358 rsurface_modelsvector3f_bufferobject = rsurface_model->surfmesh.vbo;
3359 rsurface_modelsvector3f_bufferoffset = rsurface_model->surfmesh.vbooffset_svector3f;
3360 rsurface_modeltvector3f = rsurface_model->surfmesh.data_tvector3f;
3361 rsurface_modeltvector3f_bufferobject = rsurface_model->surfmesh.vbo;
3362 rsurface_modeltvector3f_bufferoffset = rsurface_model->surfmesh.vbooffset_tvector3f;
3363 rsurface_modelnormal3f = rsurface_model->surfmesh.data_normal3f;
3364 rsurface_modelnormal3f_bufferobject = rsurface_model->surfmesh.vbo;
3365 rsurface_modelnormal3f_bufferoffset = rsurface_model->surfmesh.vbooffset_normal3f;
3366 rsurface_generatedvertex = false;
3367 rsurface_vertex3f = rsurface_modelvertex3f;
3368 rsurface_vertex3f_bufferobject = rsurface_modelvertex3f_bufferobject;
3369 rsurface_vertex3f_bufferoffset = rsurface_modelvertex3f_bufferoffset;
3370 rsurface_svector3f = rsurface_modelsvector3f;
3371 rsurface_svector3f_bufferobject = rsurface_modelsvector3f_bufferobject;
3372 rsurface_svector3f_bufferoffset = rsurface_modelsvector3f_bufferoffset;
3373 rsurface_tvector3f = rsurface_modeltvector3f;
3374 rsurface_tvector3f_bufferobject = rsurface_modeltvector3f_bufferobject;
3375 rsurface_tvector3f_bufferoffset = rsurface_modeltvector3f_bufferoffset;
3376 rsurface_normal3f = rsurface_modelnormal3f;
3377 rsurface_normal3f_bufferobject = rsurface_modelnormal3f_bufferobject;
3378 rsurface_normal3f_bufferoffset = rsurface_modelnormal3f_bufferoffset;
3381 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
3384 rsurface_entity = ent;
3385 rsurface_model = ent->model;
3386 if (rsurface_array_size < rsurface_model->surfmesh.num_vertices)
3387 R_Mesh_ResizeArrays(rsurface_model->surfmesh.num_vertices);
3388 R_Mesh_Matrix(&ent->matrix);
3389 Matrix4x4_Transform(&ent->inversematrix, r_view.origin, rsurface_modelorg);
3390 if (rsurface_model->surfmesh.isanimated && (rsurface_entity->frameblend[0].lerp != 1 || rsurface_entity->frameblend[0].frame != 0))
3394 rsurface_modelvertex3f = rsurface_array_modelvertex3f;
3395 rsurface_modelsvector3f = rsurface_array_modelsvector3f;
3396 rsurface_modeltvector3f = rsurface_array_modeltvector3f;
3397 rsurface_modelnormal3f = rsurface_array_modelnormal3f;
3398 Mod_Alias_GetMesh_Vertices(rsurface_model, rsurface_entity->frameblend, rsurface_array_modelvertex3f, rsurface_array_modelnormal3f, rsurface_array_modelsvector3f, rsurface_array_modeltvector3f);
3400 else if (wantnormals)
3402 rsurface_modelvertex3f = rsurface_array_modelvertex3f;
3403 rsurface_modelsvector3f = NULL;
3404 rsurface_modeltvector3f = NULL;
3405 rsurface_modelnormal3f = rsurface_array_modelnormal3f;
3406 Mod_Alias_GetMesh_Vertices(rsurface_model, rsurface_entity->frameblend, rsurface_array_modelvertex3f, rsurface_array_modelnormal3f, NULL, NULL);
3410 rsurface_modelvertex3f = rsurface_array_modelvertex3f;
3411 rsurface_modelsvector3f = NULL;
3412 rsurface_modeltvector3f = NULL;
3413 rsurface_modelnormal3f = NULL;
3414 Mod_Alias_GetMesh_Vertices(rsurface_model, rsurface_entity->frameblend, rsurface_array_modelvertex3f, NULL, NULL, NULL);
3416 rsurface_modelvertex3f_bufferobject = 0;
3417 rsurface_modelvertex3f_bufferoffset = 0;
3418 rsurface_modelsvector3f_bufferobject = 0;
3419 rsurface_modelsvector3f_bufferoffset = 0;
3420 rsurface_modeltvector3f_bufferobject = 0;
3421 rsurface_modeltvector3f_bufferoffset = 0;
3422 rsurface_modelnormal3f_bufferobject = 0;
3423 rsurface_modelnormal3f_bufferoffset = 0;
3424 rsurface_generatedvertex = true;
3428 rsurface_modelvertex3f = rsurface_model->surfmesh.data_vertex3f;
3429 rsurface_modelvertex3f_bufferobject = rsurface_model->surfmesh.vbo;
3430 rsurface_modelvertex3f_bufferoffset = rsurface_model->surfmesh.vbooffset_vertex3f;
3431 rsurface_modelsvector3f = rsurface_model->surfmesh.data_svector3f;
3432 rsurface_modelsvector3f_bufferobject = rsurface_model->surfmesh.vbo;
3433 rsurface_modelsvector3f_bufferoffset = rsurface_model->surfmesh.vbooffset_svector3f;
3434 rsurface_modeltvector3f = rsurface_model->surfmesh.data_tvector3f;
3435 rsurface_modeltvector3f_bufferobject = rsurface_model->surfmesh.vbo;
3436 rsurface_modeltvector3f_bufferoffset = rsurface_model->surfmesh.vbooffset_tvector3f;
3437 rsurface_modelnormal3f = rsurface_model->surfmesh.data_normal3f;
3438 rsurface_modelnormal3f_bufferobject = rsurface_model->surfmesh.vbo;
3439 rsurface_modelnormal3f_bufferoffset = rsurface_model->surfmesh.vbooffset_normal3f;
3440 rsurface_generatedvertex = false;
3442 rsurface_vertex3f = rsurface_modelvertex3f;
3443 rsurface_vertex3f_bufferobject = rsurface_modelvertex3f_bufferobject;
3444 rsurface_vertex3f_bufferoffset = rsurface_modelvertex3f_bufferoffset;
3445 rsurface_svector3f = rsurface_modelsvector3f;
3446 rsurface_svector3f_bufferobject = rsurface_modelsvector3f_bufferobject;
3447 rsurface_svector3f_bufferoffset = rsurface_modelsvector3f_bufferoffset;
3448 rsurface_tvector3f = rsurface_modeltvector3f;
3449 rsurface_tvector3f_bufferobject = rsurface_modeltvector3f_bufferobject;
3450 rsurface_tvector3f_bufferoffset = rsurface_modeltvector3f_bufferoffset;
3451 rsurface_normal3f = rsurface_modelnormal3f;
3452 rsurface_normal3f_bufferobject = rsurface_modelnormal3f_bufferobject;
3453 rsurface_normal3f_bufferoffset = rsurface_modelnormal3f_bufferoffset;
3456 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, msurface_t **texturesurfacelist)
3458 // 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
3459 if (rsurface_generatedvertex)
3461 if (rsurface_texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
3462 generatetangents = true;
3463 if (generatetangents)
3464 generatenormals = true;
3465 if (generatenormals && !rsurface_modelnormal3f)
3467 rsurface_normal3f = rsurface_modelnormal3f = rsurface_array_modelnormal3f;
3468 rsurface_normal3f_bufferobject = rsurface_modelnormal3f_bufferobject = 0;
3469 rsurface_normal3f_bufferoffset = rsurface_modelnormal3f_bufferoffset = 0;
3470 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);
3472 if (generatetangents && !rsurface_modelsvector3f)
3474 rsurface_svector3f = rsurface_modelsvector3f = rsurface_array_modelsvector3f;
3475 rsurface_svector3f_bufferobject = rsurface_modelsvector3f_bufferobject = 0;
3476 rsurface_svector3f_bufferoffset = rsurface_modelsvector3f_bufferoffset = 0;
3477 rsurface_tvector3f = rsurface_modeltvector3f = rsurface_array_modeltvector3f;
3478 rsurface_tvector3f_bufferobject = rsurface_modeltvector3f_bufferobject = 0;
3479 rsurface_tvector3f_bufferoffset = rsurface_modeltvector3f_bufferoffset = 0;
3480 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);
3483 // 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)
3484 if (rsurface_texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
3486 int texturesurfaceindex;
3487 float center[3], forward[3], right[3], up[3], v[4][3];
3488 matrix4x4_t matrix1, imatrix1;
3489 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_view.forward, forward);
3490 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_view.right, right);
3491 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_view.up, up);
3492 // make deformed versions of only the model vertices used by the specified surfaces
3493 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3496 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3497 // a single autosprite surface can contain multiple sprites...
3498 for (j = 0;j < surface->num_vertices - 3;j += 4)
3500 VectorClear(center);
3501 for (i = 0;i < 4;i++)
3502 VectorAdd(center, (rsurface_modelvertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
3503 VectorScale(center, 0.25f, center);
3504 if (rsurface_texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE2)
3506 forward[0] = rsurface_modelorg[0] - center[0];
3507 forward[1] = rsurface_modelorg[1] - center[1];
3509 VectorNormalize(forward);
3510 right[0] = forward[1];
3511 right[1] = -forward[0];
3513 VectorSet(up, 0, 0, 1);
3515 // FIXME: calculate vectors from triangle edges instead of using texture vectors as an easy way out?
3516 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);
3517 Matrix4x4_Invert_Simple(&imatrix1, &matrix1);
3518 for (i = 0;i < 4;i++)
3519 Matrix4x4_Transform(&imatrix1, (rsurface_modelvertex3f + 3 * surface->num_firstvertex) + (j+i)*3, v[i]);
3520 for (i = 0;i < 4;i++)
3521 VectorMAMAMAM(1, center, v[i][0], forward, v[i][1], right, v[i][2], up, rsurface_array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
3523 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);
3524 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);
3526 rsurface_vertex3f = rsurface_array_deformedvertex3f;
3527 rsurface_vertex3f_bufferobject = 0;
3528 rsurface_vertex3f_bufferoffset = 0;
3529 rsurface_svector3f = rsurface_array_deformedsvector3f;
3530 rsurface_svector3f_bufferobject = 0;
3531 rsurface_svector3f_bufferoffset = 0;
3532 rsurface_tvector3f = rsurface_array_deformedtvector3f;
3533 rsurface_tvector3f_bufferobject = 0;
3534 rsurface_tvector3f_bufferoffset = 0;
3535 rsurface_normal3f = rsurface_array_deformednormal3f;
3536 rsurface_normal3f_bufferobject = 0;
3537 rsurface_normal3f_bufferoffset = 0;
3541 rsurface_vertex3f = rsurface_modelvertex3f;
3542 rsurface_vertex3f_bufferobject = rsurface_modelvertex3f_bufferobject;
3543 rsurface_vertex3f_bufferoffset = rsurface_modelvertex3f_bufferoffset;
3544 rsurface_svector3f = rsurface_modelsvector3f;
3545 rsurface_svector3f_bufferobject = rsurface_modelsvector3f_bufferobject;
3546 rsurface_svector3f_bufferoffset = rsurface_modelsvector3f_bufferoffset;
3547 rsurface_tvector3f = rsurface_modeltvector3f;
3548 rsurface_tvector3f_bufferobject = rsurface_modeltvector3f_bufferobject;
3549 rsurface_tvector3f_bufferoffset = rsurface_modeltvector3f_bufferoffset;
3550 rsurface_normal3f = rsurface_modelnormal3f;
3551 rsurface_normal3f_bufferobject = rsurface_modelnormal3f_bufferobject;
3552 rsurface_normal3f_bufferoffset = rsurface_modelnormal3f_bufferoffset;
3554 R_Mesh_VertexPointer(rsurface_vertex3f, rsurface_vertex3f_bufferobject, rsurface_vertex3f_bufferoffset);
3557 void RSurf_DrawBatch_Simple(int texturenumsurfaces, msurface_t **texturesurfacelist)
3560 const msurface_t *surface = texturesurfacelist[0];
3561 const msurface_t *surface2;
3566 // TODO: lock all array ranges before render, rather than on each surface
3567 if (texturenumsurfaces == 1)
3569 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
3570 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));
3572 else if (r_batchmode.integer == 2)
3574 #define MAXBATCHTRIANGLES 4096
3575 int batchtriangles = 0;
3576 int batchelements[MAXBATCHTRIANGLES*3];
3577 for (i = 0;i < texturenumsurfaces;i = j)
3579 surface = texturesurfacelist[i];
3581 if (surface->num_triangles > MAXBATCHTRIANGLES)
3583 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));
3586 memcpy(batchelements, rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
3587 batchtriangles = surface->num_triangles;
3588 firstvertex = surface->num_firstvertex;
3589 endvertex = surface->num_firstvertex + surface->num_vertices;
3590 for (;j < texturenumsurfaces;j++)
3592 surface2 = texturesurfacelist[j];
3593 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
3595 memcpy(batchelements + batchtriangles * 3, rsurface_model->surfmesh.data_element3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
3596 batchtriangles += surface2->num_triangles;
3597 firstvertex = min(firstvertex, surface2->num_firstvertex);
3598 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
3600 surface2 = texturesurfacelist[j-1];
3601 numvertices = endvertex - firstvertex;
3602 R_Mesh_Draw(firstvertex, numvertices, batchtriangles, batchelements, 0, 0);
3605 else if (r_batchmode.integer == 1)
3607 for (i = 0;i < texturenumsurfaces;i = j)
3609 surface = texturesurfacelist[i];
3610 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
3611 if (texturesurfacelist[j] != surface2)
3613 surface2 = texturesurfacelist[j-1];
3614 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
3615 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
3616 GL_LockArrays(surface->num_firstvertex, numvertices);
3617 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));
3622 for (i = 0;i < texturenumsurfaces;i++)
3624 surface = texturesurfacelist[i];
3625 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
3626 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));
3631 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
3634 int texturesurfaceindex;
3635 if (r_showsurfaces.integer == 2)
3637 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3639 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3640 for (j = 0;j < surface->num_triangles;j++)
3642 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_view.colorscale;
3643 GL_Color(f, f, f, 1);
3644 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)));
3650 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3652 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3653 int k = (int)(((size_t)surface) / sizeof(msurface_t));
3654 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);
3655 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
3656 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));
3661 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, msurface_t **texturesurfacelist)
3663 int texturesurfaceindex;
3667 if (rsurface_lightmapcolor4f)
3669 // generate color arrays for the surfaces in this list
3670 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3672 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3673 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)
3675 f = FogPoint_Model(v);
3685 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3687 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3688 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)
3690 f = FogPoint_Model(v);
3698 rsurface_lightmapcolor4f = rsurface_array_color4f;
3699 rsurface_lightmapcolor4f_bufferobject = 0;
3700 rsurface_lightmapcolor4f_bufferoffset = 0;
3703 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a)
3705 int texturesurfaceindex;
3708 if (!rsurface_lightmapcolor4f)
3710 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3712 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3713 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)
3721 rsurface_lightmapcolor4f = rsurface_array_color4f;
3722 rsurface_lightmapcolor4f_bufferobject = 0;
3723 rsurface_lightmapcolor4f_bufferoffset = 0;
3726 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
3729 rsurface_lightmapcolor4f = NULL;
3730 rsurface_lightmapcolor4f_bufferobject = 0;
3731 rsurface_lightmapcolor4f_bufferoffset = 0;
3732 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
3733 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
3734 R_Mesh_ColorPointer(rsurface_lightmapcolor4f, rsurface_lightmapcolor4f_bufferobject, rsurface_lightmapcolor4f_bufferoffset);
3735 GL_Color(r, g, b, a);
3736 R_Mesh_TexBind(0, R_GetTexture(rsurface_lightmaptexture));
3737 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3740 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
3742 // TODO: optimize applyfog && applycolor case
3743 // just apply fog if necessary, and tint the fog color array if necessary
3744 rsurface_lightmapcolor4f = NULL;
3745 rsurface_lightmapcolor4f_bufferobject = 0;
3746 rsurface_lightmapcolor4f_bufferoffset = 0;
3747 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
3748 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
3749 R_Mesh_ColorPointer(rsurface_lightmapcolor4f, rsurface_lightmapcolor4f_bufferobject, rsurface_lightmapcolor4f_bufferoffset);
3750 GL_Color(r, g, b, a);
3751 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3754 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
3756 int texturesurfaceindex;
3760 if (texturesurfacelist[0]->lightmapinfo && texturesurfacelist[0]->lightmapinfo->stainsamples)
3762 // generate color arrays for the surfaces in this list
3763 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3765 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3766 for (i = 0, c = rsurface_array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
3768 if (surface->lightmapinfo->samples)
3770 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface_model->surfmesh.data_lightmapoffsets + surface->num_firstvertex)[i];
3771 float scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
3772 VectorScale(lm, scale, c);
3773 if (surface->lightmapinfo->styles[1] != 255)
3775 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
3777 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
3778 VectorMA(c, scale, lm, c);
3779 if (surface->lightmapinfo->styles[2] != 255)
3782 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
3783 VectorMA(c, scale, lm, c);
3784 if (surface->lightmapinfo->styles[3] != 255)
3787 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
3788 VectorMA(c, scale, lm, c);
3798 rsurface_lightmapcolor4f = rsurface_array_color4f;
3799 rsurface_lightmapcolor4f_bufferobject = 0;
3800 rsurface_lightmapcolor4f_bufferoffset = 0;
3804 rsurface_lightmapcolor4f = rsurface_model->surfmesh.data_lightmapcolor4f;
3805 rsurface_lightmapcolor4f_bufferobject = rsurface_model->surfmesh.vbo;
3806 rsurface_lightmapcolor4f_bufferoffset = rsurface_model->surfmesh.vbooffset_lightmapcolor4f;
3808 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
3809 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
3810 R_Mesh_ColorPointer(rsurface_lightmapcolor4f, rsurface_lightmapcolor4f_bufferobject, rsurface_lightmapcolor4f_bufferoffset);
3811 GL_Color(r, g, b, a);
3812 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3815 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
3817 int texturesurfaceindex;
3821 vec3_t ambientcolor;
3822 vec3_t diffusecolor;
3826 VectorCopy(rsurface_entity->modellight_lightdir, lightdir);
3827 ambientcolor[0] = rsurface_entity->modellight_ambient[0] * r * 0.5f;
3828 ambientcolor[1] = rsurface_entity->modellight_ambient[1] * g * 0.5f;
3829 ambientcolor[2] = rsurface_entity->modellight_ambient[2] * b * 0.5f;
3830 diffusecolor[0] = rsurface_entity->modellight_diffuse[0] * r * 0.5f;
3831 diffusecolor[1] = rsurface_entity->modellight_diffuse[1] * g * 0.5f;
3832 diffusecolor[2] = rsurface_entity->modellight_diffuse[2] * b * 0.5f;
3833 if (VectorLength2(diffusecolor) > 0)
3835 // generate color arrays for the surfaces in this list
3836 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3838 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3839 int numverts = surface->num_vertices;
3840 v = rsurface_vertex3f + 3 * surface->num_firstvertex;
3841 c2 = rsurface_normal3f + 3 * surface->num_firstvertex;
3842 c = rsurface_array_color4f + 4 * surface->num_firstvertex;
3843 // q3-style directional shading
3844 for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
3846 if ((f = DotProduct(c2, lightdir)) > 0)
3847 VectorMA(ambientcolor, f, diffusecolor, c);
3849 VectorCopy(ambientcolor, c);
3858 rsurface_lightmapcolor4f = rsurface_array_color4f;
3859 rsurface_lightmapcolor4f_bufferobject = 0;
3860 rsurface_lightmapcolor4f_bufferoffset = 0;
3864 r = ambientcolor[0];
3865 g = ambientcolor[1];
3866 b = ambientcolor[2];
3867 rsurface_lightmapcolor4f = NULL;
3868 rsurface_lightmapcolor4f_bufferobject = 0;
3869 rsurface_lightmapcolor4f_bufferoffset = 0;
3871 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
3872 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
3873 R_Mesh_ColorPointer(rsurface_lightmapcolor4f, rsurface_lightmapcolor4f_bufferobject, rsurface_lightmapcolor4f_bufferoffset);
3874 GL_Color(r, g, b, a);
3875 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3878 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
3880 GL_DepthRange(0, (rsurface_texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
3881 GL_DepthTest(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
3882 GL_CullFace((rsurface_texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
3883 if (rsurface_mode != RSURFMODE_SHOWSURFACES)
3885 rsurface_mode = RSURFMODE_SHOWSURFACES;
3887 GL_BlendFunc(GL_ONE, GL_ZERO);
3888 R_Mesh_ColorPointer(NULL, 0, 0);
3889 R_Mesh_ResetTextureState();
3891 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
3892 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
3895 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, msurface_t **texturesurfacelist)
3897 // transparent sky would be ridiculous
3898 if ((rsurface_texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED))
3900 if (rsurface_mode != RSURFMODE_SKY)
3902 if (rsurface_mode == RSURFMODE_GLSL)
3904 qglUseProgramObjectARB(0);CHECKGLERROR
3906 rsurface_mode = RSURFMODE_SKY;
3910 skyrendernow = false;
3912 // restore entity matrix
3913 R_Mesh_Matrix(&rsurface_entity->matrix);
3915 GL_DepthRange(0, (rsurface_texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
3916 GL_DepthTest(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
3917 GL_CullFace((rsurface_texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
3919 // LordHavoc: HalfLife maps have freaky skypolys so don't use
3920 // skymasking on them, and Quake3 never did sky masking (unlike
3921 // software Quake and software Quake2), so disable the sky masking
3922 // in Quake3 maps as it causes problems with q3map2 sky tricks,
3923 // and skymasking also looks very bad when noclipping outside the
3924 // level, so don't use it then either.
3925 if (rsurface_model->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_viewcache.world_novis)
3927 GL_Color(r_refdef.fogcolor[0] * r_view.colorscale, r_refdef.fogcolor[1] * r_view.colorscale, r_refdef.fogcolor[2] * r_view.colorscale, 1);
3928 R_Mesh_ColorPointer(NULL, 0, 0);
3929 R_Mesh_ResetTextureState();
3930 if (skyrendermasked)
3932 // depth-only (masking)
3933 GL_ColorMask(0,0,0,0);
3934 // just to make sure that braindead drivers don't draw
3935 // anything despite that colormask...
3936 GL_BlendFunc(GL_ZERO, GL_ONE);
3941 GL_BlendFunc(GL_ONE, GL_ZERO);
3943 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
3944 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3945 if (skyrendermasked)
3946 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
3950 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, msurface_t **texturesurfacelist)
3952 if (rsurface_mode != RSURFMODE_GLSL)
3954 rsurface_mode = RSURFMODE_GLSL;
3955 R_Mesh_ResetTextureState();
3958 R_SetupSurfaceShader(vec3_origin, rsurface_lightmode == 2, 1, 1, rsurface_texture->specularscale);
3959 if (!r_glsl_permutation)
3962 if (rsurface_lightmode == 2)
3963 RSurf_PrepareVerticesForBatch(true, r_glsl_permutation->loc_Texture_Normal, texturenumsurfaces, texturesurfacelist);
3965 RSurf_PrepareVerticesForBatch(r_glsl_permutation->loc_Texture_Normal, r_glsl_permutation->loc_Texture_Normal, texturenumsurfaces, texturesurfacelist);
3966 R_Mesh_TexCoordPointer(0, 2, rsurface_model->surfmesh.data_texcoordtexture2f, rsurface_model->surfmesh.vbo, rsurface_model->surfmesh.vbooffset_texcoordtexture2f);
3967 R_Mesh_TexCoordPointer(1, 3, rsurface_svector3f, rsurface_svector3f_bufferobject, rsurface_svector3f_bufferoffset);
3968 R_Mesh_TexCoordPointer(2, 3, rsurface_tvector3f, rsurface_tvector3f_bufferobject, rsurface_tvector3f_bufferoffset);
3969 R_Mesh_TexCoordPointer(3, 3, rsurface_normal3f, rsurface_normal3f_bufferobject, rsurface_normal3f_bufferoffset);
3970 R_Mesh_TexCoordPointer(4, 2, rsurface_model->surfmesh.data_texcoordlightmap2f, rsurface_model->surfmesh.vbo, rsurface_model->surfmesh.vbooffset_texcoordlightmap2f);
3972 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
3974 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
3975 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
3976 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
3977 R_Mesh_ColorPointer(NULL, 0, 0);
3979 else if (rsurface_lightmaptexture)
3981 R_Mesh_TexBind(7, R_GetTexture(rsurface_lightmaptexture));
3982 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
3983 R_Mesh_TexBind(8, R_GetTexture(rsurface_deluxemaptexture));
3984 R_Mesh_ColorPointer(NULL, 0, 0);
3988 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
3989 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
3990 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
3991 R_Mesh_ColorPointer(rsurface_model->surfmesh.data_lightmapcolor4f, rsurface_model->surfmesh.vbo, rsurface_model->surfmesh.vbooffset_lightmapcolor4f);
3994 if (rsurface_lightmaptexture && !(rsurface_texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
3996 R_Mesh_TexBind(7, R_GetTexture(rsurface_lightmaptexture));
3997 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
3998 R_Mesh_TexBind(8, R_GetTexture(rsurface_deluxemaptexture));
4000 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
4001 if (rsurface_texture->backgroundnumskinframes && !(rsurface_texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED))
4006 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, msurface_t **texturesurfacelist)
4008 // OpenGL 1.3 path - anything not completely ancient
4009 int texturesurfaceindex;
4010 qboolean applycolor;
4014 const texturelayer_t *layer;
4015 if (rsurface_mode != RSURFMODE_MULTIPASS)
4016 rsurface_mode = RSURFMODE_MULTIPASS;
4017 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
4018 for (layerindex = 0, layer = rsurface_texture->currentlayers;layerindex < rsurface_texture->currentnumlayers;layerindex++, layer++)
4021 int layertexrgbscale;
4022 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
4024 if (layerindex == 0)
4028 GL_AlphaTest(false);
4029 qglDepthFunc(GL_EQUAL);CHECKGLERROR
4032 GL_DepthMask(layer->depthmask);
4033 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
4034 if ((layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2) && (gl_combine.integer || layer->depthmask))
4036 layertexrgbscale = 4;
4037 VectorScale(layer->color, 0.25f, layercolor);
4039 else if ((layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1) && (gl_combine.integer || layer->depthmask))
4041 layertexrgbscale = 2;
4042 VectorScale(layer->color, 0.5f, layercolor);
4046 layertexrgbscale = 1;
4047 VectorScale(layer->color, 1.0f, layercolor);
4049 layercolor[3] = layer->color[3];
4050 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
4051 R_Mesh_ColorPointer(NULL, 0, 0);
4052 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
4053 switch (layer->type)
4055 case TEXTURELAYERTYPE_LITTEXTURE:
4056 memset(&m, 0, sizeof(m));
4057 m.tex[0] = R_GetTexture(r_texture_white);
4058 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordlightmap2f;
4059 m.pointer_texcoord_bufferobject[0] = rsurface_model->surfmesh.vbo;
4060 m.pointer_texcoord_bufferoffset[0] = rsurface_model->surfmesh.vbooffset_texcoordlightmap2f;
4061 m.tex[1] = R_GetTexture(layer->texture);
4062 m.texmatrix[1] = layer->texmatrix;
4063 m.texrgbscale[1] = layertexrgbscale;
4064 m.pointer_texcoord[1] = rsurface_model->surfmesh.data_texcoordtexture2f;
4065 m.pointer_texcoord_bufferobject[1] = rsurface_model->surfmesh.vbo;
4066 m.pointer_texcoord_bufferoffset[1] = rsurface_model->surfmesh.vbooffset_texcoordtexture2f;
4067 R_Mesh_TextureState(&m);
4068 if (rsurface_lightmode == 2)
4069 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
4070 else if (rsurface_lightmaptexture)
4071 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
4073 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
4075 case TEXTURELAYERTYPE_TEXTURE:
4076 memset(&m, 0, sizeof(m));
4077 m.tex[0] = R_GetTexture(layer->texture);
4078 m.texmatrix[0] = layer->texmatrix;
4079 m.texrgbscale[0] = layertexrgbscale;
4080 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
4081 m.pointer_texcoord_bufferobject[0] = rsurface_model->surfmesh.vbo;
4082 m.pointer_texcoord_bufferoffset[0] = rsurface_model->surfmesh.vbooffset_texcoordtexture2f;
4083 R_Mesh_TextureState(&m);
4084 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
4086 case TEXTURELAYERTYPE_FOG:
4087 memset(&m, 0, sizeof(m));
4088 m.texrgbscale[0] = layertexrgbscale;
4091 m.tex[0] = R_GetTexture(layer->texture);
4092 m.texmatrix[0] = layer->texmatrix;
4093 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
4094 m.pointer_texcoord_bufferobject[0] = rsurface_model->surfmesh.vbo;
4095 m.pointer_texcoord_bufferoffset[0] = rsurface_model->surfmesh.vbooffset_texcoordtexture2f;
4097 R_Mesh_TextureState(&m);
4098 // generate a color array for the fog pass
4099 R_Mesh_ColorPointer(rsurface_array_color4f, 0, 0);
4100 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4104 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4105 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)
4107 f = 1 - FogPoint_Model(v);
4108 c[0] = layercolor[0];
4109 c[1] = layercolor[1];
4110 c[2] = layercolor[2];
4111 c[3] = f * layercolor[3];
4114 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
4117 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
4119 GL_LockArrays(0, 0);
4122 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
4124 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
4125 GL_AlphaTest(false);
4129 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, msurface_t **texturesurfacelist)
4131 // OpenGL 1.1 - crusty old voodoo path
4132 int texturesurfaceindex;
4136 const texturelayer_t *layer;
4137 if (rsurface_mode != RSURFMODE_MULTIPASS)
4138 rsurface_mode = RSURFMODE_MULTIPASS;
4139 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
4140 for (layerindex = 0, layer = rsurface_texture->currentlayers;layerindex < rsurface_texture->currentnumlayers;layerindex++, layer++)
4142 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
4144 if (layerindex == 0)
4148 GL_AlphaTest(false);
4149 qglDepthFunc(GL_EQUAL);CHECKGLERROR
4152 GL_DepthMask(layer->depthmask);
4153 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
4154 R_Mesh_ColorPointer(NULL, 0, 0);
4155 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
4156 switch (layer->type)
4158 case TEXTURELAYERTYPE_LITTEXTURE:
4159 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
4161 // two-pass lit texture with 2x rgbscale
4162 // first the lightmap pass
4163 memset(&m, 0, sizeof(m));
4164 m.tex[0] = R_GetTexture(r_texture_white);
4165 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordlightmap2f;
4166 m.pointer_texcoord_bufferobject[0] = rsurface_model->surfmesh.vbo;
4167 m.pointer_texcoord_bufferoffset[0] = rsurface_model->surfmesh.vbooffset_texcoordlightmap2f;
4168 R_Mesh_TextureState(&m);
4169 if (rsurface_lightmode == 2)
4170 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
4171 else if (rsurface_lightmaptexture)
4172 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
4174 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
4175 GL_LockArrays(0, 0);
4176 // then apply the texture to it
4177 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
4178 memset(&m, 0, sizeof(m));
4179 m.tex[0] = R_GetTexture(layer->texture);
4180 m.texmatrix[0] = layer->texmatrix;
4181 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
4182 m.pointer_texcoord_bufferobject[0] = rsurface_model->surfmesh.vbo;
4183 m.pointer_texcoord_bufferoffset[0] = rsurface_model->surfmesh.vbooffset_texcoordtexture2f;
4184 R_Mesh_TextureState(&m);
4185 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);
4189 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
4190 memset(&m, 0, sizeof(m));
4191 m.tex[0] = R_GetTexture(layer->texture);
4192 m.texmatrix[0] = layer->texmatrix;
4193 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
4194 m.pointer_texcoord_bufferobject[0] = rsurface_model->surfmesh.vbo;
4195 m.pointer_texcoord_bufferoffset[0] = rsurface_model->surfmesh.vbooffset_texcoordtexture2f;
4196 R_Mesh_TextureState(&m);
4197 if (rsurface_lightmode == 2)
4198 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);
4200 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);
4203 case TEXTURELAYERTYPE_TEXTURE:
4204 // singletexture unlit texture with transparency support
4205 memset(&m, 0, sizeof(m));
4206 m.tex[0] = R_GetTexture(layer->texture);
4207 m.texmatrix[0] = layer->texmatrix;
4208 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
4209 m.pointer_texcoord_bufferobject[0] = rsurface_model->surfmesh.vbo;
4210 m.pointer_texcoord_bufferoffset[0] = rsurface_model->surfmesh.vbooffset_texcoordtexture2f;
4211 R_Mesh_TextureState(&m);
4212 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);
4214 case TEXTURELAYERTYPE_FOG:
4215 // singletexture fogging
4216 R_Mesh_ColorPointer(rsurface_array_color4f, 0, 0);
4219 memset(&m, 0, sizeof(m));
4220 m.tex[0] = R_GetTexture(layer->texture);
4221 m.texmatrix[0] = layer->texmatrix;
4222 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
4223 m.pointer_texcoord_bufferobject[0] = rsurface_model->surfmesh.vbo;
4224 m.pointer_texcoord_bufferoffset[0] = rsurface_model->surfmesh.vbooffset_texcoordtexture2f;
4225 R_Mesh_TextureState(&m);
4228 R_Mesh_ResetTextureState();
4229 // generate a color array for the fog pass
4230 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4234 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4235 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)
4237 f = 1 - FogPoint_Model(v);
4238 c[0] = layer->color[0];
4239 c[1] = layer->color[1];
4240 c[2] = layer->color[2];
4241 c[3] = f * layer->color[3];
4244 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
4247 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
4249 GL_LockArrays(0, 0);
4252 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
4254 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
4255 GL_AlphaTest(false);
4259 static void R_DrawTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist)
4261 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_NODRAW)
4263 r_shadow_rtlight = NULL;
4264 r_refdef.stats.entities_surfaces += texturenumsurfaces;
4266 if (r_showsurfaces.integer)
4267 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
4268 else if (rsurface_texture->currentmaterialflags & MATERIALFLAG_SKY)
4269 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
4270 else if (rsurface_texture->currentnumlayers)
4272 GL_DepthRange(0, (rsurface_texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
4273 GL_DepthTest(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
4274 GL_CullFace((rsurface_texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
4275 GL_BlendFunc(rsurface_texture->currentlayers[0].blendfunc1, rsurface_texture->currentlayers[0].blendfunc2);
4276 GL_DepthMask(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_BLENDED));
4277 GL_Color(rsurface_entity->colormod[0], rsurface_entity->colormod[1], rsurface_entity->colormod[2], rsurface_texture->currentalpha);
4278 GL_AlphaTest((rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4279 // FIXME: identify models using a better check than rsurface_model->brush.shadowmesh
4280 rsurface_lightmode = ((rsurface_texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT) || rsurface_model->brush.shadowmesh) ? 0 : 2;
4281 if (r_glsl.integer && gl_support_fragment_shader)
4282 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist);
4283 else if (gl_combine.integer && r_textureunits.integer >= 2)
4284 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist);
4286 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist);
4289 GL_LockArrays(0, 0);
4292 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
4295 int texturenumsurfaces, endsurface;
4297 msurface_t *surface;
4298 msurface_t *texturesurfacelist[1024];
4300 // if the model is static it doesn't matter what value we give for
4301 // wantnormals and wanttangents, so this logic uses only rules applicable
4302 // to a model, knowing that they are meaningless otherwise
4303 if (ent == r_refdef.worldentity)
4304 RSurf_ActiveWorldEntity();
4305 else if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
4306 RSurf_ActiveModelEntity(ent, false, false);
4308 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
4310 for (i = 0;i < numsurfaces;i = j)
4313 surface = rsurface_model->data_surfaces + surfacelist[i];
4314 texture = surface->texture;
4315 R_UpdateTextureInfo(ent, texture);
4316 rsurface_texture = texture->currentframe;
4317 rsurface_lightmaptexture = surface->lightmaptexture;
4318 rsurface_deluxemaptexture = surface->deluxemaptexture;
4319 // scan ahead until we find a different texture
4320 endsurface = min(i + 1024, numsurfaces);
4321 texturenumsurfaces = 0;
4322 texturesurfacelist[texturenumsurfaces++] = surface;
4323 for (;j < endsurface;j++)
4325 surface = rsurface_model->data_surfaces + surfacelist[j];
4326 if (texture != surface->texture || rsurface_lightmaptexture != surface->lightmaptexture)
4328 texturesurfacelist[texturenumsurfaces++] = surface;
4330 // render the range of surfaces
4331 R_DrawTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
4337 void R_QueueSurfaceList(int numsurfaces, msurface_t **surfacelist, int flagsmask)
4340 vec3_t tempcenter, center;
4342 // break the surface list down into batches by texture and use of lightmapping
4343 for (i = 0;i < numsurfaces;i = j)
4346 // texture is the base texture pointer, rsurface_texture is the
4347 // current frame/skin the texture is directing us to use (for example
4348 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
4349 // use skin 1 instead)
4350 texture = surfacelist[i]->texture;
4351 rsurface_texture = texture->currentframe;
4352 rsurface_lightmaptexture = surfacelist[i]->lightmaptexture;
4353 rsurface_deluxemaptexture = surfacelist[i]->deluxemaptexture;
4354 if (!(rsurface_texture->currentmaterialflags & flagsmask))
4356 // if this texture is not the kind we want, skip ahead to the next one
4357 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
4361 if (rsurface_texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
4363 // transparent surfaces get pushed off into the transparent queue
4364 const msurface_t *surface = surfacelist[i];
4365 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
4366 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
4367 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
4368 Matrix4x4_Transform(&rsurface_entity->matrix, tempcenter, center);
4369 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);
4373 // simply scan ahead until we find a different texture or lightmap state
4374 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface_lightmaptexture == surfacelist[j]->lightmaptexture;j++)
4376 // render the range of surfaces
4377 R_DrawTextureSurfaceList(j - i, surfacelist + i);
4382 float locboxvertex3f[6*4*3] =
4384 1,0,1, 1,0,0, 1,1,0, 1,1,1,
4385 0,1,1, 0,1,0, 0,0,0, 0,0,1,
4386 1,1,1, 1,1,0, 0,1,0, 0,1,1,
4387 0,0,1, 0,0,0, 1,0,0, 1,0,1,
4388 0,0,1, 1,0,1, 1,1,1, 0,1,1,
4389 1,0,0, 0,0,0, 0,1,0, 1,1,0
4392 int locboxelement3i[6*2*3] =
4402 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
4405 cl_locnode_t *loc = (cl_locnode_t *)ent;
4407 float vertex3f[6*4*3];
4409 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4410 GL_DepthMask(false);
4411 GL_DepthRange(0, 1);
4413 GL_CullFace(GL_NONE);
4414 R_Mesh_Matrix(&identitymatrix);
4416 R_Mesh_VertexPointer(vertex3f, 0, 0);
4417 R_Mesh_ColorPointer(NULL, 0, 0);
4418 R_Mesh_ResetTextureState();
4421 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_view.colorscale,
4422 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_view.colorscale,
4423 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_view.colorscale,
4424 surfacelist[0] < 0 ? 0.5f : 0.125f);
4426 if (VectorCompare(loc->mins, loc->maxs))
4428 VectorSet(size, 2, 2, 2);
4429 VectorMA(loc->mins, -0.5f, size, mins);
4433 VectorCopy(loc->mins, mins);
4434 VectorSubtract(loc->maxs, loc->mins, size);
4437 for (i = 0;i < 6*4*3;)
4438 for (j = 0;j < 3;j++, i++)
4439 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
4441 R_Mesh_Draw(0, 6*4, 6*2, locboxelement3i, 0, 0);
4444 void R_DrawLocs(void)
4447 cl_locnode_t *loc, *nearestloc;
4449 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
4450 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
4452 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
4453 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
4457 void R_DrawCollisionBrushes(entity_render_t *ent)
4461 msurface_t *surface;
4462 model_t *model = ent->model;
4463 if (!model->brush.num_brushes)
4466 R_Mesh_ColorPointer(NULL, 0, 0);
4467 R_Mesh_ResetTextureState();
4468 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
4469 GL_DepthMask(false);
4470 GL_DepthRange(0, 1);
4471 GL_DepthTest(!r_showdisabledepthtest.integer);
4472 qglPolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);CHECKGLERROR
4473 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
4474 if (brush->colbrushf && brush->colbrushf->numtriangles)
4475 R_DrawCollisionBrush(brush->colbrushf);
4476 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
4477 if (surface->num_collisiontriangles)
4478 R_DrawCollisionSurface(ent, surface);
4479 qglPolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR
4482 void R_DrawTrianglesAndNormals(entity_render_t *ent, qboolean drawtris, qboolean drawnormals, int flagsmask)
4485 const int *elements;
4486 msurface_t *surface;
4487 model_t *model = ent->model;
4490 GL_DepthRange(0, 1);
4491 GL_DepthTest(!r_showdisabledepthtest.integer);
4493 GL_BlendFunc(GL_ONE, GL_ZERO);
4494 R_Mesh_ColorPointer(NULL, 0, 0);
4495 R_Mesh_ResetTextureState();
4496 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
4498 if (ent == r_refdef.worldentity && !r_viewcache.world_surfacevisible[j])
4500 rsurface_texture = surface->texture->currentframe;
4501 if ((rsurface_texture->currentmaterialflags & flagsmask) && surface->num_triangles)
4503 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
4506 if (!rsurface_texture->currentlayers->depthmask)
4507 GL_Color(r_showtris.value * r_view.colorscale, 0, 0, 1);
4508 else if (ent == r_refdef.worldentity)
4509 GL_Color(r_showtris.value * r_view.colorscale, r_showtris.value * r_view.colorscale, r_showtris.value * r_view.colorscale, 1);
4511 GL_Color(0, r_showtris.value * r_view.colorscale, 0, 1);
4512 elements = (ent->model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
4515 for (k = 0;k < surface->num_triangles;k++, elements += 3)
4517 #define GLVERTEXELEMENT(n) qglVertex3f(rsurface_vertex3f[elements[n]*3+0], rsurface_vertex3f[elements[n]*3+1], rsurface_vertex3f[elements[n]*3+2])
4518 GLVERTEXELEMENT(0);GLVERTEXELEMENT(1);
4519 GLVERTEXELEMENT(1);GLVERTEXELEMENT(2);
4520 GLVERTEXELEMENT(2);GLVERTEXELEMENT(0);
4527 GL_Color(r_shownormals.value * r_view.colorscale, 0, 0, 1);
4529 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
4531 VectorCopy(rsurface_vertex3f + l * 3, v);
4532 qglVertex3f(v[0], v[1], v[2]);
4533 VectorMA(v, 8, rsurface_svector3f + l * 3, v);
4534 qglVertex3f(v[0], v[1], v[2]);
4538 GL_Color(0, 0, r_shownormals.value * r_view.colorscale, 1);
4540 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
4542 VectorCopy(rsurface_vertex3f + l * 3, v);
4543 qglVertex3f(v[0], v[1], v[2]);
4544 VectorMA(v, 8, rsurface_tvector3f + l * 3, v);
4545 qglVertex3f(v[0], v[1], v[2]);
4549 GL_Color(0, r_shownormals.value * r_view.colorscale, 0, 1);
4551 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
4553 VectorCopy(rsurface_vertex3f + l * 3, v);
4554 qglVertex3f(v[0], v[1], v[2]);
4555 VectorMA(v, 8, rsurface_normal3f + l * 3, v);
4556 qglVertex3f(v[0], v[1], v[2]);
4563 rsurface_texture = NULL;
4566 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
4567 void R_DrawWorldSurfaces(qboolean skysurfaces)
4569 int i, j, endj, f, flagsmask;
4570 int counttriangles = 0;
4571 msurface_t *surface, **surfacechain;
4573 model_t *model = r_refdef.worldmodel;
4574 const int maxsurfacelist = 1024;
4575 int numsurfacelist = 0;
4576 msurface_t *surfacelist[1024];
4580 RSurf_ActiveWorldEntity();
4582 // update light styles
4583 if (!skysurfaces && model->brushq1.light_styleupdatechains)
4585 for (i = 0;i < model->brushq1.light_styles;i++)
4587 if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
4589 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
4590 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
4591 for (;(surface = *surfacechain);surfacechain++)
4592 surface->cached_dlight = true;
4597 R_UpdateAllTextureInfo(r_refdef.worldentity);
4598 flagsmask = skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL);
4601 rsurface_lightmaptexture = NULL;
4602 rsurface_deluxemaptexture = NULL;
4603 rsurface_texture = NULL;
4605 j = model->firstmodelsurface;
4606 endj = j + model->nummodelsurfaces;
4609 // quickly skip over non-visible surfaces
4610 for (;j < endj && !r_viewcache.world_surfacevisible[j];j++)
4612 // quickly iterate over visible surfaces
4613 for (;j < endj && r_viewcache.world_surfacevisible[j];j++)
4615 // process this surface
4616 surface = model->data_surfaces + j;
4617 // if this surface fits the criteria, add it to the list
4618 if (surface->num_triangles)
4620 // if lightmap parameters changed, rebuild lightmap texture
4621 if (surface->cached_dlight)
4622 R_BuildLightMap(r_refdef.worldentity, surface);
4623 // add face to draw list
4624 surfacelist[numsurfacelist++] = surface;
4625 counttriangles += surface->num_triangles;
4626 if (numsurfacelist >= maxsurfacelist)
4628 R_QueueSurfaceList(numsurfacelist, surfacelist, flagsmask);
4635 R_QueueSurfaceList(numsurfacelist, surfacelist, flagsmask);
4636 r_refdef.stats.entities_triangles += counttriangles;
4639 if (r_showcollisionbrushes.integer && !skysurfaces)
4640 R_DrawCollisionBrushes(r_refdef.worldentity);
4642 if (r_showtris.integer || r_shownormals.integer)
4643 R_DrawTrianglesAndNormals(r_refdef.worldentity, r_showtris.integer, r_shownormals.integer, flagsmask);
4646 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces)
4648 int i, f, flagsmask;
4649 int counttriangles = 0;
4650 msurface_t *surface, *endsurface, **surfacechain;
4652 model_t *model = ent->model;
4653 const int maxsurfacelist = 1024;
4654 int numsurfacelist = 0;
4655 msurface_t *surfacelist[1024];
4659 // if the model is static it doesn't matter what value we give for
4660 // wantnormals and wanttangents, so this logic uses only rules applicable
4661 // to a model, knowing that they are meaningless otherwise
4662 if (ent == r_refdef.worldentity)
4663 RSurf_ActiveWorldEntity();
4664 else if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
4665 RSurf_ActiveModelEntity(ent, false, false);
4667 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
4669 // update light styles
4670 if (!skysurfaces && model->brushq1.light_styleupdatechains)
4672 for (i = 0;i < model->brushq1.light_styles;i++)
4674 if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
4676 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
4677 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
4678 for (;(surface = *surfacechain);surfacechain++)
4679 surface->cached_dlight = true;
4684 R_UpdateAllTextureInfo(ent);
4685 flagsmask = skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL);
4688 rsurface_lightmaptexture = NULL;
4689 rsurface_deluxemaptexture = NULL;
4690 rsurface_texture = NULL;
4692 surface = model->data_surfaces + model->firstmodelsurface;
4693 endsurface = surface + model->nummodelsurfaces;
4694 for (;surface < endsurface;surface++)
4696 // if this surface fits the criteria, add it to the list
4697 if (surface->num_triangles)
4699 // if lightmap parameters changed, rebuild lightmap texture
4700 if (surface->cached_dlight)
4701 R_BuildLightMap(ent, surface);
4702 // add face to draw list
4703 surfacelist[numsurfacelist++] = surface;
4704 counttriangles += surface->num_triangles;
4705 if (numsurfacelist >= maxsurfacelist)
4707 R_QueueSurfaceList(numsurfacelist, surfacelist, flagsmask);
4713 R_QueueSurfaceList(numsurfacelist, surfacelist, flagsmask);
4714 r_refdef.stats.entities_triangles += counttriangles;
4717 if (r_showcollisionbrushes.integer && !skysurfaces)
4718 R_DrawCollisionBrushes(ent);
4720 if (r_showtris.integer || r_shownormals.integer)
4721 R_DrawTrianglesAndNormals(ent, r_showtris.integer, r_shownormals.integer, flagsmask);