2 Copyright (C) 1996-1997 Id Software, Inc.
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26 mempool_t *r_main_mempool;
27 rtexturepool_t *r_main_texturepool;
34 r_viewcache_t r_viewcache;
36 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
37 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
38 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
39 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
40 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
41 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
42 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
43 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
44 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
45 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
46 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
47 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
48 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
49 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
50 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling"};
51 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
52 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
53 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
54 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
55 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
56 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
57 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
58 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this)"};
59 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
60 cvar_t r_q1bsp_skymasking = {0, "r_qb1sp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
62 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
63 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
64 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
65 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
66 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
67 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
68 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
70 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of hardware texture units reported by driver (note: setting this to 1 turns off gl_combine)"};
72 cvar_t r_glsl = {CVAR_SAVE, "r_glsl", "1", "enables use of OpenGL 2.0 pixel shaders for lighting"};
73 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
74 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
75 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
76 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)"};
78 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1", "enables animation smoothing on sprites (requires r_lerpmodels 1)"};
79 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
80 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
82 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
83 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
84 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
85 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
86 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
87 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
88 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
90 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
91 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
92 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
93 cvar_t r_hdr_range = {CVAR_SAVE, "r_hdr_range", "4", "how much dynamic range to render bloom with (equivilant to multiplying r_bloom_brighten by this value and dividing r_bloom_colorscale by this value)"};
95 cvar_t r_smoothnormals_areaweighting = {0, "r_smoothnormals_areaweighting", "1", "uses significantly faster (and supposedly higher quality) area-weighted vertex normals and tangent vectors rather than summing normalized triangle normals and tangents"};
97 cvar_t developer_texturelogging = {0, "developer_texturelogging", "0", "produces a textures.log file containing names of skins and map textures the engine tried to load"};
99 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
101 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
102 cvar_t r_batchmode = {0, "r_batchmode", "1", "selects method of rendering multiple surfaces with one driver call (values are 0, 1, 2, etc...)"};
104 typedef struct r_glsl_bloomshader_s
107 int loc_Texture_Bloom;
109 r_glsl_bloomshader_t;
111 static struct r_bloomstate_s
116 int bloomwidth, bloomheight;
118 int screentexturewidth, screentextureheight;
119 rtexture_t *texture_screen;
121 int bloomtexturewidth, bloomtextureheight;
122 rtexture_t *texture_bloom;
124 r_glsl_bloomshader_t *shader;
126 // arrays for rendering the screen passes
127 float screentexcoord2f[8];
128 float bloomtexcoord2f[8];
129 float offsettexcoord2f[8];
133 // shadow volume bsp struct with automatically growing nodes buffer
136 rtexture_t *r_texture_blanknormalmap;
137 rtexture_t *r_texture_white;
138 rtexture_t *r_texture_black;
139 rtexture_t *r_texture_notexture;
140 rtexture_t *r_texture_whitecube;
141 rtexture_t *r_texture_normalizationcube;
142 rtexture_t *r_texture_fogattenuation;
143 //rtexture_t *r_texture_fogintensity;
145 // information about each possible shader permutation
146 r_glsl_permutation_t r_glsl_permutations[SHADERPERMUTATION_MAX];
147 // currently selected permutation
148 r_glsl_permutation_t *r_glsl_permutation;
150 // vertex coordinates for a quad that covers the screen exactly
151 const static float r_screenvertex3f[12] =
159 extern void R_DrawModelShadows(void);
161 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
164 for (i = 0;i < verts;i++)
175 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
178 for (i = 0;i < verts;i++)
188 // FIXME: move this to client?
191 if (gamemode == GAME_NEHAHRA)
193 Cvar_Set("gl_fogenable", "0");
194 Cvar_Set("gl_fogdensity", "0.2");
195 Cvar_Set("gl_fogred", "0.3");
196 Cvar_Set("gl_foggreen", "0.3");
197 Cvar_Set("gl_fogblue", "0.3");
199 r_refdef.fog_density = r_refdef.fog_red = r_refdef.fog_green = r_refdef.fog_blue = 0.0f;
202 // FIXME: move this to client?
203 void FOG_registercvars(void)
208 if (gamemode == GAME_NEHAHRA)
210 Cvar_RegisterVariable (&gl_fogenable);
211 Cvar_RegisterVariable (&gl_fogdensity);
212 Cvar_RegisterVariable (&gl_fogred);
213 Cvar_RegisterVariable (&gl_foggreen);
214 Cvar_RegisterVariable (&gl_fogblue);
215 Cvar_RegisterVariable (&gl_fogstart);
216 Cvar_RegisterVariable (&gl_fogend);
219 r = (-1.0/256.0) * (FOGTABLEWIDTH * FOGTABLEWIDTH);
220 for (x = 0;x < FOGTABLEWIDTH;x++)
222 alpha = exp(r / ((double)x*(double)x));
223 if (x == FOGTABLEWIDTH - 1)
225 r_refdef.fogtable[x] = bound(0, alpha, 1);
229 static void R_BuildBlankTextures(void)
231 unsigned char data[4];
232 data[0] = 128; // normal X
233 data[1] = 128; // normal Y
234 data[2] = 255; // normal Z
235 data[3] = 128; // height
236 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
241 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
246 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
249 static void R_BuildNoTexture(void)
252 unsigned char pix[16][16][4];
253 // this makes a light grey/dark grey checkerboard texture
254 for (y = 0;y < 16;y++)
256 for (x = 0;x < 16;x++)
258 if ((y < 8) ^ (x < 8))
274 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_RGBA, TEXF_MIPMAP, NULL);
277 static void R_BuildWhiteCube(void)
279 unsigned char data[6*1*1*4];
280 data[ 0] = 255;data[ 1] = 255;data[ 2] = 255;data[ 3] = 255;
281 data[ 4] = 255;data[ 5] = 255;data[ 6] = 255;data[ 7] = 255;
282 data[ 8] = 255;data[ 9] = 255;data[10] = 255;data[11] = 255;
283 data[12] = 255;data[13] = 255;data[14] = 255;data[15] = 255;
284 data[16] = 255;data[17] = 255;data[18] = 255;data[19] = 255;
285 data[20] = 255;data[21] = 255;data[22] = 255;data[23] = 255;
286 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
289 static void R_BuildNormalizationCube(void)
293 vec_t s, t, intensity;
295 unsigned char data[6][NORMSIZE][NORMSIZE][4];
296 for (side = 0;side < 6;side++)
298 for (y = 0;y < NORMSIZE;y++)
300 for (x = 0;x < NORMSIZE;x++)
302 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
303 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
338 intensity = 127.0f / sqrt(DotProduct(v, v));
339 data[side][y][x][0] = (unsigned char)(128.0f + intensity * v[0]);
340 data[side][y][x][1] = (unsigned char)(128.0f + intensity * v[1]);
341 data[side][y][x][2] = (unsigned char)(128.0f + intensity * v[2]);
342 data[side][y][x][3] = 255;
346 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, &data[0][0][0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
349 static void R_BuildFogTexture(void)
354 unsigned char data1[FOGWIDTH][4];
355 //unsigned char data2[FOGWIDTH][4];
356 r = (-1.0/256.0) * (FOGWIDTH * FOGWIDTH);
357 for (x = 0;x < FOGWIDTH;x++)
359 alpha = exp(r / ((double)x*(double)x));
360 if (x == FOGWIDTH - 1)
362 b = (int)(256.0 * alpha);
363 b = bound(0, b, 255);
364 data1[x][0] = 255 - b;
365 data1[x][1] = 255 - b;
366 data1[x][2] = 255 - b;
373 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
374 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
377 static const char *builtinshaderstring =
378 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
379 "// written by Forest 'LordHavoc' Hale\n"
381 "// common definitions between vertex shader and fragment shader:\n"
383 "#ifdef __GLSL_CG_DATA_TYPES\n"
384 "#define myhalf half\n"
385 "#define myhvec2 hvec2\n"
386 "#define myhvec3 hvec3\n"
387 "#define myhvec4 hvec4\n"
389 "#define myhalf float\n"
390 "#define myhvec2 vec2\n"
391 "#define myhvec3 vec3\n"
392 "#define myhvec4 vec4\n"
395 "varying vec2 TexCoord;\n"
396 "varying vec2 TexCoordLightmap;\n"
398 "varying vec3 CubeVector;\n"
399 "varying vec3 LightVector;\n"
400 "varying vec3 EyeVector;\n"
402 "varying vec3 EyeVectorModelSpace;\n"
405 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
406 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
407 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
412 "// vertex shader specific:\n"
413 "#ifdef VERTEX_SHADER\n"
415 "uniform vec3 LightPosition;\n"
416 "uniform vec3 EyePosition;\n"
417 "uniform vec3 LightDir;\n"
419 "// TODO: get rid of tangentt (texcoord2) and use a crossproduct to regenerate it from tangents (texcoord1) and normal (texcoord3)\n"
423 " gl_FrontColor = gl_Color;\n"
424 " // copy the surface texcoord\n"
425 " TexCoord = vec2(gl_TextureMatrix[0] * gl_MultiTexCoord0);\n"
426 "#if !defined(MODE_LIGHTSOURCE) && !defined(MODE_LIGHTDIRECTION)\n"
427 " TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
430 "#ifdef MODE_LIGHTSOURCE\n"
431 " // transform vertex position into light attenuation/cubemap space\n"
432 " // (-1 to +1 across the light box)\n"
433 " CubeVector = vec3(gl_TextureMatrix[3] * gl_Vertex);\n"
435 " // transform unnormalized light direction into tangent space\n"
436 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
437 " // normalize it per pixel)\n"
438 " vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
439 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
440 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
441 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
444 "#ifdef MODE_LIGHTDIRECTION\n"
445 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
446 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
447 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
450 " // transform unnormalized eye direction into tangent space\n"
452 " vec3 EyeVectorModelSpace;\n"
454 " EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
455 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
456 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
457 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
459 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
460 " VectorS = gl_MultiTexCoord1.xyz;\n"
461 " VectorT = gl_MultiTexCoord2.xyz;\n"
462 " VectorR = gl_MultiTexCoord3.xyz;\n"
465 " // transform vertex to camera space, using ftransform to match non-VS\n"
467 " gl_Position = ftransform();\n"
470 "#endif // VERTEX_SHADER\n"
475 "// fragment shader specific:\n"
476 "#ifdef FRAGMENT_SHADER\n"
478 "// 11 textures, we can only use up to 16 on DX9-class hardware\n"
479 "uniform sampler2D Texture_Normal;\n"
480 "uniform sampler2D Texture_Color;\n"
481 "uniform sampler2D Texture_Gloss;\n"
482 "uniform samplerCube Texture_Cube;\n"
483 "uniform sampler2D Texture_Attenuation;\n"
484 "uniform sampler2D Texture_FogMask;\n"
485 "uniform sampler2D Texture_Pants;\n"
486 "uniform sampler2D Texture_Shirt;\n"
487 "uniform sampler2D Texture_Lightmap;\n"
488 "uniform sampler2D Texture_Deluxemap;\n"
489 "uniform sampler2D Texture_Glow;\n"
491 "uniform myhvec3 LightColor;\n"
492 "uniform myhvec3 AmbientColor;\n"
493 "uniform myhvec3 DiffuseColor;\n"
494 "uniform myhvec3 SpecularColor;\n"
495 "uniform myhvec3 Color_Pants;\n"
496 "uniform myhvec3 Color_Shirt;\n"
497 "uniform myhvec3 FogColor;\n"
499 "uniform myhalf GlowScale;\n"
500 "uniform myhalf SceneBrightness;\n"
502 "uniform float OffsetMapping_Scale;\n"
503 "uniform float OffsetMapping_Bias;\n"
504 "uniform float FogRangeRecip;\n"
506 "uniform myhalf AmbientScale;\n"
507 "uniform myhalf DiffuseScale;\n"
508 "uniform myhalf SpecularScale;\n"
509 "uniform myhalf SpecularPower;\n"
511 "#ifdef USEOFFSETMAPPING\n"
512 "vec2 OffsetMapping(vec2 TexCoord)\n"
514 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
515 " // 14 sample relief mapping: linear search and then binary search\n"
516 " // this basically steps forward a small amount repeatedly until it finds\n"
517 " // itself inside solid, then jitters forward and back using decreasing\n"
518 " // amounts to find the impact\n"
519 " //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
520 " //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
521 " vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
522 " vec3 RT = vec3(TexCoord, 1);\n"
523 " OffsetVector *= 0.1;\n"
524 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
525 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
526 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
527 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
528 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
529 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
530 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
531 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
532 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
533 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) - 0.5);\n"
534 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5 - 0.25);\n"
535 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25 - 0.125);\n"
536 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125 - 0.0625);\n"
537 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
540 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
541 " // this basically moves forward the full distance, and then backs up based\n"
542 " // on height of samples\n"
543 " //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
544 " //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
545 " vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
546 " TexCoord += OffsetVector;\n"
547 " OffsetVector *= 0.333;\n"
548 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
549 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
550 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
551 " return TexCoord;\n"
558 "#ifdef USEOFFSETMAPPING\n"
559 " // apply offsetmapping\n"
560 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
561 "#define TexCoord TexCoordOffset\n"
564 " // combine the diffuse textures (base, pants, shirt)\n"
565 " myhvec4 color = myhvec4(texture2D(Texture_Color, TexCoord));\n"
566 "#ifdef USECOLORMAPPING\n"
567 " color.rgb += myhvec3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhvec3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
573 "#ifdef MODE_LIGHTSOURCE\n"
576 " // calculate surface normal, light normal, and specular normal\n"
577 " // compute color intensity for the two textures (colormap and glossmap)\n"
578 " // scale by light color and attenuation as efficiently as possible\n"
579 " // (do as much scalar math as possible rather than vector math)\n"
580 "#ifdef USESPECULAR\n"
581 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
582 " myhvec3 diffusenormal = myhvec3(normalize(LightVector));\n"
583 " myhvec3 specularnormal = normalize(diffusenormal + myhvec3(normalize(EyeVector)));\n"
585 " // calculate directional shading\n"
586 " 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"
588 "#ifdef USEDIFFUSE\n"
589 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
590 " myhvec3 diffusenormal = myhvec3(normalize(LightVector));\n"
592 " // calculate directional shading\n"
593 " 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"
595 " // calculate directionless shading\n"
596 " color.rgb = color.rgb * LightColor * myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
600 "#ifdef USECUBEFILTER\n"
601 " // apply light cubemap filter\n"
602 " //color.rgb *= normalize(CubeVector) * 0.5 + 0.5;//vec3(textureCube(Texture_Cube, CubeVector));\n"
603 " color.rgb *= myhvec3(textureCube(Texture_Cube, CubeVector));\n"
609 "#elif defined(MODE_LIGHTDIRECTION)\n"
610 " // directional model lighting\n"
612 " // get the surface normal and light normal\n"
613 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
614 " myhvec3 diffusenormal = myhvec3(normalize(LightVector));\n"
616 " // calculate directional shading\n"
617 " color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
618 "#ifdef USESPECULAR\n"
619 " myhvec3 specularnormal = normalize(diffusenormal + myhvec3(normalize(EyeVector)));\n"
620 " color.rgb += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
626 "#elif defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
627 " // deluxemap lightmapping using light vectors in modelspace (evil q3map2)\n"
629 " // get the surface normal and light normal\n"
630 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
632 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
633 " myhvec3 diffusenormal_modelspace = myhvec3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - myhvec3(0.5);\n"
634 " myhvec3 diffusenormal = normalize(myhvec3(dot(diffusenormal_modelspace, myhvec3(VectorS)), dot(diffusenormal_modelspace, myhvec3(VectorT)), dot(diffusenormal_modelspace, myhvec3(VectorR))));\n"
636 " myhvec3 diffusenormal = normalize(myhvec3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - myhvec3(0.5));\n"
638 " // calculate directional shading\n"
639 " myhvec3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0)));\n"
640 "#ifdef USESPECULAR\n"
641 " myhvec3 specularnormal = myhvec3(normalize(diffusenormal + myhvec3(normalize(EyeVector))));\n"
642 " tempcolor += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
645 " // apply lightmap color\n"
646 " color.rgb = tempcolor * myhvec3(texture2D(Texture_Lightmap, TexCoordLightmap)) + color.rgb * AmbientScale;\n"
649 "#else // MODE none (lightmap)\n"
650 " // apply lightmap color\n"
651 " color.rgb *= myhvec3(texture2D(Texture_Lightmap, TexCoordLightmap)) * DiffuseScale + myhvec3(AmbientScale);\n"
654 " color *= myhvec4(gl_Color);\n"
657 " color.rgb += myhvec3(texture2D(Texture_Glow, TexCoord)) * GlowScale;\n"
662 " color.rgb = mix(FogColor, color.rgb, myhalf(texture2D(Texture_FogMask, myhvec2(length(EyeVectorModelSpace)*FogRangeRecip, 0.0))));\n"
665 " color.rgb *= SceneBrightness;\n"
667 " gl_FragColor = vec4(color);\n"
670 "#endif // FRAGMENT_SHADER\n"
673 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
674 const char *permutationinfo[][2] =
676 {"#define MODE_LIGHTSOURCE\n", " lightsource"},
677 {"#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
678 {"#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
679 {"#define MODE_LIGHTDIRECTION\n", " lightdirection"},
680 {"#define USEGLOW\n", " glow"},
681 {"#define USEFOG\n", " fog"},
682 {"#define USECOLORMAPPING\n", " colormapping"},
683 {"#define USEDIFFUSE\n", " diffuse"},
684 {"#define USESPECULAR\n", " specular"},
685 {"#define USECUBEFILTER\n", " cubefilter"},
686 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
687 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
691 void R_GLSL_CompilePermutation(const char *filename, int permutation)
694 qboolean shaderfound;
695 r_glsl_permutation_t *p = r_glsl_permutations + (permutation & SHADERPERMUTATION_MASK);
696 int vertstrings_count;
697 int geomstrings_count;
698 int fragstrings_count;
700 const char *vertstrings_list[32+1];
701 const char *geomstrings_list[32+1];
702 const char *fragstrings_list[32+1];
703 char permutationname[256];
708 vertstrings_list[0] = "#define VERTEX_SHADER\n";
709 geomstrings_list[0] = "#define GEOMETRY_SHADER\n";
710 fragstrings_list[0] = "#define FRAGMENT_SHADER\n";
711 vertstrings_count = 1;
712 geomstrings_count = 1;
713 fragstrings_count = 1;
714 permutationname[0] = 0;
715 for (i = 0;permutationinfo[i][0];i++)
717 if (permutation & (1<<i))
719 vertstrings_list[vertstrings_count++] = permutationinfo[i][0];
720 geomstrings_list[geomstrings_count++] = permutationinfo[i][0];
721 fragstrings_list[fragstrings_count++] = permutationinfo[i][0];
722 strlcat(permutationname, permutationinfo[i][1], sizeof(permutationname));
726 // keep line numbers correct
727 vertstrings_list[vertstrings_count++] = "\n";
728 geomstrings_list[geomstrings_count++] = "\n";
729 fragstrings_list[fragstrings_count++] = "\n";
732 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
736 Con_DPrintf("GLSL shader text for \"%s\" loaded from disk\n", filename);
737 vertstrings_list[vertstrings_count++] = shaderstring;
738 geomstrings_list[geomstrings_count++] = shaderstring;
739 fragstrings_list[fragstrings_count++] = shaderstring;
742 else if (!strcmp(filename, "glsl/default.glsl"))
744 Con_DPrintf("GLSL shader text for \"%s\" loaded from engine\n", filename);
745 vertstrings_list[vertstrings_count++] = builtinshaderstring;
746 geomstrings_list[geomstrings_count++] = builtinshaderstring;
747 fragstrings_list[fragstrings_count++] = builtinshaderstring;
750 // clear any lists that are not needed by this shader
751 if (!(permutation & SHADERPERMUTATION_USES_VERTEXSHADER))
752 vertstrings_count = 0;
753 if (!(permutation & SHADERPERMUTATION_USES_GEOMETRYSHADER))
754 geomstrings_count = 0;
755 if (!(permutation & SHADERPERMUTATION_USES_FRAGMENTSHADER))
756 fragstrings_count = 0;
757 // compile the shader program
758 if (shaderfound && vertstrings_count + geomstrings_count + fragstrings_count)
759 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
763 qglUseProgramObjectARB(p->program);CHECKGLERROR
764 // look up all the uniform variable names we care about, so we don't
765 // have to look them up every time we set them
766 p->loc_Texture_Normal = qglGetUniformLocationARB(p->program, "Texture_Normal");
767 p->loc_Texture_Color = qglGetUniformLocationARB(p->program, "Texture_Color");
768 p->loc_Texture_Gloss = qglGetUniformLocationARB(p->program, "Texture_Gloss");
769 p->loc_Texture_Cube = qglGetUniformLocationARB(p->program, "Texture_Cube");
770 p->loc_Texture_Attenuation = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
771 p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
772 p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
773 p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
774 p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
775 p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
776 p->loc_Texture_Glow = qglGetUniformLocationARB(p->program, "Texture_Glow");
777 p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
778 p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
779 p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
780 p->loc_LightColor = qglGetUniformLocationARB(p->program, "LightColor");
781 p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants");
782 p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt");
783 p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip");
784 p->loc_AmbientScale = qglGetUniformLocationARB(p->program, "AmbientScale");
785 p->loc_DiffuseScale = qglGetUniformLocationARB(p->program, "DiffuseScale");
786 p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
787 p->loc_SpecularScale = qglGetUniformLocationARB(p->program, "SpecularScale");
788 p->loc_GlowScale = qglGetUniformLocationARB(p->program, "GlowScale");
789 p->loc_SceneBrightness = qglGetUniformLocationARB(p->program, "SceneBrightness");
790 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
791 p->loc_AmbientColor = qglGetUniformLocationARB(p->program, "AmbientColor");
792 p->loc_DiffuseColor = qglGetUniformLocationARB(p->program, "DiffuseColor");
793 p->loc_SpecularColor = qglGetUniformLocationARB(p->program, "SpecularColor");
794 p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
795 // initialize the samplers to refer to the texture units we use
796 if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal, 0);
797 if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color, 1);
798 if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss, 2);
799 if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube, 3);
800 if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask, 4);
801 if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants, 5);
802 if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt, 6);
803 if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap, 7);
804 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap, 8);
805 if (p->loc_Texture_Glow >= 0) qglUniform1iARB(p->loc_Texture_Glow, 9);
806 if (p->loc_Texture_Attenuation >= 0) qglUniform1iARB(p->loc_Texture_Attenuation, 10);
808 qglUseProgramObjectARB(0);CHECKGLERROR
811 Con_Printf("permutation%s failed for shader %s, some features may not work properly!\n", permutationname, "glsl/default.glsl");
813 Mem_Free(shaderstring);
816 void R_GLSL_Restart_f(void)
819 for (i = 0;i < SHADERPERMUTATION_MAX;i++)
820 if (r_glsl_permutations[i].program)
821 GL_Backend_FreeProgram(r_glsl_permutations[i].program);
822 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
825 extern rtexture_t *r_shadow_attenuationgradienttexture;
826 extern rtexture_t *r_shadow_attenuation2dtexture;
827 extern rtexture_t *r_shadow_attenuation3dtexture;
828 int R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale)
830 // select a permutation of the lighting shader appropriate to this
831 // combination of texture, entity, light source, and fogging, only use the
832 // minimum features necessary to avoid wasting rendering time in the
833 // fragment shader on features that are not being used
834 const char *shaderfilename = NULL;
835 unsigned int permutation = 0;
836 r_glsl_permutation = NULL;
837 // TODO: implement geometry-shader based shadow volumes someday
838 if (r_shadow_rtlight)
841 shaderfilename = "glsl/default.glsl";
842 permutation = SHADERPERMUTATION_MODE_LIGHTSOURCE | SHADERPERMUTATION_USES_VERTEXSHADER | SHADERPERMUTATION_USES_FRAGMENTSHADER;
843 if (r_shadow_rtlight->currentcubemap != r_texture_whitecube)
844 permutation |= SHADERPERMUTATION_CUBEFILTER;
845 if (diffusescale > 0)
846 permutation |= SHADERPERMUTATION_DIFFUSE;
847 if (specularscale > 0)
848 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
849 if (r_refdef.fogenabled)
850 permutation |= SHADERPERMUTATION_FOG;
851 if (rsurface_texture->colormapping)
852 permutation |= SHADERPERMUTATION_COLORMAPPING;
853 if (r_glsl_offsetmapping.integer)
855 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
856 if (r_glsl_offsetmapping_reliefmapping.integer)
857 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
860 else if (rsurface_texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
862 // bright unshaded geometry
863 shaderfilename = "glsl/default.glsl";
864 permutation = SHADERPERMUTATION_USES_VERTEXSHADER | SHADERPERMUTATION_USES_FRAGMENTSHADER;
865 if (rsurface_texture->currentskinframe->glow)
866 permutation |= SHADERPERMUTATION_GLOW;
867 if (r_refdef.fogenabled)
868 permutation |= SHADERPERMUTATION_FOG;
869 if (rsurface_texture->colormapping)
870 permutation |= SHADERPERMUTATION_COLORMAPPING;
871 if (r_glsl_offsetmapping.integer)
873 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
874 if (r_glsl_offsetmapping_reliefmapping.integer)
875 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
878 else if (modellighting)
880 // directional model lighting
881 shaderfilename = "glsl/default.glsl";
882 permutation = SHADERPERMUTATION_USES_VERTEXSHADER | SHADERPERMUTATION_USES_FRAGMENTSHADER;
883 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTION;
884 if (rsurface_texture->currentskinframe->glow)
885 permutation |= SHADERPERMUTATION_GLOW;
886 if (specularscale > 0)
887 permutation |= SHADERPERMUTATION_SPECULAR;
888 if (r_refdef.fogenabled)
889 permutation |= SHADERPERMUTATION_FOG;
890 if (rsurface_texture->colormapping)
891 permutation |= SHADERPERMUTATION_COLORMAPPING;
892 if (r_glsl_offsetmapping.integer)
894 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
895 if (r_glsl_offsetmapping_reliefmapping.integer)
896 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
902 shaderfilename = "glsl/default.glsl";
903 permutation = SHADERPERMUTATION_USES_VERTEXSHADER | SHADERPERMUTATION_USES_FRAGMENTSHADER;
904 if (r_glsl_deluxemapping.integer >= 1 && rsurface_uselightmaptexture && r_refdef.worldmodel && r_refdef.worldmodel->brushq3.deluxemapping)
906 // deluxemapping (light direction texture)
907 if (rsurface_uselightmaptexture && r_refdef.worldmodel && r_refdef.worldmodel->brushq3.deluxemapping && r_refdef.worldmodel->brushq3.deluxemapping_modelspace)
908 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_MODELSPACE;
910 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
911 if (specularscale > 0)
912 permutation |= SHADERPERMUTATION_SPECULAR;
914 else if (r_glsl_deluxemapping.integer >= 2)
916 // fake deluxemapping (uniform light direction in tangentspace)
917 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
918 if (specularscale > 0)
919 permutation |= SHADERPERMUTATION_SPECULAR;
923 // ordinary lightmapping
926 if (rsurface_texture->currentskinframe->glow)
927 permutation |= SHADERPERMUTATION_GLOW;
928 if (r_refdef.fogenabled)
929 permutation |= SHADERPERMUTATION_FOG;
930 if (rsurface_texture->colormapping)
931 permutation |= SHADERPERMUTATION_COLORMAPPING;
932 if (r_glsl_offsetmapping.integer)
934 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
935 if (r_glsl_offsetmapping_reliefmapping.integer)
936 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
939 if (!r_glsl_permutations[permutation & SHADERPERMUTATION_MASK].program)
941 if (!r_glsl_permutations[permutation & SHADERPERMUTATION_MASK].compiled)
942 R_GLSL_CompilePermutation(shaderfilename, permutation);
943 if (!r_glsl_permutations[permutation & SHADERPERMUTATION_MASK].program)
945 // remove features until we find a valid permutation
947 for (i = SHADERPERMUTATION_MASK;;i>>=1)
950 return 0; // utterly failed
951 // reduce i more quickly whenever it would not remove any bits
955 if (!r_glsl_permutations[permutation & SHADERPERMUTATION_MASK].compiled)
956 R_GLSL_CompilePermutation(shaderfilename, permutation);
957 if (r_glsl_permutations[permutation & SHADERPERMUTATION_MASK].program)
962 r_glsl_permutation = r_glsl_permutations + (permutation & SHADERPERMUTATION_MASK);
964 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
965 R_Mesh_TexMatrix(0, &rsurface_texture->currenttexmatrix);
966 if (permutation & SHADERPERMUTATION_MODE_LIGHTSOURCE)
968 if (r_glsl_permutation->loc_Texture_Cube >= 0 && r_shadow_rtlight) R_Mesh_TexBindCubeMap(3, R_GetTexture(r_shadow_rtlight->currentcubemap));
969 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]);
970 if (permutation & SHADERPERMUTATION_DIFFUSE)
972 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
973 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, ambientscale);
974 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, diffusescale);
975 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, specularscale);
979 // ambient only is simpler
980 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0] * ambientscale, lightcolorbase[1] * ambientscale, lightcolorbase[2] * ambientscale);
981 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, 1);
982 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, 0);
983 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, 0);
986 else if (permutation & SHADERPERMUTATION_MODE_LIGHTDIRECTION)
988 if (r_glsl_permutation->loc_AmbientColor >= 0)
989 qglUniform3fARB(r_glsl_permutation->loc_AmbientColor, rsurface_entity->modellight_ambient[0] * ambientscale, rsurface_entity->modellight_ambient[1] * ambientscale, rsurface_entity->modellight_ambient[2] * ambientscale);
990 if (r_glsl_permutation->loc_DiffuseColor >= 0)
991 qglUniform3fARB(r_glsl_permutation->loc_DiffuseColor, rsurface_entity->modellight_diffuse[0] * diffusescale, rsurface_entity->modellight_diffuse[1] * diffusescale, rsurface_entity->modellight_diffuse[2] * diffusescale);
992 if (r_glsl_permutation->loc_SpecularColor >= 0)
993 qglUniform3fARB(r_glsl_permutation->loc_SpecularColor, rsurface_entity->modellight_diffuse[0] * specularscale, rsurface_entity->modellight_diffuse[1] * specularscale, rsurface_entity->modellight_diffuse[2] * specularscale);
994 if (r_glsl_permutation->loc_LightDir >= 0)
995 qglUniform3fARB(r_glsl_permutation->loc_LightDir, rsurface_entity->modellight_lightdir[0], rsurface_entity->modellight_lightdir[1], rsurface_entity->modellight_lightdir[2]);
999 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_ambient.value * 2.0f / 128.0f);
1000 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_refdef.lightmapintensity * 2.0f);
1001 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, r_refdef.lightmapintensity * specularscale * 2.0f);
1003 if (r_glsl_permutation->loc_Texture_Normal >= 0) R_Mesh_TexBind(0, R_GetTexture(rsurface_texture->currentskinframe->nmap));
1004 if (r_glsl_permutation->loc_Texture_Color >= 0) R_Mesh_TexBind(1, R_GetTexture(rsurface_texture->basetexture));
1005 if (r_glsl_permutation->loc_Texture_Gloss >= 0) R_Mesh_TexBind(2, R_GetTexture(rsurface_texture->glosstexture));
1006 //if (r_glsl_permutation->loc_Texture_Cube >= 0 && permutation & SHADERPERMUTATION_MODE_LIGHTSOURCE) R_Mesh_TexBindCubeMap(3, R_GetTexture(r_shadow_rtlight->currentcubemap));
1007 if (r_glsl_permutation->loc_Texture_Attenuation >= 0) R_Mesh_TexBind(10, R_GetTexture(r_shadow_attenuationgradienttexture));
1008 if (r_glsl_permutation->loc_Texture_FogMask >= 0) R_Mesh_TexBind(4, R_GetTexture(r_texture_fogattenuation));
1009 if (r_glsl_permutation->loc_Texture_Pants >= 0) R_Mesh_TexBind(5, R_GetTexture(rsurface_texture->currentskinframe->pants));
1010 if (r_glsl_permutation->loc_Texture_Shirt >= 0) R_Mesh_TexBind(6, R_GetTexture(rsurface_texture->currentskinframe->shirt));
1011 //if (r_glsl_permutation->loc_Texture_Lightmap >= 0) R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
1012 //if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
1013 if (r_glsl_permutation->loc_Texture_Glow >= 0) R_Mesh_TexBind(9, R_GetTexture(rsurface_texture->currentskinframe->glow));
1014 if (r_glsl_permutation->loc_GlowScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_GlowScale, r_hdr_glowintensity.value);
1015 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_view.colorscale);
1016 if (r_glsl_permutation->loc_FogColor >= 0)
1018 // additive passes are only darkened by fog, not tinted
1019 if (r_shadow_rtlight || (rsurface_texture->currentmaterialflags & MATERIALFLAG_ADD))
1020 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
1022 qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
1024 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface_modelorg[0], rsurface_modelorg[1], rsurface_modelorg[2]);
1025 if (r_glsl_permutation->loc_Color_Pants >= 0)
1027 if (rsurface_texture->currentskinframe->pants)
1028 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface_entity->colormap_pantscolor[0], rsurface_entity->colormap_pantscolor[1], rsurface_entity->colormap_pantscolor[2]);
1030 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
1032 if (r_glsl_permutation->loc_Color_Shirt >= 0)
1034 if (rsurface_texture->currentskinframe->shirt)
1035 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface_entity->colormap_shirtcolor[0], rsurface_entity->colormap_shirtcolor[1], rsurface_entity->colormap_shirtcolor[2]);
1037 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
1039 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, r_refdef.fograngerecip);
1040 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface_texture->specularpower);
1041 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
1046 void R_SwitchSurfaceShader(int permutation)
1048 if (r_glsl_permutation != r_glsl_permutations + (permutation & SHADERPERMUTATION_MASK))
1050 r_glsl_permutation = r_glsl_permutations + (permutation & SHADERPERMUTATION_MASK);
1052 qglUseProgramObjectARB(r_glsl_permutation->program);
1057 void gl_main_start(void)
1059 r_main_texturepool = R_AllocTexturePool();
1060 R_BuildBlankTextures();
1062 if (gl_texturecubemap)
1065 R_BuildNormalizationCube();
1067 R_BuildFogTexture();
1068 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
1069 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
1070 memset(&r_svbsp, 0, sizeof (r_svbsp));
1073 void gl_main_shutdown(void)
1076 Mem_Free(r_svbsp.nodes);
1077 memset(&r_svbsp, 0, sizeof (r_svbsp));
1078 R_FreeTexturePool(&r_main_texturepool);
1079 r_texture_blanknormalmap = NULL;
1080 r_texture_white = NULL;
1081 r_texture_black = NULL;
1082 r_texture_whitecube = NULL;
1083 r_texture_normalizationcube = NULL;
1084 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
1088 extern void CL_ParseEntityLump(char *entitystring);
1089 void gl_main_newmap(void)
1091 // FIXME: move this code to client
1093 char *entities, entname[MAX_QPATH];
1096 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
1097 l = (int)strlen(entname) - 4;
1098 if (l >= 0 && !strcmp(entname + l, ".bsp"))
1100 memcpy(entname + l, ".ent", 5);
1101 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
1103 CL_ParseEntityLump(entities);
1108 if (cl.worldmodel->brush.entities)
1109 CL_ParseEntityLump(cl.worldmodel->brush.entities);
1113 void GL_Main_Init(void)
1115 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
1117 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
1118 FOG_registercvars(); // FIXME: move this fog stuff to client?
1119 Cvar_RegisterVariable(&r_nearclip);
1120 Cvar_RegisterVariable(&r_showsurfaces);
1121 Cvar_RegisterVariable(&r_showtris);
1122 Cvar_RegisterVariable(&r_shownormals);
1123 Cvar_RegisterVariable(&r_showlighting);
1124 Cvar_RegisterVariable(&r_showshadowvolumes);
1125 Cvar_RegisterVariable(&r_showcollisionbrushes);
1126 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
1127 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
1128 Cvar_RegisterVariable(&r_showdisabledepthtest);
1129 Cvar_RegisterVariable(&r_drawportals);
1130 Cvar_RegisterVariable(&r_drawentities);
1131 Cvar_RegisterVariable(&r_cullentities_trace);
1132 Cvar_RegisterVariable(&r_cullentities_trace_samples);
1133 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
1134 Cvar_RegisterVariable(&r_cullentities_trace_delay);
1135 Cvar_RegisterVariable(&r_drawviewmodel);
1136 Cvar_RegisterVariable(&r_speeds);
1137 Cvar_RegisterVariable(&r_fullbrights);
1138 Cvar_RegisterVariable(&r_wateralpha);
1139 Cvar_RegisterVariable(&r_dynamic);
1140 Cvar_RegisterVariable(&r_fullbright);
1141 Cvar_RegisterVariable(&r_shadows);
1142 Cvar_RegisterVariable(&r_shadows_throwdistance);
1143 Cvar_RegisterVariable(&r_q1bsp_skymasking);
1144 Cvar_RegisterVariable(&r_textureunits);
1145 Cvar_RegisterVariable(&r_glsl);
1146 Cvar_RegisterVariable(&r_glsl_offsetmapping);
1147 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
1148 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
1149 Cvar_RegisterVariable(&r_glsl_deluxemapping);
1150 Cvar_RegisterVariable(&r_lerpsprites);
1151 Cvar_RegisterVariable(&r_lerpmodels);
1152 Cvar_RegisterVariable(&r_waterscroll);
1153 Cvar_RegisterVariable(&r_bloom);
1154 Cvar_RegisterVariable(&r_bloom_colorscale);
1155 Cvar_RegisterVariable(&r_bloom_brighten);
1156 Cvar_RegisterVariable(&r_bloom_blur);
1157 Cvar_RegisterVariable(&r_bloom_resolution);
1158 Cvar_RegisterVariable(&r_bloom_colorexponent);
1159 Cvar_RegisterVariable(&r_bloom_colorsubtract);
1160 Cvar_RegisterVariable(&r_hdr);
1161 Cvar_RegisterVariable(&r_hdr_scenebrightness);
1162 Cvar_RegisterVariable(&r_hdr_glowintensity);
1163 Cvar_RegisterVariable(&r_hdr_range);
1164 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
1165 Cvar_RegisterVariable(&developer_texturelogging);
1166 Cvar_RegisterVariable(&gl_lightmaps);
1167 Cvar_RegisterVariable(&r_test);
1168 Cvar_RegisterVariable(&r_batchmode);
1169 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
1170 Cvar_SetValue("r_fullbrights", 0);
1171 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
1174 extern void R_Textures_Init(void);
1175 extern void GL_Draw_Init(void);
1176 extern void GL_Main_Init(void);
1177 extern void R_Shadow_Init(void);
1178 extern void R_Sky_Init(void);
1179 extern void GL_Surf_Init(void);
1180 extern void R_Light_Init(void);
1181 extern void R_Particles_Init(void);
1182 extern void R_Explosion_Init(void);
1183 extern void gl_backend_init(void);
1184 extern void Sbar_Init(void);
1185 extern void R_LightningBeams_Init(void);
1186 extern void Mod_RenderInit(void);
1188 void Render_Init(void)
1201 R_LightningBeams_Init();
1210 extern char *ENGINE_EXTENSIONS;
1213 VID_CheckExtensions();
1215 // LordHavoc: report supported extensions
1216 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
1218 // clear to black (loading plaque will be seen over this)
1220 qglClearColor(0,0,0,1);CHECKGLERROR
1221 qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
1224 int R_CullBox(const vec3_t mins, const vec3_t maxs)
1228 for (i = 0;i < 4;i++)
1230 p = r_view.frustum + i;
1235 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1239 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1243 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1247 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1251 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1255 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1259 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1263 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1271 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
1275 for (i = 0;i < numplanes;i++)
1282 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1286 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1290 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1294 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1298 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1302 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1306 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1310 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1318 //==================================================================================
1320 static void R_UpdateEntityLighting(entity_render_t *ent)
1322 vec3_t tempdiffusenormal;
1324 // fetch the lighting from the worldmodel data
1325 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));
1326 VectorClear(ent->modellight_diffuse);
1327 VectorClear(tempdiffusenormal);
1328 if ((ent->flags & RENDER_LIGHT) && r_refdef.worldmodel && r_refdef.worldmodel->brush.LightPoint)
1331 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
1332 r_refdef.worldmodel->brush.LightPoint(r_refdef.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
1335 VectorSet(ent->modellight_ambient, 1, 1, 1);
1337 // move the light direction into modelspace coordinates for lighting code
1338 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
1339 VectorNormalize(ent->modellight_lightdir);
1341 // scale ambient and directional light contributions according to rendering variables
1342 ent->modellight_ambient[0] *= ent->colormod[0] * r_refdef.lightmapintensity;
1343 ent->modellight_ambient[1] *= ent->colormod[1] * r_refdef.lightmapintensity;
1344 ent->modellight_ambient[2] *= ent->colormod[2] * r_refdef.lightmapintensity;
1345 ent->modellight_diffuse[0] *= ent->colormod[0] * r_refdef.lightmapintensity;
1346 ent->modellight_diffuse[1] *= ent->colormod[1] * r_refdef.lightmapintensity;
1347 ent->modellight_diffuse[2] *= ent->colormod[2] * r_refdef.lightmapintensity;
1350 static void R_View_UpdateEntityVisible (void)
1353 entity_render_t *ent;
1355 if (!r_drawentities.integer)
1358 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : (chase_active.integer ? 0 : RENDER_EXTERIORMODEL);
1359 if (r_refdef.worldmodel && r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs)
1361 // worldmodel can check visibility
1362 for (i = 0;i < r_refdef.numentities;i++)
1364 ent = r_refdef.entities[i];
1365 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));
1367 if(r_cullentities_trace.integer)
1369 for (i = 0;i < r_refdef.numentities;i++)
1371 ent = r_refdef.entities[i];
1372 if(r_viewcache.entityvisible[i] && !(ent->effects & EF_NODEPTHTEST) && !(ent->flags & RENDER_VIEWMODEL) && !(ent->model && (ent->model->name[0] == '*')))
1374 if(Mod_CanSeeBox_Trace(r_cullentities_trace_samples.integer, r_cullentities_trace_enlarge.value, r_refdef.worldmodel, r_view.origin, ent->mins, ent->maxs))
1375 ent->last_trace_visibility = realtime;
1376 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
1377 r_viewcache.entityvisible[i] = 0;
1384 // no worldmodel or it can't check visibility
1385 for (i = 0;i < r_refdef.numentities;i++)
1387 ent = r_refdef.entities[i];
1388 r_viewcache.entityvisible[i] = !(ent->flags & renderimask) && !R_CullBox(ent->mins, ent->maxs);
1392 // update entity lighting (even on hidden entities for r_shadows)
1393 for (i = 0;i < r_refdef.numentities;i++)
1394 R_UpdateEntityLighting(r_refdef.entities[i]);
1397 // only used if skyrendermasked, and normally returns false
1398 int R_DrawBrushModelsSky (void)
1401 entity_render_t *ent;
1403 if (!r_drawentities.integer)
1407 for (i = 0;i < r_refdef.numentities;i++)
1409 if (!r_viewcache.entityvisible[i])
1411 ent = r_refdef.entities[i];
1412 if (!ent->model || !ent->model->DrawSky)
1414 ent->model->DrawSky(ent);
1420 void R_DrawNoModel(entity_render_t *ent);
1421 void R_DrawModels(void)
1424 entity_render_t *ent;
1426 if (!r_drawentities.integer)
1429 for (i = 0;i < r_refdef.numentities;i++)
1431 if (!r_viewcache.entityvisible[i])
1433 ent = r_refdef.entities[i];
1434 r_refdef.stats.entities++;
1435 if (ent->model && ent->model->Draw != NULL)
1436 ent->model->Draw(ent);
1442 static void R_View_SetFrustum(void)
1444 double slopex, slopey;
1446 // break apart the view matrix into vectors for various purposes
1447 Matrix4x4_ToVectors(&r_view.matrix, r_view.forward, r_view.left, r_view.up, r_view.origin);
1448 VectorNegate(r_view.left, r_view.right);
1451 r_view.frustum[0].normal[0] = 0 - 1.0 / r_view.frustum_x;
1452 r_view.frustum[0].normal[1] = 0 - 0;
1453 r_view.frustum[0].normal[2] = -1 - 0;
1454 r_view.frustum[1].normal[0] = 0 + 1.0 / r_view.frustum_x;
1455 r_view.frustum[1].normal[1] = 0 + 0;
1456 r_view.frustum[1].normal[2] = -1 + 0;
1457 r_view.frustum[2].normal[0] = 0 - 0;
1458 r_view.frustum[2].normal[1] = 0 - 1.0 / r_view.frustum_y;
1459 r_view.frustum[2].normal[2] = -1 - 0;
1460 r_view.frustum[3].normal[0] = 0 + 0;
1461 r_view.frustum[3].normal[1] = 0 + 1.0 / r_view.frustum_y;
1462 r_view.frustum[3].normal[2] = -1 + 0;
1466 zNear = r_refdef.nearclip;
1467 nudge = 1.0 - 1.0 / (1<<23);
1468 r_view.frustum[4].normal[0] = 0 - 0;
1469 r_view.frustum[4].normal[1] = 0 - 0;
1470 r_view.frustum[4].normal[2] = -1 - -nudge;
1471 r_view.frustum[4].dist = 0 - -2 * zNear * nudge;
1472 r_view.frustum[5].normal[0] = 0 + 0;
1473 r_view.frustum[5].normal[1] = 0 + 0;
1474 r_view.frustum[5].normal[2] = -1 + -nudge;
1475 r_view.frustum[5].dist = 0 + -2 * zNear * nudge;
1481 r_view.frustum[0].normal[0] = m[3] - m[0];
1482 r_view.frustum[0].normal[1] = m[7] - m[4];
1483 r_view.frustum[0].normal[2] = m[11] - m[8];
1484 r_view.frustum[0].dist = m[15] - m[12];
1486 r_view.frustum[1].normal[0] = m[3] + m[0];
1487 r_view.frustum[1].normal[1] = m[7] + m[4];
1488 r_view.frustum[1].normal[2] = m[11] + m[8];
1489 r_view.frustum[1].dist = m[15] + m[12];
1491 r_view.frustum[2].normal[0] = m[3] - m[1];
1492 r_view.frustum[2].normal[1] = m[7] - m[5];
1493 r_view.frustum[2].normal[2] = m[11] - m[9];
1494 r_view.frustum[2].dist = m[15] - m[13];
1496 r_view.frustum[3].normal[0] = m[3] + m[1];
1497 r_view.frustum[3].normal[1] = m[7] + m[5];
1498 r_view.frustum[3].normal[2] = m[11] + m[9];
1499 r_view.frustum[3].dist = m[15] + m[13];
1501 r_view.frustum[4].normal[0] = m[3] - m[2];
1502 r_view.frustum[4].normal[1] = m[7] - m[6];
1503 r_view.frustum[4].normal[2] = m[11] - m[10];
1504 r_view.frustum[4].dist = m[15] - m[14];
1506 r_view.frustum[5].normal[0] = m[3] + m[2];
1507 r_view.frustum[5].normal[1] = m[7] + m[6];
1508 r_view.frustum[5].normal[2] = m[11] + m[10];
1509 r_view.frustum[5].dist = m[15] + m[14];
1514 slopex = 1.0 / r_view.frustum_x;
1515 slopey = 1.0 / r_view.frustum_y;
1516 VectorMA(r_view.forward, -slopex, r_view.left, r_view.frustum[0].normal);
1517 VectorMA(r_view.forward, slopex, r_view.left, r_view.frustum[1].normal);
1518 VectorMA(r_view.forward, -slopey, r_view.up , r_view.frustum[2].normal);
1519 VectorMA(r_view.forward, slopey, r_view.up , r_view.frustum[3].normal);
1520 VectorCopy(r_view.forward, r_view.frustum[4].normal);
1521 VectorNormalize(r_view.frustum[0].normal);
1522 VectorNormalize(r_view.frustum[1].normal);
1523 VectorNormalize(r_view.frustum[2].normal);
1524 VectorNormalize(r_view.frustum[3].normal);
1525 r_view.frustum[0].dist = DotProduct (r_view.origin, r_view.frustum[0].normal);
1526 r_view.frustum[1].dist = DotProduct (r_view.origin, r_view.frustum[1].normal);
1527 r_view.frustum[2].dist = DotProduct (r_view.origin, r_view.frustum[2].normal);
1528 r_view.frustum[3].dist = DotProduct (r_view.origin, r_view.frustum[3].normal);
1529 r_view.frustum[4].dist = DotProduct (r_view.origin, r_view.frustum[4].normal) + r_refdef.nearclip;
1530 PlaneClassify(&r_view.frustum[0]);
1531 PlaneClassify(&r_view.frustum[1]);
1532 PlaneClassify(&r_view.frustum[2]);
1533 PlaneClassify(&r_view.frustum[3]);
1534 PlaneClassify(&r_view.frustum[4]);
1536 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
1537 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, -1024 * slopex, r_view.left, -1024 * slopey, r_view.up, r_view.frustumcorner[0]);
1538 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, 1024 * slopex, r_view.left, -1024 * slopey, r_view.up, r_view.frustumcorner[1]);
1539 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, -1024 * slopex, r_view.left, 1024 * slopey, r_view.up, r_view.frustumcorner[2]);
1540 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, 1024 * slopex, r_view.left, 1024 * slopey, r_view.up, r_view.frustumcorner[3]);
1542 // LordHavoc: note to all quake engine coders, Quake had a special case
1543 // for 90 degrees which assumed a square view (wrong), so I removed it,
1544 // Quake2 has it disabled as well.
1546 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
1547 //RotatePointAroundVector( r_view.frustum[0].normal, r_view.up, r_view.forward, -(90 - r_refdef.fov_x / 2));
1548 //r_view.frustum[0].dist = DotProduct (r_view.origin, frustum[0].normal);
1549 //PlaneClassify(&frustum[0]);
1551 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
1552 //RotatePointAroundVector( r_view.frustum[1].normal, r_view.up, r_view.forward, (90 - r_refdef.fov_x / 2));
1553 //r_view.frustum[1].dist = DotProduct (r_view.origin, frustum[1].normal);
1554 //PlaneClassify(&frustum[1]);
1556 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
1557 //RotatePointAroundVector( r_view.frustum[2].normal, r_view.left, r_view.forward, -(90 - r_refdef.fov_y / 2));
1558 //r_view.frustum[2].dist = DotProduct (r_view.origin, frustum[2].normal);
1559 //PlaneClassify(&frustum[2]);
1561 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
1562 //RotatePointAroundVector( r_view.frustum[3].normal, r_view.left, r_view.forward, (90 - r_refdef.fov_y / 2));
1563 //r_view.frustum[3].dist = DotProduct (r_view.origin, frustum[3].normal);
1564 //PlaneClassify(&frustum[3]);
1567 //VectorCopy(r_view.forward, r_view.frustum[4].normal);
1568 //r_view.frustum[4].dist = DotProduct (r_view.origin, frustum[4].normal) + r_nearclip.value;
1569 //PlaneClassify(&frustum[4]);
1572 void R_View_Update(void)
1574 R_View_SetFrustum();
1575 R_View_WorldVisibility();
1576 R_View_UpdateEntityVisible();
1579 void R_SetupView(const matrix4x4_t *matrix)
1581 if (r_refdef.rtworldshadows || r_refdef.rtdlightshadows)
1582 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_view.frustum_x, r_view.frustum_y, r_refdef.nearclip);
1584 GL_SetupView_Mode_Perspective(r_view.frustum_x, r_view.frustum_y, r_refdef.nearclip, r_refdef.farclip);
1586 GL_SetupView_Orientation_FromEntity(matrix);
1589 void R_ResetViewRendering2D(void)
1591 if (gl_support_fragment_shader)
1593 qglUseProgramObjectARB(0);CHECKGLERROR
1598 // GL is weird because it's bottom to top, r_view.y is top to bottom
1599 qglViewport(r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
1600 GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
1601 GL_Scissor(r_view.x, r_view.y, r_view.width, r_view.height);
1602 GL_Color(1, 1, 1, 1);
1603 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
1604 GL_BlendFunc(GL_ONE, GL_ZERO);
1605 GL_AlphaTest(false);
1606 GL_ScissorTest(false);
1607 GL_DepthMask(false);
1608 GL_DepthRange(0, 1);
1609 GL_DepthTest(false);
1610 R_Mesh_Matrix(&identitymatrix);
1611 R_Mesh_ResetTextureState();
1612 qglPolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR
1613 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
1614 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
1615 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
1616 qglStencilMask(~0);CHECKGLERROR
1617 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
1618 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
1619 GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
1622 void R_ResetViewRendering3D(void)
1624 if (gl_support_fragment_shader)
1626 qglUseProgramObjectARB(0);CHECKGLERROR
1631 // GL is weird because it's bottom to top, r_view.y is top to bottom
1632 qglViewport(r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
1633 R_SetupView(&r_view.matrix);
1634 GL_Scissor(r_view.x, r_view.y, r_view.width, r_view.height);
1635 GL_Color(1, 1, 1, 1);
1636 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
1637 GL_BlendFunc(GL_ONE, GL_ZERO);
1638 GL_AlphaTest(false);
1639 GL_ScissorTest(true);
1641 GL_DepthRange(0, 1);
1643 R_Mesh_Matrix(&identitymatrix);
1644 R_Mesh_ResetTextureState();
1645 qglPolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR
1646 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
1647 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
1648 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
1649 qglStencilMask(~0);CHECKGLERROR
1650 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
1651 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
1652 GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
1656 R_Bloom_SetupShader(
1658 "// written by Forest 'LordHavoc' Hale\n"
1660 "// common definitions between vertex shader and fragment shader:\n"
1662 "#ifdef __GLSL_CG_DATA_TYPES\n"
1663 "#define myhalf half\n"
1664 "#define myhvec2 hvec2\n"
1665 "#define myhvec3 hvec3\n"
1666 "#define myhvec4 hvec4\n"
1668 "#define myhalf float\n"
1669 "#define myhvec2 vec2\n"
1670 "#define myhvec3 vec3\n"
1671 "#define myhvec4 vec4\n"
1674 "varying vec2 ScreenTexCoord;\n"
1675 "varying vec2 BloomTexCoord;\n"
1680 "// vertex shader specific:\n"
1681 "#ifdef VERTEX_SHADER\n"
1685 " ScreenTexCoord = vec2(gl_MultiTexCoord0);\n"
1686 " BloomTexCoord = vec2(gl_MultiTexCoord1);\n"
1687 " // transform vertex to camera space, using ftransform to match non-VS\n"
1689 " gl_Position = ftransform();\n"
1692 "#endif // VERTEX_SHADER\n"
1697 "// fragment shader specific:\n"
1698 "#ifdef FRAGMENT_SHADER\n"
1703 " myhvec3 color = myhvec3(texture2D(Texture_Screen, ScreenTexCoord));\n"
1704 " for (x = -BLUR_X;x <= BLUR_X;x++)
1705 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
1706 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
1707 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
1708 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
1710 " gl_FragColor = vec4(color);\n"
1713 "#endif // FRAGMENT_SHADER\n"
1716 void R_RenderScene(void);
1718 void R_Bloom_StartFrame(void)
1720 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
1722 // set bloomwidth and bloomheight to the bloom resolution that will be
1723 // used (often less than the screen resolution for faster rendering)
1724 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_view.width);
1725 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_view.height / r_view.width;
1726 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_view.height);
1728 // calculate desired texture sizes
1729 if (gl_support_arb_texture_non_power_of_two)
1731 screentexturewidth = r_view.width;
1732 screentextureheight = r_view.height;
1733 bloomtexturewidth = r_bloomstate.bloomwidth;
1734 bloomtextureheight = r_bloomstate.bloomheight;
1738 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
1739 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
1740 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
1741 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
1746 screentexturewidth = screentextureheight = 0;
1748 else if (r_bloom.integer)
1753 screentexturewidth = screentextureheight = 0;
1754 bloomtexturewidth = bloomtextureheight = 0;
1757 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)
1759 // can't use bloom if the parameters are too weird
1760 // can't use bloom if the card does not support the texture size
1761 if (r_bloomstate.texture_screen)
1762 R_FreeTexture(r_bloomstate.texture_screen);
1763 if (r_bloomstate.texture_bloom)
1764 R_FreeTexture(r_bloomstate.texture_bloom);
1765 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
1769 r_bloomstate.enabled = true;
1770 r_bloomstate.hdr = r_hdr.integer != 0;
1772 // allocate textures as needed
1773 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
1775 if (r_bloomstate.texture_screen)
1776 R_FreeTexture(r_bloomstate.texture_screen);
1777 r_bloomstate.texture_screen = NULL;
1778 r_bloomstate.screentexturewidth = screentexturewidth;
1779 r_bloomstate.screentextureheight = screentextureheight;
1780 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
1781 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);
1783 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
1785 if (r_bloomstate.texture_bloom)
1786 R_FreeTexture(r_bloomstate.texture_bloom);
1787 r_bloomstate.texture_bloom = NULL;
1788 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
1789 r_bloomstate.bloomtextureheight = bloomtextureheight;
1790 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
1791 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);
1794 // set up a texcoord array for the full resolution screen image
1795 // (we have to keep this around to copy back during final render)
1796 r_bloomstate.screentexcoord2f[0] = 0;
1797 r_bloomstate.screentexcoord2f[1] = (float)r_view.height / (float)r_bloomstate.screentextureheight;
1798 r_bloomstate.screentexcoord2f[2] = (float)r_view.width / (float)r_bloomstate.screentexturewidth;
1799 r_bloomstate.screentexcoord2f[3] = (float)r_view.height / (float)r_bloomstate.screentextureheight;
1800 r_bloomstate.screentexcoord2f[4] = (float)r_view.width / (float)r_bloomstate.screentexturewidth;
1801 r_bloomstate.screentexcoord2f[5] = 0;
1802 r_bloomstate.screentexcoord2f[6] = 0;
1803 r_bloomstate.screentexcoord2f[7] = 0;
1805 // set up a texcoord array for the reduced resolution bloom image
1806 // (which will be additive blended over the screen image)
1807 r_bloomstate.bloomtexcoord2f[0] = 0;
1808 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
1809 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
1810 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
1811 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
1812 r_bloomstate.bloomtexcoord2f[5] = 0;
1813 r_bloomstate.bloomtexcoord2f[6] = 0;
1814 r_bloomstate.bloomtexcoord2f[7] = 0;
1817 void R_Bloom_CopyScreenTexture(float colorscale)
1819 r_refdef.stats.bloom++;
1821 R_ResetViewRendering2D();
1822 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
1823 R_Mesh_ColorPointer(NULL, 0, 0);
1824 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
1825 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
1827 // copy view into the screen texture
1828 GL_ActiveTexture(0);
1830 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
1831 r_refdef.stats.bloom_copypixels += r_view.width * r_view.height;
1833 // now scale it down to the bloom texture size
1835 qglViewport(r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
1836 GL_BlendFunc(GL_ONE, GL_ZERO);
1837 GL_Color(colorscale, colorscale, colorscale, 1);
1838 // TODO: optimize with multitexture or GLSL
1839 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
1840 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
1842 // we now have a bloom image in the framebuffer
1843 // copy it into the bloom image texture for later processing
1844 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
1845 GL_ActiveTexture(0);
1847 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
1848 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
1851 void R_Bloom_CopyHDRTexture(void)
1853 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
1854 GL_ActiveTexture(0);
1856 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
1857 r_refdef.stats.bloom_copypixels += r_view.width * r_view.height;
1860 void R_Bloom_MakeTexture(void)
1863 float xoffset, yoffset, r, brighten;
1865 r_refdef.stats.bloom++;
1867 R_ResetViewRendering2D();
1868 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
1869 R_Mesh_ColorPointer(NULL, 0, 0);
1871 // we have a bloom image in the framebuffer
1873 qglViewport(r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
1875 for (x = 1;x < r_bloom_colorexponent.value;)
1878 r = bound(0, r_bloom_colorexponent.value / x, 1);
1879 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
1880 GL_Color(r, r, r, 1);
1881 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
1882 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
1883 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
1884 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
1886 // copy the vertically blurred bloom view to a texture
1887 GL_ActiveTexture(0);
1889 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
1890 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
1893 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
1894 brighten = r_bloom_brighten.value;
1896 brighten *= r_hdr_range.value;
1897 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
1898 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
1900 for (dir = 0;dir < 2;dir++)
1902 // blend on at multiple vertical offsets to achieve a vertical blur
1903 // TODO: do offset blends using GLSL
1904 GL_BlendFunc(GL_ONE, GL_ZERO);
1905 for (x = -range;x <= range;x++)
1907 if (!dir){xoffset = 0;yoffset = x;}
1908 else {xoffset = x;yoffset = 0;}
1909 xoffset /= (float)r_bloomstate.bloomtexturewidth;
1910 yoffset /= (float)r_bloomstate.bloomtextureheight;
1911 // compute a texcoord array with the specified x and y offset
1912 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
1913 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
1914 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
1915 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
1916 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
1917 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
1918 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
1919 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
1920 // this r value looks like a 'dot' particle, fading sharply to
1921 // black at the edges
1922 // (probably not realistic but looks good enough)
1923 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
1924 //r = (dir ? 1.0f : brighten)/(range*2+1);
1925 r = (dir ? 1.0f : brighten)/(range*2+1)*(1 - x*x/(float)(range*range));
1926 GL_Color(r, r, r, 1);
1927 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
1928 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
1929 GL_BlendFunc(GL_ONE, GL_ONE);
1932 // copy the vertically blurred bloom view to a texture
1933 GL_ActiveTexture(0);
1935 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
1936 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
1939 // apply subtract last
1940 // (just like it would be in a GLSL shader)
1941 if (r_bloom_colorsubtract.value > 0 && gl_support_ext_blend_subtract)
1943 GL_BlendFunc(GL_ONE, GL_ZERO);
1944 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
1945 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
1946 GL_Color(1, 1, 1, 1);
1947 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
1948 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
1950 GL_BlendFunc(GL_ONE, GL_ONE);
1951 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
1952 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
1953 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
1954 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
1955 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
1956 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
1957 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
1959 // copy the darkened bloom view to a texture
1960 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
1961 GL_ActiveTexture(0);
1963 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
1964 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
1968 void R_HDR_RenderBloomTexture(void)
1970 int oldwidth, oldheight;
1972 oldwidth = r_view.width;
1973 oldheight = r_view.height;
1974 r_view.width = r_bloomstate.bloomwidth;
1975 r_view.height = r_bloomstate.bloomheight;
1977 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
1978 // TODO: add exposure compensation features
1979 // TODO: add fp16 framebuffer support
1981 r_view.colorscale = r_bloom_colorscale.value * r_hdr_scenebrightness.value;
1983 r_view.colorscale /= r_hdr_range.value;
1986 R_ResetViewRendering2D();
1988 R_Bloom_CopyHDRTexture();
1989 R_Bloom_MakeTexture();
1991 R_ResetViewRendering3D();
1994 if (r_timereport_active)
1995 R_TimeReport("clear");
1998 // restore the view settings
1999 r_view.width = oldwidth;
2000 r_view.height = oldheight;
2003 static void R_BlendView(void)
2005 if (r_bloomstate.enabled && r_bloomstate.hdr)
2007 // render high dynamic range bloom effect
2008 // the bloom texture was made earlier this render, so we just need to
2009 // blend it onto the screen...
2010 R_ResetViewRendering2D();
2011 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
2012 R_Mesh_ColorPointer(NULL, 0, 0);
2013 GL_Color(1, 1, 1, 1);
2014 GL_BlendFunc(GL_ONE, GL_ONE);
2015 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2016 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
2017 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2018 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
2020 else if (r_bloomstate.enabled)
2022 // render simple bloom effect
2023 // copy the screen and shrink it and darken it for the bloom process
2024 R_Bloom_CopyScreenTexture(r_bloom_colorscale.value);
2025 // make the bloom texture
2026 R_Bloom_MakeTexture();
2027 // put the original screen image back in place and blend the bloom
2029 R_ResetViewRendering2D();
2030 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
2031 R_Mesh_ColorPointer(NULL, 0, 0);
2032 GL_Color(1, 1, 1, 1);
2033 GL_BlendFunc(GL_ONE, GL_ZERO);
2034 // do both in one pass if possible
2035 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2036 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
2037 if (r_textureunits.integer >= 2 && gl_combine.integer)
2039 R_Mesh_TexCombine(1, GL_ADD, GL_ADD, 1, 1);
2040 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_screen));
2041 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.screentexcoord2f, 0, 0);
2045 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2046 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
2047 // now blend on the bloom texture
2048 GL_BlendFunc(GL_ONE, GL_ONE);
2049 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
2050 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
2052 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2053 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
2055 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
2057 // apply a color tint to the whole view
2058 R_ResetViewRendering2D();
2059 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
2060 R_Mesh_ColorPointer(NULL, 0, 0);
2061 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2062 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
2063 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2067 void R_RenderScene(void);
2069 matrix4x4_t r_waterscrollmatrix;
2071 void R_UpdateVariables(void)
2075 r_refdef.farclip = 4096;
2076 if (r_refdef.worldmodel)
2077 r_refdef.farclip += VectorDistance(r_refdef.worldmodel->normalmins, r_refdef.worldmodel->normalmaxs);
2078 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
2080 r_refdef.polygonfactor = 0;
2081 r_refdef.polygonoffset = 0;
2082 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_shadow_polygonfactor.value;
2083 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_shadow_polygonoffset.value;
2085 r_refdef.rtworld = r_shadow_realtime_world.integer;
2086 r_refdef.rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
2087 r_refdef.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
2088 r_refdef.rtdlightshadows = r_refdef.rtdlight && (r_refdef.rtworld ? r_shadow_realtime_world_dlightshadows.integer : r_shadow_realtime_dlight_shadows.integer) && gl_stencil;
2089 r_refdef.lightmapintensity = r_refdef.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
2090 if (r_showsurfaces.integer)
2092 r_refdef.rtworld = false;
2093 r_refdef.rtworldshadows = false;
2094 r_refdef.rtdlight = false;
2095 r_refdef.rtdlightshadows = false;
2096 r_refdef.lightmapintensity = 0;
2099 if (gamemode == GAME_NEHAHRA)
2101 if (gl_fogenable.integer)
2103 r_refdef.oldgl_fogenable = true;
2104 r_refdef.fog_density = gl_fogdensity.value;
2105 r_refdef.fog_red = gl_fogred.value;
2106 r_refdef.fog_green = gl_foggreen.value;
2107 r_refdef.fog_blue = gl_fogblue.value;
2109 else if (r_refdef.oldgl_fogenable)
2111 r_refdef.oldgl_fogenable = false;
2112 r_refdef.fog_density = 0;
2113 r_refdef.fog_red = 0;
2114 r_refdef.fog_green = 0;
2115 r_refdef.fog_blue = 0;
2118 if (r_refdef.fog_density)
2120 r_refdef.fogcolor[0] = bound(0.0f, r_refdef.fog_red , 1.0f);
2121 r_refdef.fogcolor[1] = bound(0.0f, r_refdef.fog_green, 1.0f);
2122 r_refdef.fogcolor[2] = bound(0.0f, r_refdef.fog_blue , 1.0f);
2124 if (r_refdef.fog_density)
2126 r_refdef.fogenabled = true;
2127 // this is the point where the fog reaches 0.9986 alpha, which we
2128 // consider a good enough cutoff point for the texture
2129 // (0.9986 * 256 == 255.6)
2130 r_refdef.fogrange = 400 / r_refdef.fog_density;
2131 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
2132 r_refdef.fogtabledistmultiplier = FOGTABLEWIDTH * r_refdef.fograngerecip;
2133 // fog color was already set
2136 r_refdef.fogenabled = false;
2144 void R_RenderView(void)
2146 if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
2147 return; //Host_Error ("R_RenderView: NULL worldmodel");
2149 R_Shadow_UpdateWorldLightSelection();
2152 if (r_timereport_active)
2153 R_TimeReport("setup");
2156 if (r_timereport_active)
2157 R_TimeReport("visibility");
2159 R_ResetViewRendering3D();
2162 if (r_timereport_active)
2163 R_TimeReport("clear");
2165 R_Bloom_StartFrame();
2167 // this produces a bloom texture to be used in R_BlendView() later
2169 R_HDR_RenderBloomTexture();
2171 r_view.colorscale = r_hdr_scenebrightness.value;
2175 if (r_timereport_active)
2176 R_TimeReport("blendview");
2178 GL_Scissor(0, 0, vid.width, vid.height);
2179 GL_ScissorTest(false);
2183 extern void R_DrawLightningBeams (void);
2184 extern void VM_CL_AddPolygonsToMeshQueue (void);
2185 extern void R_DrawPortals (void);
2186 extern cvar_t cl_locs_show;
2187 static void R_DrawLocs(void);
2188 void R_RenderScene(void)
2190 // don't let sound skip if going slow
2191 if (r_refdef.extraupdate)
2194 R_ResetViewRendering3D();
2196 R_MeshQueue_BeginScene();
2200 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);
2202 if (cl.csqc_vidvars.drawworld)
2204 // don't let sound skip if going slow
2205 if (r_refdef.extraupdate)
2208 if (r_refdef.worldmodel && r_refdef.worldmodel->DrawSky)
2210 r_refdef.worldmodel->DrawSky(r_refdef.worldentity);
2211 if (r_timereport_active)
2212 R_TimeReport("worldsky");
2215 if (R_DrawBrushModelsSky() && r_timereport_active)
2216 R_TimeReport("bmodelsky");
2218 if (r_refdef.worldmodel && r_refdef.worldmodel->Draw)
2220 r_refdef.worldmodel->Draw(r_refdef.worldentity);
2221 if (r_timereport_active)
2222 R_TimeReport("world");
2226 // don't let sound skip if going slow
2227 if (r_refdef.extraupdate)
2231 if (r_timereport_active)
2232 R_TimeReport("models");
2234 // don't let sound skip if going slow
2235 if (r_refdef.extraupdate)
2238 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
2240 R_DrawModelShadows();
2242 R_ResetViewRendering3D();
2244 // don't let sound skip if going slow
2245 if (r_refdef.extraupdate)
2249 R_ShadowVolumeLighting(false);
2250 if (r_timereport_active)
2251 R_TimeReport("rtlights");
2253 // don't let sound skip if going slow
2254 if (r_refdef.extraupdate)
2257 if (cl.csqc_vidvars.drawworld)
2259 R_DrawLightningBeams();
2260 if (r_timereport_active)
2261 R_TimeReport("lightning");
2264 if (r_timereport_active)
2265 R_TimeReport("particles");
2268 if (r_timereport_active)
2269 R_TimeReport("explosions");
2272 if (gl_support_fragment_shader)
2274 qglUseProgramObjectARB(0);CHECKGLERROR
2276 VM_CL_AddPolygonsToMeshQueue();
2278 if (cl_locs_show.integer)
2281 if (r_timereport_active)
2282 R_TimeReport("showlocs");
2285 if (r_drawportals.integer)
2288 if (r_timereport_active)
2289 R_TimeReport("portals");
2292 if (gl_support_fragment_shader)
2294 qglUseProgramObjectARB(0);CHECKGLERROR
2296 R_MeshQueue_RenderTransparent();
2297 if (r_timereport_active)
2298 R_TimeReport("drawtrans");
2300 if (gl_support_fragment_shader)
2302 qglUseProgramObjectARB(0);CHECKGLERROR
2305 if (cl.csqc_vidvars.drawworld)
2308 if (r_timereport_active)
2309 R_TimeReport("coronas");
2312 // don't let sound skip if going slow
2313 if (r_refdef.extraupdate)
2316 R_ResetViewRendering2D();
2320 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
2323 float *v, *c, f1, f2, diff[3], vertex3f[8*3], color4f[8*4];
2324 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2325 GL_DepthMask(false);
2326 GL_DepthRange(0, 1);
2328 R_Mesh_Matrix(&identitymatrix);
2330 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2];
2331 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
2332 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
2333 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
2334 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
2335 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
2336 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
2337 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
2338 R_FillColors(color, 8, cr, cg, cb, ca);
2339 if (r_refdef.fogenabled)
2341 for (i = 0, v = vertex, c = color;i < 8;i++, v += 4, c += 4)
2343 f2 = VERTEXFOGTABLE(VectorDistance(v, r_view.origin));
2345 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
2346 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
2347 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
2350 R_Mesh_VertexPointer(vertex3f, 0, 0);
2351 R_Mesh_ColorPointer(color, 0, 0);
2352 R_Mesh_ResetTextureState();
2353 R_Mesh_Draw(8, 12, 0, 0);
2357 int nomodelelements[24] =
2369 float nomodelvertex3f[6*3] =
2379 float nomodelcolor4f[6*4] =
2381 0.0f, 0.0f, 0.5f, 1.0f,
2382 0.0f, 0.0f, 0.5f, 1.0f,
2383 0.0f, 0.5f, 0.0f, 1.0f,
2384 0.0f, 0.5f, 0.0f, 1.0f,
2385 0.5f, 0.0f, 0.0f, 1.0f,
2386 0.5f, 0.0f, 0.0f, 1.0f
2389 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
2394 // this is only called once per entity so numsurfaces is always 1, and
2395 // surfacelist is always {0}, so this code does not handle batches
2396 R_Mesh_Matrix(&ent->matrix);
2398 if (ent->flags & EF_ADDITIVE)
2400 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2401 GL_DepthMask(false);
2403 else if (ent->alpha < 1)
2405 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2406 GL_DepthMask(false);
2410 GL_BlendFunc(GL_ONE, GL_ZERO);
2413 GL_DepthRange(0, (ent->flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
2414 GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
2415 GL_CullFace((ent->effects & EF_DOUBLESIDED) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
2416 R_Mesh_VertexPointer(nomodelvertex3f, 0, 0);
2417 if (r_refdef.fogenabled)
2420 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
2421 R_Mesh_ColorPointer(color4f, 0, 0);
2422 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
2423 f2 = VERTEXFOGTABLE(VectorDistance(org, r_view.origin));
2425 for (i = 0, c = color4f;i < 6;i++, c += 4)
2427 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
2428 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
2429 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
2433 else if (ent->alpha != 1)
2435 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
2436 R_Mesh_ColorPointer(color4f, 0, 0);
2437 for (i = 0, c = color4f;i < 6;i++, c += 4)
2441 R_Mesh_ColorPointer(nomodelcolor4f, 0, 0);
2442 R_Mesh_ResetTextureState();
2443 R_Mesh_Draw(0, 6, 8, nomodelelements, 0, 0);
2446 void R_DrawNoModel(entity_render_t *ent)
2449 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
2450 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
2451 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, r_shadow_rtlight);
2453 // R_DrawNoModelCallback(ent, 0);
2456 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
2458 vec3_t right1, right2, diff, normal;
2460 VectorSubtract (org2, org1, normal);
2462 // calculate 'right' vector for start
2463 VectorSubtract (r_view.origin, org1, diff);
2464 CrossProduct (normal, diff, right1);
2465 VectorNormalize (right1);
2467 // calculate 'right' vector for end
2468 VectorSubtract (r_view.origin, org2, diff);
2469 CrossProduct (normal, diff, right2);
2470 VectorNormalize (right2);
2472 vert[ 0] = org1[0] + width * right1[0];
2473 vert[ 1] = org1[1] + width * right1[1];
2474 vert[ 2] = org1[2] + width * right1[2];
2475 vert[ 3] = org1[0] - width * right1[0];
2476 vert[ 4] = org1[1] - width * right1[1];
2477 vert[ 5] = org1[2] - width * right1[2];
2478 vert[ 6] = org2[0] - width * right2[0];
2479 vert[ 7] = org2[1] - width * right2[1];
2480 vert[ 8] = org2[2] - width * right2[2];
2481 vert[ 9] = org2[0] + width * right2[0];
2482 vert[10] = org2[1] + width * right2[1];
2483 vert[11] = org2[2] + width * right2[2];
2486 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
2488 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)
2490 float fog = 0.0f, ifog;
2493 if (r_refdef.fogenabled)
2494 fog = VERTEXFOGTABLE(VectorDistance(origin, r_view.origin));
2497 R_Mesh_Matrix(&identitymatrix);
2498 GL_BlendFunc(blendfunc1, blendfunc2);
2499 GL_DepthMask(false);
2500 GL_DepthRange(0, depthshort ? 0.0625 : 1);
2501 GL_DepthTest(!depthdisable);
2503 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
2504 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
2505 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
2506 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
2507 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
2508 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
2509 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
2510 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
2511 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
2512 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
2513 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
2514 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
2516 R_Mesh_VertexPointer(vertex3f, 0, 0);
2517 R_Mesh_ColorPointer(NULL, 0, 0);
2518 R_Mesh_ResetTextureState();
2519 R_Mesh_TexBind(0, R_GetTexture(texture));
2520 R_Mesh_TexCoordPointer(0, 2, spritetexcoord2f, 0, 0);
2521 // FIXME: fixed function path can't properly handle r_view.colorscale > 1
2522 GL_Color(cr * ifog * r_view.colorscale, cg * ifog * r_view.colorscale, cb * ifog * r_view.colorscale, ca);
2523 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2525 if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
2527 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
2528 GL_BlendFunc(blendfunc1, GL_ONE);
2529 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);
2530 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2534 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
2539 VectorSet(v, x, y, z);
2540 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
2541 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
2543 if (i == mesh->numvertices)
2545 if (mesh->numvertices < mesh->maxvertices)
2547 VectorCopy(v, vertex3f);
2548 mesh->numvertices++;
2550 return mesh->numvertices;
2556 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
2560 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
2561 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
2562 e = mesh->element3i + mesh->numtriangles * 3;
2563 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
2565 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
2566 if (mesh->numtriangles < mesh->maxtriangles)
2571 mesh->numtriangles++;
2573 element[1] = element[2];
2577 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
2581 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
2582 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
2583 e = mesh->element3i + mesh->numtriangles * 3;
2584 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
2586 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
2587 if (mesh->numtriangles < mesh->maxtriangles)
2592 mesh->numtriangles++;
2594 element[1] = element[2];
2598 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
2599 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
2601 int planenum, planenum2;
2604 mplane_t *plane, *plane2;
2606 double temppoints[2][256*3];
2607 // figure out how large a bounding box we need to properly compute this brush
2609 for (w = 0;w < numplanes;w++)
2610 maxdist = max(maxdist, planes[w].dist);
2611 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
2612 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
2613 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
2617 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
2618 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
2620 if (planenum2 == planenum)
2622 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);
2625 if (tempnumpoints < 3)
2627 // generate elements forming a triangle fan for this polygon
2628 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
2632 static void R_DrawCollisionBrush(const colbrushf_t *brush)
2635 R_Mesh_VertexPointer(brush->points->v, 0, 0);
2636 i = (int)(((size_t)brush) / sizeof(colbrushf_t));
2637 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);
2638 GL_LockArrays(0, brush->numpoints);
2639 R_Mesh_Draw(0, brush->numpoints, brush->numtriangles, brush->elements, 0, 0);
2640 GL_LockArrays(0, 0);
2643 static void R_DrawCollisionSurface(const entity_render_t *ent, const msurface_t *surface)
2646 if (!surface->num_collisiontriangles)
2648 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
2649 i = (int)(((size_t)surface) / sizeof(msurface_t));
2650 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);
2651 GL_LockArrays(0, surface->num_collisionvertices);
2652 R_Mesh_Draw(0, surface->num_collisionvertices, surface->num_collisiontriangles, surface->data_collisionelement3i, 0, 0);
2653 GL_LockArrays(0, 0);
2656 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)
2658 texturelayer_t *layer;
2659 layer = t->currentlayers + t->currentnumlayers++;
2661 layer->depthmask = depthmask;
2662 layer->blendfunc1 = blendfunc1;
2663 layer->blendfunc2 = blendfunc2;
2664 layer->texture = texture;
2665 layer->texmatrix = *matrix;
2666 layer->color[0] = r * r_view.colorscale;
2667 layer->color[1] = g * r_view.colorscale;
2668 layer->color[2] = b * r_view.colorscale;
2669 layer->color[3] = a;
2672 void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
2674 model_t *model = ent->model;
2676 // switch to an alternate material if this is a q1bsp animated material
2678 texture_t *texture = t;
2679 int s = ent->skinnum;
2680 if ((unsigned int)s >= (unsigned int)model->numskins)
2682 if (model->skinscenes)
2684 if (model->skinscenes[s].framecount > 1)
2685 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
2687 s = model->skinscenes[s].firstframe;
2690 t = t + s * model->num_surfaces;
2693 // use an alternate animation if the entity's frame is not 0,
2694 // and only if the texture has an alternate animation
2695 if (ent->frame != 0 && t->anim_total[1])
2696 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.time * 5.0f) % t->anim_total[1]) : 0];
2698 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.time * 5.0f) % t->anim_total[0]) : 0];
2700 texture->currentframe = t;
2703 // pick a new currentskinframe if the material is animated
2704 if (t->numskinframes >= 2)
2705 t->currentskinframe = t->skinframes + ((int)(t->skinframerate * (cl.time - ent->frame2time)) % t->numskinframes);
2706 if (t->backgroundnumskinframes >= 2)
2707 t->backgroundcurrentskinframe = t->backgroundskinframes + ((int)(t->backgroundskinframerate * (cl.time - ent->frame2time)) % t->backgroundnumskinframes);
2709 t->currentmaterialflags = t->basematerialflags;
2710 t->currentalpha = ent->alpha;
2711 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
2712 t->currentalpha *= r_wateralpha.value;
2713 if (!(ent->flags & RENDER_LIGHT))
2714 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
2715 if (ent->effects & EF_ADDITIVE)
2716 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
2717 else if (t->currentalpha < 1)
2718 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
2719 if (ent->effects & EF_DOUBLESIDED)
2720 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
2721 if (ent->effects & EF_NODEPTHTEST)
2722 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
2723 if (ent->flags & RENDER_VIEWMODEL)
2724 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
2725 if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
2726 t->currenttexmatrix = r_waterscrollmatrix;
2728 t->currenttexmatrix = identitymatrix;
2729 if (t->backgroundnumskinframes && !(t->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED))
2730 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
2732 t->colormapping = VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f);
2733 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
2734 t->glosstexture = r_texture_white;
2735 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
2736 t->backgroundglosstexture = r_texture_white;
2737 t->specularpower = r_shadow_glossexponent.value;
2738 // TODO: store reference values for these in the texture?
2739 t->specularscale = 0;
2740 if (r_shadow_gloss.integer > 0)
2742 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
2744 if (r_shadow_glossintensity.value > 0)
2746 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_black;
2747 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_black;
2748 t->specularscale = r_shadow_glossintensity.value;
2751 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
2752 t->specularscale = r_shadow_gloss2intensity.value;
2755 t->currentnumlayers = 0;
2756 if (!(t->currentmaterialflags & MATERIALFLAG_NODRAW))
2758 if (gl_lightmaps.integer)
2759 R_Texture_AddLayer(t, true, GL_ONE, GL_ZERO, TEXTURELAYERTYPE_LITTEXTURE, r_texture_white, &identitymatrix, 1, 1, 1, 1);
2760 else if (!(t->currentmaterialflags & MATERIALFLAG_SKY))
2762 int blendfunc1, blendfunc2, depthmask;
2763 if (t->currentmaterialflags & MATERIALFLAG_ADD)
2765 blendfunc1 = GL_SRC_ALPHA;
2766 blendfunc2 = GL_ONE;
2768 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
2770 blendfunc1 = GL_SRC_ALPHA;
2771 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
2773 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
2775 blendfunc1 = t->customblendfunc[0];
2776 blendfunc2 = t->customblendfunc[1];
2780 blendfunc1 = GL_ONE;
2781 blendfunc2 = GL_ZERO;
2783 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
2784 if (t->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL))
2786 rtexture_t *currentbasetexture;
2788 if (r_refdef.fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED))
2789 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
2790 currentbasetexture = (VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) < (1.0f / 1048576.0f) && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
2791 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2793 // fullbright is not affected by r_refdef.lightmapintensity
2794 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
2795 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
2796 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);
2797 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
2798 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);
2804 // q3bsp has no lightmap updates, so the lightstylevalue that
2805 // would normally be baked into the lightmap must be
2806 // applied to the color
2807 if (ent->model->type == mod_brushq3)
2808 colorscale *= r_refdef.lightstylevalue[0] * (1.0f / 256.0f);
2809 colorscale *= r_refdef.lightmapintensity;
2810 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);
2811 if (r_ambient.value >= (1.0f/64.0f))
2812 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);
2813 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
2815 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);
2816 if (r_ambient.value >= (1.0f/64.0f))
2817 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);
2819 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
2821 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);
2822 if (r_ambient.value >= (1.0f/64.0f))
2823 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);
2826 if (t->currentskinframe->glow != NULL)
2827 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);
2828 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
2830 // if this is opaque use alpha blend which will darken the earlier
2833 // if this is an alpha blended material, all the earlier passes
2834 // were darkened by fog already, so we only need to add the fog
2835 // color ontop through the fog mask texture
2837 // if this is an additive blended material, all the earlier passes
2838 // were darkened by fog already, and we should not add fog color
2839 // (because the background was not darkened, there is no fog color
2840 // that was lost behind it).
2841 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);
2848 void R_UpdateAllTextureInfo(entity_render_t *ent)
2852 for (i = 0;i < ent->model->num_textures;i++)
2853 R_UpdateTextureInfo(ent, ent->model->data_textures + i);
2856 int rsurface_array_size = 0;
2857 float *rsurface_array_modelvertex3f = NULL;
2858 float *rsurface_array_modelsvector3f = NULL;
2859 float *rsurface_array_modeltvector3f = NULL;
2860 float *rsurface_array_modelnormal3f = NULL;
2861 float *rsurface_array_deformedvertex3f = NULL;
2862 float *rsurface_array_deformedsvector3f = NULL;
2863 float *rsurface_array_deformedtvector3f = NULL;
2864 float *rsurface_array_deformednormal3f = NULL;
2865 float *rsurface_array_color4f = NULL;
2866 float *rsurface_array_texcoord3f = NULL;
2868 void R_Mesh_ResizeArrays(int newvertices)
2871 if (rsurface_array_size >= newvertices)
2873 if (rsurface_array_modelvertex3f)
2874 Mem_Free(rsurface_array_modelvertex3f);
2875 rsurface_array_size = (newvertices + 1023) & ~1023;
2876 base = (float *)Mem_Alloc(r_main_mempool, rsurface_array_size * sizeof(float[31]));
2877 rsurface_array_modelvertex3f = base + rsurface_array_size * 0;
2878 rsurface_array_modelsvector3f = base + rsurface_array_size * 3;
2879 rsurface_array_modeltvector3f = base + rsurface_array_size * 6;
2880 rsurface_array_modelnormal3f = base + rsurface_array_size * 9;
2881 rsurface_array_deformedvertex3f = base + rsurface_array_size * 12;
2882 rsurface_array_deformedsvector3f = base + rsurface_array_size * 15;
2883 rsurface_array_deformedtvector3f = base + rsurface_array_size * 18;
2884 rsurface_array_deformednormal3f = base + rsurface_array_size * 21;
2885 rsurface_array_texcoord3f = base + rsurface_array_size * 24;
2886 rsurface_array_color4f = base + rsurface_array_size * 27;
2889 float *rsurface_modelvertex3f;
2890 int rsurface_modelvertex3f_bufferobject;
2891 size_t rsurface_modelvertex3f_bufferoffset;
2892 float *rsurface_modelsvector3f;
2893 int rsurface_modelsvector3f_bufferobject;
2894 size_t rsurface_modelsvector3f_bufferoffset;
2895 float *rsurface_modeltvector3f;
2896 int rsurface_modeltvector3f_bufferobject;
2897 size_t rsurface_modeltvector3f_bufferoffset;
2898 float *rsurface_modelnormal3f;
2899 int rsurface_modelnormal3f_bufferobject;
2900 size_t rsurface_modelnormal3f_bufferoffset;
2901 float *rsurface_vertex3f;
2902 int rsurface_vertex3f_bufferobject;
2903 size_t rsurface_vertex3f_bufferoffset;
2904 float *rsurface_svector3f;
2905 int rsurface_svector3f_bufferobject;
2906 size_t rsurface_svector3f_bufferoffset;
2907 float *rsurface_tvector3f;
2908 int rsurface_tvector3f_bufferobject;
2909 size_t rsurface_tvector3f_bufferoffset;
2910 float *rsurface_normal3f;
2911 int rsurface_normal3f_bufferobject;
2912 size_t rsurface_normal3f_bufferoffset;
2913 float *rsurface_lightmapcolor4f;
2914 int rsurface_lightmapcolor4f_bufferobject;
2915 size_t rsurface_lightmapcolor4f_bufferoffset;
2916 vec3_t rsurface_modelorg;
2917 qboolean rsurface_generatedvertex;
2918 const entity_render_t *rsurface_entity;
2919 const model_t *rsurface_model;
2920 texture_t *rsurface_texture;
2921 qboolean rsurface_uselightmaptexture;
2922 rsurfmode_t rsurface_mode;
2923 int rsurface_lightmode; // 0 = lightmap or fullbright, 1 = color array from q3bsp, 2 = vertex shaded model
2925 void RSurf_CleanUp(void)
2928 if (rsurface_mode == RSURFMODE_GLSL)
2930 qglUseProgramObjectARB(0);CHECKGLERROR
2932 GL_AlphaTest(false);
2933 rsurface_mode = RSURFMODE_NONE;
2934 rsurface_uselightmaptexture = false;
2935 rsurface_texture = NULL;
2938 void RSurf_ActiveWorldEntity(void)
2941 rsurface_entity = r_refdef.worldentity;
2942 rsurface_model = r_refdef.worldmodel;
2943 if (rsurface_array_size < rsurface_model->surfmesh.num_vertices)
2944 R_Mesh_ResizeArrays(rsurface_model->surfmesh.num_vertices);
2945 R_Mesh_Matrix(&identitymatrix);
2946 VectorCopy(r_view.origin, rsurface_modelorg);
2947 rsurface_modelvertex3f = rsurface_model->surfmesh.data_vertex3f;
2948 rsurface_modelvertex3f_bufferobject = rsurface_model->surfmesh.vbo;
2949 rsurface_modelvertex3f_bufferoffset = rsurface_model->surfmesh.vbooffset_vertex3f;
2950 rsurface_modelsvector3f = rsurface_model->surfmesh.data_svector3f;
2951 rsurface_modelsvector3f_bufferobject = rsurface_model->surfmesh.vbo;
2952 rsurface_modelsvector3f_bufferoffset = rsurface_model->surfmesh.vbooffset_svector3f;
2953 rsurface_modeltvector3f = rsurface_model->surfmesh.data_tvector3f;
2954 rsurface_modeltvector3f_bufferobject = rsurface_model->surfmesh.vbo;
2955 rsurface_modeltvector3f_bufferoffset = rsurface_model->surfmesh.vbooffset_tvector3f;
2956 rsurface_modelnormal3f = rsurface_model->surfmesh.data_normal3f;
2957 rsurface_modelnormal3f_bufferobject = rsurface_model->surfmesh.vbo;
2958 rsurface_modelnormal3f_bufferoffset = rsurface_model->surfmesh.vbooffset_normal3f;
2959 rsurface_generatedvertex = false;
2960 rsurface_vertex3f = rsurface_modelvertex3f;
2961 rsurface_vertex3f_bufferobject = rsurface_modelvertex3f_bufferobject;
2962 rsurface_vertex3f_bufferoffset = rsurface_modelvertex3f_bufferoffset;
2963 rsurface_svector3f = rsurface_modelsvector3f;
2964 rsurface_svector3f_bufferobject = rsurface_modelsvector3f_bufferobject;
2965 rsurface_svector3f_bufferoffset = rsurface_modelsvector3f_bufferoffset;
2966 rsurface_tvector3f = rsurface_modeltvector3f;
2967 rsurface_tvector3f_bufferobject = rsurface_modeltvector3f_bufferobject;
2968 rsurface_tvector3f_bufferoffset = rsurface_modeltvector3f_bufferoffset;
2969 rsurface_normal3f = rsurface_modelnormal3f;
2970 rsurface_normal3f_bufferobject = rsurface_modelnormal3f_bufferobject;
2971 rsurface_normal3f_bufferoffset = rsurface_modelnormal3f_bufferoffset;
2974 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
2977 rsurface_entity = ent;
2978 rsurface_model = ent->model;
2979 if (rsurface_array_size < rsurface_model->surfmesh.num_vertices)
2980 R_Mesh_ResizeArrays(rsurface_model->surfmesh.num_vertices);
2981 R_Mesh_Matrix(&ent->matrix);
2982 Matrix4x4_Transform(&ent->inversematrix, r_view.origin, rsurface_modelorg);
2983 if (rsurface_model->surfmesh.isanimated && (rsurface_entity->frameblend[0].lerp != 1 || rsurface_entity->frameblend[0].frame != 0))
2987 rsurface_modelvertex3f = rsurface_array_modelvertex3f;
2988 rsurface_modelsvector3f = rsurface_array_modelsvector3f;
2989 rsurface_modeltvector3f = rsurface_array_modeltvector3f;
2990 rsurface_modelnormal3f = rsurface_array_modelnormal3f;
2991 Mod_Alias_GetMesh_Vertices(rsurface_model, rsurface_entity->frameblend, rsurface_array_modelvertex3f, rsurface_array_modelnormal3f, rsurface_array_modelsvector3f, rsurface_array_modeltvector3f);
2993 else if (wantnormals)
2995 rsurface_modelvertex3f = rsurface_array_modelvertex3f;
2996 rsurface_modelsvector3f = NULL;
2997 rsurface_modeltvector3f = NULL;
2998 rsurface_modelnormal3f = rsurface_array_modelnormal3f;
2999 Mod_Alias_GetMesh_Vertices(rsurface_model, rsurface_entity->frameblend, rsurface_array_modelvertex3f, rsurface_array_modelnormal3f, NULL, NULL);
3003 rsurface_modelvertex3f = rsurface_array_modelvertex3f;
3004 rsurface_modelsvector3f = NULL;
3005 rsurface_modeltvector3f = NULL;
3006 rsurface_modelnormal3f = NULL;
3007 Mod_Alias_GetMesh_Vertices(rsurface_model, rsurface_entity->frameblend, rsurface_array_modelvertex3f, NULL, NULL, NULL);
3009 rsurface_modelvertex3f_bufferobject = 0;
3010 rsurface_modelvertex3f_bufferoffset = 0;
3011 rsurface_modelsvector3f_bufferobject = 0;
3012 rsurface_modelsvector3f_bufferoffset = 0;
3013 rsurface_modeltvector3f_bufferobject = 0;
3014 rsurface_modeltvector3f_bufferoffset = 0;
3015 rsurface_modelnormal3f_bufferobject = 0;
3016 rsurface_modelnormal3f_bufferoffset = 0;
3017 rsurface_generatedvertex = true;
3021 rsurface_modelvertex3f = rsurface_model->surfmesh.data_vertex3f;
3022 rsurface_modelvertex3f_bufferobject = rsurface_model->surfmesh.vbo;
3023 rsurface_modelvertex3f_bufferoffset = rsurface_model->surfmesh.vbooffset_vertex3f;
3024 rsurface_modelsvector3f = rsurface_model->surfmesh.data_svector3f;
3025 rsurface_modelsvector3f_bufferobject = rsurface_model->surfmesh.vbo;
3026 rsurface_modelsvector3f_bufferoffset = rsurface_model->surfmesh.vbooffset_svector3f;
3027 rsurface_modeltvector3f = rsurface_model->surfmesh.data_tvector3f;
3028 rsurface_modeltvector3f_bufferobject = rsurface_model->surfmesh.vbo;
3029 rsurface_modeltvector3f_bufferoffset = rsurface_model->surfmesh.vbooffset_tvector3f;
3030 rsurface_modelnormal3f = rsurface_model->surfmesh.data_normal3f;
3031 rsurface_modelnormal3f_bufferobject = rsurface_model->surfmesh.vbo;
3032 rsurface_modelnormal3f_bufferoffset = rsurface_model->surfmesh.vbooffset_normal3f;
3033 rsurface_generatedvertex = false;
3035 rsurface_vertex3f = rsurface_modelvertex3f;
3036 rsurface_vertex3f_bufferobject = rsurface_modelvertex3f_bufferobject;
3037 rsurface_vertex3f_bufferoffset = rsurface_modelvertex3f_bufferoffset;
3038 rsurface_svector3f = rsurface_modelsvector3f;
3039 rsurface_svector3f_bufferobject = rsurface_modelsvector3f_bufferobject;
3040 rsurface_svector3f_bufferoffset = rsurface_modelsvector3f_bufferoffset;
3041 rsurface_tvector3f = rsurface_modeltvector3f;
3042 rsurface_tvector3f_bufferobject = rsurface_modeltvector3f_bufferobject;
3043 rsurface_tvector3f_bufferoffset = rsurface_modeltvector3f_bufferoffset;
3044 rsurface_normal3f = rsurface_modelnormal3f;
3045 rsurface_normal3f_bufferobject = rsurface_modelnormal3f_bufferobject;
3046 rsurface_normal3f_bufferoffset = rsurface_modelnormal3f_bufferoffset;
3049 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, msurface_t **texturesurfacelist)
3051 // 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
3052 if (rsurface_generatedvertex)
3054 if (rsurface_texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
3055 generatetangents = true;
3056 if (generatetangents)
3057 generatenormals = true;
3058 if (generatenormals && !rsurface_modelnormal3f)
3060 rsurface_normal3f = rsurface_modelnormal3f = rsurface_array_modelnormal3f;
3061 rsurface_normal3f_bufferobject = rsurface_modelnormal3f_bufferobject = 0;
3062 rsurface_normal3f_bufferoffset = rsurface_modelnormal3f_bufferoffset = 0;
3063 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);
3065 if (generatetangents && !rsurface_modelsvector3f)
3067 rsurface_svector3f = rsurface_modelsvector3f = rsurface_array_modelsvector3f;
3068 rsurface_svector3f_bufferobject = rsurface_modelsvector3f_bufferobject = 0;
3069 rsurface_svector3f_bufferoffset = rsurface_modelsvector3f_bufferoffset = 0;
3070 rsurface_tvector3f = rsurface_modeltvector3f = rsurface_array_modeltvector3f;
3071 rsurface_tvector3f_bufferobject = rsurface_modeltvector3f_bufferobject = 0;
3072 rsurface_tvector3f_bufferoffset = rsurface_modeltvector3f_bufferoffset = 0;
3073 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);
3076 // 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)
3077 if (rsurface_texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
3079 int texturesurfaceindex;
3080 float center[3], forward[3], right[3], up[3], v[4][3];
3081 matrix4x4_t matrix1, imatrix1;
3082 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_view.forward, forward);
3083 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_view.right, right);
3084 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_view.up, up);
3085 // make deformed versions of only the model vertices used by the specified surfaces
3086 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3089 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3090 // a single autosprite surface can contain multiple sprites...
3091 for (j = 0;j < surface->num_vertices - 3;j += 4)
3093 VectorClear(center);
3094 for (i = 0;i < 4;i++)
3095 VectorAdd(center, (rsurface_modelvertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
3096 VectorScale(center, 0.25f, center);
3097 if (rsurface_texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE2)
3099 forward[0] = rsurface_modelorg[0] - center[0];
3100 forward[1] = rsurface_modelorg[1] - center[1];
3102 VectorNormalize(forward);
3103 right[0] = forward[1];
3104 right[1] = -forward[0];
3106 VectorSet(up, 0, 0, 1);
3108 // FIXME: calculate vectors from triangle edges instead of using texture vectors as an easy way out?
3109 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);
3110 Matrix4x4_Invert_Simple(&imatrix1, &matrix1);
3111 for (i = 0;i < 4;i++)
3112 Matrix4x4_Transform(&imatrix1, (rsurface_modelvertex3f + 3 * surface->num_firstvertex) + (j+i)*3, v[i]);
3113 for (i = 0;i < 4;i++)
3114 VectorMAMAMAM(1, center, v[i][0], forward, v[i][1], right, v[i][2], up, rsurface_array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
3116 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);
3117 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);
3119 rsurface_vertex3f = rsurface_array_deformedvertex3f;
3120 rsurface_vertex3f_bufferobject = 0;
3121 rsurface_vertex3f_bufferoffset = 0;
3122 rsurface_svector3f = rsurface_array_deformedsvector3f;
3123 rsurface_svector3f_bufferobject = 0;
3124 rsurface_svector3f_bufferoffset = 0;
3125 rsurface_tvector3f = rsurface_array_deformedtvector3f;
3126 rsurface_tvector3f_bufferobject = 0;
3127 rsurface_tvector3f_bufferoffset = 0;
3128 rsurface_normal3f = rsurface_array_deformednormal3f;
3129 rsurface_normal3f_bufferobject = 0;
3130 rsurface_normal3f_bufferoffset = 0;
3134 rsurface_vertex3f = rsurface_modelvertex3f;
3135 rsurface_vertex3f_bufferobject = rsurface_modelvertex3f_bufferobject;
3136 rsurface_vertex3f_bufferoffset = rsurface_modelvertex3f_bufferoffset;
3137 rsurface_svector3f = rsurface_modelsvector3f;
3138 rsurface_svector3f_bufferobject = rsurface_modelsvector3f_bufferobject;
3139 rsurface_svector3f_bufferoffset = rsurface_modelsvector3f_bufferoffset;
3140 rsurface_tvector3f = rsurface_modeltvector3f;
3141 rsurface_tvector3f_bufferobject = rsurface_modeltvector3f_bufferobject;
3142 rsurface_tvector3f_bufferoffset = rsurface_modeltvector3f_bufferoffset;
3143 rsurface_normal3f = rsurface_modelnormal3f;
3144 rsurface_normal3f_bufferobject = rsurface_modelnormal3f_bufferobject;
3145 rsurface_normal3f_bufferoffset = rsurface_modelnormal3f_bufferoffset;
3147 R_Mesh_VertexPointer(rsurface_vertex3f, rsurface_vertex3f_bufferobject, rsurface_vertex3f_bufferoffset);
3150 void RSurf_DrawBatch_Simple(int texturenumsurfaces, msurface_t **texturesurfacelist)
3153 const msurface_t *surface = texturesurfacelist[0];
3154 const msurface_t *surface2;
3159 // TODO: lock all array ranges before render, rather than on each surface
3160 if (texturenumsurfaces == 1)
3162 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
3163 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));
3165 else if (r_batchmode.integer == 2)
3167 #define MAXBATCHTRIANGLES 4096
3168 int batchtriangles = 0;
3169 int batchelements[MAXBATCHTRIANGLES*3];
3170 for (i = 0;i < texturenumsurfaces;i = j)
3172 surface = texturesurfacelist[i];
3174 if (surface->num_triangles > MAXBATCHTRIANGLES)
3176 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));
3179 memcpy(batchelements, rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
3180 batchtriangles = surface->num_triangles;
3181 firstvertex = surface->num_firstvertex;
3182 endvertex = surface->num_firstvertex + surface->num_vertices;
3183 for (;j < texturenumsurfaces;j++)
3185 surface2 = texturesurfacelist[j];
3186 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
3188 memcpy(batchelements + batchtriangles * 3, rsurface_model->surfmesh.data_element3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
3189 batchtriangles += surface2->num_triangles;
3190 firstvertex = min(firstvertex, surface2->num_firstvertex);
3191 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
3193 surface2 = texturesurfacelist[j-1];
3194 numvertices = endvertex - firstvertex;
3195 R_Mesh_Draw(firstvertex, numvertices, batchtriangles, batchelements, 0, 0);
3198 else if (r_batchmode.integer == 1)
3200 for (i = 0;i < texturenumsurfaces;i = j)
3202 surface = texturesurfacelist[i];
3203 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
3204 if (texturesurfacelist[j] != surface2)
3206 surface2 = texturesurfacelist[j-1];
3207 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
3208 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
3209 GL_LockArrays(surface->num_firstvertex, numvertices);
3210 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));
3215 for (i = 0;i < texturenumsurfaces;i++)
3217 surface = texturesurfacelist[i];
3218 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
3219 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));
3224 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit)
3228 const msurface_t *surface = texturesurfacelist[0];
3229 const msurface_t *surface2;
3234 // TODO: lock all array ranges before render, rather than on each surface
3235 if (texturenumsurfaces == 1)
3237 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
3238 if (deluxemaptexunit >= 0)
3239 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
3240 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
3241 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));
3243 else if (r_batchmode.integer == 2)
3245 #define MAXBATCHTRIANGLES 4096
3246 int batchtriangles = 0;
3247 int batchelements[MAXBATCHTRIANGLES*3];
3248 for (i = 0;i < texturenumsurfaces;i = j)
3250 surface = texturesurfacelist[i];
3251 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
3252 if (deluxemaptexunit >= 0)
3253 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
3255 if (surface->num_triangles > MAXBATCHTRIANGLES)
3257 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));
3260 memcpy(batchelements, rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
3261 batchtriangles = surface->num_triangles;
3262 firstvertex = surface->num_firstvertex;
3263 endvertex = surface->num_firstvertex + surface->num_vertices;
3264 for (;j < texturenumsurfaces;j++)
3266 surface2 = texturesurfacelist[j];
3267 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
3269 memcpy(batchelements + batchtriangles * 3, rsurface_model->surfmesh.data_element3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
3270 batchtriangles += surface2->num_triangles;
3271 firstvertex = min(firstvertex, surface2->num_firstvertex);
3272 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
3274 surface2 = texturesurfacelist[j-1];
3275 numvertices = endvertex - firstvertex;
3276 R_Mesh_Draw(firstvertex, numvertices, batchtriangles, batchelements, 0, 0);
3279 else if (r_batchmode.integer == 1)
3282 Con_Printf("%s batch sizes ignoring lightmap:", rsurface_texture->name);
3283 for (i = 0;i < texturenumsurfaces;i = j)
3285 surface = texturesurfacelist[i];
3286 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
3287 if (texturesurfacelist[j] != surface2)
3289 Con_Printf(" %i", j - i);
3292 Con_Printf("%s batch sizes honoring lightmap:", rsurface_texture->name);
3294 for (i = 0;i < texturenumsurfaces;i = j)
3296 surface = texturesurfacelist[i];
3297 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
3298 if (deluxemaptexunit >= 0)
3299 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
3300 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
3301 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
3304 Con_Printf(" %i", j - i);
3306 surface2 = texturesurfacelist[j-1];
3307 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
3308 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
3309 GL_LockArrays(surface->num_firstvertex, numvertices);
3310 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));
3318 for (i = 0;i < texturenumsurfaces;i++)
3320 surface = texturesurfacelist[i];
3321 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
3322 if (deluxemaptexunit >= 0)
3323 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
3324 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
3325 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));
3330 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
3333 int texturesurfaceindex;
3334 if (r_showsurfaces.integer == 2)
3336 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3338 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3339 for (j = 0;j < surface->num_triangles;j++)
3341 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_view.colorscale;
3342 GL_Color(f, f, f, 1);
3343 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)));
3349 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3351 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3352 int k = (int)(((size_t)surface) / sizeof(msurface_t));
3353 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);
3354 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
3355 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));
3360 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, msurface_t **texturesurfacelist)
3362 int texturesurfaceindex;
3366 if (rsurface_lightmapcolor4f)
3368 // generate color arrays for the surfaces in this list
3369 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3371 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3372 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)
3374 f = 1 - VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
3384 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3386 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3387 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)
3389 f = 1 - VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
3397 rsurface_lightmapcolor4f = rsurface_array_color4f;
3398 rsurface_lightmapcolor4f_bufferobject = 0;
3399 rsurface_lightmapcolor4f_bufferoffset = 0;
3402 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a)
3404 int texturesurfaceindex;
3407 if (!rsurface_lightmapcolor4f)
3409 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3411 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3412 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)
3420 rsurface_lightmapcolor4f = rsurface_array_color4f;
3421 rsurface_lightmapcolor4f_bufferobject = 0;
3422 rsurface_lightmapcolor4f_bufferoffset = 0;
3425 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
3428 rsurface_lightmapcolor4f = NULL;
3429 rsurface_lightmapcolor4f_bufferobject = 0;
3430 rsurface_lightmapcolor4f_bufferoffset = 0;
3431 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
3432 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
3433 R_Mesh_ColorPointer(rsurface_lightmapcolor4f, rsurface_lightmapcolor4f_bufferobject, rsurface_lightmapcolor4f_bufferoffset);
3434 GL_Color(r, g, b, a);
3435 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 0, -1);
3438 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
3440 // TODO: optimize applyfog && applycolor case
3441 // just apply fog if necessary, and tint the fog color array if necessary
3442 rsurface_lightmapcolor4f = NULL;
3443 rsurface_lightmapcolor4f_bufferobject = 0;
3444 rsurface_lightmapcolor4f_bufferoffset = 0;
3445 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
3446 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
3447 R_Mesh_ColorPointer(rsurface_lightmapcolor4f, rsurface_lightmapcolor4f_bufferobject, rsurface_lightmapcolor4f_bufferoffset);
3448 GL_Color(r, g, b, a);
3449 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3452 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
3454 int texturesurfaceindex;
3458 if (texturesurfacelist[0]->lightmapinfo && texturesurfacelist[0]->lightmapinfo->stainsamples)
3460 // generate color arrays for the surfaces in this list
3461 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3463 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3464 for (i = 0, c = rsurface_array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
3466 if (surface->lightmapinfo->samples)
3468 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface_model->surfmesh.data_lightmapoffsets + surface->num_firstvertex)[i];
3469 float scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
3470 VectorScale(lm, scale, c);
3471 if (surface->lightmapinfo->styles[1] != 255)
3473 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
3475 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
3476 VectorMA(c, scale, lm, c);
3477 if (surface->lightmapinfo->styles[2] != 255)
3480 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
3481 VectorMA(c, scale, lm, c);
3482 if (surface->lightmapinfo->styles[3] != 255)
3485 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
3486 VectorMA(c, scale, lm, c);
3496 rsurface_lightmapcolor4f = rsurface_array_color4f;
3497 rsurface_lightmapcolor4f_bufferobject = 0;
3498 rsurface_lightmapcolor4f_bufferoffset = 0;
3502 rsurface_lightmapcolor4f = rsurface_model->surfmesh.data_lightmapcolor4f;
3503 rsurface_lightmapcolor4f_bufferobject = rsurface_model->surfmesh.vbo;
3504 rsurface_lightmapcolor4f_bufferoffset = rsurface_model->surfmesh.vbooffset_lightmapcolor4f;
3506 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
3507 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
3508 R_Mesh_ColorPointer(rsurface_lightmapcolor4f, rsurface_lightmapcolor4f_bufferobject, rsurface_lightmapcolor4f_bufferoffset);
3509 GL_Color(r, g, b, a);
3510 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3513 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
3515 int texturesurfaceindex;
3519 vec3_t ambientcolor;
3520 vec3_t diffusecolor;
3524 VectorCopy(rsurface_entity->modellight_lightdir, lightdir);
3525 ambientcolor[0] = rsurface_entity->modellight_ambient[0] * r * 0.5f;
3526 ambientcolor[1] = rsurface_entity->modellight_ambient[1] * g * 0.5f;
3527 ambientcolor[2] = rsurface_entity->modellight_ambient[2] * b * 0.5f;
3528 diffusecolor[0] = rsurface_entity->modellight_diffuse[0] * r * 0.5f;
3529 diffusecolor[1] = rsurface_entity->modellight_diffuse[1] * g * 0.5f;
3530 diffusecolor[2] = rsurface_entity->modellight_diffuse[2] * b * 0.5f;
3531 if (VectorLength2(diffusecolor) > 0)
3533 // generate color arrays for the surfaces in this list
3534 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3536 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3537 int numverts = surface->num_vertices;
3538 v = rsurface_vertex3f + 3 * surface->num_firstvertex;
3539 c2 = rsurface_normal3f + 3 * surface->num_firstvertex;
3540 c = rsurface_array_color4f + 4 * surface->num_firstvertex;
3541 // q3-style directional shading
3542 for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
3544 if ((f = DotProduct(c2, lightdir)) > 0)
3545 VectorMA(ambientcolor, f, diffusecolor, c);
3547 VectorCopy(ambientcolor, c);
3556 rsurface_lightmapcolor4f = rsurface_array_color4f;
3557 rsurface_lightmapcolor4f_bufferobject = 0;
3558 rsurface_lightmapcolor4f_bufferoffset = 0;
3562 r = ambientcolor[0];
3563 g = ambientcolor[1];
3564 b = ambientcolor[2];
3565 rsurface_lightmapcolor4f = NULL;
3566 rsurface_lightmapcolor4f_bufferobject = 0;
3567 rsurface_lightmapcolor4f_bufferoffset = 0;
3569 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
3570 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
3571 R_Mesh_ColorPointer(rsurface_lightmapcolor4f, rsurface_lightmapcolor4f_bufferobject, rsurface_lightmapcolor4f_bufferoffset);
3572 GL_Color(r, g, b, a);
3573 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3576 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
3578 GL_DepthRange(0, (rsurface_texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
3579 GL_DepthTest(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
3580 GL_CullFace((rsurface_texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
3581 if (rsurface_mode != RSURFMODE_SHOWSURFACES)
3583 rsurface_mode = RSURFMODE_SHOWSURFACES;
3585 GL_BlendFunc(GL_ONE, GL_ZERO);
3586 R_Mesh_ColorPointer(NULL, 0, 0);
3587 R_Mesh_ResetTextureState();
3589 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
3590 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
3593 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, msurface_t **texturesurfacelist)
3595 // transparent sky would be ridiculous
3596 if ((rsurface_texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED))
3598 if (rsurface_mode != RSURFMODE_SKY)
3600 if (rsurface_mode == RSURFMODE_GLSL)
3602 qglUseProgramObjectARB(0);CHECKGLERROR
3604 rsurface_mode = RSURFMODE_SKY;
3608 skyrendernow = false;
3610 // restore entity matrix
3611 R_Mesh_Matrix(&rsurface_entity->matrix);
3613 GL_DepthRange(0, (rsurface_texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
3614 GL_DepthTest(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
3615 GL_CullFace((rsurface_texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
3617 // LordHavoc: HalfLife maps have freaky skypolys so don't use
3618 // skymasking on them, and Quake3 never did sky masking (unlike
3619 // software Quake and software Quake2), so disable the sky masking
3620 // in Quake3 maps as it causes problems with q3map2 sky tricks,
3621 // and skymasking also looks very bad when noclipping outside the
3622 // level, so don't use it then either.
3623 if (rsurface_model->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_viewcache.world_novis)
3625 GL_Color(r_refdef.fogcolor[0] * r_view.colorscale, r_refdef.fogcolor[1] * r_view.colorscale, r_refdef.fogcolor[2] * r_view.colorscale, 1);
3626 R_Mesh_ColorPointer(NULL, 0, 0);
3627 R_Mesh_ResetTextureState();
3628 if (skyrendermasked)
3630 // depth-only (masking)
3631 GL_ColorMask(0,0,0,0);
3632 // just to make sure that braindead drivers don't draw
3633 // anything despite that colormask...
3634 GL_BlendFunc(GL_ZERO, GL_ONE);
3639 GL_BlendFunc(GL_ONE, GL_ZERO);
3641 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
3642 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3643 if (skyrendermasked)
3644 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
3648 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, msurface_t **texturesurfacelist)
3650 if (rsurface_mode != RSURFMODE_GLSL)
3652 rsurface_mode = RSURFMODE_GLSL;
3653 R_Mesh_ResetTextureState();
3656 R_SetupSurfaceShader(vec3_origin, rsurface_lightmode == 2, 1, 1, rsurface_texture->specularscale);
3657 if (!r_glsl_permutation)
3660 if (rsurface_lightmode == 2)
3661 RSurf_PrepareVerticesForBatch(true, r_glsl_permutation->loc_Texture_Normal, texturenumsurfaces, texturesurfacelist);
3663 RSurf_PrepareVerticesForBatch(r_glsl_permutation->loc_Texture_Normal, r_glsl_permutation->loc_Texture_Normal, texturenumsurfaces, texturesurfacelist);
3664 R_Mesh_TexCoordPointer(0, 2, rsurface_model->surfmesh.data_texcoordtexture2f, rsurface_model->surfmesh.vbo, rsurface_model->surfmesh.vbooffset_texcoordtexture2f);
3665 R_Mesh_TexCoordPointer(1, 3, rsurface_svector3f, rsurface_svector3f_bufferobject, rsurface_svector3f_bufferoffset);
3666 R_Mesh_TexCoordPointer(2, 3, rsurface_tvector3f, rsurface_tvector3f_bufferobject, rsurface_tvector3f_bufferoffset);
3667 R_Mesh_TexCoordPointer(3, 3, rsurface_normal3f, rsurface_normal3f_bufferobject, rsurface_normal3f_bufferoffset);
3668 R_Mesh_TexCoordPointer(4, 2, rsurface_model->surfmesh.data_texcoordlightmap2f, rsurface_model->surfmesh.vbo, rsurface_model->surfmesh.vbooffset_texcoordlightmap2f);
3670 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
3672 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
3673 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
3674 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
3675 R_Mesh_ColorPointer(NULL, 0, 0);
3677 else if (rsurface_uselightmaptexture)
3679 R_Mesh_TexBind(7, R_GetTexture(texturesurfacelist[0]->lightmaptexture));
3680 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
3681 R_Mesh_TexBind(8, R_GetTexture(texturesurfacelist[0]->deluxemaptexture));
3682 R_Mesh_ColorPointer(NULL, 0, 0);
3686 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
3687 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
3688 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
3689 R_Mesh_ColorPointer(rsurface_model->surfmesh.data_lightmapcolor4f, rsurface_model->surfmesh.vbo, rsurface_model->surfmesh.vbooffset_lightmapcolor4f);
3692 if (rsurface_uselightmaptexture && !(rsurface_texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
3693 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 7, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? 8 : -1);
3695 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3696 if (rsurface_texture->backgroundnumskinframes && !(rsurface_texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED))
3701 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, msurface_t **texturesurfacelist)
3703 // OpenGL 1.3 path - anything not completely ancient
3704 int texturesurfaceindex;
3705 qboolean applycolor;
3709 const texturelayer_t *layer;
3710 if (rsurface_mode != RSURFMODE_MULTIPASS)
3711 rsurface_mode = RSURFMODE_MULTIPASS;
3712 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
3713 for (layerindex = 0, layer = rsurface_texture->currentlayers;layerindex < rsurface_texture->currentnumlayers;layerindex++, layer++)
3716 int layertexrgbscale;
3717 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
3719 if (layerindex == 0)
3723 GL_AlphaTest(false);
3724 qglDepthFunc(GL_EQUAL);CHECKGLERROR
3727 GL_DepthMask(layer->depthmask);
3728 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
3729 if ((layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2) && (gl_combine.integer || layer->depthmask))
3731 layertexrgbscale = 4;
3732 VectorScale(layer->color, 0.25f, layercolor);
3734 else if ((layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1) && (gl_combine.integer || layer->depthmask))
3736 layertexrgbscale = 2;
3737 VectorScale(layer->color, 0.5f, layercolor);
3741 layertexrgbscale = 1;
3742 VectorScale(layer->color, 1.0f, layercolor);
3744 layercolor[3] = layer->color[3];
3745 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
3746 R_Mesh_ColorPointer(NULL, 0, 0);
3747 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
3748 switch (layer->type)
3750 case TEXTURELAYERTYPE_LITTEXTURE:
3751 memset(&m, 0, sizeof(m));
3752 m.tex[0] = R_GetTexture(r_texture_white);
3753 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordlightmap2f;
3754 m.pointer_texcoord_bufferobject[0] = rsurface_model->surfmesh.vbo;
3755 m.pointer_texcoord_bufferoffset[0] = rsurface_model->surfmesh.vbooffset_texcoordlightmap2f;
3756 m.tex[1] = R_GetTexture(layer->texture);
3757 m.texmatrix[1] = layer->texmatrix;
3758 m.texrgbscale[1] = layertexrgbscale;
3759 m.pointer_texcoord[1] = rsurface_model->surfmesh.data_texcoordtexture2f;
3760 m.pointer_texcoord_bufferobject[1] = rsurface_model->surfmesh.vbo;
3761 m.pointer_texcoord_bufferoffset[1] = rsurface_model->surfmesh.vbooffset_texcoordtexture2f;
3762 R_Mesh_TextureState(&m);
3763 if (rsurface_lightmode == 2)
3764 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
3765 else if (rsurface_uselightmaptexture)
3766 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
3768 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
3770 case TEXTURELAYERTYPE_TEXTURE:
3771 memset(&m, 0, sizeof(m));
3772 m.tex[0] = R_GetTexture(layer->texture);
3773 m.texmatrix[0] = layer->texmatrix;
3774 m.texrgbscale[0] = layertexrgbscale;
3775 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3776 m.pointer_texcoord_bufferobject[0] = rsurface_model->surfmesh.vbo;
3777 m.pointer_texcoord_bufferoffset[0] = rsurface_model->surfmesh.vbooffset_texcoordtexture2f;
3778 R_Mesh_TextureState(&m);
3779 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
3781 case TEXTURELAYERTYPE_FOG:
3782 memset(&m, 0, sizeof(m));
3783 m.texrgbscale[0] = layertexrgbscale;
3786 m.tex[0] = R_GetTexture(layer->texture);
3787 m.texmatrix[0] = layer->texmatrix;
3788 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3789 m.pointer_texcoord_bufferobject[0] = rsurface_model->surfmesh.vbo;
3790 m.pointer_texcoord_bufferoffset[0] = rsurface_model->surfmesh.vbooffset_texcoordtexture2f;
3792 R_Mesh_TextureState(&m);
3793 // generate a color array for the fog pass
3794 R_Mesh_ColorPointer(rsurface_array_color4f, 0, 0);
3795 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3799 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3800 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)
3802 f = VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
3803 c[0] = layercolor[0];
3804 c[1] = layercolor[1];
3805 c[2] = layercolor[2];
3806 c[3] = f * layercolor[3];
3809 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3812 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
3814 GL_LockArrays(0, 0);
3817 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
3819 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3820 GL_AlphaTest(false);
3824 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, msurface_t **texturesurfacelist)
3826 // OpenGL 1.1 - crusty old voodoo path
3827 int texturesurfaceindex;
3831 const texturelayer_t *layer;
3832 if (rsurface_mode != RSURFMODE_MULTIPASS)
3833 rsurface_mode = RSURFMODE_MULTIPASS;
3834 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
3835 for (layerindex = 0, layer = rsurface_texture->currentlayers;layerindex < rsurface_texture->currentnumlayers;layerindex++, layer++)
3837 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
3839 if (layerindex == 0)
3843 GL_AlphaTest(false);
3844 qglDepthFunc(GL_EQUAL);CHECKGLERROR
3847 GL_DepthMask(layer->depthmask);
3848 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
3849 R_Mesh_ColorPointer(NULL, 0, 0);
3850 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
3851 switch (layer->type)
3853 case TEXTURELAYERTYPE_LITTEXTURE:
3854 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
3856 // two-pass lit texture with 2x rgbscale
3857 // first the lightmap pass
3858 memset(&m, 0, sizeof(m));
3859 m.tex[0] = R_GetTexture(r_texture_white);
3860 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordlightmap2f;
3861 m.pointer_texcoord_bufferobject[0] = rsurface_model->surfmesh.vbo;
3862 m.pointer_texcoord_bufferoffset[0] = rsurface_model->surfmesh.vbooffset_texcoordlightmap2f;
3863 R_Mesh_TextureState(&m);
3864 if (rsurface_lightmode == 2)
3865 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
3866 else if (rsurface_uselightmaptexture)
3867 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
3869 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
3870 GL_LockArrays(0, 0);
3871 // then apply the texture to it
3872 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
3873 memset(&m, 0, sizeof(m));
3874 m.tex[0] = R_GetTexture(layer->texture);
3875 m.texmatrix[0] = layer->texmatrix;
3876 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3877 m.pointer_texcoord_bufferobject[0] = rsurface_model->surfmesh.vbo;
3878 m.pointer_texcoord_bufferoffset[0] = rsurface_model->surfmesh.vbooffset_texcoordtexture2f;
3879 R_Mesh_TextureState(&m);
3880 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);
3884 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
3885 memset(&m, 0, sizeof(m));
3886 m.tex[0] = R_GetTexture(layer->texture);
3887 m.texmatrix[0] = layer->texmatrix;
3888 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3889 m.pointer_texcoord_bufferobject[0] = rsurface_model->surfmesh.vbo;
3890 m.pointer_texcoord_bufferoffset[0] = rsurface_model->surfmesh.vbooffset_texcoordtexture2f;
3891 R_Mesh_TextureState(&m);
3892 if (rsurface_lightmode == 2)
3893 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);
3895 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);
3898 case TEXTURELAYERTYPE_TEXTURE:
3899 // singletexture unlit texture with transparency support
3900 memset(&m, 0, sizeof(m));
3901 m.tex[0] = R_GetTexture(layer->texture);
3902 m.texmatrix[0] = layer->texmatrix;
3903 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3904 m.pointer_texcoord_bufferobject[0] = rsurface_model->surfmesh.vbo;
3905 m.pointer_texcoord_bufferoffset[0] = rsurface_model->surfmesh.vbooffset_texcoordtexture2f;
3906 R_Mesh_TextureState(&m);
3907 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);
3909 case TEXTURELAYERTYPE_FOG:
3910 // singletexture fogging
3911 R_Mesh_ColorPointer(rsurface_array_color4f, 0, 0);
3914 memset(&m, 0, sizeof(m));
3915 m.tex[0] = R_GetTexture(layer->texture);
3916 m.texmatrix[0] = layer->texmatrix;
3917 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3918 m.pointer_texcoord_bufferobject[0] = rsurface_model->surfmesh.vbo;
3919 m.pointer_texcoord_bufferoffset[0] = rsurface_model->surfmesh.vbooffset_texcoordtexture2f;
3920 R_Mesh_TextureState(&m);
3923 R_Mesh_ResetTextureState();
3924 // generate a color array for the fog pass
3925 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3929 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3930 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)
3932 f = VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
3933 c[0] = layer->color[0];
3934 c[1] = layer->color[1];
3935 c[2] = layer->color[2];
3936 c[3] = f * layer->color[3];
3939 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3942 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
3944 GL_LockArrays(0, 0);
3947 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
3949 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3950 GL_AlphaTest(false);
3954 static void R_DrawTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist)
3956 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_NODRAW)
3958 r_shadow_rtlight = NULL;
3959 r_refdef.stats.entities_surfaces += texturenumsurfaces;
3961 if (r_showsurfaces.integer)
3962 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
3963 else if (rsurface_texture->currentmaterialflags & MATERIALFLAG_SKY)
3964 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
3965 else if (rsurface_texture->currentnumlayers)
3967 GL_DepthRange(0, (rsurface_texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
3968 GL_DepthTest(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
3969 GL_CullFace((rsurface_texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
3970 GL_BlendFunc(rsurface_texture->currentlayers[0].blendfunc1, rsurface_texture->currentlayers[0].blendfunc2);
3971 GL_DepthMask(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_BLENDED));
3972 GL_Color(rsurface_entity->colormod[0], rsurface_entity->colormod[1], rsurface_entity->colormod[2], rsurface_texture->currentalpha);
3973 GL_AlphaTest((rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
3974 // FIXME: identify models using a better check than rsurface_model->brush.shadowmesh
3975 rsurface_lightmode = ((rsurface_texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT) || rsurface_model->brush.shadowmesh) ? 0 : 2;
3976 if (r_glsl.integer && gl_support_fragment_shader)
3977 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist);
3978 else if (gl_combine.integer && r_textureunits.integer >= 2)
3979 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist);
3981 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist);
3984 GL_LockArrays(0, 0);
3987 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
3990 int texturenumsurfaces, endsurface;
3992 msurface_t *surface;
3993 msurface_t *texturesurfacelist[1024];
3995 // if the model is static it doesn't matter what value we give for
3996 // wantnormals and wanttangents, so this logic uses only rules applicable
3997 // to a model, knowing that they are meaningless otherwise
3998 if (ent == r_refdef.worldentity)
3999 RSurf_ActiveWorldEntity();
4000 else if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
4001 RSurf_ActiveModelEntity(ent, false, false);
4003 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
4005 for (i = 0;i < numsurfaces;i = j)
4008 surface = rsurface_model->data_surfaces + surfacelist[i];
4009 texture = surface->texture;
4010 R_UpdateTextureInfo(ent, texture);
4011 rsurface_texture = texture->currentframe;
4012 rsurface_uselightmaptexture = surface->lightmaptexture != NULL;
4013 // scan ahead until we find a different texture
4014 endsurface = min(i + 1024, numsurfaces);
4015 texturenumsurfaces = 0;
4016 texturesurfacelist[texturenumsurfaces++] = surface;
4017 for (;j < endsurface;j++)
4019 surface = rsurface_model->data_surfaces + surfacelist[j];
4020 if (texture != surface->texture || rsurface_uselightmaptexture != (surface->lightmaptexture != NULL))
4022 texturesurfacelist[texturenumsurfaces++] = surface;
4024 // render the range of surfaces
4025 R_DrawTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
4031 void R_QueueSurfaceList(int numsurfaces, msurface_t **surfacelist, int flagsmask)
4034 vec3_t tempcenter, center;
4036 // break the surface list down into batches by texture and use of lightmapping
4037 for (i = 0;i < numsurfaces;i = j)
4040 // texture is the base texture pointer, rsurface_texture is the
4041 // current frame/skin the texture is directing us to use (for example
4042 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
4043 // use skin 1 instead)
4044 texture = surfacelist[i]->texture;
4045 rsurface_texture = texture->currentframe;
4046 rsurface_uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
4047 if (!(rsurface_texture->currentmaterialflags & flagsmask))
4049 // if this texture is not the kind we want, skip ahead to the next one
4050 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
4054 if (rsurface_texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
4056 // transparent surfaces get pushed off into the transparent queue
4057 const msurface_t *surface = surfacelist[i];
4058 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
4059 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
4060 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
4061 Matrix4x4_Transform(&rsurface_entity->matrix, tempcenter, center);
4062 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);
4066 // simply scan ahead until we find a different texture or lightmap state
4067 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface_uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
4069 // render the range of surfaces
4070 R_DrawTextureSurfaceList(j - i, surfacelist + i);
4075 float locboxvertex3f[6*4*3] =
4077 1,0,1, 1,0,0, 1,1,0, 1,1,1,
4078 0,1,1, 0,1,0, 0,0,0, 0,0,1,
4079 1,1,1, 1,1,0, 0,1,0, 0,1,1,
4080 0,0,1, 0,0,0, 1,0,0, 1,0,1,
4081 0,0,1, 1,0,1, 1,1,1, 0,1,1,
4082 1,0,0, 0,0,0, 0,1,0, 1,1,0
4085 int locboxelement3i[6*2*3] =
4095 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
4098 cl_locnode_t *loc = (cl_locnode_t *)ent;
4100 float vertex3f[6*4*3];
4102 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4103 GL_DepthMask(false);
4104 GL_DepthRange(0, 1);
4106 GL_CullFace(GL_NONE);
4107 R_Mesh_Matrix(&identitymatrix);
4109 R_Mesh_VertexPointer(vertex3f, 0, 0);
4110 R_Mesh_ColorPointer(NULL, 0, 0);
4111 R_Mesh_ResetTextureState();
4114 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_view.colorscale,
4115 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_view.colorscale,
4116 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_view.colorscale,
4117 surfacelist[0] < 0 ? 0.5f : 0.125f);
4119 if (VectorCompare(loc->mins, loc->maxs))
4121 VectorSet(size, 2, 2, 2);
4122 VectorMA(loc->mins, -0.5f, size, mins);
4126 VectorCopy(loc->mins, mins);
4127 VectorSubtract(loc->maxs, loc->mins, size);
4130 for (i = 0;i < 6*4*3;)
4131 for (j = 0;j < 3;j++, i++)
4132 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
4134 R_Mesh_Draw(0, 6*4, 6*2, locboxelement3i, 0, 0);
4137 void R_DrawLocs(void)
4140 cl_locnode_t *loc, *nearestloc;
4142 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
4143 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
4145 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
4146 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
4150 void R_DrawCollisionBrushes(entity_render_t *ent)
4154 msurface_t *surface;
4155 model_t *model = ent->model;
4156 if (!model->brush.num_brushes)
4159 R_Mesh_ColorPointer(NULL, 0, 0);
4160 R_Mesh_ResetTextureState();
4161 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
4162 GL_DepthMask(false);
4163 GL_DepthRange(0, 1);
4164 GL_DepthTest(!r_showdisabledepthtest.integer);
4165 qglPolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);CHECKGLERROR
4166 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
4167 if (brush->colbrushf && brush->colbrushf->numtriangles)
4168 R_DrawCollisionBrush(brush->colbrushf);
4169 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
4170 if (surface->num_collisiontriangles)
4171 R_DrawCollisionSurface(ent, surface);
4172 qglPolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR
4175 void R_DrawTrianglesAndNormals(entity_render_t *ent, qboolean drawtris, qboolean drawnormals, int flagsmask)
4178 const int *elements;
4179 msurface_t *surface;
4180 model_t *model = ent->model;
4183 GL_DepthRange(0, 1);
4184 GL_DepthTest(!r_showdisabledepthtest.integer);
4186 GL_BlendFunc(GL_ONE, GL_ZERO);
4187 R_Mesh_ColorPointer(NULL, 0, 0);
4188 R_Mesh_ResetTextureState();
4189 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
4191 if (ent == r_refdef.worldentity && !r_viewcache.world_surfacevisible[j])
4193 rsurface_texture = surface->texture->currentframe;
4194 if ((rsurface_texture->currentmaterialflags & flagsmask) && surface->num_triangles)
4196 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
4199 if (!rsurface_texture->currentlayers->depthmask)
4200 GL_Color(r_showtris.value * r_view.colorscale, 0, 0, 1);
4201 else if (ent == r_refdef.worldentity)
4202 GL_Color(r_showtris.value * r_view.colorscale, r_showtris.value * r_view.colorscale, r_showtris.value * r_view.colorscale, 1);
4204 GL_Color(0, r_showtris.value * r_view.colorscale, 0, 1);
4205 elements = (ent->model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
4208 for (k = 0;k < surface->num_triangles;k++, elements += 3)
4210 qglArrayElement(elements[0]);qglArrayElement(elements[1]);
4211 qglArrayElement(elements[1]);qglArrayElement(elements[2]);
4212 qglArrayElement(elements[2]);qglArrayElement(elements[0]);
4219 GL_Color(r_shownormals.value * r_view.colorscale, 0, 0, 1);
4221 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
4223 VectorCopy(rsurface_vertex3f + l * 3, v);
4224 qglVertex3f(v[0], v[1], v[2]);
4225 VectorMA(v, 8, rsurface_svector3f + l * 3, v);
4226 qglVertex3f(v[0], v[1], v[2]);
4230 GL_Color(0, 0, r_shownormals.value * r_view.colorscale, 1);
4232 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
4234 VectorCopy(rsurface_vertex3f + l * 3, v);
4235 qglVertex3f(v[0], v[1], v[2]);
4236 VectorMA(v, 8, rsurface_tvector3f + l * 3, v);
4237 qglVertex3f(v[0], v[1], v[2]);
4241 GL_Color(0, r_shownormals.value * r_view.colorscale, 0, 1);
4243 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
4245 VectorCopy(rsurface_vertex3f + l * 3, v);
4246 qglVertex3f(v[0], v[1], v[2]);
4247 VectorMA(v, 8, rsurface_normal3f + l * 3, v);
4248 qglVertex3f(v[0], v[1], v[2]);
4255 rsurface_texture = NULL;
4258 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
4259 void R_DrawWorldSurfaces(qboolean skysurfaces)
4261 int i, j, endj, f, flagsmask;
4262 int counttriangles = 0;
4263 msurface_t *surface, **surfacechain;
4265 model_t *model = r_refdef.worldmodel;
4266 const int maxsurfacelist = 1024;
4267 int numsurfacelist = 0;
4268 msurface_t *surfacelist[1024];
4272 RSurf_ActiveWorldEntity();
4274 // update light styles
4275 if (!skysurfaces && model->brushq1.light_styleupdatechains)
4277 for (i = 0;i < model->brushq1.light_styles;i++)
4279 if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
4281 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
4282 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
4283 for (;(surface = *surfacechain);surfacechain++)
4284 surface->cached_dlight = true;
4289 R_UpdateAllTextureInfo(r_refdef.worldentity);
4290 flagsmask = skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL);
4293 rsurface_uselightmaptexture = false;
4294 rsurface_texture = NULL;
4296 j = model->firstmodelsurface;
4297 endj = j + model->nummodelsurfaces;
4300 // quickly skip over non-visible surfaces
4301 for (;j < endj && !r_viewcache.world_surfacevisible[j];j++)
4303 // quickly iterate over visible surfaces
4304 for (;j < endj && r_viewcache.world_surfacevisible[j];j++)
4306 // process this surface
4307 surface = model->data_surfaces + j;
4308 // if this surface fits the criteria, add it to the list
4309 if (surface->num_triangles)
4311 // if lightmap parameters changed, rebuild lightmap texture
4312 if (surface->cached_dlight)
4313 R_BuildLightMap(r_refdef.worldentity, surface);
4314 // add face to draw list
4315 surfacelist[numsurfacelist++] = surface;
4316 counttriangles += surface->num_triangles;
4317 if (numsurfacelist >= maxsurfacelist)
4319 R_QueueSurfaceList(numsurfacelist, surfacelist, flagsmask);
4326 R_QueueSurfaceList(numsurfacelist, surfacelist, flagsmask);
4327 r_refdef.stats.entities_triangles += counttriangles;
4330 if (r_showcollisionbrushes.integer && !skysurfaces)
4331 R_DrawCollisionBrushes(r_refdef.worldentity);
4333 if (r_showtris.integer || r_shownormals.integer)
4334 R_DrawTrianglesAndNormals(r_refdef.worldentity, r_showtris.integer, r_shownormals.integer, flagsmask);
4337 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces)
4339 int i, f, flagsmask;
4340 int counttriangles = 0;
4341 msurface_t *surface, *endsurface, **surfacechain;
4343 model_t *model = ent->model;
4344 const int maxsurfacelist = 1024;
4345 int numsurfacelist = 0;
4346 msurface_t *surfacelist[1024];
4350 // if the model is static it doesn't matter what value we give for
4351 // wantnormals and wanttangents, so this logic uses only rules applicable
4352 // to a model, knowing that they are meaningless otherwise
4353 if (ent == r_refdef.worldentity)
4354 RSurf_ActiveWorldEntity();
4355 else if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
4356 RSurf_ActiveModelEntity(ent, false, false);
4358 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
4360 // update light styles
4361 if (!skysurfaces && model->brushq1.light_styleupdatechains)
4363 for (i = 0;i < model->brushq1.light_styles;i++)
4365 if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
4367 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
4368 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
4369 for (;(surface = *surfacechain);surfacechain++)
4370 surface->cached_dlight = true;
4375 R_UpdateAllTextureInfo(ent);
4376 flagsmask = skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL);
4379 rsurface_uselightmaptexture = false;
4380 rsurface_texture = NULL;
4382 surface = model->data_surfaces + model->firstmodelsurface;
4383 endsurface = surface + model->nummodelsurfaces;
4384 for (;surface < endsurface;surface++)
4386 // if this surface fits the criteria, add it to the list
4387 if (surface->num_triangles)
4389 // if lightmap parameters changed, rebuild lightmap texture
4390 if (surface->cached_dlight)
4391 R_BuildLightMap(ent, surface);
4392 // add face to draw list
4393 surfacelist[numsurfacelist++] = surface;
4394 counttriangles += surface->num_triangles;
4395 if (numsurfacelist >= maxsurfacelist)
4397 R_QueueSurfaceList(numsurfacelist, surfacelist, flagsmask);
4403 R_QueueSurfaceList(numsurfacelist, surfacelist, flagsmask);
4404 r_refdef.stats.entities_triangles += counttriangles;
4407 if (r_showcollisionbrushes.integer && !skysurfaces)
4408 R_DrawCollisionBrushes(ent);
4410 if (r_showtris.integer || r_shownormals.integer)
4411 R_DrawTrianglesAndNormals(ent, r_showtris.integer, r_shownormals.integer, flagsmask);