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 float FogPoint_World(const vec3_t p)
204 int fogmasktableindex = (int)(VectorDistance((p), r_view.origin) * r_refdef.fogmasktabledistmultiplier);
205 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
208 float FogPoint_Model(const vec3_t p)
210 int fogmasktableindex = (int)(VectorDistance((p), rsurface_modelorg) * r_refdef.fogmasktabledistmultiplier);
211 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
214 static void R_BuildBlankTextures(void)
216 unsigned char data[4];
217 data[0] = 128; // normal X
218 data[1] = 128; // normal Y
219 data[2] = 255; // normal Z
220 data[3] = 128; // height
221 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
226 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
231 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
234 static void R_BuildNoTexture(void)
237 unsigned char pix[16][16][4];
238 // this makes a light grey/dark grey checkerboard texture
239 for (y = 0;y < 16;y++)
241 for (x = 0;x < 16;x++)
243 if ((y < 8) ^ (x < 8))
259 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_RGBA, TEXF_MIPMAP, NULL);
262 static void R_BuildWhiteCube(void)
264 unsigned char data[6*1*1*4];
265 data[ 0] = 255;data[ 1] = 255;data[ 2] = 255;data[ 3] = 255;
266 data[ 4] = 255;data[ 5] = 255;data[ 6] = 255;data[ 7] = 255;
267 data[ 8] = 255;data[ 9] = 255;data[10] = 255;data[11] = 255;
268 data[12] = 255;data[13] = 255;data[14] = 255;data[15] = 255;
269 data[16] = 255;data[17] = 255;data[18] = 255;data[19] = 255;
270 data[20] = 255;data[21] = 255;data[22] = 255;data[23] = 255;
271 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
274 static void R_BuildNormalizationCube(void)
278 vec_t s, t, intensity;
280 unsigned char data[6][NORMSIZE][NORMSIZE][4];
281 for (side = 0;side < 6;side++)
283 for (y = 0;y < NORMSIZE;y++)
285 for (x = 0;x < NORMSIZE;x++)
287 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
288 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
323 intensity = 127.0f / sqrt(DotProduct(v, v));
324 data[side][y][x][0] = (unsigned char)(128.0f + intensity * v[0]);
325 data[side][y][x][1] = (unsigned char)(128.0f + intensity * v[1]);
326 data[side][y][x][2] = (unsigned char)(128.0f + intensity * v[2]);
327 data[side][y][x][3] = 255;
331 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, &data[0][0][0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
334 static void R_BuildFogTexture(void)
338 unsigned char data1[FOGWIDTH][4];
339 //unsigned char data2[FOGWIDTH][4];
340 for (x = 0;x < FOGWIDTH;x++)
342 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
347 //data2[x][0] = 255 - b;
348 //data2[x][1] = 255 - b;
349 //data2[x][2] = 255 - b;
352 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
353 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
356 static const char *builtinshaderstring =
357 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
358 "// written by Forest 'LordHavoc' Hale\n"
360 "// common definitions between vertex shader and fragment shader:\n"
362 "#ifdef __GLSL_CG_DATA_TYPES\n"
363 "#define myhalf half\n"
364 "#define myhvec2 hvec2\n"
365 "#define myhvec3 hvec3\n"
366 "#define myhvec4 hvec4\n"
368 "#define myhalf float\n"
369 "#define myhvec2 vec2\n"
370 "#define myhvec3 vec3\n"
371 "#define myhvec4 vec4\n"
374 "varying vec2 TexCoord;\n"
375 "varying vec2 TexCoordLightmap;\n"
377 "varying vec3 CubeVector;\n"
378 "varying vec3 LightVector;\n"
379 "varying vec3 EyeVector;\n"
381 "varying vec3 EyeVectorModelSpace;\n"
384 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
385 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
386 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
391 "// vertex shader specific:\n"
392 "#ifdef VERTEX_SHADER\n"
394 "uniform vec3 LightPosition;\n"
395 "uniform vec3 EyePosition;\n"
396 "uniform vec3 LightDir;\n"
398 "// TODO: get rid of tangentt (texcoord2) and use a crossproduct to regenerate it from tangents (texcoord1) and normal (texcoord3)\n"
402 " gl_FrontColor = gl_Color;\n"
403 " // copy the surface texcoord\n"
404 " TexCoord = vec2(gl_TextureMatrix[0] * gl_MultiTexCoord0);\n"
405 "#if !defined(MODE_LIGHTSOURCE) && !defined(MODE_LIGHTDIRECTION)\n"
406 " TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
409 "#ifdef MODE_LIGHTSOURCE\n"
410 " // transform vertex position into light attenuation/cubemap space\n"
411 " // (-1 to +1 across the light box)\n"
412 " CubeVector = vec3(gl_TextureMatrix[3] * gl_Vertex);\n"
414 " // transform unnormalized light direction into tangent space\n"
415 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
416 " // normalize it per pixel)\n"
417 " vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
418 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
419 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
420 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
423 "#ifdef MODE_LIGHTDIRECTION\n"
424 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
425 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
426 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
429 " // transform unnormalized eye direction into tangent space\n"
431 " vec3 EyeVectorModelSpace;\n"
433 " EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
434 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
435 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
436 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
438 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
439 " VectorS = gl_MultiTexCoord1.xyz;\n"
440 " VectorT = gl_MultiTexCoord2.xyz;\n"
441 " VectorR = gl_MultiTexCoord3.xyz;\n"
444 " // transform vertex to camera space, using ftransform to match non-VS\n"
446 " gl_Position = ftransform();\n"
449 "#endif // VERTEX_SHADER\n"
454 "// fragment shader specific:\n"
455 "#ifdef FRAGMENT_SHADER\n"
457 "// 11 textures, we can only use up to 16 on DX9-class hardware\n"
458 "uniform sampler2D Texture_Normal;\n"
459 "uniform sampler2D Texture_Color;\n"
460 "uniform sampler2D Texture_Gloss;\n"
461 "uniform samplerCube Texture_Cube;\n"
462 "uniform sampler2D Texture_Attenuation;\n"
463 "uniform sampler2D Texture_FogMask;\n"
464 "uniform sampler2D Texture_Pants;\n"
465 "uniform sampler2D Texture_Shirt;\n"
466 "uniform sampler2D Texture_Lightmap;\n"
467 "uniform sampler2D Texture_Deluxemap;\n"
468 "uniform sampler2D Texture_Glow;\n"
470 "uniform myhvec3 LightColor;\n"
471 "uniform myhvec3 AmbientColor;\n"
472 "uniform myhvec3 DiffuseColor;\n"
473 "uniform myhvec3 SpecularColor;\n"
474 "uniform myhvec3 Color_Pants;\n"
475 "uniform myhvec3 Color_Shirt;\n"
476 "uniform myhvec3 FogColor;\n"
478 "uniform myhalf GlowScale;\n"
479 "uniform myhalf SceneBrightness;\n"
481 "uniform float OffsetMapping_Scale;\n"
482 "uniform float OffsetMapping_Bias;\n"
483 "uniform float FogRangeRecip;\n"
485 "uniform myhalf AmbientScale;\n"
486 "uniform myhalf DiffuseScale;\n"
487 "uniform myhalf SpecularScale;\n"
488 "uniform myhalf SpecularPower;\n"
490 "#ifdef USEOFFSETMAPPING\n"
491 "vec2 OffsetMapping(vec2 TexCoord)\n"
493 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
494 " // 14 sample relief mapping: linear search and then binary search\n"
495 " // this basically steps forward a small amount repeatedly until it finds\n"
496 " // itself inside solid, then jitters forward and back using decreasing\n"
497 " // amounts to find the impact\n"
498 " //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
499 " //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
500 " vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
501 " vec3 RT = vec3(TexCoord, 1);\n"
502 " OffsetVector *= 0.1;\n"
503 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
504 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
505 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
506 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
507 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
508 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
509 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
510 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
511 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
512 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) - 0.5);\n"
513 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5 - 0.25);\n"
514 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25 - 0.125);\n"
515 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125 - 0.0625);\n"
516 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
519 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
520 " // this basically moves forward the full distance, and then backs up based\n"
521 " // on height of samples\n"
522 " //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
523 " //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
524 " vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
525 " TexCoord += OffsetVector;\n"
526 " OffsetVector *= 0.333;\n"
527 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
528 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
529 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
530 " return TexCoord;\n"
537 "#ifdef USEOFFSETMAPPING\n"
538 " // apply offsetmapping\n"
539 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
540 "#define TexCoord TexCoordOffset\n"
543 " // combine the diffuse textures (base, pants, shirt)\n"
544 " myhvec4 color = myhvec4(texture2D(Texture_Color, TexCoord));\n"
545 "#ifdef USECOLORMAPPING\n"
546 " color.rgb += myhvec3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhvec3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
552 "#ifdef MODE_LIGHTSOURCE\n"
555 " // calculate surface normal, light normal, and specular normal\n"
556 " // compute color intensity for the two textures (colormap and glossmap)\n"
557 " // scale by light color and attenuation as efficiently as possible\n"
558 " // (do as much scalar math as possible rather than vector math)\n"
559 "#ifdef USESPECULAR\n"
560 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
561 " myhvec3 diffusenormal = myhvec3(normalize(LightVector));\n"
562 " myhvec3 specularnormal = normalize(diffusenormal + myhvec3(normalize(EyeVector)));\n"
564 " // calculate directional shading\n"
565 " 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"
567 "#ifdef USEDIFFUSE\n"
568 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
569 " myhvec3 diffusenormal = myhvec3(normalize(LightVector));\n"
571 " // calculate directional shading\n"
572 " 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"
574 " // calculate directionless shading\n"
575 " color.rgb = color.rgb * LightColor * myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
579 "#ifdef USECUBEFILTER\n"
580 " // apply light cubemap filter\n"
581 " //color.rgb *= normalize(CubeVector) * 0.5 + 0.5;//vec3(textureCube(Texture_Cube, CubeVector));\n"
582 " color.rgb *= myhvec3(textureCube(Texture_Cube, CubeVector));\n"
588 "#elif defined(MODE_LIGHTDIRECTION)\n"
589 " // directional model lighting\n"
591 " // get the surface normal and light normal\n"
592 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
593 " myhvec3 diffusenormal = myhvec3(normalize(LightVector));\n"
595 " // calculate directional shading\n"
596 " color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
597 "#ifdef USESPECULAR\n"
598 " myhvec3 specularnormal = normalize(diffusenormal + myhvec3(normalize(EyeVector)));\n"
599 " color.rgb += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
605 "#elif defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
606 " // deluxemap lightmapping using light vectors in modelspace (evil q3map2)\n"
608 " // get the surface normal and light normal\n"
609 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
611 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
612 " myhvec3 diffusenormal_modelspace = myhvec3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - myhvec3(0.5);\n"
613 " myhvec3 diffusenormal = normalize(myhvec3(dot(diffusenormal_modelspace, myhvec3(VectorS)), dot(diffusenormal_modelspace, myhvec3(VectorT)), dot(diffusenormal_modelspace, myhvec3(VectorR))));\n"
615 " myhvec3 diffusenormal = normalize(myhvec3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - myhvec3(0.5));\n"
617 " // calculate directional shading\n"
618 " myhvec3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0)));\n"
619 "#ifdef USESPECULAR\n"
620 " myhvec3 specularnormal = myhvec3(normalize(diffusenormal + myhvec3(normalize(EyeVector))));\n"
621 " tempcolor += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
624 " // apply lightmap color\n"
625 " color.rgb = tempcolor * myhvec3(texture2D(Texture_Lightmap, TexCoordLightmap)) + color.rgb * AmbientScale;\n"
628 "#else // MODE none (lightmap)\n"
629 " // apply lightmap color\n"
630 " color.rgb *= myhvec3(texture2D(Texture_Lightmap, TexCoordLightmap)) * DiffuseScale + myhvec3(AmbientScale);\n"
633 " color *= myhvec4(gl_Color);\n"
636 " color.rgb += myhvec3(texture2D(Texture_Glow, TexCoord)) * GlowScale;\n"
641 " color.rgb = mix(FogColor, color.rgb, myhalf(texture2D(Texture_FogMask, myhvec2(length(EyeVectorModelSpace)*FogRangeRecip, 0.0))));\n"
644 " color.rgb *= SceneBrightness;\n"
646 " gl_FragColor = vec4(color);\n"
649 "#endif // FRAGMENT_SHADER\n"
652 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
653 const char *permutationinfo[][2] =
655 {"#define MODE_LIGHTSOURCE\n", " lightsource"},
656 {"#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
657 {"#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
658 {"#define MODE_LIGHTDIRECTION\n", " lightdirection"},
659 {"#define USEGLOW\n", " glow"},
660 {"#define USEFOG\n", " fog"},
661 {"#define USECOLORMAPPING\n", " colormapping"},
662 {"#define USEDIFFUSE\n", " diffuse"},
663 {"#define USESPECULAR\n", " specular"},
664 {"#define USECUBEFILTER\n", " cubefilter"},
665 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
666 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
670 void R_GLSL_CompilePermutation(const char *filename, int permutation)
673 qboolean shaderfound;
674 r_glsl_permutation_t *p = r_glsl_permutations + (permutation & SHADERPERMUTATION_MASK);
675 int vertstrings_count;
676 int geomstrings_count;
677 int fragstrings_count;
679 const char *vertstrings_list[32+1];
680 const char *geomstrings_list[32+1];
681 const char *fragstrings_list[32+1];
682 char permutationname[256];
687 vertstrings_list[0] = "#define VERTEX_SHADER\n";
688 geomstrings_list[0] = "#define GEOMETRY_SHADER\n";
689 fragstrings_list[0] = "#define FRAGMENT_SHADER\n";
690 vertstrings_count = 1;
691 geomstrings_count = 1;
692 fragstrings_count = 1;
693 permutationname[0] = 0;
694 for (i = 0;permutationinfo[i][0];i++)
696 if (permutation & (1<<i))
698 vertstrings_list[vertstrings_count++] = permutationinfo[i][0];
699 geomstrings_list[geomstrings_count++] = permutationinfo[i][0];
700 fragstrings_list[fragstrings_count++] = permutationinfo[i][0];
701 strlcat(permutationname, permutationinfo[i][1], sizeof(permutationname));
705 // keep line numbers correct
706 vertstrings_list[vertstrings_count++] = "\n";
707 geomstrings_list[geomstrings_count++] = "\n";
708 fragstrings_list[fragstrings_count++] = "\n";
711 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
715 Con_DPrintf("GLSL shader text for \"%s\" loaded from disk\n", filename);
716 vertstrings_list[vertstrings_count++] = shaderstring;
717 geomstrings_list[geomstrings_count++] = shaderstring;
718 fragstrings_list[fragstrings_count++] = shaderstring;
721 else if (!strcmp(filename, "glsl/default.glsl"))
723 Con_DPrintf("GLSL shader text for \"%s\" loaded from engine\n", filename);
724 vertstrings_list[vertstrings_count++] = builtinshaderstring;
725 geomstrings_list[geomstrings_count++] = builtinshaderstring;
726 fragstrings_list[fragstrings_count++] = builtinshaderstring;
729 // clear any lists that are not needed by this shader
730 if (!(permutation & SHADERPERMUTATION_USES_VERTEXSHADER))
731 vertstrings_count = 0;
732 if (!(permutation & SHADERPERMUTATION_USES_GEOMETRYSHADER))
733 geomstrings_count = 0;
734 if (!(permutation & SHADERPERMUTATION_USES_FRAGMENTSHADER))
735 fragstrings_count = 0;
736 // compile the shader program
737 if (shaderfound && vertstrings_count + geomstrings_count + fragstrings_count)
738 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
742 qglUseProgramObjectARB(p->program);CHECKGLERROR
743 // look up all the uniform variable names we care about, so we don't
744 // have to look them up every time we set them
745 p->loc_Texture_Normal = qglGetUniformLocationARB(p->program, "Texture_Normal");
746 p->loc_Texture_Color = qglGetUniformLocationARB(p->program, "Texture_Color");
747 p->loc_Texture_Gloss = qglGetUniformLocationARB(p->program, "Texture_Gloss");
748 p->loc_Texture_Cube = qglGetUniformLocationARB(p->program, "Texture_Cube");
749 p->loc_Texture_Attenuation = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
750 p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
751 p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
752 p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
753 p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
754 p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
755 p->loc_Texture_Glow = qglGetUniformLocationARB(p->program, "Texture_Glow");
756 p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
757 p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
758 p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
759 p->loc_LightColor = qglGetUniformLocationARB(p->program, "LightColor");
760 p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants");
761 p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt");
762 p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip");
763 p->loc_AmbientScale = qglGetUniformLocationARB(p->program, "AmbientScale");
764 p->loc_DiffuseScale = qglGetUniformLocationARB(p->program, "DiffuseScale");
765 p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
766 p->loc_SpecularScale = qglGetUniformLocationARB(p->program, "SpecularScale");
767 p->loc_GlowScale = qglGetUniformLocationARB(p->program, "GlowScale");
768 p->loc_SceneBrightness = qglGetUniformLocationARB(p->program, "SceneBrightness");
769 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
770 p->loc_AmbientColor = qglGetUniformLocationARB(p->program, "AmbientColor");
771 p->loc_DiffuseColor = qglGetUniformLocationARB(p->program, "DiffuseColor");
772 p->loc_SpecularColor = qglGetUniformLocationARB(p->program, "SpecularColor");
773 p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
774 // initialize the samplers to refer to the texture units we use
775 if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal, 0);
776 if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color, 1);
777 if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss, 2);
778 if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube, 3);
779 if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask, 4);
780 if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants, 5);
781 if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt, 6);
782 if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap, 7);
783 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap, 8);
784 if (p->loc_Texture_Glow >= 0) qglUniform1iARB(p->loc_Texture_Glow, 9);
785 if (p->loc_Texture_Attenuation >= 0) qglUniform1iARB(p->loc_Texture_Attenuation, 10);
787 qglUseProgramObjectARB(0);CHECKGLERROR
790 Con_Printf("permutation%s failed for shader %s, some features may not work properly!\n", permutationname, "glsl/default.glsl");
792 Mem_Free(shaderstring);
795 void R_GLSL_Restart_f(void)
798 for (i = 0;i < SHADERPERMUTATION_MAX;i++)
799 if (r_glsl_permutations[i].program)
800 GL_Backend_FreeProgram(r_glsl_permutations[i].program);
801 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
804 extern rtexture_t *r_shadow_attenuationgradienttexture;
805 extern rtexture_t *r_shadow_attenuation2dtexture;
806 extern rtexture_t *r_shadow_attenuation3dtexture;
807 int R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale)
809 // select a permutation of the lighting shader appropriate to this
810 // combination of texture, entity, light source, and fogging, only use the
811 // minimum features necessary to avoid wasting rendering time in the
812 // fragment shader on features that are not being used
813 const char *shaderfilename = NULL;
814 unsigned int permutation = 0;
815 r_glsl_permutation = NULL;
816 // TODO: implement geometry-shader based shadow volumes someday
817 if (r_shadow_rtlight)
820 shaderfilename = "glsl/default.glsl";
821 permutation = SHADERPERMUTATION_MODE_LIGHTSOURCE | SHADERPERMUTATION_USES_VERTEXSHADER | SHADERPERMUTATION_USES_FRAGMENTSHADER;
822 if (r_shadow_rtlight->currentcubemap != r_texture_whitecube)
823 permutation |= SHADERPERMUTATION_CUBEFILTER;
824 if (diffusescale > 0)
825 permutation |= SHADERPERMUTATION_DIFFUSE;
826 if (specularscale > 0)
827 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
828 if (r_refdef.fogenabled)
829 permutation |= SHADERPERMUTATION_FOG;
830 if (rsurface_texture->colormapping)
831 permutation |= SHADERPERMUTATION_COLORMAPPING;
832 if (r_glsl_offsetmapping.integer)
834 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
835 if (r_glsl_offsetmapping_reliefmapping.integer)
836 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
839 else if (rsurface_texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
841 // bright unshaded geometry
842 shaderfilename = "glsl/default.glsl";
843 permutation = SHADERPERMUTATION_USES_VERTEXSHADER | SHADERPERMUTATION_USES_FRAGMENTSHADER;
844 if (rsurface_texture->currentskinframe->glow)
845 permutation |= SHADERPERMUTATION_GLOW;
846 if (r_refdef.fogenabled)
847 permutation |= SHADERPERMUTATION_FOG;
848 if (rsurface_texture->colormapping)
849 permutation |= SHADERPERMUTATION_COLORMAPPING;
850 if (r_glsl_offsetmapping.integer)
852 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
853 if (r_glsl_offsetmapping_reliefmapping.integer)
854 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
857 else if (modellighting)
859 // directional model lighting
860 shaderfilename = "glsl/default.glsl";
861 permutation = SHADERPERMUTATION_USES_VERTEXSHADER | SHADERPERMUTATION_USES_FRAGMENTSHADER;
862 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTION;
863 if (rsurface_texture->currentskinframe->glow)
864 permutation |= SHADERPERMUTATION_GLOW;
865 if (specularscale > 0)
866 permutation |= SHADERPERMUTATION_SPECULAR;
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;
881 shaderfilename = "glsl/default.glsl";
882 permutation = SHADERPERMUTATION_USES_VERTEXSHADER | SHADERPERMUTATION_USES_FRAGMENTSHADER;
883 if (r_glsl_deluxemapping.integer >= 1 && rsurface_uselightmaptexture && r_refdef.worldmodel && r_refdef.worldmodel->brushq3.deluxemapping)
885 // deluxemapping (light direction texture)
886 if (rsurface_uselightmaptexture && r_refdef.worldmodel && r_refdef.worldmodel->brushq3.deluxemapping && r_refdef.worldmodel->brushq3.deluxemapping_modelspace)
887 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_MODELSPACE;
889 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
890 if (specularscale > 0)
891 permutation |= SHADERPERMUTATION_SPECULAR;
893 else if (r_glsl_deluxemapping.integer >= 2)
895 // fake deluxemapping (uniform light direction in tangentspace)
896 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
897 if (specularscale > 0)
898 permutation |= SHADERPERMUTATION_SPECULAR;
902 // ordinary lightmapping
905 if (rsurface_texture->currentskinframe->glow)
906 permutation |= SHADERPERMUTATION_GLOW;
907 if (r_refdef.fogenabled)
908 permutation |= SHADERPERMUTATION_FOG;
909 if (rsurface_texture->colormapping)
910 permutation |= SHADERPERMUTATION_COLORMAPPING;
911 if (r_glsl_offsetmapping.integer)
913 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
914 if (r_glsl_offsetmapping_reliefmapping.integer)
915 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
918 if (!r_glsl_permutations[permutation & SHADERPERMUTATION_MASK].program)
920 if (!r_glsl_permutations[permutation & SHADERPERMUTATION_MASK].compiled)
921 R_GLSL_CompilePermutation(shaderfilename, permutation);
922 if (!r_glsl_permutations[permutation & SHADERPERMUTATION_MASK].program)
924 // remove features until we find a valid permutation
926 for (i = SHADERPERMUTATION_MASK;;i>>=1)
929 return 0; // utterly failed
930 // reduce i more quickly whenever it would not remove any bits
934 if (!r_glsl_permutations[permutation & SHADERPERMUTATION_MASK].compiled)
935 R_GLSL_CompilePermutation(shaderfilename, permutation);
936 if (r_glsl_permutations[permutation & SHADERPERMUTATION_MASK].program)
941 r_glsl_permutation = r_glsl_permutations + (permutation & SHADERPERMUTATION_MASK);
943 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
944 R_Mesh_TexMatrix(0, &rsurface_texture->currenttexmatrix);
945 if (permutation & SHADERPERMUTATION_MODE_LIGHTSOURCE)
947 if (r_glsl_permutation->loc_Texture_Cube >= 0 && r_shadow_rtlight) R_Mesh_TexBindCubeMap(3, R_GetTexture(r_shadow_rtlight->currentcubemap));
948 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]);
949 if (permutation & SHADERPERMUTATION_DIFFUSE)
951 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
952 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, ambientscale);
953 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, diffusescale);
954 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, specularscale);
958 // ambient only is simpler
959 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0] * ambientscale, lightcolorbase[1] * ambientscale, lightcolorbase[2] * ambientscale);
960 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, 1);
961 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, 0);
962 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, 0);
965 else if (permutation & SHADERPERMUTATION_MODE_LIGHTDIRECTION)
967 if (r_glsl_permutation->loc_AmbientColor >= 0)
968 qglUniform3fARB(r_glsl_permutation->loc_AmbientColor, rsurface_entity->modellight_ambient[0] * ambientscale, rsurface_entity->modellight_ambient[1] * ambientscale, rsurface_entity->modellight_ambient[2] * ambientscale);
969 if (r_glsl_permutation->loc_DiffuseColor >= 0)
970 qglUniform3fARB(r_glsl_permutation->loc_DiffuseColor, rsurface_entity->modellight_diffuse[0] * diffusescale, rsurface_entity->modellight_diffuse[1] * diffusescale, rsurface_entity->modellight_diffuse[2] * diffusescale);
971 if (r_glsl_permutation->loc_SpecularColor >= 0)
972 qglUniform3fARB(r_glsl_permutation->loc_SpecularColor, rsurface_entity->modellight_diffuse[0] * specularscale, rsurface_entity->modellight_diffuse[1] * specularscale, rsurface_entity->modellight_diffuse[2] * specularscale);
973 if (r_glsl_permutation->loc_LightDir >= 0)
974 qglUniform3fARB(r_glsl_permutation->loc_LightDir, rsurface_entity->modellight_lightdir[0], rsurface_entity->modellight_lightdir[1], rsurface_entity->modellight_lightdir[2]);
978 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_ambient.value * 2.0f / 128.0f);
979 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_refdef.lightmapintensity * 2.0f);
980 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, r_refdef.lightmapintensity * specularscale * 2.0f);
982 if (r_glsl_permutation->loc_Texture_Normal >= 0) R_Mesh_TexBind(0, R_GetTexture(rsurface_texture->currentskinframe->nmap));
983 if (r_glsl_permutation->loc_Texture_Color >= 0) R_Mesh_TexBind(1, R_GetTexture(rsurface_texture->basetexture));
984 if (r_glsl_permutation->loc_Texture_Gloss >= 0) R_Mesh_TexBind(2, R_GetTexture(rsurface_texture->glosstexture));
985 //if (r_glsl_permutation->loc_Texture_Cube >= 0 && permutation & SHADERPERMUTATION_MODE_LIGHTSOURCE) R_Mesh_TexBindCubeMap(3, R_GetTexture(r_shadow_rtlight->currentcubemap));
986 if (r_glsl_permutation->loc_Texture_Attenuation >= 0) R_Mesh_TexBind(10, R_GetTexture(r_shadow_attenuationgradienttexture));
987 if (r_glsl_permutation->loc_Texture_FogMask >= 0) R_Mesh_TexBind(4, R_GetTexture(r_texture_fogattenuation));
988 if (r_glsl_permutation->loc_Texture_Pants >= 0) R_Mesh_TexBind(5, R_GetTexture(rsurface_texture->currentskinframe->pants));
989 if (r_glsl_permutation->loc_Texture_Shirt >= 0) R_Mesh_TexBind(6, R_GetTexture(rsurface_texture->currentskinframe->shirt));
990 //if (r_glsl_permutation->loc_Texture_Lightmap >= 0) R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
991 //if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
992 if (r_glsl_permutation->loc_Texture_Glow >= 0) R_Mesh_TexBind(9, R_GetTexture(rsurface_texture->currentskinframe->glow));
993 if (r_glsl_permutation->loc_GlowScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_GlowScale, r_hdr_glowintensity.value);
994 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_view.colorscale);
995 if (r_glsl_permutation->loc_FogColor >= 0)
997 // additive passes are only darkened by fog, not tinted
998 if (r_shadow_rtlight || (rsurface_texture->currentmaterialflags & MATERIALFLAG_ADD))
999 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
1001 qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
1003 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface_modelorg[0], rsurface_modelorg[1], rsurface_modelorg[2]);
1004 if (r_glsl_permutation->loc_Color_Pants >= 0)
1006 if (rsurface_texture->currentskinframe->pants)
1007 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface_entity->colormap_pantscolor[0], rsurface_entity->colormap_pantscolor[1], rsurface_entity->colormap_pantscolor[2]);
1009 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
1011 if (r_glsl_permutation->loc_Color_Shirt >= 0)
1013 if (rsurface_texture->currentskinframe->shirt)
1014 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface_entity->colormap_shirtcolor[0], rsurface_entity->colormap_shirtcolor[1], rsurface_entity->colormap_shirtcolor[2]);
1016 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
1018 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, r_refdef.fograngerecip);
1019 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface_texture->specularpower);
1020 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
1025 void R_SwitchSurfaceShader(int permutation)
1027 if (r_glsl_permutation != r_glsl_permutations + (permutation & SHADERPERMUTATION_MASK))
1029 r_glsl_permutation = r_glsl_permutations + (permutation & SHADERPERMUTATION_MASK);
1031 qglUseProgramObjectARB(r_glsl_permutation->program);
1036 void gl_main_start(void)
1041 r = (-1.0/256.0) * (FOGMASKTABLEWIDTH * FOGMASKTABLEWIDTH);
1042 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
1044 alpha = 1 - exp(r / ((double)x*(double)x));
1045 if (x == FOGMASKTABLEWIDTH - 1)
1047 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
1050 r_main_texturepool = R_AllocTexturePool();
1051 R_BuildBlankTextures();
1053 if (gl_texturecubemap)
1056 R_BuildNormalizationCube();
1058 R_BuildFogTexture();
1059 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
1060 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
1061 memset(&r_svbsp, 0, sizeof (r_svbsp));
1064 void gl_main_shutdown(void)
1067 Mem_Free(r_svbsp.nodes);
1068 memset(&r_svbsp, 0, sizeof (r_svbsp));
1069 R_FreeTexturePool(&r_main_texturepool);
1070 r_texture_blanknormalmap = NULL;
1071 r_texture_white = NULL;
1072 r_texture_black = NULL;
1073 r_texture_whitecube = NULL;
1074 r_texture_normalizationcube = NULL;
1075 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
1079 extern void CL_ParseEntityLump(char *entitystring);
1080 void gl_main_newmap(void)
1082 // FIXME: move this code to client
1084 char *entities, entname[MAX_QPATH];
1087 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
1088 l = (int)strlen(entname) - 4;
1089 if (l >= 0 && !strcmp(entname + l, ".bsp"))
1091 memcpy(entname + l, ".ent", 5);
1092 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
1094 CL_ParseEntityLump(entities);
1099 if (cl.worldmodel->brush.entities)
1100 CL_ParseEntityLump(cl.worldmodel->brush.entities);
1104 void GL_Main_Init(void)
1106 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
1108 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
1109 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
1110 if (gamemode == GAME_NEHAHRA)
1112 Cvar_RegisterVariable (&gl_fogenable);
1113 Cvar_RegisterVariable (&gl_fogdensity);
1114 Cvar_RegisterVariable (&gl_fogred);
1115 Cvar_RegisterVariable (&gl_foggreen);
1116 Cvar_RegisterVariable (&gl_fogblue);
1117 Cvar_RegisterVariable (&gl_fogstart);
1118 Cvar_RegisterVariable (&gl_fogend);
1120 Cvar_RegisterVariable(&r_nearclip);
1121 Cvar_RegisterVariable(&r_showsurfaces);
1122 Cvar_RegisterVariable(&r_showtris);
1123 Cvar_RegisterVariable(&r_shownormals);
1124 Cvar_RegisterVariable(&r_showlighting);
1125 Cvar_RegisterVariable(&r_showshadowvolumes);
1126 Cvar_RegisterVariable(&r_showcollisionbrushes);
1127 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
1128 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
1129 Cvar_RegisterVariable(&r_showdisabledepthtest);
1130 Cvar_RegisterVariable(&r_drawportals);
1131 Cvar_RegisterVariable(&r_drawentities);
1132 Cvar_RegisterVariable(&r_cullentities_trace);
1133 Cvar_RegisterVariable(&r_cullentities_trace_samples);
1134 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
1135 Cvar_RegisterVariable(&r_cullentities_trace_delay);
1136 Cvar_RegisterVariable(&r_drawviewmodel);
1137 Cvar_RegisterVariable(&r_speeds);
1138 Cvar_RegisterVariable(&r_fullbrights);
1139 Cvar_RegisterVariable(&r_wateralpha);
1140 Cvar_RegisterVariable(&r_dynamic);
1141 Cvar_RegisterVariable(&r_fullbright);
1142 Cvar_RegisterVariable(&r_shadows);
1143 Cvar_RegisterVariable(&r_shadows_throwdistance);
1144 Cvar_RegisterVariable(&r_q1bsp_skymasking);
1145 Cvar_RegisterVariable(&r_textureunits);
1146 Cvar_RegisterVariable(&r_glsl);
1147 Cvar_RegisterVariable(&r_glsl_offsetmapping);
1148 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
1149 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
1150 Cvar_RegisterVariable(&r_glsl_deluxemapping);
1151 Cvar_RegisterVariable(&r_lerpsprites);
1152 Cvar_RegisterVariable(&r_lerpmodels);
1153 Cvar_RegisterVariable(&r_waterscroll);
1154 Cvar_RegisterVariable(&r_bloom);
1155 Cvar_RegisterVariable(&r_bloom_colorscale);
1156 Cvar_RegisterVariable(&r_bloom_brighten);
1157 Cvar_RegisterVariable(&r_bloom_blur);
1158 Cvar_RegisterVariable(&r_bloom_resolution);
1159 Cvar_RegisterVariable(&r_bloom_colorexponent);
1160 Cvar_RegisterVariable(&r_bloom_colorsubtract);
1161 Cvar_RegisterVariable(&r_hdr);
1162 Cvar_RegisterVariable(&r_hdr_scenebrightness);
1163 Cvar_RegisterVariable(&r_hdr_glowintensity);
1164 Cvar_RegisterVariable(&r_hdr_range);
1165 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
1166 Cvar_RegisterVariable(&developer_texturelogging);
1167 Cvar_RegisterVariable(&gl_lightmaps);
1168 Cvar_RegisterVariable(&r_test);
1169 Cvar_RegisterVariable(&r_batchmode);
1170 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
1171 Cvar_SetValue("r_fullbrights", 0);
1172 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
1175 extern void R_Textures_Init(void);
1176 extern void GL_Draw_Init(void);
1177 extern void GL_Main_Init(void);
1178 extern void R_Shadow_Init(void);
1179 extern void R_Sky_Init(void);
1180 extern void GL_Surf_Init(void);
1181 extern void R_Light_Init(void);
1182 extern void R_Particles_Init(void);
1183 extern void R_Explosion_Init(void);
1184 extern void gl_backend_init(void);
1185 extern void Sbar_Init(void);
1186 extern void R_LightningBeams_Init(void);
1187 extern void Mod_RenderInit(void);
1189 void Render_Init(void)
1202 R_LightningBeams_Init();
1211 extern char *ENGINE_EXTENSIONS;
1214 VID_CheckExtensions();
1216 // LordHavoc: report supported extensions
1217 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
1219 // clear to black (loading plaque will be seen over this)
1221 qglClearColor(0,0,0,1);CHECKGLERROR
1222 qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
1225 int R_CullBox(const vec3_t mins, const vec3_t maxs)
1229 for (i = 0;i < 4;i++)
1231 p = r_view.frustum + i;
1236 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1240 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1244 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1248 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1252 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1256 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1260 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1264 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1272 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
1276 for (i = 0;i < numplanes;i++)
1283 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1287 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1291 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1295 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1299 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1303 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1307 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1311 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1319 //==================================================================================
1321 static void R_UpdateEntityLighting(entity_render_t *ent)
1323 vec3_t tempdiffusenormal;
1325 // fetch the lighting from the worldmodel data
1326 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));
1327 VectorClear(ent->modellight_diffuse);
1328 VectorClear(tempdiffusenormal);
1329 if ((ent->flags & RENDER_LIGHT) && r_refdef.worldmodel && r_refdef.worldmodel->brush.LightPoint)
1332 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
1333 r_refdef.worldmodel->brush.LightPoint(r_refdef.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
1336 VectorSet(ent->modellight_ambient, 1, 1, 1);
1338 // move the light direction into modelspace coordinates for lighting code
1339 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
1340 VectorNormalize(ent->modellight_lightdir);
1342 // scale ambient and directional light contributions according to rendering variables
1343 ent->modellight_ambient[0] *= ent->colormod[0] * r_refdef.lightmapintensity;
1344 ent->modellight_ambient[1] *= ent->colormod[1] * r_refdef.lightmapintensity;
1345 ent->modellight_ambient[2] *= ent->colormod[2] * r_refdef.lightmapintensity;
1346 ent->modellight_diffuse[0] *= ent->colormod[0] * r_refdef.lightmapintensity;
1347 ent->modellight_diffuse[1] *= ent->colormod[1] * r_refdef.lightmapintensity;
1348 ent->modellight_diffuse[2] *= ent->colormod[2] * r_refdef.lightmapintensity;
1351 static void R_View_UpdateEntityVisible (void)
1354 entity_render_t *ent;
1356 if (!r_drawentities.integer)
1359 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : (chase_active.integer ? 0 : RENDER_EXTERIORMODEL);
1360 if (r_refdef.worldmodel && r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs)
1362 // worldmodel can check visibility
1363 for (i = 0;i < r_refdef.numentities;i++)
1365 ent = r_refdef.entities[i];
1366 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));
1368 if(r_cullentities_trace.integer)
1370 for (i = 0;i < r_refdef.numentities;i++)
1372 ent = r_refdef.entities[i];
1373 if(r_viewcache.entityvisible[i] && !(ent->effects & EF_NODEPTHTEST) && !(ent->flags & RENDER_VIEWMODEL) && !(ent->model && (ent->model->name[0] == '*')))
1375 if(Mod_CanSeeBox_Trace(r_cullentities_trace_samples.integer, r_cullentities_trace_enlarge.value, r_refdef.worldmodel, r_view.origin, ent->mins, ent->maxs))
1376 ent->last_trace_visibility = realtime;
1377 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
1378 r_viewcache.entityvisible[i] = 0;
1385 // no worldmodel or it can't check visibility
1386 for (i = 0;i < r_refdef.numentities;i++)
1388 ent = r_refdef.entities[i];
1389 r_viewcache.entityvisible[i] = !(ent->flags & renderimask) && !R_CullBox(ent->mins, ent->maxs);
1393 // update entity lighting (even on hidden entities for r_shadows)
1394 for (i = 0;i < r_refdef.numentities;i++)
1395 R_UpdateEntityLighting(r_refdef.entities[i]);
1398 // only used if skyrendermasked, and normally returns false
1399 int R_DrawBrushModelsSky (void)
1402 entity_render_t *ent;
1404 if (!r_drawentities.integer)
1408 for (i = 0;i < r_refdef.numentities;i++)
1410 if (!r_viewcache.entityvisible[i])
1412 ent = r_refdef.entities[i];
1413 if (!ent->model || !ent->model->DrawSky)
1415 ent->model->DrawSky(ent);
1421 void R_DrawNoModel(entity_render_t *ent);
1422 void R_DrawModels(void)
1425 entity_render_t *ent;
1427 if (!r_drawentities.integer)
1430 for (i = 0;i < r_refdef.numentities;i++)
1432 if (!r_viewcache.entityvisible[i])
1434 ent = r_refdef.entities[i];
1435 r_refdef.stats.entities++;
1436 if (ent->model && ent->model->Draw != NULL)
1437 ent->model->Draw(ent);
1443 static void R_View_SetFrustum(void)
1445 double slopex, slopey;
1447 // break apart the view matrix into vectors for various purposes
1448 Matrix4x4_ToVectors(&r_view.matrix, r_view.forward, r_view.left, r_view.up, r_view.origin);
1449 VectorNegate(r_view.left, r_view.right);
1452 r_view.frustum[0].normal[0] = 0 - 1.0 / r_view.frustum_x;
1453 r_view.frustum[0].normal[1] = 0 - 0;
1454 r_view.frustum[0].normal[2] = -1 - 0;
1455 r_view.frustum[1].normal[0] = 0 + 1.0 / r_view.frustum_x;
1456 r_view.frustum[1].normal[1] = 0 + 0;
1457 r_view.frustum[1].normal[2] = -1 + 0;
1458 r_view.frustum[2].normal[0] = 0 - 0;
1459 r_view.frustum[2].normal[1] = 0 - 1.0 / r_view.frustum_y;
1460 r_view.frustum[2].normal[2] = -1 - 0;
1461 r_view.frustum[3].normal[0] = 0 + 0;
1462 r_view.frustum[3].normal[1] = 0 + 1.0 / r_view.frustum_y;
1463 r_view.frustum[3].normal[2] = -1 + 0;
1467 zNear = r_refdef.nearclip;
1468 nudge = 1.0 - 1.0 / (1<<23);
1469 r_view.frustum[4].normal[0] = 0 - 0;
1470 r_view.frustum[4].normal[1] = 0 - 0;
1471 r_view.frustum[4].normal[2] = -1 - -nudge;
1472 r_view.frustum[4].dist = 0 - -2 * zNear * nudge;
1473 r_view.frustum[5].normal[0] = 0 + 0;
1474 r_view.frustum[5].normal[1] = 0 + 0;
1475 r_view.frustum[5].normal[2] = -1 + -nudge;
1476 r_view.frustum[5].dist = 0 + -2 * zNear * nudge;
1482 r_view.frustum[0].normal[0] = m[3] - m[0];
1483 r_view.frustum[0].normal[1] = m[7] - m[4];
1484 r_view.frustum[0].normal[2] = m[11] - m[8];
1485 r_view.frustum[0].dist = m[15] - m[12];
1487 r_view.frustum[1].normal[0] = m[3] + m[0];
1488 r_view.frustum[1].normal[1] = m[7] + m[4];
1489 r_view.frustum[1].normal[2] = m[11] + m[8];
1490 r_view.frustum[1].dist = m[15] + m[12];
1492 r_view.frustum[2].normal[0] = m[3] - m[1];
1493 r_view.frustum[2].normal[1] = m[7] - m[5];
1494 r_view.frustum[2].normal[2] = m[11] - m[9];
1495 r_view.frustum[2].dist = m[15] - m[13];
1497 r_view.frustum[3].normal[0] = m[3] + m[1];
1498 r_view.frustum[3].normal[1] = m[7] + m[5];
1499 r_view.frustum[3].normal[2] = m[11] + m[9];
1500 r_view.frustum[3].dist = m[15] + m[13];
1502 r_view.frustum[4].normal[0] = m[3] - m[2];
1503 r_view.frustum[4].normal[1] = m[7] - m[6];
1504 r_view.frustum[4].normal[2] = m[11] - m[10];
1505 r_view.frustum[4].dist = m[15] - m[14];
1507 r_view.frustum[5].normal[0] = m[3] + m[2];
1508 r_view.frustum[5].normal[1] = m[7] + m[6];
1509 r_view.frustum[5].normal[2] = m[11] + m[10];
1510 r_view.frustum[5].dist = m[15] + m[14];
1515 slopex = 1.0 / r_view.frustum_x;
1516 slopey = 1.0 / r_view.frustum_y;
1517 VectorMA(r_view.forward, -slopex, r_view.left, r_view.frustum[0].normal);
1518 VectorMA(r_view.forward, slopex, r_view.left, r_view.frustum[1].normal);
1519 VectorMA(r_view.forward, -slopey, r_view.up , r_view.frustum[2].normal);
1520 VectorMA(r_view.forward, slopey, r_view.up , r_view.frustum[3].normal);
1521 VectorCopy(r_view.forward, r_view.frustum[4].normal);
1522 VectorNormalize(r_view.frustum[0].normal);
1523 VectorNormalize(r_view.frustum[1].normal);
1524 VectorNormalize(r_view.frustum[2].normal);
1525 VectorNormalize(r_view.frustum[3].normal);
1526 r_view.frustum[0].dist = DotProduct (r_view.origin, r_view.frustum[0].normal);
1527 r_view.frustum[1].dist = DotProduct (r_view.origin, r_view.frustum[1].normal);
1528 r_view.frustum[2].dist = DotProduct (r_view.origin, r_view.frustum[2].normal);
1529 r_view.frustum[3].dist = DotProduct (r_view.origin, r_view.frustum[3].normal);
1530 r_view.frustum[4].dist = DotProduct (r_view.origin, r_view.frustum[4].normal) + r_refdef.nearclip;
1531 PlaneClassify(&r_view.frustum[0]);
1532 PlaneClassify(&r_view.frustum[1]);
1533 PlaneClassify(&r_view.frustum[2]);
1534 PlaneClassify(&r_view.frustum[3]);
1535 PlaneClassify(&r_view.frustum[4]);
1537 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
1538 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, -1024 * slopex, r_view.left, -1024 * slopey, r_view.up, r_view.frustumcorner[0]);
1539 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, 1024 * slopex, r_view.left, -1024 * slopey, r_view.up, r_view.frustumcorner[1]);
1540 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, -1024 * slopex, r_view.left, 1024 * slopey, r_view.up, r_view.frustumcorner[2]);
1541 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, 1024 * slopex, r_view.left, 1024 * slopey, r_view.up, r_view.frustumcorner[3]);
1543 // LordHavoc: note to all quake engine coders, Quake had a special case
1544 // for 90 degrees which assumed a square view (wrong), so I removed it,
1545 // Quake2 has it disabled as well.
1547 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
1548 //RotatePointAroundVector( r_view.frustum[0].normal, r_view.up, r_view.forward, -(90 - r_refdef.fov_x / 2));
1549 //r_view.frustum[0].dist = DotProduct (r_view.origin, frustum[0].normal);
1550 //PlaneClassify(&frustum[0]);
1552 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
1553 //RotatePointAroundVector( r_view.frustum[1].normal, r_view.up, r_view.forward, (90 - r_refdef.fov_x / 2));
1554 //r_view.frustum[1].dist = DotProduct (r_view.origin, frustum[1].normal);
1555 //PlaneClassify(&frustum[1]);
1557 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
1558 //RotatePointAroundVector( r_view.frustum[2].normal, r_view.left, r_view.forward, -(90 - r_refdef.fov_y / 2));
1559 //r_view.frustum[2].dist = DotProduct (r_view.origin, frustum[2].normal);
1560 //PlaneClassify(&frustum[2]);
1562 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
1563 //RotatePointAroundVector( r_view.frustum[3].normal, r_view.left, r_view.forward, (90 - r_refdef.fov_y / 2));
1564 //r_view.frustum[3].dist = DotProduct (r_view.origin, frustum[3].normal);
1565 //PlaneClassify(&frustum[3]);
1568 //VectorCopy(r_view.forward, r_view.frustum[4].normal);
1569 //r_view.frustum[4].dist = DotProduct (r_view.origin, frustum[4].normal) + r_nearclip.value;
1570 //PlaneClassify(&frustum[4]);
1573 void R_View_Update(void)
1575 R_View_SetFrustum();
1576 R_View_WorldVisibility();
1577 R_View_UpdateEntityVisible();
1580 void R_SetupView(const matrix4x4_t *matrix)
1582 if (r_refdef.rtworldshadows || r_refdef.rtdlightshadows)
1583 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_view.frustum_x, r_view.frustum_y, r_refdef.nearclip);
1585 GL_SetupView_Mode_Perspective(r_view.frustum_x, r_view.frustum_y, r_refdef.nearclip, r_refdef.farclip);
1587 GL_SetupView_Orientation_FromEntity(matrix);
1590 void R_ResetViewRendering2D(void)
1592 if (gl_support_fragment_shader)
1594 qglUseProgramObjectARB(0);CHECKGLERROR
1599 // GL is weird because it's bottom to top, r_view.y is top to bottom
1600 qglViewport(r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
1601 GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
1602 GL_Scissor(r_view.x, r_view.y, r_view.width, r_view.height);
1603 GL_Color(1, 1, 1, 1);
1604 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
1605 GL_BlendFunc(GL_ONE, GL_ZERO);
1606 GL_AlphaTest(false);
1607 GL_ScissorTest(false);
1608 GL_DepthMask(false);
1609 GL_DepthRange(0, 1);
1610 GL_DepthTest(false);
1611 R_Mesh_Matrix(&identitymatrix);
1612 R_Mesh_ResetTextureState();
1613 qglPolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR
1614 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
1615 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
1616 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
1617 qglStencilMask(~0);CHECKGLERROR
1618 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
1619 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
1620 GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
1623 void R_ResetViewRendering3D(void)
1625 if (gl_support_fragment_shader)
1627 qglUseProgramObjectARB(0);CHECKGLERROR
1632 // GL is weird because it's bottom to top, r_view.y is top to bottom
1633 qglViewport(r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
1634 R_SetupView(&r_view.matrix);
1635 GL_Scissor(r_view.x, r_view.y, r_view.width, r_view.height);
1636 GL_Color(1, 1, 1, 1);
1637 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
1638 GL_BlendFunc(GL_ONE, GL_ZERO);
1639 GL_AlphaTest(false);
1640 GL_ScissorTest(true);
1642 GL_DepthRange(0, 1);
1644 R_Mesh_Matrix(&identitymatrix);
1645 R_Mesh_ResetTextureState();
1646 qglPolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR
1647 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
1648 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
1649 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
1650 qglStencilMask(~0);CHECKGLERROR
1651 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
1652 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
1653 GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
1657 R_Bloom_SetupShader(
1659 "// written by Forest 'LordHavoc' Hale\n"
1661 "// common definitions between vertex shader and fragment shader:\n"
1663 "#ifdef __GLSL_CG_DATA_TYPES\n"
1664 "#define myhalf half\n"
1665 "#define myhvec2 hvec2\n"
1666 "#define myhvec3 hvec3\n"
1667 "#define myhvec4 hvec4\n"
1669 "#define myhalf float\n"
1670 "#define myhvec2 vec2\n"
1671 "#define myhvec3 vec3\n"
1672 "#define myhvec4 vec4\n"
1675 "varying vec2 ScreenTexCoord;\n"
1676 "varying vec2 BloomTexCoord;\n"
1681 "// vertex shader specific:\n"
1682 "#ifdef VERTEX_SHADER\n"
1686 " ScreenTexCoord = vec2(gl_MultiTexCoord0);\n"
1687 " BloomTexCoord = vec2(gl_MultiTexCoord1);\n"
1688 " // transform vertex to camera space, using ftransform to match non-VS\n"
1690 " gl_Position = ftransform();\n"
1693 "#endif // VERTEX_SHADER\n"
1698 "// fragment shader specific:\n"
1699 "#ifdef FRAGMENT_SHADER\n"
1704 " myhvec3 color = myhvec3(texture2D(Texture_Screen, ScreenTexCoord));\n"
1705 " for (x = -BLUR_X;x <= BLUR_X;x++)
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"
1709 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
1711 " gl_FragColor = vec4(color);\n"
1714 "#endif // FRAGMENT_SHADER\n"
1717 void R_RenderScene(void);
1719 void R_Bloom_StartFrame(void)
1721 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
1723 // set bloomwidth and bloomheight to the bloom resolution that will be
1724 // used (often less than the screen resolution for faster rendering)
1725 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_view.width);
1726 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_view.height / r_view.width;
1727 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_view.height);
1729 // calculate desired texture sizes
1730 if (gl_support_arb_texture_non_power_of_two)
1732 screentexturewidth = r_view.width;
1733 screentextureheight = r_view.height;
1734 bloomtexturewidth = r_bloomstate.bloomwidth;
1735 bloomtextureheight = r_bloomstate.bloomheight;
1739 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
1740 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
1741 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
1742 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
1747 screentexturewidth = screentextureheight = 0;
1749 else if (r_bloom.integer)
1754 screentexturewidth = screentextureheight = 0;
1755 bloomtexturewidth = bloomtextureheight = 0;
1758 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)
1760 // can't use bloom if the parameters are too weird
1761 // can't use bloom if the card does not support the texture size
1762 if (r_bloomstate.texture_screen)
1763 R_FreeTexture(r_bloomstate.texture_screen);
1764 if (r_bloomstate.texture_bloom)
1765 R_FreeTexture(r_bloomstate.texture_bloom);
1766 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
1770 r_bloomstate.enabled = true;
1771 r_bloomstate.hdr = r_hdr.integer != 0;
1773 // allocate textures as needed
1774 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
1776 if (r_bloomstate.texture_screen)
1777 R_FreeTexture(r_bloomstate.texture_screen);
1778 r_bloomstate.texture_screen = NULL;
1779 r_bloomstate.screentexturewidth = screentexturewidth;
1780 r_bloomstate.screentextureheight = screentextureheight;
1781 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
1782 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);
1784 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
1786 if (r_bloomstate.texture_bloom)
1787 R_FreeTexture(r_bloomstate.texture_bloom);
1788 r_bloomstate.texture_bloom = NULL;
1789 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
1790 r_bloomstate.bloomtextureheight = bloomtextureheight;
1791 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
1792 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);
1795 // set up a texcoord array for the full resolution screen image
1796 // (we have to keep this around to copy back during final render)
1797 r_bloomstate.screentexcoord2f[0] = 0;
1798 r_bloomstate.screentexcoord2f[1] = (float)r_view.height / (float)r_bloomstate.screentextureheight;
1799 r_bloomstate.screentexcoord2f[2] = (float)r_view.width / (float)r_bloomstate.screentexturewidth;
1800 r_bloomstate.screentexcoord2f[3] = (float)r_view.height / (float)r_bloomstate.screentextureheight;
1801 r_bloomstate.screentexcoord2f[4] = (float)r_view.width / (float)r_bloomstate.screentexturewidth;
1802 r_bloomstate.screentexcoord2f[5] = 0;
1803 r_bloomstate.screentexcoord2f[6] = 0;
1804 r_bloomstate.screentexcoord2f[7] = 0;
1806 // set up a texcoord array for the reduced resolution bloom image
1807 // (which will be additive blended over the screen image)
1808 r_bloomstate.bloomtexcoord2f[0] = 0;
1809 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
1810 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
1811 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
1812 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
1813 r_bloomstate.bloomtexcoord2f[5] = 0;
1814 r_bloomstate.bloomtexcoord2f[6] = 0;
1815 r_bloomstate.bloomtexcoord2f[7] = 0;
1818 void R_Bloom_CopyScreenTexture(float colorscale)
1820 r_refdef.stats.bloom++;
1822 R_ResetViewRendering2D();
1823 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
1824 R_Mesh_ColorPointer(NULL, 0, 0);
1825 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
1826 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
1828 // copy view into the screen texture
1829 GL_ActiveTexture(0);
1831 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
1832 r_refdef.stats.bloom_copypixels += r_view.width * r_view.height;
1834 // now scale it down to the bloom texture size
1836 qglViewport(r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
1837 GL_BlendFunc(GL_ONE, GL_ZERO);
1838 GL_Color(colorscale, colorscale, colorscale, 1);
1839 // TODO: optimize with multitexture or GLSL
1840 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
1841 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
1843 // we now have a bloom image in the framebuffer
1844 // copy it into the bloom image texture for later processing
1845 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
1846 GL_ActiveTexture(0);
1848 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
1849 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
1852 void R_Bloom_CopyHDRTexture(void)
1854 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
1855 GL_ActiveTexture(0);
1857 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
1858 r_refdef.stats.bloom_copypixels += r_view.width * r_view.height;
1861 void R_Bloom_MakeTexture(void)
1864 float xoffset, yoffset, r, brighten;
1866 r_refdef.stats.bloom++;
1868 R_ResetViewRendering2D();
1869 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
1870 R_Mesh_ColorPointer(NULL, 0, 0);
1872 // we have a bloom image in the framebuffer
1874 qglViewport(r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
1876 for (x = 1;x < r_bloom_colorexponent.value;)
1879 r = bound(0, r_bloom_colorexponent.value / x, 1);
1880 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
1881 GL_Color(r, r, r, 1);
1882 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
1883 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
1884 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
1885 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
1887 // copy the vertically blurred bloom view to a texture
1888 GL_ActiveTexture(0);
1890 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
1891 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
1894 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
1895 brighten = r_bloom_brighten.value;
1897 brighten *= r_hdr_range.value;
1898 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
1899 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
1901 for (dir = 0;dir < 2;dir++)
1903 // blend on at multiple vertical offsets to achieve a vertical blur
1904 // TODO: do offset blends using GLSL
1905 GL_BlendFunc(GL_ONE, GL_ZERO);
1906 for (x = -range;x <= range;x++)
1908 if (!dir){xoffset = 0;yoffset = x;}
1909 else {xoffset = x;yoffset = 0;}
1910 xoffset /= (float)r_bloomstate.bloomtexturewidth;
1911 yoffset /= (float)r_bloomstate.bloomtextureheight;
1912 // compute a texcoord array with the specified x and y offset
1913 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
1914 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
1915 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
1916 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
1917 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
1918 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
1919 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
1920 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
1921 // this r value looks like a 'dot' particle, fading sharply to
1922 // black at the edges
1923 // (probably not realistic but looks good enough)
1924 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
1925 //r = (dir ? 1.0f : brighten)/(range*2+1);
1926 r = (dir ? 1.0f : brighten)/(range*2+1)*(1 - x*x/(float)(range*range));
1927 GL_Color(r, r, r, 1);
1928 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
1929 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
1930 GL_BlendFunc(GL_ONE, GL_ONE);
1933 // copy the vertically blurred bloom view to a texture
1934 GL_ActiveTexture(0);
1936 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
1937 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
1940 // apply subtract last
1941 // (just like it would be in a GLSL shader)
1942 if (r_bloom_colorsubtract.value > 0 && gl_support_ext_blend_subtract)
1944 GL_BlendFunc(GL_ONE, GL_ZERO);
1945 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
1946 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
1947 GL_Color(1, 1, 1, 1);
1948 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
1949 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
1951 GL_BlendFunc(GL_ONE, GL_ONE);
1952 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
1953 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
1954 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
1955 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
1956 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
1957 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
1958 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
1960 // copy the darkened bloom view to a texture
1961 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
1962 GL_ActiveTexture(0);
1964 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
1965 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
1969 void R_HDR_RenderBloomTexture(void)
1971 int oldwidth, oldheight;
1973 oldwidth = r_view.width;
1974 oldheight = r_view.height;
1975 r_view.width = r_bloomstate.bloomwidth;
1976 r_view.height = r_bloomstate.bloomheight;
1978 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
1979 // TODO: add exposure compensation features
1980 // TODO: add fp16 framebuffer support
1982 r_view.colorscale = r_bloom_colorscale.value * r_hdr_scenebrightness.value;
1984 r_view.colorscale /= r_hdr_range.value;
1987 R_ResetViewRendering2D();
1989 R_Bloom_CopyHDRTexture();
1990 R_Bloom_MakeTexture();
1992 R_ResetViewRendering3D();
1995 if (r_timereport_active)
1996 R_TimeReport("clear");
1999 // restore the view settings
2000 r_view.width = oldwidth;
2001 r_view.height = oldheight;
2004 static void R_BlendView(void)
2006 if (r_bloomstate.enabled && r_bloomstate.hdr)
2008 // render high dynamic range bloom effect
2009 // the bloom texture was made earlier this render, so we just need to
2010 // blend it onto the screen...
2011 R_ResetViewRendering2D();
2012 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
2013 R_Mesh_ColorPointer(NULL, 0, 0);
2014 GL_Color(1, 1, 1, 1);
2015 GL_BlendFunc(GL_ONE, GL_ONE);
2016 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2017 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
2018 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2019 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
2021 else if (r_bloomstate.enabled)
2023 // render simple bloom effect
2024 // copy the screen and shrink it and darken it for the bloom process
2025 R_Bloom_CopyScreenTexture(r_bloom_colorscale.value);
2026 // make the bloom texture
2027 R_Bloom_MakeTexture();
2028 // put the original screen image back in place and blend the bloom
2030 R_ResetViewRendering2D();
2031 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
2032 R_Mesh_ColorPointer(NULL, 0, 0);
2033 GL_Color(1, 1, 1, 1);
2034 GL_BlendFunc(GL_ONE, GL_ZERO);
2035 // do both in one pass if possible
2036 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2037 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
2038 if (r_textureunits.integer >= 2 && gl_combine.integer)
2040 R_Mesh_TexCombine(1, GL_ADD, GL_ADD, 1, 1);
2041 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_screen));
2042 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.screentexcoord2f, 0, 0);
2046 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2047 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
2048 // now blend on the bloom texture
2049 GL_BlendFunc(GL_ONE, GL_ONE);
2050 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
2051 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
2053 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2054 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
2056 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
2058 // apply a color tint to the whole view
2059 R_ResetViewRendering2D();
2060 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
2061 R_Mesh_ColorPointer(NULL, 0, 0);
2062 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2063 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
2064 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2068 void R_RenderScene(void);
2070 matrix4x4_t r_waterscrollmatrix;
2072 void R_UpdateVariables(void)
2076 r_refdef.farclip = 4096;
2077 if (r_refdef.worldmodel)
2078 r_refdef.farclip += VectorDistance(r_refdef.worldmodel->normalmins, r_refdef.worldmodel->normalmaxs);
2079 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
2081 r_refdef.polygonfactor = 0;
2082 r_refdef.polygonoffset = 0;
2083 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_shadow_polygonfactor.value;
2084 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_shadow_polygonoffset.value;
2086 r_refdef.rtworld = r_shadow_realtime_world.integer;
2087 r_refdef.rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
2088 r_refdef.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
2089 r_refdef.rtdlightshadows = r_refdef.rtdlight && (r_refdef.rtworld ? r_shadow_realtime_world_dlightshadows.integer : r_shadow_realtime_dlight_shadows.integer) && gl_stencil;
2090 r_refdef.lightmapintensity = r_refdef.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
2091 if (r_showsurfaces.integer)
2093 r_refdef.rtworld = false;
2094 r_refdef.rtworldshadows = false;
2095 r_refdef.rtdlight = false;
2096 r_refdef.rtdlightshadows = false;
2097 r_refdef.lightmapintensity = 0;
2100 if (gamemode == GAME_NEHAHRA)
2102 if (gl_fogenable.integer)
2104 r_refdef.oldgl_fogenable = true;
2105 r_refdef.fog_density = gl_fogdensity.value;
2106 r_refdef.fog_red = gl_fogred.value;
2107 r_refdef.fog_green = gl_foggreen.value;
2108 r_refdef.fog_blue = gl_fogblue.value;
2110 else if (r_refdef.oldgl_fogenable)
2112 r_refdef.oldgl_fogenable = false;
2113 r_refdef.fog_density = 0;
2114 r_refdef.fog_red = 0;
2115 r_refdef.fog_green = 0;
2116 r_refdef.fog_blue = 0;
2119 if (r_refdef.fog_density)
2121 r_refdef.fogcolor[0] = bound(0.0f, r_refdef.fog_red , 1.0f);
2122 r_refdef.fogcolor[1] = bound(0.0f, r_refdef.fog_green, 1.0f);
2123 r_refdef.fogcolor[2] = bound(0.0f, r_refdef.fog_blue , 1.0f);
2125 if (r_refdef.fog_density)
2127 r_refdef.fogenabled = true;
2128 // this is the point where the fog reaches 0.9986 alpha, which we
2129 // consider a good enough cutoff point for the texture
2130 // (0.9986 * 256 == 255.6)
2131 r_refdef.fogrange = 400 / r_refdef.fog_density;
2132 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
2133 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
2134 // fog color was already set
2137 r_refdef.fogenabled = false;
2145 void R_RenderView(void)
2147 if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
2148 return; //Host_Error ("R_RenderView: NULL worldmodel");
2150 R_Shadow_UpdateWorldLightSelection();
2153 if (r_timereport_active)
2154 R_TimeReport("setup");
2157 if (r_timereport_active)
2158 R_TimeReport("visibility");
2160 R_ResetViewRendering3D();
2163 if (r_timereport_active)
2164 R_TimeReport("clear");
2166 R_Bloom_StartFrame();
2168 // this produces a bloom texture to be used in R_BlendView() later
2170 R_HDR_RenderBloomTexture();
2172 r_view.colorscale = r_hdr_scenebrightness.value;
2176 if (r_timereport_active)
2177 R_TimeReport("blendview");
2179 GL_Scissor(0, 0, vid.width, vid.height);
2180 GL_ScissorTest(false);
2184 extern void R_DrawLightningBeams (void);
2185 extern void VM_CL_AddPolygonsToMeshQueue (void);
2186 extern void R_DrawPortals (void);
2187 extern cvar_t cl_locs_show;
2188 static void R_DrawLocs(void);
2189 void R_RenderScene(void)
2191 // don't let sound skip if going slow
2192 if (r_refdef.extraupdate)
2195 R_ResetViewRendering3D();
2197 R_MeshQueue_BeginScene();
2201 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);
2203 if (cl.csqc_vidvars.drawworld)
2205 // don't let sound skip if going slow
2206 if (r_refdef.extraupdate)
2209 if (r_refdef.worldmodel && r_refdef.worldmodel->DrawSky)
2211 r_refdef.worldmodel->DrawSky(r_refdef.worldentity);
2212 if (r_timereport_active)
2213 R_TimeReport("worldsky");
2216 if (R_DrawBrushModelsSky() && r_timereport_active)
2217 R_TimeReport("bmodelsky");
2219 if (r_refdef.worldmodel && r_refdef.worldmodel->Draw)
2221 r_refdef.worldmodel->Draw(r_refdef.worldentity);
2222 if (r_timereport_active)
2223 R_TimeReport("world");
2227 // don't let sound skip if going slow
2228 if (r_refdef.extraupdate)
2232 if (r_timereport_active)
2233 R_TimeReport("models");
2235 // don't let sound skip if going slow
2236 if (r_refdef.extraupdate)
2239 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
2241 R_DrawModelShadows();
2243 R_ResetViewRendering3D();
2245 // don't let sound skip if going slow
2246 if (r_refdef.extraupdate)
2250 R_ShadowVolumeLighting(false);
2251 if (r_timereport_active)
2252 R_TimeReport("rtlights");
2254 // don't let sound skip if going slow
2255 if (r_refdef.extraupdate)
2258 if (cl.csqc_vidvars.drawworld)
2260 R_DrawLightningBeams();
2261 if (r_timereport_active)
2262 R_TimeReport("lightning");
2265 if (r_timereport_active)
2266 R_TimeReport("particles");
2269 if (r_timereport_active)
2270 R_TimeReport("explosions");
2273 if (gl_support_fragment_shader)
2275 qglUseProgramObjectARB(0);CHECKGLERROR
2277 VM_CL_AddPolygonsToMeshQueue();
2279 if (cl_locs_show.integer)
2282 if (r_timereport_active)
2283 R_TimeReport("showlocs");
2286 if (r_drawportals.integer)
2289 if (r_timereport_active)
2290 R_TimeReport("portals");
2293 if (gl_support_fragment_shader)
2295 qglUseProgramObjectARB(0);CHECKGLERROR
2297 R_MeshQueue_RenderTransparent();
2298 if (r_timereport_active)
2299 R_TimeReport("drawtrans");
2301 if (gl_support_fragment_shader)
2303 qglUseProgramObjectARB(0);CHECKGLERROR
2306 if (cl.csqc_vidvars.drawworld)
2309 if (r_timereport_active)
2310 R_TimeReport("coronas");
2313 // don't let sound skip if going slow
2314 if (r_refdef.extraupdate)
2317 R_ResetViewRendering2D();
2321 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
2324 float *v, *c, f1, f2, diff[3], vertex3f[8*3], color4f[8*4];
2325 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2326 GL_DepthMask(false);
2327 GL_DepthRange(0, 1);
2329 R_Mesh_Matrix(&identitymatrix);
2331 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2];
2332 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
2333 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
2334 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
2335 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
2336 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
2337 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
2338 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
2339 R_FillColors(color, 8, cr, cg, cb, ca);
2340 if (r_refdef.fogenabled)
2342 for (i = 0, v = vertex, c = color;i < 8;i++, v += 4, c += 4)
2344 f1 = FogPoint_World(v);
2346 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
2347 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
2348 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
2351 R_Mesh_VertexPointer(vertex3f, 0, 0);
2352 R_Mesh_ColorPointer(color, 0, 0);
2353 R_Mesh_ResetTextureState();
2354 R_Mesh_Draw(8, 12, 0, 0);
2358 int nomodelelements[24] =
2370 float nomodelvertex3f[6*3] =
2380 float nomodelcolor4f[6*4] =
2382 0.0f, 0.0f, 0.5f, 1.0f,
2383 0.0f, 0.0f, 0.5f, 1.0f,
2384 0.0f, 0.5f, 0.0f, 1.0f,
2385 0.0f, 0.5f, 0.0f, 1.0f,
2386 0.5f, 0.0f, 0.0f, 1.0f,
2387 0.5f, 0.0f, 0.0f, 1.0f
2390 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
2395 // this is only called once per entity so numsurfaces is always 1, and
2396 // surfacelist is always {0}, so this code does not handle batches
2397 R_Mesh_Matrix(&ent->matrix);
2399 if (ent->flags & EF_ADDITIVE)
2401 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2402 GL_DepthMask(false);
2404 else if (ent->alpha < 1)
2406 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2407 GL_DepthMask(false);
2411 GL_BlendFunc(GL_ONE, GL_ZERO);
2414 GL_DepthRange(0, (ent->flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
2415 GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
2416 GL_CullFace((ent->effects & EF_DOUBLESIDED) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
2417 R_Mesh_VertexPointer(nomodelvertex3f, 0, 0);
2418 if (r_refdef.fogenabled)
2421 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
2422 R_Mesh_ColorPointer(color4f, 0, 0);
2423 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
2424 f1 = FogPoint_World(org);
2426 for (i = 0, c = color4f;i < 6;i++, c += 4)
2428 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
2429 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
2430 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
2434 else if (ent->alpha != 1)
2436 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
2437 R_Mesh_ColorPointer(color4f, 0, 0);
2438 for (i = 0, c = color4f;i < 6;i++, c += 4)
2442 R_Mesh_ColorPointer(nomodelcolor4f, 0, 0);
2443 R_Mesh_ResetTextureState();
2444 R_Mesh_Draw(0, 6, 8, nomodelelements, 0, 0);
2447 void R_DrawNoModel(entity_render_t *ent)
2450 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
2451 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
2452 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, r_shadow_rtlight);
2454 // R_DrawNoModelCallback(ent, 0);
2457 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
2459 vec3_t right1, right2, diff, normal;
2461 VectorSubtract (org2, org1, normal);
2463 // calculate 'right' vector for start
2464 VectorSubtract (r_view.origin, org1, diff);
2465 CrossProduct (normal, diff, right1);
2466 VectorNormalize (right1);
2468 // calculate 'right' vector for end
2469 VectorSubtract (r_view.origin, org2, diff);
2470 CrossProduct (normal, diff, right2);
2471 VectorNormalize (right2);
2473 vert[ 0] = org1[0] + width * right1[0];
2474 vert[ 1] = org1[1] + width * right1[1];
2475 vert[ 2] = org1[2] + width * right1[2];
2476 vert[ 3] = org1[0] - width * right1[0];
2477 vert[ 4] = org1[1] - width * right1[1];
2478 vert[ 5] = org1[2] - width * right1[2];
2479 vert[ 6] = org2[0] - width * right2[0];
2480 vert[ 7] = org2[1] - width * right2[1];
2481 vert[ 8] = org2[2] - width * right2[2];
2482 vert[ 9] = org2[0] + width * right2[0];
2483 vert[10] = org2[1] + width * right2[1];
2484 vert[11] = org2[2] + width * right2[2];
2487 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
2489 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)
2494 if (r_refdef.fogenabled)
2495 fog = FogPoint_World(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 * fog * r_view.colorscale, cg * fog * r_view.colorscale, cb * fog * 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);
2530 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);
2531 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2535 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
2540 VectorSet(v, x, y, z);
2541 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
2542 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
2544 if (i == mesh->numvertices)
2546 if (mesh->numvertices < mesh->maxvertices)
2548 VectorCopy(v, vertex3f);
2549 mesh->numvertices++;
2551 return mesh->numvertices;
2557 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
2561 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
2562 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
2563 e = mesh->element3i + mesh->numtriangles * 3;
2564 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
2566 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
2567 if (mesh->numtriangles < mesh->maxtriangles)
2572 mesh->numtriangles++;
2574 element[1] = element[2];
2578 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
2582 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
2583 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
2584 e = mesh->element3i + mesh->numtriangles * 3;
2585 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
2587 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
2588 if (mesh->numtriangles < mesh->maxtriangles)
2593 mesh->numtriangles++;
2595 element[1] = element[2];
2599 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
2600 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
2602 int planenum, planenum2;
2605 mplane_t *plane, *plane2;
2607 double temppoints[2][256*3];
2608 // figure out how large a bounding box we need to properly compute this brush
2610 for (w = 0;w < numplanes;w++)
2611 maxdist = max(maxdist, planes[w].dist);
2612 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
2613 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
2614 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
2618 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
2619 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
2621 if (planenum2 == planenum)
2623 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);
2626 if (tempnumpoints < 3)
2628 // generate elements forming a triangle fan for this polygon
2629 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
2633 static void R_DrawCollisionBrush(const colbrushf_t *brush)
2636 R_Mesh_VertexPointer(brush->points->v, 0, 0);
2637 i = (int)(((size_t)brush) / sizeof(colbrushf_t));
2638 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);
2639 GL_LockArrays(0, brush->numpoints);
2640 R_Mesh_Draw(0, brush->numpoints, brush->numtriangles, brush->elements, 0, 0);
2641 GL_LockArrays(0, 0);
2644 static void R_DrawCollisionSurface(const entity_render_t *ent, const msurface_t *surface)
2647 if (!surface->num_collisiontriangles)
2649 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
2650 i = (int)(((size_t)surface) / sizeof(msurface_t));
2651 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);
2652 GL_LockArrays(0, surface->num_collisionvertices);
2653 R_Mesh_Draw(0, surface->num_collisionvertices, surface->num_collisiontriangles, surface->data_collisionelement3i, 0, 0);
2654 GL_LockArrays(0, 0);
2657 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)
2659 texturelayer_t *layer;
2660 layer = t->currentlayers + t->currentnumlayers++;
2662 layer->depthmask = depthmask;
2663 layer->blendfunc1 = blendfunc1;
2664 layer->blendfunc2 = blendfunc2;
2665 layer->texture = texture;
2666 layer->texmatrix = *matrix;
2667 layer->color[0] = r * r_view.colorscale;
2668 layer->color[1] = g * r_view.colorscale;
2669 layer->color[2] = b * r_view.colorscale;
2670 layer->color[3] = a;
2673 void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
2675 model_t *model = ent->model;
2677 // switch to an alternate material if this is a q1bsp animated material
2679 texture_t *texture = t;
2680 int s = ent->skinnum;
2681 if ((unsigned int)s >= (unsigned int)model->numskins)
2683 if (model->skinscenes)
2685 if (model->skinscenes[s].framecount > 1)
2686 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
2688 s = model->skinscenes[s].firstframe;
2691 t = t + s * model->num_surfaces;
2694 // use an alternate animation if the entity's frame is not 0,
2695 // and only if the texture has an alternate animation
2696 if (ent->frame != 0 && t->anim_total[1])
2697 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.time * 5.0f) % t->anim_total[1]) : 0];
2699 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.time * 5.0f) % t->anim_total[0]) : 0];
2701 texture->currentframe = t;
2704 // pick a new currentskinframe if the material is animated
2705 if (t->numskinframes >= 2)
2706 t->currentskinframe = t->skinframes + ((int)(t->skinframerate * (cl.time - ent->frame2time)) % t->numskinframes);
2707 if (t->backgroundnumskinframes >= 2)
2708 t->backgroundcurrentskinframe = t->backgroundskinframes + ((int)(t->backgroundskinframerate * (cl.time - ent->frame2time)) % t->backgroundnumskinframes);
2710 t->currentmaterialflags = t->basematerialflags;
2711 t->currentalpha = ent->alpha;
2712 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
2713 t->currentalpha *= r_wateralpha.value;
2714 if (!(ent->flags & RENDER_LIGHT))
2715 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
2716 if (ent->effects & EF_ADDITIVE)
2717 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
2718 else if (t->currentalpha < 1)
2719 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
2720 if (ent->effects & EF_DOUBLESIDED)
2721 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
2722 if (ent->effects & EF_NODEPTHTEST)
2723 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
2724 if (ent->flags & RENDER_VIEWMODEL)
2725 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
2726 if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
2727 t->currenttexmatrix = r_waterscrollmatrix;
2729 t->currenttexmatrix = identitymatrix;
2730 if (t->backgroundnumskinframes && !(t->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED))
2731 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
2733 t->colormapping = VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f);
2734 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
2735 t->glosstexture = r_texture_white;
2736 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
2737 t->backgroundglosstexture = r_texture_white;
2738 t->specularpower = r_shadow_glossexponent.value;
2739 // TODO: store reference values for these in the texture?
2740 t->specularscale = 0;
2741 if (r_shadow_gloss.integer > 0)
2743 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
2745 if (r_shadow_glossintensity.value > 0)
2747 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_black;
2748 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_black;
2749 t->specularscale = r_shadow_glossintensity.value;
2752 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
2753 t->specularscale = r_shadow_gloss2intensity.value;
2756 t->currentnumlayers = 0;
2757 if (!(t->currentmaterialflags & MATERIALFLAG_NODRAW))
2759 if (gl_lightmaps.integer)
2760 R_Texture_AddLayer(t, true, GL_ONE, GL_ZERO, TEXTURELAYERTYPE_LITTEXTURE, r_texture_white, &identitymatrix, 1, 1, 1, 1);
2761 else if (!(t->currentmaterialflags & MATERIALFLAG_SKY))
2763 int blendfunc1, blendfunc2, depthmask;
2764 if (t->currentmaterialflags & MATERIALFLAG_ADD)
2766 blendfunc1 = GL_SRC_ALPHA;
2767 blendfunc2 = GL_ONE;
2769 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
2771 blendfunc1 = GL_SRC_ALPHA;
2772 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
2774 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
2776 blendfunc1 = t->customblendfunc[0];
2777 blendfunc2 = t->customblendfunc[1];
2781 blendfunc1 = GL_ONE;
2782 blendfunc2 = GL_ZERO;
2784 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
2785 if (t->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL))
2787 rtexture_t *currentbasetexture;
2789 if (r_refdef.fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED))
2790 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
2791 currentbasetexture = (VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) < (1.0f / 1048576.0f) && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
2792 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2794 // fullbright is not affected by r_refdef.lightmapintensity
2795 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
2796 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
2797 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);
2798 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
2799 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);
2805 // q3bsp has no lightmap updates, so the lightstylevalue that
2806 // would normally be baked into the lightmap must be
2807 // applied to the color
2808 if (ent->model->type == mod_brushq3)
2809 colorscale *= r_refdef.lightstylevalue[0] * (1.0f / 256.0f);
2810 colorscale *= r_refdef.lightmapintensity;
2811 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);
2812 if (r_ambient.value >= (1.0f/64.0f))
2813 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);
2814 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
2816 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);
2817 if (r_ambient.value >= (1.0f/64.0f))
2818 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);
2820 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
2822 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);
2823 if (r_ambient.value >= (1.0f/64.0f))
2824 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);
2827 if (t->currentskinframe->glow != NULL)
2828 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);
2829 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
2831 // if this is opaque use alpha blend which will darken the earlier
2834 // if this is an alpha blended material, all the earlier passes
2835 // were darkened by fog already, so we only need to add the fog
2836 // color ontop through the fog mask texture
2838 // if this is an additive blended material, all the earlier passes
2839 // were darkened by fog already, and we should not add fog color
2840 // (because the background was not darkened, there is no fog color
2841 // that was lost behind it).
2842 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);
2849 void R_UpdateAllTextureInfo(entity_render_t *ent)
2853 for (i = 0;i < ent->model->num_textures;i++)
2854 R_UpdateTextureInfo(ent, ent->model->data_textures + i);
2857 int rsurface_array_size = 0;
2858 float *rsurface_array_modelvertex3f = NULL;
2859 float *rsurface_array_modelsvector3f = NULL;
2860 float *rsurface_array_modeltvector3f = NULL;
2861 float *rsurface_array_modelnormal3f = NULL;
2862 float *rsurface_array_deformedvertex3f = NULL;
2863 float *rsurface_array_deformedsvector3f = NULL;
2864 float *rsurface_array_deformedtvector3f = NULL;
2865 float *rsurface_array_deformednormal3f = NULL;
2866 float *rsurface_array_color4f = NULL;
2867 float *rsurface_array_texcoord3f = NULL;
2869 void R_Mesh_ResizeArrays(int newvertices)
2872 if (rsurface_array_size >= newvertices)
2874 if (rsurface_array_modelvertex3f)
2875 Mem_Free(rsurface_array_modelvertex3f);
2876 rsurface_array_size = (newvertices + 1023) & ~1023;
2877 base = (float *)Mem_Alloc(r_main_mempool, rsurface_array_size * sizeof(float[31]));
2878 rsurface_array_modelvertex3f = base + rsurface_array_size * 0;
2879 rsurface_array_modelsvector3f = base + rsurface_array_size * 3;
2880 rsurface_array_modeltvector3f = base + rsurface_array_size * 6;
2881 rsurface_array_modelnormal3f = base + rsurface_array_size * 9;
2882 rsurface_array_deformedvertex3f = base + rsurface_array_size * 12;
2883 rsurface_array_deformedsvector3f = base + rsurface_array_size * 15;
2884 rsurface_array_deformedtvector3f = base + rsurface_array_size * 18;
2885 rsurface_array_deformednormal3f = base + rsurface_array_size * 21;
2886 rsurface_array_texcoord3f = base + rsurface_array_size * 24;
2887 rsurface_array_color4f = base + rsurface_array_size * 27;
2890 float *rsurface_modelvertex3f;
2891 int rsurface_modelvertex3f_bufferobject;
2892 size_t rsurface_modelvertex3f_bufferoffset;
2893 float *rsurface_modelsvector3f;
2894 int rsurface_modelsvector3f_bufferobject;
2895 size_t rsurface_modelsvector3f_bufferoffset;
2896 float *rsurface_modeltvector3f;
2897 int rsurface_modeltvector3f_bufferobject;
2898 size_t rsurface_modeltvector3f_bufferoffset;
2899 float *rsurface_modelnormal3f;
2900 int rsurface_modelnormal3f_bufferobject;
2901 size_t rsurface_modelnormal3f_bufferoffset;
2902 float *rsurface_vertex3f;
2903 int rsurface_vertex3f_bufferobject;
2904 size_t rsurface_vertex3f_bufferoffset;
2905 float *rsurface_svector3f;
2906 int rsurface_svector3f_bufferobject;
2907 size_t rsurface_svector3f_bufferoffset;
2908 float *rsurface_tvector3f;
2909 int rsurface_tvector3f_bufferobject;
2910 size_t rsurface_tvector3f_bufferoffset;
2911 float *rsurface_normal3f;
2912 int rsurface_normal3f_bufferobject;
2913 size_t rsurface_normal3f_bufferoffset;
2914 float *rsurface_lightmapcolor4f;
2915 int rsurface_lightmapcolor4f_bufferobject;
2916 size_t rsurface_lightmapcolor4f_bufferoffset;
2917 vec3_t rsurface_modelorg;
2918 qboolean rsurface_generatedvertex;
2919 const entity_render_t *rsurface_entity;
2920 const model_t *rsurface_model;
2921 texture_t *rsurface_texture;
2922 qboolean rsurface_uselightmaptexture;
2923 rsurfmode_t rsurface_mode;
2924 int rsurface_lightmode; // 0 = lightmap or fullbright, 1 = color array from q3bsp, 2 = vertex shaded model
2926 void RSurf_CleanUp(void)
2929 if (rsurface_mode == RSURFMODE_GLSL)
2931 qglUseProgramObjectARB(0);CHECKGLERROR
2933 GL_AlphaTest(false);
2934 rsurface_mode = RSURFMODE_NONE;
2935 rsurface_uselightmaptexture = false;
2936 rsurface_texture = NULL;
2939 void RSurf_ActiveWorldEntity(void)
2942 rsurface_entity = r_refdef.worldentity;
2943 rsurface_model = r_refdef.worldmodel;
2944 if (rsurface_array_size < rsurface_model->surfmesh.num_vertices)
2945 R_Mesh_ResizeArrays(rsurface_model->surfmesh.num_vertices);
2946 R_Mesh_Matrix(&identitymatrix);
2947 VectorCopy(r_view.origin, rsurface_modelorg);
2948 rsurface_modelvertex3f = rsurface_model->surfmesh.data_vertex3f;
2949 rsurface_modelvertex3f_bufferobject = rsurface_model->surfmesh.vbo;
2950 rsurface_modelvertex3f_bufferoffset = rsurface_model->surfmesh.vbooffset_vertex3f;
2951 rsurface_modelsvector3f = rsurface_model->surfmesh.data_svector3f;
2952 rsurface_modelsvector3f_bufferobject = rsurface_model->surfmesh.vbo;
2953 rsurface_modelsvector3f_bufferoffset = rsurface_model->surfmesh.vbooffset_svector3f;
2954 rsurface_modeltvector3f = rsurface_model->surfmesh.data_tvector3f;
2955 rsurface_modeltvector3f_bufferobject = rsurface_model->surfmesh.vbo;
2956 rsurface_modeltvector3f_bufferoffset = rsurface_model->surfmesh.vbooffset_tvector3f;
2957 rsurface_modelnormal3f = rsurface_model->surfmesh.data_normal3f;
2958 rsurface_modelnormal3f_bufferobject = rsurface_model->surfmesh.vbo;
2959 rsurface_modelnormal3f_bufferoffset = rsurface_model->surfmesh.vbooffset_normal3f;
2960 rsurface_generatedvertex = false;
2961 rsurface_vertex3f = rsurface_modelvertex3f;
2962 rsurface_vertex3f_bufferobject = rsurface_modelvertex3f_bufferobject;
2963 rsurface_vertex3f_bufferoffset = rsurface_modelvertex3f_bufferoffset;
2964 rsurface_svector3f = rsurface_modelsvector3f;
2965 rsurface_svector3f_bufferobject = rsurface_modelsvector3f_bufferobject;
2966 rsurface_svector3f_bufferoffset = rsurface_modelsvector3f_bufferoffset;
2967 rsurface_tvector3f = rsurface_modeltvector3f;
2968 rsurface_tvector3f_bufferobject = rsurface_modeltvector3f_bufferobject;
2969 rsurface_tvector3f_bufferoffset = rsurface_modeltvector3f_bufferoffset;
2970 rsurface_normal3f = rsurface_modelnormal3f;
2971 rsurface_normal3f_bufferobject = rsurface_modelnormal3f_bufferobject;
2972 rsurface_normal3f_bufferoffset = rsurface_modelnormal3f_bufferoffset;
2975 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
2978 rsurface_entity = ent;
2979 rsurface_model = ent->model;
2980 if (rsurface_array_size < rsurface_model->surfmesh.num_vertices)
2981 R_Mesh_ResizeArrays(rsurface_model->surfmesh.num_vertices);
2982 R_Mesh_Matrix(&ent->matrix);
2983 Matrix4x4_Transform(&ent->inversematrix, r_view.origin, rsurface_modelorg);
2984 if (rsurface_model->surfmesh.isanimated && (rsurface_entity->frameblend[0].lerp != 1 || rsurface_entity->frameblend[0].frame != 0))
2988 rsurface_modelvertex3f = rsurface_array_modelvertex3f;
2989 rsurface_modelsvector3f = rsurface_array_modelsvector3f;
2990 rsurface_modeltvector3f = rsurface_array_modeltvector3f;
2991 rsurface_modelnormal3f = rsurface_array_modelnormal3f;
2992 Mod_Alias_GetMesh_Vertices(rsurface_model, rsurface_entity->frameblend, rsurface_array_modelvertex3f, rsurface_array_modelnormal3f, rsurface_array_modelsvector3f, rsurface_array_modeltvector3f);
2994 else if (wantnormals)
2996 rsurface_modelvertex3f = rsurface_array_modelvertex3f;
2997 rsurface_modelsvector3f = NULL;
2998 rsurface_modeltvector3f = NULL;
2999 rsurface_modelnormal3f = rsurface_array_modelnormal3f;
3000 Mod_Alias_GetMesh_Vertices(rsurface_model, rsurface_entity->frameblend, rsurface_array_modelvertex3f, rsurface_array_modelnormal3f, NULL, NULL);
3004 rsurface_modelvertex3f = rsurface_array_modelvertex3f;
3005 rsurface_modelsvector3f = NULL;
3006 rsurface_modeltvector3f = NULL;
3007 rsurface_modelnormal3f = NULL;
3008 Mod_Alias_GetMesh_Vertices(rsurface_model, rsurface_entity->frameblend, rsurface_array_modelvertex3f, NULL, NULL, NULL);
3010 rsurface_modelvertex3f_bufferobject = 0;
3011 rsurface_modelvertex3f_bufferoffset = 0;
3012 rsurface_modelsvector3f_bufferobject = 0;
3013 rsurface_modelsvector3f_bufferoffset = 0;
3014 rsurface_modeltvector3f_bufferobject = 0;
3015 rsurface_modeltvector3f_bufferoffset = 0;
3016 rsurface_modelnormal3f_bufferobject = 0;
3017 rsurface_modelnormal3f_bufferoffset = 0;
3018 rsurface_generatedvertex = true;
3022 rsurface_modelvertex3f = rsurface_model->surfmesh.data_vertex3f;
3023 rsurface_modelvertex3f_bufferobject = rsurface_model->surfmesh.vbo;
3024 rsurface_modelvertex3f_bufferoffset = rsurface_model->surfmesh.vbooffset_vertex3f;
3025 rsurface_modelsvector3f = rsurface_model->surfmesh.data_svector3f;
3026 rsurface_modelsvector3f_bufferobject = rsurface_model->surfmesh.vbo;
3027 rsurface_modelsvector3f_bufferoffset = rsurface_model->surfmesh.vbooffset_svector3f;
3028 rsurface_modeltvector3f = rsurface_model->surfmesh.data_tvector3f;
3029 rsurface_modeltvector3f_bufferobject = rsurface_model->surfmesh.vbo;
3030 rsurface_modeltvector3f_bufferoffset = rsurface_model->surfmesh.vbooffset_tvector3f;
3031 rsurface_modelnormal3f = rsurface_model->surfmesh.data_normal3f;
3032 rsurface_modelnormal3f_bufferobject = rsurface_model->surfmesh.vbo;
3033 rsurface_modelnormal3f_bufferoffset = rsurface_model->surfmesh.vbooffset_normal3f;
3034 rsurface_generatedvertex = false;
3036 rsurface_vertex3f = rsurface_modelvertex3f;
3037 rsurface_vertex3f_bufferobject = rsurface_modelvertex3f_bufferobject;
3038 rsurface_vertex3f_bufferoffset = rsurface_modelvertex3f_bufferoffset;
3039 rsurface_svector3f = rsurface_modelsvector3f;
3040 rsurface_svector3f_bufferobject = rsurface_modelsvector3f_bufferobject;
3041 rsurface_svector3f_bufferoffset = rsurface_modelsvector3f_bufferoffset;
3042 rsurface_tvector3f = rsurface_modeltvector3f;
3043 rsurface_tvector3f_bufferobject = rsurface_modeltvector3f_bufferobject;
3044 rsurface_tvector3f_bufferoffset = rsurface_modeltvector3f_bufferoffset;
3045 rsurface_normal3f = rsurface_modelnormal3f;
3046 rsurface_normal3f_bufferobject = rsurface_modelnormal3f_bufferobject;
3047 rsurface_normal3f_bufferoffset = rsurface_modelnormal3f_bufferoffset;
3050 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, msurface_t **texturesurfacelist)
3052 // 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
3053 if (rsurface_generatedvertex)
3055 if (rsurface_texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
3056 generatetangents = true;
3057 if (generatetangents)
3058 generatenormals = true;
3059 if (generatenormals && !rsurface_modelnormal3f)
3061 rsurface_normal3f = rsurface_modelnormal3f = rsurface_array_modelnormal3f;
3062 rsurface_normal3f_bufferobject = rsurface_modelnormal3f_bufferobject = 0;
3063 rsurface_normal3f_bufferoffset = rsurface_modelnormal3f_bufferoffset = 0;
3064 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);
3066 if (generatetangents && !rsurface_modelsvector3f)
3068 rsurface_svector3f = rsurface_modelsvector3f = rsurface_array_modelsvector3f;
3069 rsurface_svector3f_bufferobject = rsurface_modelsvector3f_bufferobject = 0;
3070 rsurface_svector3f_bufferoffset = rsurface_modelsvector3f_bufferoffset = 0;
3071 rsurface_tvector3f = rsurface_modeltvector3f = rsurface_array_modeltvector3f;
3072 rsurface_tvector3f_bufferobject = rsurface_modeltvector3f_bufferobject = 0;
3073 rsurface_tvector3f_bufferoffset = rsurface_modeltvector3f_bufferoffset = 0;
3074 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);
3077 // 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)
3078 if (rsurface_texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
3080 int texturesurfaceindex;
3081 float center[3], forward[3], right[3], up[3], v[4][3];
3082 matrix4x4_t matrix1, imatrix1;
3083 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_view.forward, forward);
3084 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_view.right, right);
3085 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_view.up, up);
3086 // make deformed versions of only the model vertices used by the specified surfaces
3087 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3090 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3091 // a single autosprite surface can contain multiple sprites...
3092 for (j = 0;j < surface->num_vertices - 3;j += 4)
3094 VectorClear(center);
3095 for (i = 0;i < 4;i++)
3096 VectorAdd(center, (rsurface_modelvertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
3097 VectorScale(center, 0.25f, center);
3098 if (rsurface_texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE2)
3100 forward[0] = rsurface_modelorg[0] - center[0];
3101 forward[1] = rsurface_modelorg[1] - center[1];
3103 VectorNormalize(forward);
3104 right[0] = forward[1];
3105 right[1] = -forward[0];
3107 VectorSet(up, 0, 0, 1);
3109 // FIXME: calculate vectors from triangle edges instead of using texture vectors as an easy way out?
3110 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);
3111 Matrix4x4_Invert_Simple(&imatrix1, &matrix1);
3112 for (i = 0;i < 4;i++)
3113 Matrix4x4_Transform(&imatrix1, (rsurface_modelvertex3f + 3 * surface->num_firstvertex) + (j+i)*3, v[i]);
3114 for (i = 0;i < 4;i++)
3115 VectorMAMAMAM(1, center, v[i][0], forward, v[i][1], right, v[i][2], up, rsurface_array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
3117 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);
3118 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);
3120 rsurface_vertex3f = rsurface_array_deformedvertex3f;
3121 rsurface_vertex3f_bufferobject = 0;
3122 rsurface_vertex3f_bufferoffset = 0;
3123 rsurface_svector3f = rsurface_array_deformedsvector3f;
3124 rsurface_svector3f_bufferobject = 0;
3125 rsurface_svector3f_bufferoffset = 0;
3126 rsurface_tvector3f = rsurface_array_deformedtvector3f;
3127 rsurface_tvector3f_bufferobject = 0;
3128 rsurface_tvector3f_bufferoffset = 0;
3129 rsurface_normal3f = rsurface_array_deformednormal3f;
3130 rsurface_normal3f_bufferobject = 0;
3131 rsurface_normal3f_bufferoffset = 0;
3135 rsurface_vertex3f = rsurface_modelvertex3f;
3136 rsurface_vertex3f_bufferobject = rsurface_modelvertex3f_bufferobject;
3137 rsurface_vertex3f_bufferoffset = rsurface_modelvertex3f_bufferoffset;
3138 rsurface_svector3f = rsurface_modelsvector3f;
3139 rsurface_svector3f_bufferobject = rsurface_modelsvector3f_bufferobject;
3140 rsurface_svector3f_bufferoffset = rsurface_modelsvector3f_bufferoffset;
3141 rsurface_tvector3f = rsurface_modeltvector3f;
3142 rsurface_tvector3f_bufferobject = rsurface_modeltvector3f_bufferobject;
3143 rsurface_tvector3f_bufferoffset = rsurface_modeltvector3f_bufferoffset;
3144 rsurface_normal3f = rsurface_modelnormal3f;
3145 rsurface_normal3f_bufferobject = rsurface_modelnormal3f_bufferobject;
3146 rsurface_normal3f_bufferoffset = rsurface_modelnormal3f_bufferoffset;
3148 R_Mesh_VertexPointer(rsurface_vertex3f, rsurface_vertex3f_bufferobject, rsurface_vertex3f_bufferoffset);
3151 void RSurf_DrawBatch_Simple(int texturenumsurfaces, msurface_t **texturesurfacelist)
3154 const msurface_t *surface = texturesurfacelist[0];
3155 const msurface_t *surface2;
3160 // TODO: lock all array ranges before render, rather than on each surface
3161 if (texturenumsurfaces == 1)
3163 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
3164 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));
3166 else if (r_batchmode.integer == 2)
3168 #define MAXBATCHTRIANGLES 4096
3169 int batchtriangles = 0;
3170 int batchelements[MAXBATCHTRIANGLES*3];
3171 for (i = 0;i < texturenumsurfaces;i = j)
3173 surface = texturesurfacelist[i];
3175 if (surface->num_triangles > MAXBATCHTRIANGLES)
3177 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));
3180 memcpy(batchelements, rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
3181 batchtriangles = surface->num_triangles;
3182 firstvertex = surface->num_firstvertex;
3183 endvertex = surface->num_firstvertex + surface->num_vertices;
3184 for (;j < texturenumsurfaces;j++)
3186 surface2 = texturesurfacelist[j];
3187 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
3189 memcpy(batchelements + batchtriangles * 3, rsurface_model->surfmesh.data_element3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
3190 batchtriangles += surface2->num_triangles;
3191 firstvertex = min(firstvertex, surface2->num_firstvertex);
3192 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
3194 surface2 = texturesurfacelist[j-1];
3195 numvertices = endvertex - firstvertex;
3196 R_Mesh_Draw(firstvertex, numvertices, batchtriangles, batchelements, 0, 0);
3199 else if (r_batchmode.integer == 1)
3201 for (i = 0;i < texturenumsurfaces;i = j)
3203 surface = texturesurfacelist[i];
3204 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
3205 if (texturesurfacelist[j] != surface2)
3207 surface2 = texturesurfacelist[j-1];
3208 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
3209 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
3210 GL_LockArrays(surface->num_firstvertex, numvertices);
3211 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));
3216 for (i = 0;i < texturenumsurfaces;i++)
3218 surface = texturesurfacelist[i];
3219 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
3220 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));
3225 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit)
3229 const msurface_t *surface = texturesurfacelist[0];
3230 const msurface_t *surface2;
3235 // TODO: lock all array ranges before render, rather than on each surface
3236 if (texturenumsurfaces == 1)
3238 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
3239 if (deluxemaptexunit >= 0)
3240 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
3241 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
3242 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));
3244 else if (r_batchmode.integer == 2)
3246 #define MAXBATCHTRIANGLES 4096
3247 int batchtriangles = 0;
3248 int batchelements[MAXBATCHTRIANGLES*3];
3249 for (i = 0;i < texturenumsurfaces;i = j)
3251 surface = texturesurfacelist[i];
3252 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
3253 if (deluxemaptexunit >= 0)
3254 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
3256 if (surface->num_triangles > MAXBATCHTRIANGLES)
3258 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));
3261 memcpy(batchelements, rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
3262 batchtriangles = surface->num_triangles;
3263 firstvertex = surface->num_firstvertex;
3264 endvertex = surface->num_firstvertex + surface->num_vertices;
3265 for (;j < texturenumsurfaces;j++)
3267 surface2 = texturesurfacelist[j];
3268 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
3270 memcpy(batchelements + batchtriangles * 3, rsurface_model->surfmesh.data_element3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
3271 batchtriangles += surface2->num_triangles;
3272 firstvertex = min(firstvertex, surface2->num_firstvertex);
3273 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
3275 surface2 = texturesurfacelist[j-1];
3276 numvertices = endvertex - firstvertex;
3277 R_Mesh_Draw(firstvertex, numvertices, batchtriangles, batchelements, 0, 0);
3280 else if (r_batchmode.integer == 1)
3283 Con_Printf("%s batch sizes ignoring lightmap:", rsurface_texture->name);
3284 for (i = 0;i < texturenumsurfaces;i = j)
3286 surface = texturesurfacelist[i];
3287 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
3288 if (texturesurfacelist[j] != surface2)
3290 Con_Printf(" %i", j - i);
3293 Con_Printf("%s batch sizes honoring lightmap:", rsurface_texture->name);
3295 for (i = 0;i < texturenumsurfaces;i = j)
3297 surface = texturesurfacelist[i];
3298 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
3299 if (deluxemaptexunit >= 0)
3300 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
3301 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
3302 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
3305 Con_Printf(" %i", j - i);
3307 surface2 = texturesurfacelist[j-1];
3308 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
3309 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
3310 GL_LockArrays(surface->num_firstvertex, numvertices);
3311 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));
3319 for (i = 0;i < texturenumsurfaces;i++)
3321 surface = texturesurfacelist[i];
3322 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
3323 if (deluxemaptexunit >= 0)
3324 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
3325 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
3326 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));
3331 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
3334 int texturesurfaceindex;
3335 if (r_showsurfaces.integer == 2)
3337 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3339 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3340 for (j = 0;j < surface->num_triangles;j++)
3342 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_view.colorscale;
3343 GL_Color(f, f, f, 1);
3344 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)));
3350 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3352 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3353 int k = (int)(((size_t)surface) / sizeof(msurface_t));
3354 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);
3355 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
3356 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));
3361 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, msurface_t **texturesurfacelist)
3363 int texturesurfaceindex;
3367 if (rsurface_lightmapcolor4f)
3369 // generate color arrays for the surfaces in this list
3370 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3372 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3373 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)
3375 f = FogPoint_Model(v);
3385 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3387 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3388 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)
3390 f = FogPoint_Model(v);
3398 rsurface_lightmapcolor4f = rsurface_array_color4f;
3399 rsurface_lightmapcolor4f_bufferobject = 0;
3400 rsurface_lightmapcolor4f_bufferoffset = 0;
3403 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a)
3405 int texturesurfaceindex;
3408 if (!rsurface_lightmapcolor4f)
3410 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3412 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3413 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)
3421 rsurface_lightmapcolor4f = rsurface_array_color4f;
3422 rsurface_lightmapcolor4f_bufferobject = 0;
3423 rsurface_lightmapcolor4f_bufferoffset = 0;
3426 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
3429 rsurface_lightmapcolor4f = NULL;
3430 rsurface_lightmapcolor4f_bufferobject = 0;
3431 rsurface_lightmapcolor4f_bufferoffset = 0;
3432 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
3433 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
3434 R_Mesh_ColorPointer(rsurface_lightmapcolor4f, rsurface_lightmapcolor4f_bufferobject, rsurface_lightmapcolor4f_bufferoffset);
3435 GL_Color(r, g, b, a);
3436 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 0, -1);
3439 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
3441 // TODO: optimize applyfog && applycolor case
3442 // just apply fog if necessary, and tint the fog color array if necessary
3443 rsurface_lightmapcolor4f = NULL;
3444 rsurface_lightmapcolor4f_bufferobject = 0;
3445 rsurface_lightmapcolor4f_bufferoffset = 0;
3446 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
3447 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
3448 R_Mesh_ColorPointer(rsurface_lightmapcolor4f, rsurface_lightmapcolor4f_bufferobject, rsurface_lightmapcolor4f_bufferoffset);
3449 GL_Color(r, g, b, a);
3450 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3453 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
3455 int texturesurfaceindex;
3459 if (texturesurfacelist[0]->lightmapinfo && texturesurfacelist[0]->lightmapinfo->stainsamples)
3461 // generate color arrays for the surfaces in this list
3462 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3464 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3465 for (i = 0, c = rsurface_array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
3467 if (surface->lightmapinfo->samples)
3469 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface_model->surfmesh.data_lightmapoffsets + surface->num_firstvertex)[i];
3470 float scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
3471 VectorScale(lm, scale, c);
3472 if (surface->lightmapinfo->styles[1] != 255)
3474 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
3476 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
3477 VectorMA(c, scale, lm, c);
3478 if (surface->lightmapinfo->styles[2] != 255)
3481 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
3482 VectorMA(c, scale, lm, c);
3483 if (surface->lightmapinfo->styles[3] != 255)
3486 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
3487 VectorMA(c, scale, lm, c);
3497 rsurface_lightmapcolor4f = rsurface_array_color4f;
3498 rsurface_lightmapcolor4f_bufferobject = 0;
3499 rsurface_lightmapcolor4f_bufferoffset = 0;
3503 rsurface_lightmapcolor4f = rsurface_model->surfmesh.data_lightmapcolor4f;
3504 rsurface_lightmapcolor4f_bufferobject = rsurface_model->surfmesh.vbo;
3505 rsurface_lightmapcolor4f_bufferoffset = rsurface_model->surfmesh.vbooffset_lightmapcolor4f;
3507 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
3508 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
3509 R_Mesh_ColorPointer(rsurface_lightmapcolor4f, rsurface_lightmapcolor4f_bufferobject, rsurface_lightmapcolor4f_bufferoffset);
3510 GL_Color(r, g, b, a);
3511 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3514 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
3516 int texturesurfaceindex;
3520 vec3_t ambientcolor;
3521 vec3_t diffusecolor;
3525 VectorCopy(rsurface_entity->modellight_lightdir, lightdir);
3526 ambientcolor[0] = rsurface_entity->modellight_ambient[0] * r * 0.5f;
3527 ambientcolor[1] = rsurface_entity->modellight_ambient[1] * g * 0.5f;
3528 ambientcolor[2] = rsurface_entity->modellight_ambient[2] * b * 0.5f;
3529 diffusecolor[0] = rsurface_entity->modellight_diffuse[0] * r * 0.5f;
3530 diffusecolor[1] = rsurface_entity->modellight_diffuse[1] * g * 0.5f;
3531 diffusecolor[2] = rsurface_entity->modellight_diffuse[2] * b * 0.5f;
3532 if (VectorLength2(diffusecolor) > 0)
3534 // generate color arrays for the surfaces in this list
3535 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3537 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3538 int numverts = surface->num_vertices;
3539 v = rsurface_vertex3f + 3 * surface->num_firstvertex;
3540 c2 = rsurface_normal3f + 3 * surface->num_firstvertex;
3541 c = rsurface_array_color4f + 4 * surface->num_firstvertex;
3542 // q3-style directional shading
3543 for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
3545 if ((f = DotProduct(c2, lightdir)) > 0)
3546 VectorMA(ambientcolor, f, diffusecolor, c);
3548 VectorCopy(ambientcolor, c);
3557 rsurface_lightmapcolor4f = rsurface_array_color4f;
3558 rsurface_lightmapcolor4f_bufferobject = 0;
3559 rsurface_lightmapcolor4f_bufferoffset = 0;
3563 r = ambientcolor[0];
3564 g = ambientcolor[1];
3565 b = ambientcolor[2];
3566 rsurface_lightmapcolor4f = NULL;
3567 rsurface_lightmapcolor4f_bufferobject = 0;
3568 rsurface_lightmapcolor4f_bufferoffset = 0;
3570 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
3571 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
3572 R_Mesh_ColorPointer(rsurface_lightmapcolor4f, rsurface_lightmapcolor4f_bufferobject, rsurface_lightmapcolor4f_bufferoffset);
3573 GL_Color(r, g, b, a);
3574 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3577 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
3579 GL_DepthRange(0, (rsurface_texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
3580 GL_DepthTest(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
3581 GL_CullFace((rsurface_texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
3582 if (rsurface_mode != RSURFMODE_SHOWSURFACES)
3584 rsurface_mode = RSURFMODE_SHOWSURFACES;
3586 GL_BlendFunc(GL_ONE, GL_ZERO);
3587 R_Mesh_ColorPointer(NULL, 0, 0);
3588 R_Mesh_ResetTextureState();
3590 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
3591 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
3594 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, msurface_t **texturesurfacelist)
3596 // transparent sky would be ridiculous
3597 if ((rsurface_texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED))
3599 if (rsurface_mode != RSURFMODE_SKY)
3601 if (rsurface_mode == RSURFMODE_GLSL)
3603 qglUseProgramObjectARB(0);CHECKGLERROR
3605 rsurface_mode = RSURFMODE_SKY;
3609 skyrendernow = false;
3611 // restore entity matrix
3612 R_Mesh_Matrix(&rsurface_entity->matrix);
3614 GL_DepthRange(0, (rsurface_texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
3615 GL_DepthTest(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
3616 GL_CullFace((rsurface_texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
3618 // LordHavoc: HalfLife maps have freaky skypolys so don't use
3619 // skymasking on them, and Quake3 never did sky masking (unlike
3620 // software Quake and software Quake2), so disable the sky masking
3621 // in Quake3 maps as it causes problems with q3map2 sky tricks,
3622 // and skymasking also looks very bad when noclipping outside the
3623 // level, so don't use it then either.
3624 if (rsurface_model->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_viewcache.world_novis)
3626 GL_Color(r_refdef.fogcolor[0] * r_view.colorscale, r_refdef.fogcolor[1] * r_view.colorscale, r_refdef.fogcolor[2] * r_view.colorscale, 1);
3627 R_Mesh_ColorPointer(NULL, 0, 0);
3628 R_Mesh_ResetTextureState();
3629 if (skyrendermasked)
3631 // depth-only (masking)
3632 GL_ColorMask(0,0,0,0);
3633 // just to make sure that braindead drivers don't draw
3634 // anything despite that colormask...
3635 GL_BlendFunc(GL_ZERO, GL_ONE);
3640 GL_BlendFunc(GL_ONE, GL_ZERO);
3642 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
3643 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3644 if (skyrendermasked)
3645 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
3649 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, msurface_t **texturesurfacelist)
3651 if (rsurface_mode != RSURFMODE_GLSL)
3653 rsurface_mode = RSURFMODE_GLSL;
3654 R_Mesh_ResetTextureState();
3657 R_SetupSurfaceShader(vec3_origin, rsurface_lightmode == 2, 1, 1, rsurface_texture->specularscale);
3658 if (!r_glsl_permutation)
3661 if (rsurface_lightmode == 2)
3662 RSurf_PrepareVerticesForBatch(true, r_glsl_permutation->loc_Texture_Normal, texturenumsurfaces, texturesurfacelist);
3664 RSurf_PrepareVerticesForBatch(r_glsl_permutation->loc_Texture_Normal, r_glsl_permutation->loc_Texture_Normal, texturenumsurfaces, texturesurfacelist);
3665 R_Mesh_TexCoordPointer(0, 2, rsurface_model->surfmesh.data_texcoordtexture2f, rsurface_model->surfmesh.vbo, rsurface_model->surfmesh.vbooffset_texcoordtexture2f);
3666 R_Mesh_TexCoordPointer(1, 3, rsurface_svector3f, rsurface_svector3f_bufferobject, rsurface_svector3f_bufferoffset);
3667 R_Mesh_TexCoordPointer(2, 3, rsurface_tvector3f, rsurface_tvector3f_bufferobject, rsurface_tvector3f_bufferoffset);
3668 R_Mesh_TexCoordPointer(3, 3, rsurface_normal3f, rsurface_normal3f_bufferobject, rsurface_normal3f_bufferoffset);
3669 R_Mesh_TexCoordPointer(4, 2, rsurface_model->surfmesh.data_texcoordlightmap2f, rsurface_model->surfmesh.vbo, rsurface_model->surfmesh.vbooffset_texcoordlightmap2f);
3671 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
3673 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
3674 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
3675 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
3676 R_Mesh_ColorPointer(NULL, 0, 0);
3678 else if (rsurface_uselightmaptexture)
3680 R_Mesh_TexBind(7, R_GetTexture(texturesurfacelist[0]->lightmaptexture));
3681 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
3682 R_Mesh_TexBind(8, R_GetTexture(texturesurfacelist[0]->deluxemaptexture));
3683 R_Mesh_ColorPointer(NULL, 0, 0);
3687 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
3688 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
3689 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
3690 R_Mesh_ColorPointer(rsurface_model->surfmesh.data_lightmapcolor4f, rsurface_model->surfmesh.vbo, rsurface_model->surfmesh.vbooffset_lightmapcolor4f);
3693 if (rsurface_uselightmaptexture && !(rsurface_texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
3694 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 7, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? 8 : -1);
3696 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3697 if (rsurface_texture->backgroundnumskinframes && !(rsurface_texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED))
3702 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, msurface_t **texturesurfacelist)
3704 // OpenGL 1.3 path - anything not completely ancient
3705 int texturesurfaceindex;
3706 qboolean applycolor;
3710 const texturelayer_t *layer;
3711 if (rsurface_mode != RSURFMODE_MULTIPASS)
3712 rsurface_mode = RSURFMODE_MULTIPASS;
3713 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
3714 for (layerindex = 0, layer = rsurface_texture->currentlayers;layerindex < rsurface_texture->currentnumlayers;layerindex++, layer++)
3717 int layertexrgbscale;
3718 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
3720 if (layerindex == 0)
3724 GL_AlphaTest(false);
3725 qglDepthFunc(GL_EQUAL);CHECKGLERROR
3728 GL_DepthMask(layer->depthmask);
3729 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
3730 if ((layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2) && (gl_combine.integer || layer->depthmask))
3732 layertexrgbscale = 4;
3733 VectorScale(layer->color, 0.25f, layercolor);
3735 else if ((layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1) && (gl_combine.integer || layer->depthmask))
3737 layertexrgbscale = 2;
3738 VectorScale(layer->color, 0.5f, layercolor);
3742 layertexrgbscale = 1;
3743 VectorScale(layer->color, 1.0f, layercolor);
3745 layercolor[3] = layer->color[3];
3746 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
3747 R_Mesh_ColorPointer(NULL, 0, 0);
3748 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
3749 switch (layer->type)
3751 case TEXTURELAYERTYPE_LITTEXTURE:
3752 memset(&m, 0, sizeof(m));
3753 m.tex[0] = R_GetTexture(r_texture_white);
3754 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordlightmap2f;
3755 m.pointer_texcoord_bufferobject[0] = rsurface_model->surfmesh.vbo;
3756 m.pointer_texcoord_bufferoffset[0] = rsurface_model->surfmesh.vbooffset_texcoordlightmap2f;
3757 m.tex[1] = R_GetTexture(layer->texture);
3758 m.texmatrix[1] = layer->texmatrix;
3759 m.texrgbscale[1] = layertexrgbscale;
3760 m.pointer_texcoord[1] = rsurface_model->surfmesh.data_texcoordtexture2f;
3761 m.pointer_texcoord_bufferobject[1] = rsurface_model->surfmesh.vbo;
3762 m.pointer_texcoord_bufferoffset[1] = rsurface_model->surfmesh.vbooffset_texcoordtexture2f;
3763 R_Mesh_TextureState(&m);
3764 if (rsurface_lightmode == 2)
3765 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
3766 else if (rsurface_uselightmaptexture)
3767 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
3769 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
3771 case TEXTURELAYERTYPE_TEXTURE:
3772 memset(&m, 0, sizeof(m));
3773 m.tex[0] = R_GetTexture(layer->texture);
3774 m.texmatrix[0] = layer->texmatrix;
3775 m.texrgbscale[0] = layertexrgbscale;
3776 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3777 m.pointer_texcoord_bufferobject[0] = rsurface_model->surfmesh.vbo;
3778 m.pointer_texcoord_bufferoffset[0] = rsurface_model->surfmesh.vbooffset_texcoordtexture2f;
3779 R_Mesh_TextureState(&m);
3780 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
3782 case TEXTURELAYERTYPE_FOG:
3783 memset(&m, 0, sizeof(m));
3784 m.texrgbscale[0] = layertexrgbscale;
3787 m.tex[0] = R_GetTexture(layer->texture);
3788 m.texmatrix[0] = layer->texmatrix;
3789 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3790 m.pointer_texcoord_bufferobject[0] = rsurface_model->surfmesh.vbo;
3791 m.pointer_texcoord_bufferoffset[0] = rsurface_model->surfmesh.vbooffset_texcoordtexture2f;
3793 R_Mesh_TextureState(&m);
3794 // generate a color array for the fog pass
3795 R_Mesh_ColorPointer(rsurface_array_color4f, 0, 0);
3796 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3800 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3801 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)
3803 f = 1 - FogPoint_Model(v);
3804 c[0] = layercolor[0];
3805 c[1] = layercolor[1];
3806 c[2] = layercolor[2];
3807 c[3] = f * layercolor[3];
3810 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3813 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
3815 GL_LockArrays(0, 0);
3818 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
3820 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3821 GL_AlphaTest(false);
3825 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, msurface_t **texturesurfacelist)
3827 // OpenGL 1.1 - crusty old voodoo path
3828 int texturesurfaceindex;
3832 const texturelayer_t *layer;
3833 if (rsurface_mode != RSURFMODE_MULTIPASS)
3834 rsurface_mode = RSURFMODE_MULTIPASS;
3835 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
3836 for (layerindex = 0, layer = rsurface_texture->currentlayers;layerindex < rsurface_texture->currentnumlayers;layerindex++, layer++)
3838 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
3840 if (layerindex == 0)
3844 GL_AlphaTest(false);
3845 qglDepthFunc(GL_EQUAL);CHECKGLERROR
3848 GL_DepthMask(layer->depthmask);
3849 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
3850 R_Mesh_ColorPointer(NULL, 0, 0);
3851 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
3852 switch (layer->type)
3854 case TEXTURELAYERTYPE_LITTEXTURE:
3855 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
3857 // two-pass lit texture with 2x rgbscale
3858 // first the lightmap pass
3859 memset(&m, 0, sizeof(m));
3860 m.tex[0] = R_GetTexture(r_texture_white);
3861 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordlightmap2f;
3862 m.pointer_texcoord_bufferobject[0] = rsurface_model->surfmesh.vbo;
3863 m.pointer_texcoord_bufferoffset[0] = rsurface_model->surfmesh.vbooffset_texcoordlightmap2f;
3864 R_Mesh_TextureState(&m);
3865 if (rsurface_lightmode == 2)
3866 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
3867 else if (rsurface_uselightmaptexture)
3868 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
3870 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
3871 GL_LockArrays(0, 0);
3872 // then apply the texture to it
3873 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
3874 memset(&m, 0, sizeof(m));
3875 m.tex[0] = R_GetTexture(layer->texture);
3876 m.texmatrix[0] = layer->texmatrix;
3877 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3878 m.pointer_texcoord_bufferobject[0] = rsurface_model->surfmesh.vbo;
3879 m.pointer_texcoord_bufferoffset[0] = rsurface_model->surfmesh.vbooffset_texcoordtexture2f;
3880 R_Mesh_TextureState(&m);
3881 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);
3885 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
3886 memset(&m, 0, sizeof(m));
3887 m.tex[0] = R_GetTexture(layer->texture);
3888 m.texmatrix[0] = layer->texmatrix;
3889 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3890 m.pointer_texcoord_bufferobject[0] = rsurface_model->surfmesh.vbo;
3891 m.pointer_texcoord_bufferoffset[0] = rsurface_model->surfmesh.vbooffset_texcoordtexture2f;
3892 R_Mesh_TextureState(&m);
3893 if (rsurface_lightmode == 2)
3894 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);
3896 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);
3899 case TEXTURELAYERTYPE_TEXTURE:
3900 // singletexture unlit texture with transparency support
3901 memset(&m, 0, sizeof(m));
3902 m.tex[0] = R_GetTexture(layer->texture);
3903 m.texmatrix[0] = layer->texmatrix;
3904 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3905 m.pointer_texcoord_bufferobject[0] = rsurface_model->surfmesh.vbo;
3906 m.pointer_texcoord_bufferoffset[0] = rsurface_model->surfmesh.vbooffset_texcoordtexture2f;
3907 R_Mesh_TextureState(&m);
3908 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);
3910 case TEXTURELAYERTYPE_FOG:
3911 // singletexture fogging
3912 R_Mesh_ColorPointer(rsurface_array_color4f, 0, 0);
3915 memset(&m, 0, sizeof(m));
3916 m.tex[0] = R_GetTexture(layer->texture);
3917 m.texmatrix[0] = layer->texmatrix;
3918 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3919 m.pointer_texcoord_bufferobject[0] = rsurface_model->surfmesh.vbo;
3920 m.pointer_texcoord_bufferoffset[0] = rsurface_model->surfmesh.vbooffset_texcoordtexture2f;
3921 R_Mesh_TextureState(&m);
3924 R_Mesh_ResetTextureState();
3925 // generate a color array for the fog pass
3926 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3930 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3931 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)
3933 f = 1 - FogPoint_Model(v);
3934 c[0] = layer->color[0];
3935 c[1] = layer->color[1];
3936 c[2] = layer->color[2];
3937 c[3] = f * layer->color[3];
3940 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3943 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
3945 GL_LockArrays(0, 0);
3948 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
3950 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3951 GL_AlphaTest(false);
3955 static void R_DrawTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist)
3957 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_NODRAW)
3959 r_shadow_rtlight = NULL;
3960 r_refdef.stats.entities_surfaces += texturenumsurfaces;
3962 if (r_showsurfaces.integer)
3963 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
3964 else if (rsurface_texture->currentmaterialflags & MATERIALFLAG_SKY)
3965 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
3966 else if (rsurface_texture->currentnumlayers)
3968 GL_DepthRange(0, (rsurface_texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
3969 GL_DepthTest(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
3970 GL_CullFace((rsurface_texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
3971 GL_BlendFunc(rsurface_texture->currentlayers[0].blendfunc1, rsurface_texture->currentlayers[0].blendfunc2);
3972 GL_DepthMask(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_BLENDED));
3973 GL_Color(rsurface_entity->colormod[0], rsurface_entity->colormod[1], rsurface_entity->colormod[2], rsurface_texture->currentalpha);
3974 GL_AlphaTest((rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
3975 // FIXME: identify models using a better check than rsurface_model->brush.shadowmesh
3976 rsurface_lightmode = ((rsurface_texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT) || rsurface_model->brush.shadowmesh) ? 0 : 2;
3977 if (r_glsl.integer && gl_support_fragment_shader)
3978 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist);
3979 else if (gl_combine.integer && r_textureunits.integer >= 2)
3980 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist);
3982 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist);
3985 GL_LockArrays(0, 0);
3988 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
3991 int texturenumsurfaces, endsurface;
3993 msurface_t *surface;
3994 msurface_t *texturesurfacelist[1024];
3996 // if the model is static it doesn't matter what value we give for
3997 // wantnormals and wanttangents, so this logic uses only rules applicable
3998 // to a model, knowing that they are meaningless otherwise
3999 if (ent == r_refdef.worldentity)
4000 RSurf_ActiveWorldEntity();
4001 else if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
4002 RSurf_ActiveModelEntity(ent, false, false);
4004 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
4006 for (i = 0;i < numsurfaces;i = j)
4009 surface = rsurface_model->data_surfaces + surfacelist[i];
4010 texture = surface->texture;
4011 R_UpdateTextureInfo(ent, texture);
4012 rsurface_texture = texture->currentframe;
4013 rsurface_uselightmaptexture = surface->lightmaptexture != NULL;
4014 // scan ahead until we find a different texture
4015 endsurface = min(i + 1024, numsurfaces);
4016 texturenumsurfaces = 0;
4017 texturesurfacelist[texturenumsurfaces++] = surface;
4018 for (;j < endsurface;j++)
4020 surface = rsurface_model->data_surfaces + surfacelist[j];
4021 if (texture != surface->texture || rsurface_uselightmaptexture != (surface->lightmaptexture != NULL))
4023 texturesurfacelist[texturenumsurfaces++] = surface;
4025 // render the range of surfaces
4026 R_DrawTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
4032 void R_QueueSurfaceList(int numsurfaces, msurface_t **surfacelist, int flagsmask)
4035 vec3_t tempcenter, center;
4037 // break the surface list down into batches by texture and use of lightmapping
4038 for (i = 0;i < numsurfaces;i = j)
4041 // texture is the base texture pointer, rsurface_texture is the
4042 // current frame/skin the texture is directing us to use (for example
4043 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
4044 // use skin 1 instead)
4045 texture = surfacelist[i]->texture;
4046 rsurface_texture = texture->currentframe;
4047 rsurface_uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
4048 if (!(rsurface_texture->currentmaterialflags & flagsmask))
4050 // if this texture is not the kind we want, skip ahead to the next one
4051 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
4055 if (rsurface_texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
4057 // transparent surfaces get pushed off into the transparent queue
4058 const msurface_t *surface = surfacelist[i];
4059 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
4060 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
4061 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
4062 Matrix4x4_Transform(&rsurface_entity->matrix, tempcenter, center);
4063 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);
4067 // simply scan ahead until we find a different texture or lightmap state
4068 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface_uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
4070 // render the range of surfaces
4071 R_DrawTextureSurfaceList(j - i, surfacelist + i);
4076 float locboxvertex3f[6*4*3] =
4078 1,0,1, 1,0,0, 1,1,0, 1,1,1,
4079 0,1,1, 0,1,0, 0,0,0, 0,0,1,
4080 1,1,1, 1,1,0, 0,1,0, 0,1,1,
4081 0,0,1, 0,0,0, 1,0,0, 1,0,1,
4082 0,0,1, 1,0,1, 1,1,1, 0,1,1,
4083 1,0,0, 0,0,0, 0,1,0, 1,1,0
4086 int locboxelement3i[6*2*3] =
4096 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
4099 cl_locnode_t *loc = (cl_locnode_t *)ent;
4101 float vertex3f[6*4*3];
4103 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4104 GL_DepthMask(false);
4105 GL_DepthRange(0, 1);
4107 GL_CullFace(GL_NONE);
4108 R_Mesh_Matrix(&identitymatrix);
4110 R_Mesh_VertexPointer(vertex3f, 0, 0);
4111 R_Mesh_ColorPointer(NULL, 0, 0);
4112 R_Mesh_ResetTextureState();
4115 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_view.colorscale,
4116 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_view.colorscale,
4117 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_view.colorscale,
4118 surfacelist[0] < 0 ? 0.5f : 0.125f);
4120 if (VectorCompare(loc->mins, loc->maxs))
4122 VectorSet(size, 2, 2, 2);
4123 VectorMA(loc->mins, -0.5f, size, mins);
4127 VectorCopy(loc->mins, mins);
4128 VectorSubtract(loc->maxs, loc->mins, size);
4131 for (i = 0;i < 6*4*3;)
4132 for (j = 0;j < 3;j++, i++)
4133 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
4135 R_Mesh_Draw(0, 6*4, 6*2, locboxelement3i, 0, 0);
4138 void R_DrawLocs(void)
4141 cl_locnode_t *loc, *nearestloc;
4143 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
4144 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
4146 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
4147 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
4151 void R_DrawCollisionBrushes(entity_render_t *ent)
4155 msurface_t *surface;
4156 model_t *model = ent->model;
4157 if (!model->brush.num_brushes)
4160 R_Mesh_ColorPointer(NULL, 0, 0);
4161 R_Mesh_ResetTextureState();
4162 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
4163 GL_DepthMask(false);
4164 GL_DepthRange(0, 1);
4165 GL_DepthTest(!r_showdisabledepthtest.integer);
4166 qglPolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);CHECKGLERROR
4167 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
4168 if (brush->colbrushf && brush->colbrushf->numtriangles)
4169 R_DrawCollisionBrush(brush->colbrushf);
4170 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
4171 if (surface->num_collisiontriangles)
4172 R_DrawCollisionSurface(ent, surface);
4173 qglPolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR
4176 void R_DrawTrianglesAndNormals(entity_render_t *ent, qboolean drawtris, qboolean drawnormals, int flagsmask)
4179 const int *elements;
4180 msurface_t *surface;
4181 model_t *model = ent->model;
4184 GL_DepthRange(0, 1);
4185 GL_DepthTest(!r_showdisabledepthtest.integer);
4187 GL_BlendFunc(GL_ONE, GL_ZERO);
4188 R_Mesh_ColorPointer(NULL, 0, 0);
4189 R_Mesh_ResetTextureState();
4190 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
4192 if (ent == r_refdef.worldentity && !r_viewcache.world_surfacevisible[j])
4194 rsurface_texture = surface->texture->currentframe;
4195 if ((rsurface_texture->currentmaterialflags & flagsmask) && surface->num_triangles)
4197 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
4200 if (!rsurface_texture->currentlayers->depthmask)
4201 GL_Color(r_showtris.value * r_view.colorscale, 0, 0, 1);
4202 else if (ent == r_refdef.worldentity)
4203 GL_Color(r_showtris.value * r_view.colorscale, r_showtris.value * r_view.colorscale, r_showtris.value * r_view.colorscale, 1);
4205 GL_Color(0, r_showtris.value * r_view.colorscale, 0, 1);
4206 elements = (ent->model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
4209 for (k = 0;k < surface->num_triangles;k++, elements += 3)
4211 qglArrayElement(elements[0]);qglArrayElement(elements[1]);
4212 qglArrayElement(elements[1]);qglArrayElement(elements[2]);
4213 qglArrayElement(elements[2]);qglArrayElement(elements[0]);
4220 GL_Color(r_shownormals.value * r_view.colorscale, 0, 0, 1);
4222 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
4224 VectorCopy(rsurface_vertex3f + l * 3, v);
4225 qglVertex3f(v[0], v[1], v[2]);
4226 VectorMA(v, 8, rsurface_svector3f + l * 3, v);
4227 qglVertex3f(v[0], v[1], v[2]);
4231 GL_Color(0, 0, r_shownormals.value * r_view.colorscale, 1);
4233 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
4235 VectorCopy(rsurface_vertex3f + l * 3, v);
4236 qglVertex3f(v[0], v[1], v[2]);
4237 VectorMA(v, 8, rsurface_tvector3f + l * 3, v);
4238 qglVertex3f(v[0], v[1], v[2]);
4242 GL_Color(0, r_shownormals.value * r_view.colorscale, 0, 1);
4244 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
4246 VectorCopy(rsurface_vertex3f + l * 3, v);
4247 qglVertex3f(v[0], v[1], v[2]);
4248 VectorMA(v, 8, rsurface_normal3f + l * 3, v);
4249 qglVertex3f(v[0], v[1], v[2]);
4256 rsurface_texture = NULL;
4259 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
4260 void R_DrawWorldSurfaces(qboolean skysurfaces)
4262 int i, j, endj, f, flagsmask;
4263 int counttriangles = 0;
4264 msurface_t *surface, **surfacechain;
4266 model_t *model = r_refdef.worldmodel;
4267 const int maxsurfacelist = 1024;
4268 int numsurfacelist = 0;
4269 msurface_t *surfacelist[1024];
4273 RSurf_ActiveWorldEntity();
4275 // update light styles
4276 if (!skysurfaces && model->brushq1.light_styleupdatechains)
4278 for (i = 0;i < model->brushq1.light_styles;i++)
4280 if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
4282 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
4283 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
4284 for (;(surface = *surfacechain);surfacechain++)
4285 surface->cached_dlight = true;
4290 R_UpdateAllTextureInfo(r_refdef.worldentity);
4291 flagsmask = skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL);
4294 rsurface_uselightmaptexture = false;
4295 rsurface_texture = NULL;
4297 j = model->firstmodelsurface;
4298 endj = j + model->nummodelsurfaces;
4301 // quickly skip over non-visible surfaces
4302 for (;j < endj && !r_viewcache.world_surfacevisible[j];j++)
4304 // quickly iterate over visible surfaces
4305 for (;j < endj && r_viewcache.world_surfacevisible[j];j++)
4307 // process this surface
4308 surface = model->data_surfaces + j;
4309 // if this surface fits the criteria, add it to the list
4310 if (surface->num_triangles)
4312 // if lightmap parameters changed, rebuild lightmap texture
4313 if (surface->cached_dlight)
4314 R_BuildLightMap(r_refdef.worldentity, surface);
4315 // add face to draw list
4316 surfacelist[numsurfacelist++] = surface;
4317 counttriangles += surface->num_triangles;
4318 if (numsurfacelist >= maxsurfacelist)
4320 R_QueueSurfaceList(numsurfacelist, surfacelist, flagsmask);
4327 R_QueueSurfaceList(numsurfacelist, surfacelist, flagsmask);
4328 r_refdef.stats.entities_triangles += counttriangles;
4331 if (r_showcollisionbrushes.integer && !skysurfaces)
4332 R_DrawCollisionBrushes(r_refdef.worldentity);
4334 if (r_showtris.integer || r_shownormals.integer)
4335 R_DrawTrianglesAndNormals(r_refdef.worldentity, r_showtris.integer, r_shownormals.integer, flagsmask);
4338 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces)
4340 int i, f, flagsmask;
4341 int counttriangles = 0;
4342 msurface_t *surface, *endsurface, **surfacechain;
4344 model_t *model = ent->model;
4345 const int maxsurfacelist = 1024;
4346 int numsurfacelist = 0;
4347 msurface_t *surfacelist[1024];
4351 // if the model is static it doesn't matter what value we give for
4352 // wantnormals and wanttangents, so this logic uses only rules applicable
4353 // to a model, knowing that they are meaningless otherwise
4354 if (ent == r_refdef.worldentity)
4355 RSurf_ActiveWorldEntity();
4356 else if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
4357 RSurf_ActiveModelEntity(ent, false, false);
4359 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
4361 // update light styles
4362 if (!skysurfaces && model->brushq1.light_styleupdatechains)
4364 for (i = 0;i < model->brushq1.light_styles;i++)
4366 if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
4368 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
4369 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
4370 for (;(surface = *surfacechain);surfacechain++)
4371 surface->cached_dlight = true;
4376 R_UpdateAllTextureInfo(ent);
4377 flagsmask = skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL);
4380 rsurface_uselightmaptexture = false;
4381 rsurface_texture = NULL;
4383 surface = model->data_surfaces + model->firstmodelsurface;
4384 endsurface = surface + model->nummodelsurfaces;
4385 for (;surface < endsurface;surface++)
4387 // if this surface fits the criteria, add it to the list
4388 if (surface->num_triangles)
4390 // if lightmap parameters changed, rebuild lightmap texture
4391 if (surface->cached_dlight)
4392 R_BuildLightMap(ent, surface);
4393 // add face to draw list
4394 surfacelist[numsurfacelist++] = surface;
4395 counttriangles += surface->num_triangles;
4396 if (numsurfacelist >= maxsurfacelist)
4398 R_QueueSurfaceList(numsurfacelist, surfacelist, flagsmask);
4404 R_QueueSurfaceList(numsurfacelist, surfacelist, flagsmask);
4405 r_refdef.stats.entities_triangles += counttriangles;
4408 if (r_showcollisionbrushes.integer && !skysurfaces)
4409 R_DrawCollisionBrushes(ent);
4411 if (r_showtris.integer || r_shownormals.integer)
4412 R_DrawTrianglesAndNormals(ent, r_showtris.integer, r_shownormals.integer, flagsmask);