2 Copyright (C) 1996-1997 Id Software, Inc.
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26 mempool_t *r_main_mempool;
27 rtexturepool_t *r_main_texturepool;
34 r_viewcache_t r_viewcache;
36 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
37 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
38 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
39 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
40 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
41 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
42 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
43 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
44 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
45 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
46 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
47 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
48 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
49 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
50 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling"};
51 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
52 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
53 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
54 cvar_t r_fullbright = {0, "r_fullbright","0", "make everything bright cheat (not allowed in multiplayer)"};
55 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
56 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
57 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
58 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this)"};
59 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
60 cvar_t r_q1bsp_skymasking = {0, "r_qb1sp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
62 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
63 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
64 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
65 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
66 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
67 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
68 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
70 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of hardware texture units reported by driver (note: setting this to 1 turns off gl_combine)"};
72 cvar_t r_glsl = {0, "r_glsl", "1", "enables use of OpenGL 2.0 pixel shaders for lighting"};
73 cvar_t r_glsl_offsetmapping = {0, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
74 cvar_t r_glsl_offsetmapping_reliefmapping = {0, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
75 cvar_t r_glsl_offsetmapping_scale = {0, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
76 cvar_t r_glsl_deluxemapping = {0, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"};
78 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1", "enables animation smoothing on sprites (requires r_lerpmodels 1)"};
79 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
80 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
82 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
83 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
84 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
85 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
86 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
87 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
88 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
90 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
91 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
92 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
93 cvar_t r_hdr_range = {CVAR_SAVE, "r_hdr_range", "4", "how much dynamic range to render bloom with (equivilant to multiplying r_bloom_brighten by this value and dividing r_bloom_colorscale by this value)"};
95 cvar_t r_smoothnormals_areaweighting = {0, "r_smoothnormals_areaweighting", "1", "uses significantly faster (and supposedly higher quality) area-weighted vertex normals and tangent vectors rather than summing normalized triangle normals and tangents"};
97 cvar_t developer_texturelogging = {0, "developer_texturelogging", "0", "produces a textures.log file containing names of skins and map textures the engine tried to load"};
99 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
101 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
102 cvar_t r_batchmode = {0, "r_batchmode", "1", "selects method of rendering multiple surfaces with one driver call (values are 0, 1, 2, etc...)"};
104 typedef struct r_glsl_bloomshader_s
107 int loc_Texture_Bloom;
109 r_glsl_bloomshader_t;
111 static struct r_bloomstate_s
116 int bloomwidth, bloomheight;
118 int screentexturewidth, screentextureheight;
119 rtexture_t *texture_screen;
121 int bloomtexturewidth, bloomtextureheight;
122 rtexture_t *texture_bloom;
124 r_glsl_bloomshader_t *shader;
126 // arrays for rendering the screen passes
127 float screentexcoord2f[8];
128 float bloomtexcoord2f[8];
129 float offsettexcoord2f[8];
133 // shadow volume bsp struct with automatically growing nodes buffer
136 rtexture_t *r_texture_blanknormalmap;
137 rtexture_t *r_texture_white;
138 rtexture_t *r_texture_black;
139 rtexture_t *r_texture_notexture;
140 rtexture_t *r_texture_whitecube;
141 rtexture_t *r_texture_normalizationcube;
142 rtexture_t *r_texture_fogattenuation;
143 //rtexture_t *r_texture_fogintensity;
145 // information about each possible shader permutation
146 r_glsl_permutation_t r_glsl_permutations[SHADERPERMUTATION_COUNT];
147 // currently selected permutation
148 r_glsl_permutation_t *r_glsl_permutation;
150 // temporary variable used by a macro
153 // vertex coordinates for a quad that covers the screen exactly
154 const static float r_screenvertex3f[12] =
162 extern void R_DrawModelShadows(void);
164 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
167 for (i = 0;i < verts;i++)
178 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
181 for (i = 0;i < verts;i++)
191 // FIXME: move this to client?
194 if (gamemode == GAME_NEHAHRA)
196 Cvar_Set("gl_fogenable", "0");
197 Cvar_Set("gl_fogdensity", "0.2");
198 Cvar_Set("gl_fogred", "0.3");
199 Cvar_Set("gl_foggreen", "0.3");
200 Cvar_Set("gl_fogblue", "0.3");
202 r_refdef.fog_density = r_refdef.fog_red = r_refdef.fog_green = r_refdef.fog_blue = 0.0f;
205 // FIXME: move this to client?
206 void FOG_registercvars(void)
211 if (gamemode == GAME_NEHAHRA)
213 Cvar_RegisterVariable (&gl_fogenable);
214 Cvar_RegisterVariable (&gl_fogdensity);
215 Cvar_RegisterVariable (&gl_fogred);
216 Cvar_RegisterVariable (&gl_foggreen);
217 Cvar_RegisterVariable (&gl_fogblue);
218 Cvar_RegisterVariable (&gl_fogstart);
219 Cvar_RegisterVariable (&gl_fogend);
222 r = (-1.0/256.0) * (FOGTABLEWIDTH * FOGTABLEWIDTH);
223 for (x = 0;x < FOGTABLEWIDTH;x++)
225 alpha = exp(r / ((double)x*(double)x));
226 if (x == FOGTABLEWIDTH - 1)
228 r_refdef.fogtable[x] = bound(0, alpha, 1);
232 static void R_BuildBlankTextures(void)
234 unsigned char data[4];
235 data[0] = 128; // normal X
236 data[1] = 128; // normal Y
237 data[2] = 255; // normal Z
238 data[3] = 128; // height
239 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
244 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
249 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
252 static void R_BuildNoTexture(void)
255 unsigned char pix[16][16][4];
256 // this makes a light grey/dark grey checkerboard texture
257 for (y = 0;y < 16;y++)
259 for (x = 0;x < 16;x++)
261 if ((y < 8) ^ (x < 8))
277 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_RGBA, TEXF_MIPMAP, NULL);
280 static void R_BuildWhiteCube(void)
282 unsigned char data[6*1*1*4];
283 data[ 0] = 255;data[ 1] = 255;data[ 2] = 255;data[ 3] = 255;
284 data[ 4] = 255;data[ 5] = 255;data[ 6] = 255;data[ 7] = 255;
285 data[ 8] = 255;data[ 9] = 255;data[10] = 255;data[11] = 255;
286 data[12] = 255;data[13] = 255;data[14] = 255;data[15] = 255;
287 data[16] = 255;data[17] = 255;data[18] = 255;data[19] = 255;
288 data[20] = 255;data[21] = 255;data[22] = 255;data[23] = 255;
289 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
292 static void R_BuildNormalizationCube(void)
296 vec_t s, t, intensity;
298 unsigned char data[6][NORMSIZE][NORMSIZE][4];
299 for (side = 0;side < 6;side++)
301 for (y = 0;y < NORMSIZE;y++)
303 for (x = 0;x < NORMSIZE;x++)
305 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
306 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
341 intensity = 127.0f / sqrt(DotProduct(v, v));
342 data[side][y][x][0] = (unsigned char)(128.0f + intensity * v[0]);
343 data[side][y][x][1] = (unsigned char)(128.0f + intensity * v[1]);
344 data[side][y][x][2] = (unsigned char)(128.0f + intensity * v[2]);
345 data[side][y][x][3] = 255;
349 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, &data[0][0][0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
352 static void R_BuildFogTexture(void)
357 unsigned char data1[FOGWIDTH][4];
358 //unsigned char data2[FOGWIDTH][4];
359 r = (-1.0/256.0) * (FOGWIDTH * FOGWIDTH);
360 for (x = 0;x < FOGWIDTH;x++)
362 alpha = exp(r / ((double)x*(double)x));
363 if (x == FOGWIDTH - 1)
365 b = (int)(256.0 * alpha);
366 b = bound(0, b, 255);
367 data1[x][0] = 255 - b;
368 data1[x][1] = 255 - b;
369 data1[x][2] = 255 - b;
376 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
377 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
380 static const char *builtinshaderstring =
381 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
382 "// written by Forest 'LordHavoc' Hale\n"
384 "// common definitions between vertex shader and fragment shader:\n"
386 "#ifdef __GLSL_CG_DATA_TYPES\n"
387 "#define myhalf half\n"
388 "#define myhvec2 hvec2\n"
389 "#define myhvec3 hvec3\n"
390 "#define myhvec4 hvec4\n"
392 "#define myhalf float\n"
393 "#define myhvec2 vec2\n"
394 "#define myhvec3 vec3\n"
395 "#define myhvec4 vec4\n"
398 "varying vec2 TexCoord;\n"
399 "varying vec2 TexCoordLightmap;\n"
401 "varying vec3 CubeVector;\n"
402 "varying vec3 LightVector;\n"
403 "varying vec3 EyeVector;\n"
405 "varying vec3 EyeVectorModelSpace;\n"
408 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
409 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
410 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
415 "// vertex shader specific:\n"
416 "#ifdef VERTEX_SHADER\n"
418 "uniform vec3 LightPosition;\n"
419 "uniform vec3 EyePosition;\n"
420 "uniform vec3 LightDir;\n"
422 "// TODO: get rid of tangentt (texcoord2) and use a crossproduct to regenerate it from tangents (texcoord1) and normal (texcoord3)\n"
426 " gl_FrontColor = gl_Color;\n"
427 " // copy the surface texcoord\n"
428 " TexCoord = vec2(gl_TextureMatrix[0] * gl_MultiTexCoord0);\n"
429 "#if !defined(MODE_LIGHTSOURCE) && !defined(MODE_LIGHTDIRECTION)\n"
430 " TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
433 "#ifdef MODE_LIGHTSOURCE\n"
434 " // transform vertex position into light attenuation/cubemap space\n"
435 " // (-1 to +1 across the light box)\n"
436 " CubeVector = vec3(gl_TextureMatrix[3] * gl_Vertex);\n"
438 " // transform unnormalized light direction into tangent space\n"
439 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
440 " // normalize it per pixel)\n"
441 " vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
442 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
443 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
444 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
447 "#ifdef MODE_LIGHTDIRECTION\n"
448 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
449 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
450 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
453 " // transform unnormalized eye direction into tangent space\n"
455 " vec3 EyeVectorModelSpace;\n"
457 " EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
458 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
459 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
460 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
462 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
463 " VectorS = gl_MultiTexCoord1.xyz;\n"
464 " VectorT = gl_MultiTexCoord2.xyz;\n"
465 " VectorR = gl_MultiTexCoord3.xyz;\n"
468 " // transform vertex to camera space, using ftransform to match non-VS\n"
470 " gl_Position = ftransform();\n"
473 "#endif // VERTEX_SHADER\n"
478 "// fragment shader specific:\n"
479 "#ifdef FRAGMENT_SHADER\n"
481 "uniform sampler2D Texture_Normal;\n"
482 "uniform sampler2D Texture_Color;\n"
483 "uniform sampler2D Texture_Gloss;\n"
484 "uniform samplerCube Texture_Cube;\n"
485 "uniform sampler2D Texture_FogMask;\n"
486 "uniform sampler2D Texture_Pants;\n"
487 "uniform sampler2D Texture_Shirt;\n"
488 "uniform sampler2D Texture_Lightmap;\n"
489 "uniform sampler2D Texture_Deluxemap;\n"
490 "uniform sampler2D Texture_Glow;\n"
492 "uniform myhvec3 LightColor;\n"
493 "uniform myhvec3 AmbientColor;\n"
494 "uniform myhvec3 DiffuseColor;\n"
495 "uniform myhvec3 SpecularColor;\n"
496 "uniform myhvec3 Color_Pants;\n"
497 "uniform myhvec3 Color_Shirt;\n"
498 "uniform myhvec3 FogColor;\n"
500 "uniform myhalf GlowScale;\n"
501 "uniform myhalf SceneBrightness;\n"
503 "uniform float OffsetMapping_Scale;\n"
504 "uniform float OffsetMapping_Bias;\n"
505 "uniform float FogRangeRecip;\n"
507 "uniform myhalf AmbientScale;\n"
508 "uniform myhalf DiffuseScale;\n"
509 "uniform myhalf SpecularScale;\n"
510 "uniform myhalf SpecularPower;\n"
514 " // apply offsetmapping\n"
515 "#ifdef USEOFFSETMAPPING\n"
516 " vec2 TexCoordOffset = TexCoord;\n"
517 "#define TexCoord TexCoordOffset\n"
519 " vec3 eyedir = vec3(normalize(EyeVector));\n"
520 " float depthbias = 1.0 - eyedir.z; // should this be a -?\n"
521 " depthbias = 1.0 - depthbias * depthbias;\n"
523 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
524 " // 14 sample relief mapping: linear search and then binary search\n"
525 " //vec3 OffsetVector = vec3(EyeVector.xy * (1.0 / EyeVector.z) * depthbias * OffsetMapping_Scale * vec2(-0.1, 0.1), -0.1);\n"
526 " //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-0.1, 0.1), -0.1);\n"
527 " vec3 OffsetVector = vec3(eyedir.xy * OffsetMapping_Scale * vec2(-0.1, 0.1), -0.1);\n"
528 " vec3 RT = vec3(TexCoord - OffsetVector.xy * 10.0, 1.0) + OffsetVector;\n"
529 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
530 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
531 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
532 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
533 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
534 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
535 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
536 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
537 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;OffsetVector *= 0.5;RT -= OffsetVector;\n"
538 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;OffsetVector *= 0.5;RT -= OffsetVector;\n"
539 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;OffsetVector *= 0.5;RT -= OffsetVector;\n"
540 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;OffsetVector *= 0.5;RT -= OffsetVector;\n"
541 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;OffsetVector *= 0.5;RT -= OffsetVector;\n"
542 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;OffsetVector *= 0.5;RT -= OffsetVector;\n"
543 " TexCoord = RT.xy;\n"
545 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
546 " //vec2 OffsetVector = vec2(EyeVector.xy * (1.0 / EyeVector.z) * depthbias) * OffsetMapping_Scale * vec2(-0.333, 0.333);\n"
547 " //vec2 OffsetVector = vec2(normalize(EyeVector.xy)) * OffsetMapping_Scale * vec2(-0.333, 0.333);\n"
548 " vec2 OffsetVector = vec2(eyedir.xy) * OffsetMapping_Scale * vec2(-0.333, 0.333);\n"
549 " //TexCoord += OffsetVector * 3.0;\n"
550 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
551 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
552 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
554 " // 10 sample offset mapping\n"
555 " //vec2 OffsetVector = vec2(EyeVector.xy * (1.0 / EyeVector.z) * depthbias) * OffsetMapping_Scale * vec2(-0.333, 0.333);\n"
556 " //vec2 OffsetVector = vec2(normalize(EyeVector.xy)) * OffsetMapping_Scale * vec2(-0.333, 0.333);\n"
557 " vec2 OffsetVector = vec2(eyedir.xy) * OffsetMapping_Scale * vec2(-0.1, 0.1);\n"
558 " //TexCoord += OffsetVector * 3.0;\n"
559 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
560 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
561 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
562 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
563 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
564 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
565 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
566 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
567 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
568 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
570 " // parallax mapping as described in the paper\n"
571 " // 'Parallax Mapping with Offset Limiting: A Per-Pixel Approximation of Uneven Surfaces' by Terry Welsh\n"
572 " // The paper provides code in the ARB fragment program assembly language\n"
573 " // I translated it to GLSL but may have done something wrong - SavageX\n"
574 " // LordHavoc: removed bias and simplified to one line\n"
575 " // LordHavoc: this is just a single sample offsetmapping...\n"
576 " TexCoordOffset += vec2(eyedir.x, -1.0 * eyedir.y) * OffsetMapping_Scale * texture2D(Texture_Normal, TexCoord).a;\n"
578 " // parallax mapping as described in the paper\n"
579 " // 'Parallax Mapping with Offset Limiting: A Per-Pixel Approximation of Uneven Surfaces' by Terry Welsh\n"
580 " // The paper provides code in the ARB fragment program assembly language\n"
581 " // I translated it to GLSL but may have done something wrong - SavageX\n"
582 " float height = texture2D(Texture_Normal, TexCoord).a;\n"
583 " height = (height - 0.5) * OffsetMapping_Scale; // bias and scale\n"
584 " TexCoordOffset += height * vec2(eyedir.x, -1.0 * eyedir.y);\n"
588 " // combine the diffuse textures (base, pants, shirt)\n"
589 " myhvec4 color = myhvec4(texture2D(Texture_Color, TexCoord));\n"
590 "#ifdef USECOLORMAPPING\n"
591 " color.rgb += myhvec3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhvec3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
597 "#ifdef MODE_LIGHTSOURCE\n"
600 " // get the surface normal and light normal\n"
601 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
602 " myhvec3 diffusenormal = myhvec3(normalize(LightVector));\n"
604 " // calculate directional shading\n"
605 " color.rgb *= AmbientScale + DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
606 "#ifdef USESPECULAR\n"
607 " myhvec3 specularnormal = normalize(diffusenormal + myhvec3(normalize(EyeVector)));\n"
608 " color.rgb += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
611 "#ifdef USECUBEFILTER\n"
612 " // apply light cubemap filter\n"
613 " //color.rgb *= normalize(CubeVector) * 0.5 + 0.5;//vec3(textureCube(Texture_Cube, CubeVector));\n"
614 " color.rgb *= myhvec3(textureCube(Texture_Cube, CubeVector));\n"
617 " // apply light color\n"
618 " color.rgb *= LightColor;\n"
620 " // apply attenuation\n"
622 " // the attenuation is (1-(x*x+y*y+z*z)) which gives a large bright\n"
623 " // center and sharp falloff at the edge, this is about the most efficient\n"
624 " // we can get away with as far as providing illumination.\n"
626 " // pow(1-(x*x+y*y+z*z), 4) is far more realistic but needs large lights to\n"
627 " // provide significant illumination, large = slow = pain.\n"
628 "// color.rgb *= myhalf(max(1.0 - dot(CubeVector, CubeVector), 0.0));\n"
629 " color.rgb *= myhalf(max(2.0 - 2.0 * length(CubeVector), 0.0) / (1 + dot(CubeVector, CubeVector)));\n"
634 "#elif defined(MODE_LIGHTDIRECTION)\n"
635 " // directional model lighting\n"
637 " // get the surface normal and light normal\n"
638 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
639 " myhvec3 diffusenormal = myhvec3(normalize(LightVector));\n"
641 " // calculate directional shading\n"
642 " color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
643 "#ifdef USESPECULAR\n"
644 " myhvec3 specularnormal = normalize(diffusenormal + myhvec3(normalize(EyeVector)));\n"
645 " color.rgb += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
651 "#elif defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
652 " // deluxemap lightmapping using light vectors in modelspace (evil q3map2)\n"
654 " // get the surface normal and light normal\n"
655 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
657 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
658 " myhvec3 diffusenormal_modelspace = myhvec3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - myhvec3(0.5);\n"
659 " myhvec3 diffusenormal = normalize(myhvec3(dot(diffusenormal_modelspace, myhvec3(VectorS)), dot(diffusenormal_modelspace, myhvec3(VectorT)), dot(diffusenormal_modelspace, myhvec3(VectorR))));\n"
661 " myhvec3 diffusenormal = normalize(myhvec3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - myhvec3(0.5));\n"
663 " // calculate directional shading\n"
664 " myhvec3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0)));\n"
665 "#ifdef USESPECULAR\n"
666 " myhvec3 specularnormal = myhvec3(normalize(diffusenormal + myhvec3(normalize(EyeVector))));\n"
667 " tempcolor += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
670 " // apply lightmap color\n"
671 " color.rgb = tempcolor * myhvec3(texture2D(Texture_Lightmap, TexCoordLightmap)) + color.rgb * AmbientScale;\n"
674 "#else // MODE none (lightmap)\n"
675 " // apply lightmap color\n"
676 " color.rgb *= myhvec3(texture2D(Texture_Lightmap, TexCoordLightmap)) * DiffuseScale + myhvec3(AmbientScale);\n"
679 " color *= myhvec4(gl_Color);\n"
682 " color.rgb += myhvec3(texture2D(Texture_Glow, TexCoord)) * GlowScale;\n"
687 " myhalf fog = myhalf(texture2D(Texture_FogMask, myhvec2(length(EyeVectorModelSpace)*FogRangeRecip, 0.0)).x);\n"
688 " color.rgb = color.rgb * fog + FogColor * (1.0 - fog);\n"
691 " color.rgb *= SceneBrightness;\n"
693 " gl_FragColor = vec4(color);\n"
696 "#endif // FRAGMENT_SHADER\n"
699 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
700 const char *permutationinfo[][2] =
702 {"#define MODE_LIGHTSOURCE\n", " lightsource"},
703 {"#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
704 {"#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
705 {"#define MODE_LIGHTDIRECTION\n", " lightdirection"},
706 {"#define USEGLOW\n", " glow"},
707 {"#define USEFOG\n", " fog"},
708 {"#define USECOLORMAPPING\n", " colormapping"},
709 {"#define USESPECULAR\n", " specular"},
710 {"#define USECUBEFILTER\n", " cubefilter"},
711 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
712 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
716 void R_GLSL_CompilePermutation(const char *filename, int permutation)
719 qboolean shaderfound;
720 r_glsl_permutation_t *p = r_glsl_permutations + (permutation & SHADERPERMUTATION_COUNTMASK);
721 int vertstrings_count;
722 int geomstrings_count;
723 int fragstrings_count;
725 const char *vertstrings_list[SHADERPERMUTATION_COUNT+1];
726 const char *geomstrings_list[SHADERPERMUTATION_COUNT+1];
727 const char *fragstrings_list[SHADERPERMUTATION_COUNT+1];
728 char permutationname[256];
733 vertstrings_list[0] = "#define VERTEX_SHADER\n";
734 geomstrings_list[0] = "#define GEOMETRY_SHADER\n";
735 fragstrings_list[0] = "#define FRAGMENT_SHADER\n";
736 vertstrings_count = 1;
737 geomstrings_count = 1;
738 fragstrings_count = 1;
739 permutationname[0] = 0;
740 for (i = 0;permutationinfo[i][0];i++)
742 if (permutation & (1<<i))
744 vertstrings_list[vertstrings_count++] = permutationinfo[i][0];
745 geomstrings_list[geomstrings_count++] = permutationinfo[i][0];
746 fragstrings_list[fragstrings_count++] = permutationinfo[i][0];
747 strlcat(permutationname, permutationinfo[i][1], sizeof(permutationname));
751 // keep line numbers correct
752 vertstrings_list[vertstrings_count++] = "\n";
753 geomstrings_list[geomstrings_count++] = "\n";
754 fragstrings_list[fragstrings_count++] = "\n";
757 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
761 Con_DPrintf("GLSL shader text for \"%s\" loaded from disk\n", filename);
762 vertstrings_list[vertstrings_count++] = shaderstring;
763 geomstrings_list[geomstrings_count++] = shaderstring;
764 fragstrings_list[fragstrings_count++] = shaderstring;
767 else if (!strcmp(filename, "glsl/default.glsl"))
769 Con_DPrintf("GLSL shader text for \"%s\" loaded from engine\n", filename);
770 vertstrings_list[vertstrings_count++] = builtinshaderstring;
771 geomstrings_list[geomstrings_count++] = builtinshaderstring;
772 fragstrings_list[fragstrings_count++] = builtinshaderstring;
775 // clear any lists that are not needed by this shader
776 if (!(permutation & SHADERPERMUTATION_USES_VERTEXSHADER))
777 vertstrings_count = 0;
778 if (!(permutation & SHADERPERMUTATION_USES_GEOMETRYSHADER))
779 geomstrings_count = 0;
780 if (!(permutation & SHADERPERMUTATION_USES_FRAGMENTSHADER))
781 fragstrings_count = 0;
782 // compile the shader program
783 if (shaderfound && vertstrings_count + geomstrings_count + fragstrings_count)
784 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
788 qglUseProgramObjectARB(p->program);CHECKGLERROR
789 // look up all the uniform variable names we care about, so we don't
790 // have to look them up every time we set them
791 p->loc_Texture_Normal = qglGetUniformLocationARB(p->program, "Texture_Normal");
792 p->loc_Texture_Color = qglGetUniformLocationARB(p->program, "Texture_Color");
793 p->loc_Texture_Gloss = qglGetUniformLocationARB(p->program, "Texture_Gloss");
794 p->loc_Texture_Cube = qglGetUniformLocationARB(p->program, "Texture_Cube");
795 p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
796 p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
797 p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
798 p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
799 p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
800 p->loc_Texture_Glow = qglGetUniformLocationARB(p->program, "Texture_Glow");
801 p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
802 p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
803 p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
804 p->loc_LightColor = qglGetUniformLocationARB(p->program, "LightColor");
805 p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants");
806 p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt");
807 p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip");
808 p->loc_AmbientScale = qglGetUniformLocationARB(p->program, "AmbientScale");
809 p->loc_DiffuseScale = qglGetUniformLocationARB(p->program, "DiffuseScale");
810 p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
811 p->loc_SpecularScale = qglGetUniformLocationARB(p->program, "SpecularScale");
812 p->loc_GlowScale = qglGetUniformLocationARB(p->program, "GlowScale");
813 p->loc_SceneBrightness = qglGetUniformLocationARB(p->program, "SceneBrightness");
814 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
815 p->loc_AmbientColor = qglGetUniformLocationARB(p->program, "AmbientColor");
816 p->loc_DiffuseColor = qglGetUniformLocationARB(p->program, "DiffuseColor");
817 p->loc_SpecularColor = qglGetUniformLocationARB(p->program, "SpecularColor");
818 p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
819 // initialize the samplers to refer to the texture units we use
820 if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal, 0);
821 if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color, 1);
822 if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss, 2);
823 if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube, 3);
824 if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask, 4);
825 if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants, 5);
826 if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt, 6);
827 if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap, 7);
828 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap, 8);
829 if (p->loc_Texture_Glow >= 0) qglUniform1iARB(p->loc_Texture_Glow, 9);
831 qglUseProgramObjectARB(0);CHECKGLERROR
834 Con_Printf("permutation%s failed for shader %s, some features may not work properly!\n", permutationname, "glsl/default.glsl");
836 Mem_Free(shaderstring);
839 void R_GLSL_Restart_f(void)
842 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
843 if (r_glsl_permutations[i].program)
844 GL_Backend_FreeProgram(r_glsl_permutations[i].program);
845 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
848 int R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting)
850 // select a permutation of the lighting shader appropriate to this
851 // combination of texture, entity, light source, and fogging, only use the
852 // minimum features necessary to avoid wasting rendering time in the
853 // fragment shader on features that are not being used
854 const char *shaderfilename = NULL;
856 float specularscale = rsurface_texture->specularscale;
857 r_glsl_permutation = NULL;
858 // TODO: implement geometry-shader based shadow volumes someday
859 if (r_shadow_rtlight)
862 shaderfilename = "glsl/default.glsl";
863 permutation = SHADERPERMUTATION_MODE_LIGHTSOURCE | SHADERPERMUTATION_USES_VERTEXSHADER | SHADERPERMUTATION_USES_FRAGMENTSHADER;
864 specularscale *= r_shadow_rtlight->specularscale;
865 if (r_shadow_rtlight->currentcubemap != r_texture_whitecube)
866 permutation |= SHADERPERMUTATION_CUBEFILTER;
867 if (specularscale > 0)
868 permutation |= SHADERPERMUTATION_SPECULAR;
869 if (r_refdef.fogenabled)
870 permutation |= SHADERPERMUTATION_FOG;
871 if (rsurface_texture->colormapping)
872 permutation |= SHADERPERMUTATION_COLORMAPPING;
873 if (r_glsl_offsetmapping.integer)
875 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
876 if (r_glsl_offsetmapping_reliefmapping.integer)
877 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
880 else if (rsurface_texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
882 // bright unshaded geometry
883 shaderfilename = "glsl/default.glsl";
884 permutation = SHADERPERMUTATION_USES_VERTEXSHADER | SHADERPERMUTATION_USES_FRAGMENTSHADER;
885 if (rsurface_texture->currentskinframe->glow)
886 permutation |= SHADERPERMUTATION_GLOW;
887 if (r_refdef.fogenabled)
888 permutation |= SHADERPERMUTATION_FOG;
889 if (rsurface_texture->colormapping)
890 permutation |= SHADERPERMUTATION_COLORMAPPING;
891 if (r_glsl_offsetmapping.integer)
893 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
894 if (r_glsl_offsetmapping_reliefmapping.integer)
895 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
898 else if (modellighting)
900 // directional model lighting
901 shaderfilename = "glsl/default.glsl";
902 permutation = SHADERPERMUTATION_USES_VERTEXSHADER | SHADERPERMUTATION_USES_FRAGMENTSHADER;
903 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTION;
904 if (rsurface_texture->currentskinframe->glow)
905 permutation |= SHADERPERMUTATION_GLOW;
906 if (specularscale > 0)
907 permutation |= SHADERPERMUTATION_SPECULAR;
908 if (r_refdef.fogenabled)
909 permutation |= SHADERPERMUTATION_FOG;
910 if (rsurface_texture->colormapping)
911 permutation |= SHADERPERMUTATION_COLORMAPPING;
912 if (r_glsl_offsetmapping.integer)
914 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
915 if (r_glsl_offsetmapping_reliefmapping.integer)
916 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
922 shaderfilename = "glsl/default.glsl";
923 permutation = SHADERPERMUTATION_USES_VERTEXSHADER | SHADERPERMUTATION_USES_FRAGMENTSHADER;
924 if (r_glsl_deluxemapping.integer >= 1 && rsurface_uselightmaptexture && r_refdef.worldmodel && r_refdef.worldmodel->brushq3.deluxemapping)
926 // deluxemapping (light direction texture)
927 if (rsurface_uselightmaptexture && r_refdef.worldmodel && r_refdef.worldmodel->brushq3.deluxemapping && r_refdef.worldmodel->brushq3.deluxemapping_modelspace)
928 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_MODELSPACE;
930 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
931 if (specularscale > 0)
932 permutation |= SHADERPERMUTATION_SPECULAR;
934 else if (r_glsl_deluxemapping.integer >= 2)
936 // fake deluxemapping (uniform light direction in tangentspace)
937 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
938 if (specularscale > 0)
939 permutation |= SHADERPERMUTATION_SPECULAR;
943 // ordinary lightmapping
946 if (rsurface_texture->currentskinframe->glow)
947 permutation |= SHADERPERMUTATION_GLOW;
948 if (r_refdef.fogenabled)
949 permutation |= SHADERPERMUTATION_FOG;
950 if (rsurface_texture->colormapping)
951 permutation |= SHADERPERMUTATION_COLORMAPPING;
952 if (r_glsl_offsetmapping.integer)
954 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
955 if (r_glsl_offsetmapping_reliefmapping.integer)
956 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
959 if (!r_glsl_permutations[permutation & SHADERPERMUTATION_COUNTMASK].program)
961 if (!r_glsl_permutations[permutation & SHADERPERMUTATION_COUNTMASK].compiled)
962 R_GLSL_CompilePermutation(shaderfilename, permutation);
963 if (!r_glsl_permutations[permutation & SHADERPERMUTATION_COUNTMASK].program)
965 // remove features until we find a valid permutation
967 for (i = SHADERPERMUTATION_COUNT-1;;i>>=1)
969 // reduce i more quickly whenever it would not remove any bits
973 if (!r_glsl_permutations[permutation & SHADERPERMUTATION_COUNTMASK].compiled)
974 R_GLSL_CompilePermutation(shaderfilename, permutation);
975 if (r_glsl_permutations[permutation & SHADERPERMUTATION_COUNTMASK].program)
978 return 0; // utterly failed
982 r_glsl_permutation = r_glsl_permutations + (permutation & SHADERPERMUTATION_COUNTMASK);
984 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
985 R_Mesh_TexMatrix(0, &rsurface_texture->currenttexmatrix);
986 if (permutation & SHADERPERMUTATION_MODE_LIGHTSOURCE)
988 if (r_glsl_permutation->loc_Texture_Cube >= 0 && r_shadow_rtlight) R_Mesh_TexBindCubeMap(3, R_GetTexture(r_shadow_rtlight->currentcubemap));
989 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, r_shadow_entitylightorigin[0], r_shadow_entitylightorigin[1], r_shadow_entitylightorigin[2]);
990 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
991 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_shadow_rtlight->ambientscale);
992 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_shadow_rtlight->diffusescale);
993 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, specularscale);
995 else if (permutation & SHADERPERMUTATION_MODE_LIGHTDIRECTION)
997 if (r_glsl_permutation->loc_AmbientColor >= 0)
998 qglUniform3fARB(r_glsl_permutation->loc_AmbientColor, rsurface_entity->modellight_ambient[0], rsurface_entity->modellight_ambient[1], rsurface_entity->modellight_ambient[2]);
999 if (r_glsl_permutation->loc_DiffuseColor >= 0)
1000 qglUniform3fARB(r_glsl_permutation->loc_DiffuseColor, rsurface_entity->modellight_diffuse[0], rsurface_entity->modellight_diffuse[1], rsurface_entity->modellight_diffuse[2]);
1001 if (r_glsl_permutation->loc_SpecularColor >= 0)
1002 qglUniform3fARB(r_glsl_permutation->loc_SpecularColor, rsurface_entity->modellight_diffuse[0] * rsurface_texture->specularscale, rsurface_entity->modellight_diffuse[1] * rsurface_texture->specularscale, rsurface_entity->modellight_diffuse[2] * rsurface_texture->specularscale);
1003 if (r_glsl_permutation->loc_LightDir >= 0)
1004 qglUniform3fARB(r_glsl_permutation->loc_LightDir, rsurface_entity->modellight_lightdir[0], rsurface_entity->modellight_lightdir[1], rsurface_entity->modellight_lightdir[2]);
1008 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_ambient.value * 2.0f / 128.0f);
1009 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_refdef.lightmapintensity * 2.0f);
1010 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, r_refdef.lightmapintensity * specularscale * 2.0f);
1012 if (r_glsl_permutation->loc_Texture_Normal >= 0) R_Mesh_TexBind(0, R_GetTexture(rsurface_texture->currentskinframe->nmap));
1013 if (r_glsl_permutation->loc_Texture_Color >= 0) R_Mesh_TexBind(1, R_GetTexture(rsurface_texture->basetexture));
1014 if (r_glsl_permutation->loc_Texture_Gloss >= 0) R_Mesh_TexBind(2, R_GetTexture(rsurface_texture->glosstexture));
1015 //if (r_glsl_permutation->loc_Texture_Cube >= 0 && permutation & SHADERPERMUTATION_MODE_LIGHTSOURCE) R_Mesh_TexBindCubeMap(3, R_GetTexture(r_shadow_rtlight->currentcubemap));
1016 if (r_glsl_permutation->loc_Texture_FogMask >= 0) R_Mesh_TexBind(4, R_GetTexture(r_texture_fogattenuation));
1017 if (r_glsl_permutation->loc_Texture_Pants >= 0) R_Mesh_TexBind(5, R_GetTexture(rsurface_texture->currentskinframe->pants));
1018 if (r_glsl_permutation->loc_Texture_Shirt >= 0) R_Mesh_TexBind(6, R_GetTexture(rsurface_texture->currentskinframe->shirt));
1019 //if (r_glsl_permutation->loc_Texture_Lightmap >= 0) R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
1020 //if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
1021 if (r_glsl_permutation->loc_Texture_Glow >= 0) R_Mesh_TexBind(9, R_GetTexture(rsurface_texture->currentskinframe->glow));
1022 if (r_glsl_permutation->loc_GlowScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_GlowScale, r_hdr_glowintensity.value);
1023 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_view.colorscale);
1024 if (r_glsl_permutation->loc_FogColor >= 0)
1026 // additive passes are only darkened by fog, not tinted
1027 if (r_shadow_rtlight || (rsurface_texture->currentmaterialflags & MATERIALFLAG_ADD))
1028 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
1030 qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
1032 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface_modelorg[0], rsurface_modelorg[1], rsurface_modelorg[2]);
1033 if (r_glsl_permutation->loc_Color_Pants >= 0)
1035 if (rsurface_texture->currentskinframe->pants)
1036 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface_entity->colormap_pantscolor[0], rsurface_entity->colormap_pantscolor[1], rsurface_entity->colormap_pantscolor[2]);
1038 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
1040 if (r_glsl_permutation->loc_Color_Shirt >= 0)
1042 if (rsurface_texture->currentskinframe->shirt)
1043 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface_entity->colormap_shirtcolor[0], rsurface_entity->colormap_shirtcolor[1], rsurface_entity->colormap_shirtcolor[2]);
1045 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
1047 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, r_refdef.fograngerecip);
1048 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface_texture->specularpower);
1049 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
1054 void R_SwitchSurfaceShader(int permutation)
1056 if (r_glsl_permutation != r_glsl_permutations + (permutation & SHADERPERMUTATION_COUNTMASK))
1058 r_glsl_permutation = r_glsl_permutations + (permutation & SHADERPERMUTATION_COUNTMASK);
1060 qglUseProgramObjectARB(r_glsl_permutation->program);
1065 void gl_main_start(void)
1067 r_main_texturepool = R_AllocTexturePool();
1068 R_BuildBlankTextures();
1070 if (gl_texturecubemap)
1073 R_BuildNormalizationCube();
1075 R_BuildFogTexture();
1076 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
1077 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
1078 memset(&r_svbsp, 0, sizeof (r_svbsp));
1081 void gl_main_shutdown(void)
1084 Mem_Free(r_svbsp.nodes);
1085 memset(&r_svbsp, 0, sizeof (r_svbsp));
1086 R_FreeTexturePool(&r_main_texturepool);
1087 r_texture_blanknormalmap = NULL;
1088 r_texture_white = NULL;
1089 r_texture_black = NULL;
1090 r_texture_whitecube = NULL;
1091 r_texture_normalizationcube = NULL;
1092 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
1096 extern void CL_ParseEntityLump(char *entitystring);
1097 void gl_main_newmap(void)
1099 // FIXME: move this code to client
1101 char *entities, entname[MAX_QPATH];
1104 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
1105 l = (int)strlen(entname) - 4;
1106 if (l >= 0 && !strcmp(entname + l, ".bsp"))
1108 memcpy(entname + l, ".ent", 5);
1109 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
1111 CL_ParseEntityLump(entities);
1116 if (cl.worldmodel->brush.entities)
1117 CL_ParseEntityLump(cl.worldmodel->brush.entities);
1121 void GL_Main_Init(void)
1123 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
1125 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
1126 FOG_registercvars(); // FIXME: move this fog stuff to client?
1127 Cvar_RegisterVariable(&r_nearclip);
1128 Cvar_RegisterVariable(&r_showsurfaces);
1129 Cvar_RegisterVariable(&r_showtris);
1130 Cvar_RegisterVariable(&r_shownormals);
1131 Cvar_RegisterVariable(&r_showlighting);
1132 Cvar_RegisterVariable(&r_showshadowvolumes);
1133 Cvar_RegisterVariable(&r_showcollisionbrushes);
1134 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
1135 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
1136 Cvar_RegisterVariable(&r_showdisabledepthtest);
1137 Cvar_RegisterVariable(&r_drawportals);
1138 Cvar_RegisterVariable(&r_drawentities);
1139 Cvar_RegisterVariable(&r_cullentities_trace);
1140 Cvar_RegisterVariable(&r_cullentities_trace_samples);
1141 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
1142 Cvar_RegisterVariable(&r_cullentities_trace_delay);
1143 Cvar_RegisterVariable(&r_drawviewmodel);
1144 Cvar_RegisterVariable(&r_speeds);
1145 Cvar_RegisterVariable(&r_fullbrights);
1146 Cvar_RegisterVariable(&r_wateralpha);
1147 Cvar_RegisterVariable(&r_dynamic);
1148 Cvar_RegisterVariable(&r_fullbright);
1149 Cvar_RegisterVariable(&r_shadows);
1150 Cvar_RegisterVariable(&r_shadows_throwdistance);
1151 Cvar_RegisterVariable(&r_q1bsp_skymasking);
1152 Cvar_RegisterVariable(&r_textureunits);
1153 Cvar_RegisterVariable(&r_glsl);
1154 Cvar_RegisterVariable(&r_glsl_offsetmapping);
1155 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
1156 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
1157 Cvar_RegisterVariable(&r_glsl_deluxemapping);
1158 Cvar_RegisterVariable(&r_lerpsprites);
1159 Cvar_RegisterVariable(&r_lerpmodels);
1160 Cvar_RegisterVariable(&r_waterscroll);
1161 Cvar_RegisterVariable(&r_bloom);
1162 Cvar_RegisterVariable(&r_bloom_colorscale);
1163 Cvar_RegisterVariable(&r_bloom_brighten);
1164 Cvar_RegisterVariable(&r_bloom_blur);
1165 Cvar_RegisterVariable(&r_bloom_resolution);
1166 Cvar_RegisterVariable(&r_bloom_colorexponent);
1167 Cvar_RegisterVariable(&r_bloom_colorsubtract);
1168 Cvar_RegisterVariable(&r_hdr);
1169 Cvar_RegisterVariable(&r_hdr_scenebrightness);
1170 Cvar_RegisterVariable(&r_hdr_glowintensity);
1171 Cvar_RegisterVariable(&r_hdr_range);
1172 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
1173 Cvar_RegisterVariable(&developer_texturelogging);
1174 Cvar_RegisterVariable(&gl_lightmaps);
1175 Cvar_RegisterVariable(&r_test);
1176 Cvar_RegisterVariable(&r_batchmode);
1177 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
1178 Cvar_SetValue("r_fullbrights", 0);
1179 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
1182 extern void R_Textures_Init(void);
1183 extern void GL_Draw_Init(void);
1184 extern void GL_Main_Init(void);
1185 extern void R_Shadow_Init(void);
1186 extern void R_Sky_Init(void);
1187 extern void GL_Surf_Init(void);
1188 extern void R_Light_Init(void);
1189 extern void R_Particles_Init(void);
1190 extern void R_Explosion_Init(void);
1191 extern void gl_backend_init(void);
1192 extern void Sbar_Init(void);
1193 extern void R_LightningBeams_Init(void);
1194 extern void Mod_RenderInit(void);
1196 void Render_Init(void)
1209 R_LightningBeams_Init();
1218 extern char *ENGINE_EXTENSIONS;
1221 VID_CheckExtensions();
1223 // LordHavoc: report supported extensions
1224 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
1226 // clear to black (loading plaque will be seen over this)
1228 qglClearColor(0,0,0,1);CHECKGLERROR
1229 qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
1232 int R_CullBox(const vec3_t mins, const vec3_t maxs)
1236 for (i = 0;i < 4;i++)
1238 p = r_view.frustum + i;
1243 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1247 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1251 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1255 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1259 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1263 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1267 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1271 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1279 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
1283 for (i = 0;i < numplanes;i++)
1290 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1294 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1298 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1302 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1306 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1310 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1314 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1318 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1326 //==================================================================================
1328 static void R_UpdateEntityLighting(entity_render_t *ent)
1330 vec3_t tempdiffusenormal;
1332 // fetch the lighting from the worldmodel data
1333 VectorSet(ent->modellight_ambient, r_ambient.value * (2.0f / 128.0f), r_ambient.value * (2.0f / 128.0f), r_ambient.value * (2.0f / 128.0f));
1334 VectorClear(ent->modellight_diffuse);
1335 VectorClear(tempdiffusenormal);
1336 if ((ent->flags & RENDER_LIGHT) && r_refdef.worldmodel && r_refdef.worldmodel->brush.LightPoint)
1339 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
1340 r_refdef.worldmodel->brush.LightPoint(r_refdef.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
1343 VectorSet(ent->modellight_ambient, 1, 1, 1);
1345 // move the light direction into modelspace coordinates for lighting code
1346 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
1347 VectorNormalize(ent->modellight_lightdir);
1349 // scale ambient and directional light contributions according to rendering variables
1350 ent->modellight_ambient[0] *= ent->colormod[0] * r_refdef.lightmapintensity;
1351 ent->modellight_ambient[1] *= ent->colormod[1] * r_refdef.lightmapintensity;
1352 ent->modellight_ambient[2] *= ent->colormod[2] * r_refdef.lightmapintensity;
1353 ent->modellight_diffuse[0] *= ent->colormod[0] * r_refdef.lightmapintensity;
1354 ent->modellight_diffuse[1] *= ent->colormod[1] * r_refdef.lightmapintensity;
1355 ent->modellight_diffuse[2] *= ent->colormod[2] * r_refdef.lightmapintensity;
1358 static void R_View_UpdateEntityVisible (void)
1361 entity_render_t *ent;
1363 if (!r_drawentities.integer)
1366 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : (chase_active.integer ? 0 : RENDER_EXTERIORMODEL);
1367 if (r_refdef.worldmodel && r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs)
1369 // worldmodel can check visibility
1370 for (i = 0;i < r_refdef.numentities;i++)
1372 ent = r_refdef.entities[i];
1373 r_viewcache.entityvisible[i] = !(ent->flags & renderimask) && !R_CullBox(ent->mins, ent->maxs) && ((ent->effects & EF_NODEPTHTEST) || r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs(r_refdef.worldmodel, r_viewcache.world_leafvisible, ent->mins, ent->maxs));
1375 if(r_cullentities_trace.integer)
1377 for (i = 0;i < r_refdef.numentities;i++)
1379 ent = r_refdef.entities[i];
1380 if(r_viewcache.entityvisible[i] && !(ent->effects & EF_NODEPTHTEST) && !(ent->model && (ent->model->name[0] == '*')))
1382 if(Mod_CanSeeBox_Trace(r_cullentities_trace_samples.integer, r_cullentities_trace_enlarge.value, r_refdef.worldmodel, r_view.origin, ent->mins, ent->maxs))
1383 ent->last_trace_visibility = realtime;
1384 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
1385 r_viewcache.entityvisible[i] = 0;
1392 // no worldmodel or it can't check visibility
1393 for (i = 0;i < r_refdef.numentities;i++)
1395 ent = r_refdef.entities[i];
1396 r_viewcache.entityvisible[i] = !(ent->flags & renderimask) && !R_CullBox(ent->mins, ent->maxs);
1400 // update entity lighting (even on hidden entities for r_shadows)
1401 for (i = 0;i < r_refdef.numentities;i++)
1402 R_UpdateEntityLighting(r_refdef.entities[i]);
1405 // only used if skyrendermasked, and normally returns false
1406 int R_DrawBrushModelsSky (void)
1409 entity_render_t *ent;
1411 if (!r_drawentities.integer)
1415 for (i = 0;i < r_refdef.numentities;i++)
1417 if (!r_viewcache.entityvisible[i])
1419 ent = r_refdef.entities[i];
1420 if (!ent->model || !ent->model->DrawSky)
1422 ent->model->DrawSky(ent);
1428 void R_DrawNoModel(entity_render_t *ent);
1429 void R_DrawModels(void)
1432 entity_render_t *ent;
1434 if (!r_drawentities.integer)
1437 for (i = 0;i < r_refdef.numentities;i++)
1439 if (!r_viewcache.entityvisible[i])
1441 ent = r_refdef.entities[i];
1442 r_refdef.stats.entities++;
1443 if (ent->model && ent->model->Draw != NULL)
1444 ent->model->Draw(ent);
1450 static void R_View_SetFrustum(void)
1452 double slopex, slopey;
1454 // break apart the view matrix into vectors for various purposes
1455 Matrix4x4_ToVectors(&r_view.matrix, r_view.forward, r_view.left, r_view.up, r_view.origin);
1456 VectorNegate(r_view.left, r_view.right);
1459 r_view.frustum[0].normal[0] = 0 - 1.0 / r_view.frustum_x;
1460 r_view.frustum[0].normal[1] = 0 - 0;
1461 r_view.frustum[0].normal[2] = -1 - 0;
1462 r_view.frustum[1].normal[0] = 0 + 1.0 / r_view.frustum_x;
1463 r_view.frustum[1].normal[1] = 0 + 0;
1464 r_view.frustum[1].normal[2] = -1 + 0;
1465 r_view.frustum[2].normal[0] = 0 - 0;
1466 r_view.frustum[2].normal[1] = 0 - 1.0 / r_view.frustum_y;
1467 r_view.frustum[2].normal[2] = -1 - 0;
1468 r_view.frustum[3].normal[0] = 0 + 0;
1469 r_view.frustum[3].normal[1] = 0 + 1.0 / r_view.frustum_y;
1470 r_view.frustum[3].normal[2] = -1 + 0;
1474 zNear = r_refdef.nearclip;
1475 nudge = 1.0 - 1.0 / (1<<23);
1476 r_view.frustum[4].normal[0] = 0 - 0;
1477 r_view.frustum[4].normal[1] = 0 - 0;
1478 r_view.frustum[4].normal[2] = -1 - -nudge;
1479 r_view.frustum[4].dist = 0 - -2 * zNear * nudge;
1480 r_view.frustum[5].normal[0] = 0 + 0;
1481 r_view.frustum[5].normal[1] = 0 + 0;
1482 r_view.frustum[5].normal[2] = -1 + -nudge;
1483 r_view.frustum[5].dist = 0 + -2 * zNear * nudge;
1489 r_view.frustum[0].normal[0] = m[3] - m[0];
1490 r_view.frustum[0].normal[1] = m[7] - m[4];
1491 r_view.frustum[0].normal[2] = m[11] - m[8];
1492 r_view.frustum[0].dist = m[15] - m[12];
1494 r_view.frustum[1].normal[0] = m[3] + m[0];
1495 r_view.frustum[1].normal[1] = m[7] + m[4];
1496 r_view.frustum[1].normal[2] = m[11] + m[8];
1497 r_view.frustum[1].dist = m[15] + m[12];
1499 r_view.frustum[2].normal[0] = m[3] - m[1];
1500 r_view.frustum[2].normal[1] = m[7] - m[5];
1501 r_view.frustum[2].normal[2] = m[11] - m[9];
1502 r_view.frustum[2].dist = m[15] - m[13];
1504 r_view.frustum[3].normal[0] = m[3] + m[1];
1505 r_view.frustum[3].normal[1] = m[7] + m[5];
1506 r_view.frustum[3].normal[2] = m[11] + m[9];
1507 r_view.frustum[3].dist = m[15] + m[13];
1509 r_view.frustum[4].normal[0] = m[3] - m[2];
1510 r_view.frustum[4].normal[1] = m[7] - m[6];
1511 r_view.frustum[4].normal[2] = m[11] - m[10];
1512 r_view.frustum[4].dist = m[15] - m[14];
1514 r_view.frustum[5].normal[0] = m[3] + m[2];
1515 r_view.frustum[5].normal[1] = m[7] + m[6];
1516 r_view.frustum[5].normal[2] = m[11] + m[10];
1517 r_view.frustum[5].dist = m[15] + m[14];
1522 slopex = 1.0 / r_view.frustum_x;
1523 slopey = 1.0 / r_view.frustum_y;
1524 VectorMA(r_view.forward, -slopex, r_view.left, r_view.frustum[0].normal);
1525 VectorMA(r_view.forward, slopex, r_view.left, r_view.frustum[1].normal);
1526 VectorMA(r_view.forward, -slopey, r_view.up , r_view.frustum[2].normal);
1527 VectorMA(r_view.forward, slopey, r_view.up , r_view.frustum[3].normal);
1528 VectorCopy(r_view.forward, r_view.frustum[4].normal);
1529 VectorNormalize(r_view.frustum[0].normal);
1530 VectorNormalize(r_view.frustum[1].normal);
1531 VectorNormalize(r_view.frustum[2].normal);
1532 VectorNormalize(r_view.frustum[3].normal);
1533 r_view.frustum[0].dist = DotProduct (r_view.origin, r_view.frustum[0].normal);
1534 r_view.frustum[1].dist = DotProduct (r_view.origin, r_view.frustum[1].normal);
1535 r_view.frustum[2].dist = DotProduct (r_view.origin, r_view.frustum[2].normal);
1536 r_view.frustum[3].dist = DotProduct (r_view.origin, r_view.frustum[3].normal);
1537 r_view.frustum[4].dist = DotProduct (r_view.origin, r_view.frustum[4].normal) + r_refdef.nearclip;
1538 PlaneClassify(&r_view.frustum[0]);
1539 PlaneClassify(&r_view.frustum[1]);
1540 PlaneClassify(&r_view.frustum[2]);
1541 PlaneClassify(&r_view.frustum[3]);
1542 PlaneClassify(&r_view.frustum[4]);
1544 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
1545 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, -1024 * slopex, r_view.left, -1024 * slopey, r_view.up, r_view.frustumcorner[0]);
1546 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, 1024 * slopex, r_view.left, -1024 * slopey, r_view.up, r_view.frustumcorner[1]);
1547 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, -1024 * slopex, r_view.left, 1024 * slopey, r_view.up, r_view.frustumcorner[2]);
1548 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, 1024 * slopex, r_view.left, 1024 * slopey, r_view.up, r_view.frustumcorner[3]);
1550 // LordHavoc: note to all quake engine coders, Quake had a special case
1551 // for 90 degrees which assumed a square view (wrong), so I removed it,
1552 // Quake2 has it disabled as well.
1554 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
1555 //RotatePointAroundVector( r_view.frustum[0].normal, r_view.up, r_view.forward, -(90 - r_refdef.fov_x / 2));
1556 //r_view.frustum[0].dist = DotProduct (r_view.origin, frustum[0].normal);
1557 //PlaneClassify(&frustum[0]);
1559 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
1560 //RotatePointAroundVector( r_view.frustum[1].normal, r_view.up, r_view.forward, (90 - r_refdef.fov_x / 2));
1561 //r_view.frustum[1].dist = DotProduct (r_view.origin, frustum[1].normal);
1562 //PlaneClassify(&frustum[1]);
1564 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
1565 //RotatePointAroundVector( r_view.frustum[2].normal, r_view.left, r_view.forward, -(90 - r_refdef.fov_y / 2));
1566 //r_view.frustum[2].dist = DotProduct (r_view.origin, frustum[2].normal);
1567 //PlaneClassify(&frustum[2]);
1569 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
1570 //RotatePointAroundVector( r_view.frustum[3].normal, r_view.left, r_view.forward, (90 - r_refdef.fov_y / 2));
1571 //r_view.frustum[3].dist = DotProduct (r_view.origin, frustum[3].normal);
1572 //PlaneClassify(&frustum[3]);
1575 //VectorCopy(r_view.forward, r_view.frustum[4].normal);
1576 //r_view.frustum[4].dist = DotProduct (r_view.origin, frustum[4].normal) + r_nearclip.value;
1577 //PlaneClassify(&frustum[4]);
1580 void R_View_Update(void)
1582 R_View_SetFrustum();
1583 R_View_WorldVisibility();
1584 R_View_UpdateEntityVisible();
1587 void R_SetupView(const matrix4x4_t *matrix)
1589 if (r_refdef.rtworldshadows || r_refdef.rtdlightshadows)
1590 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_view.frustum_x, r_view.frustum_y, r_refdef.nearclip);
1592 GL_SetupView_Mode_Perspective(r_view.frustum_x, r_view.frustum_y, r_refdef.nearclip, r_refdef.farclip);
1594 GL_SetupView_Orientation_FromEntity(matrix);
1597 void R_ResetViewRendering2D(void)
1599 if (gl_support_fragment_shader)
1601 qglUseProgramObjectARB(0);CHECKGLERROR
1606 // GL is weird because it's bottom to top, r_view.y is top to bottom
1607 qglViewport(r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
1608 GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
1609 GL_Scissor(r_view.x, r_view.y, r_view.width, r_view.height);
1610 GL_Color(1, 1, 1, 1);
1611 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
1612 GL_BlendFunc(GL_ONE, GL_ZERO);
1613 GL_AlphaTest(false);
1614 GL_ScissorTest(false);
1615 GL_DepthMask(false);
1616 GL_DepthTest(false);
1617 R_Mesh_Matrix(&identitymatrix);
1618 R_Mesh_ResetTextureState();
1619 qglPolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR
1620 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
1621 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
1622 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
1623 qglStencilMask(~0);CHECKGLERROR
1624 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
1625 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
1626 GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
1629 void R_ResetViewRendering3D(void)
1631 if (gl_support_fragment_shader)
1633 qglUseProgramObjectARB(0);CHECKGLERROR
1638 // GL is weird because it's bottom to top, r_view.y is top to bottom
1639 qglViewport(r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
1640 R_SetupView(&r_view.matrix);
1641 GL_Scissor(r_view.x, r_view.y, r_view.width, r_view.height);
1642 GL_Color(1, 1, 1, 1);
1643 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
1644 GL_BlendFunc(GL_ONE, GL_ZERO);
1645 GL_AlphaTest(false);
1646 GL_ScissorTest(true);
1649 R_Mesh_Matrix(&identitymatrix);
1650 R_Mesh_ResetTextureState();
1651 qglPolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR
1652 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
1653 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
1654 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
1655 qglStencilMask(~0);CHECKGLERROR
1656 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
1657 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
1658 GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
1662 R_Bloom_SetupShader(
1664 "// written by Forest 'LordHavoc' Hale\n"
1666 "// common definitions between vertex shader and fragment shader:\n"
1668 "#ifdef __GLSL_CG_DATA_TYPES\n"
1669 "#define myhalf half\n"
1670 "#define myhvec2 hvec2\n"
1671 "#define myhvec3 hvec3\n"
1672 "#define myhvec4 hvec4\n"
1674 "#define myhalf float\n"
1675 "#define myhvec2 vec2\n"
1676 "#define myhvec3 vec3\n"
1677 "#define myhvec4 vec4\n"
1680 "varying vec2 ScreenTexCoord;\n"
1681 "varying vec2 BloomTexCoord;\n"
1686 "// vertex shader specific:\n"
1687 "#ifdef VERTEX_SHADER\n"
1691 " ScreenTexCoord = vec2(gl_MultiTexCoord0);\n"
1692 " BloomTexCoord = vec2(gl_MultiTexCoord1);\n"
1693 " // transform vertex to camera space, using ftransform to match non-VS\n"
1695 " gl_Position = ftransform();\n"
1698 "#endif // VERTEX_SHADER\n"
1703 "// fragment shader specific:\n"
1704 "#ifdef FRAGMENT_SHADER\n"
1709 " myhvec3 color = myhvec3(texture2D(Texture_Screen, ScreenTexCoord));\n"
1710 " for (x = -BLUR_X;x <= BLUR_X;x++)
1711 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
1712 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
1713 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
1714 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
1716 " gl_FragColor = vec4(color);\n"
1719 "#endif // FRAGMENT_SHADER\n"
1722 void R_RenderScene(void);
1724 void R_Bloom_StartFrame(void)
1726 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
1728 // set bloomwidth and bloomheight to the bloom resolution that will be
1729 // used (often less than the screen resolution for faster rendering)
1730 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_view.width);
1731 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_view.height / r_view.width;
1732 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_view.height);
1734 // calculate desired texture sizes
1735 if (gl_support_arb_texture_non_power_of_two)
1737 screentexturewidth = r_view.width;
1738 screentextureheight = r_view.height;
1739 bloomtexturewidth = r_bloomstate.bloomwidth;
1740 bloomtextureheight = r_bloomstate.bloomheight;
1744 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
1745 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
1746 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
1747 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
1752 screentexturewidth = screentextureheight = 0;
1754 else if (r_bloom.integer)
1759 screentexturewidth = screentextureheight = 0;
1760 bloomtexturewidth = bloomtextureheight = 0;
1763 if ((!bloomtexturewidth && !bloomtextureheight) || r_bloom_resolution.integer < 4 || r_bloom_blur.value < 1 || r_bloom_blur.value >= 512 || screentexturewidth > gl_max_texture_size || screentextureheight > gl_max_texture_size || bloomtexturewidth > gl_max_texture_size || bloomtextureheight > gl_max_texture_size)
1765 // can't use bloom if the parameters are too weird
1766 // can't use bloom if the card does not support the texture size
1767 if (r_bloomstate.texture_screen)
1768 R_FreeTexture(r_bloomstate.texture_screen);
1769 if (r_bloomstate.texture_bloom)
1770 R_FreeTexture(r_bloomstate.texture_bloom);
1771 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
1775 r_bloomstate.enabled = true;
1776 r_bloomstate.hdr = r_hdr.integer != 0;
1778 // allocate textures as needed
1779 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
1781 if (r_bloomstate.texture_screen)
1782 R_FreeTexture(r_bloomstate.texture_screen);
1783 r_bloomstate.texture_screen = NULL;
1784 r_bloomstate.screentexturewidth = screentexturewidth;
1785 r_bloomstate.screentextureheight = screentextureheight;
1786 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
1787 r_bloomstate.texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, TEXTYPE_RGBA, TEXF_FORCENEAREST | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
1789 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
1791 if (r_bloomstate.texture_bloom)
1792 R_FreeTexture(r_bloomstate.texture_bloom);
1793 r_bloomstate.texture_bloom = NULL;
1794 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
1795 r_bloomstate.bloomtextureheight = bloomtextureheight;
1796 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
1797 r_bloomstate.texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", r_bloomstate.bloomtexturewidth, r_bloomstate.bloomtextureheight, NULL, TEXTYPE_RGBA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
1800 // set up a texcoord array for the full resolution screen image
1801 // (we have to keep this around to copy back during final render)
1802 r_bloomstate.screentexcoord2f[0] = 0;
1803 r_bloomstate.screentexcoord2f[1] = (float)r_view.height / (float)r_bloomstate.screentextureheight;
1804 r_bloomstate.screentexcoord2f[2] = (float)r_view.width / (float)r_bloomstate.screentexturewidth;
1805 r_bloomstate.screentexcoord2f[3] = (float)r_view.height / (float)r_bloomstate.screentextureheight;
1806 r_bloomstate.screentexcoord2f[4] = (float)r_view.width / (float)r_bloomstate.screentexturewidth;
1807 r_bloomstate.screentexcoord2f[5] = 0;
1808 r_bloomstate.screentexcoord2f[6] = 0;
1809 r_bloomstate.screentexcoord2f[7] = 0;
1811 // set up a texcoord array for the reduced resolution bloom image
1812 // (which will be additive blended over the screen image)
1813 r_bloomstate.bloomtexcoord2f[0] = 0;
1814 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
1815 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
1816 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
1817 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
1818 r_bloomstate.bloomtexcoord2f[5] = 0;
1819 r_bloomstate.bloomtexcoord2f[6] = 0;
1820 r_bloomstate.bloomtexcoord2f[7] = 0;
1823 void R_Bloom_CopyScreenTexture(float colorscale)
1825 r_refdef.stats.bloom++;
1827 R_ResetViewRendering2D();
1828 R_Mesh_VertexPointer(r_screenvertex3f);
1829 R_Mesh_ColorPointer(NULL);
1830 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f);
1831 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
1833 // copy view into the screen texture
1834 GL_ActiveTexture(0);
1836 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
1837 r_refdef.stats.bloom_copypixels += r_view.width * r_view.height;
1839 // now scale it down to the bloom texture size
1841 qglViewport(r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
1842 GL_BlendFunc(GL_ONE, GL_ZERO);
1843 GL_Color(colorscale, colorscale, colorscale, 1);
1844 // TODO: optimize with multitexture or GLSL
1845 R_Mesh_Draw(0, 4, 2, polygonelements);
1846 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
1848 // we now have a bloom image in the framebuffer
1849 // copy it into the bloom image texture for later processing
1850 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
1851 GL_ActiveTexture(0);
1853 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
1854 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
1857 void R_Bloom_CopyHDRTexture(void)
1859 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
1860 GL_ActiveTexture(0);
1862 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
1863 r_refdef.stats.bloom_copypixels += r_view.width * r_view.height;
1866 void R_Bloom_MakeTexture(void)
1869 float xoffset, yoffset, r, brighten;
1871 r_refdef.stats.bloom++;
1873 R_ResetViewRendering2D();
1874 R_Mesh_VertexPointer(r_screenvertex3f);
1875 R_Mesh_ColorPointer(NULL);
1877 // we have a bloom image in the framebuffer
1879 qglViewport(r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
1881 for (x = 1;x < r_bloom_colorexponent.value;)
1884 r = bound(0, r_bloom_colorexponent.value / x, 1);
1885 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
1886 GL_Color(r, r, r, 1);
1887 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
1888 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f);
1889 R_Mesh_Draw(0, 4, 2, polygonelements);
1890 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
1892 // copy the vertically blurred bloom view to a texture
1893 GL_ActiveTexture(0);
1895 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
1896 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
1899 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
1900 brighten = r_bloom_brighten.value;
1902 brighten *= r_hdr_range.value;
1903 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
1904 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f);
1906 for (dir = 0;dir < 2;dir++)
1908 // blend on at multiple vertical offsets to achieve a vertical blur
1909 // TODO: do offset blends using GLSL
1910 GL_BlendFunc(GL_ONE, GL_ZERO);
1911 for (x = -range;x <= range;x++)
1913 if (!dir){xoffset = 0;yoffset = x;}
1914 else {xoffset = x;yoffset = 0;}
1915 xoffset /= (float)r_bloomstate.bloomtexturewidth;
1916 yoffset /= (float)r_bloomstate.bloomtextureheight;
1917 // compute a texcoord array with the specified x and y offset
1918 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
1919 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
1920 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
1921 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
1922 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
1923 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
1924 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
1925 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
1926 // this r value looks like a 'dot' particle, fading sharply to
1927 // black at the edges
1928 // (probably not realistic but looks good enough)
1929 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
1930 //r = (dir ? 1.0f : brighten)/(range*2+1);
1931 r = (dir ? 1.0f : brighten)/(range*2+1)*(1 - x*x/(float)(range*range));
1932 GL_Color(r, r, r, 1);
1933 R_Mesh_Draw(0, 4, 2, polygonelements);
1934 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
1935 GL_BlendFunc(GL_ONE, GL_ONE);
1938 // copy the vertically blurred bloom view to a texture
1939 GL_ActiveTexture(0);
1941 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
1942 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
1945 // apply subtract last
1946 // (just like it would be in a GLSL shader)
1947 if (r_bloom_colorsubtract.value > 0 && gl_support_ext_blend_subtract)
1949 GL_BlendFunc(GL_ONE, GL_ZERO);
1950 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
1951 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f);
1952 GL_Color(1, 1, 1, 1);
1953 R_Mesh_Draw(0, 4, 2, polygonelements);
1954 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
1956 GL_BlendFunc(GL_ONE, GL_ONE);
1957 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
1958 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
1959 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f);
1960 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
1961 R_Mesh_Draw(0, 4, 2, polygonelements);
1962 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
1963 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
1965 // copy the darkened bloom view to a texture
1966 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
1967 GL_ActiveTexture(0);
1969 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
1970 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
1974 void R_HDR_RenderBloomTexture(void)
1976 int oldwidth, oldheight;
1978 oldwidth = r_view.width;
1979 oldheight = r_view.height;
1980 r_view.width = r_bloomstate.bloomwidth;
1981 r_view.height = r_bloomstate.bloomheight;
1983 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
1984 // TODO: add exposure compensation features
1985 // TODO: add fp16 framebuffer support
1987 r_view.colorscale = r_bloom_colorscale.value * r_hdr_scenebrightness.value;
1989 r_view.colorscale /= r_hdr_range.value;
1992 R_ResetViewRendering2D();
1994 R_Bloom_CopyHDRTexture();
1995 R_Bloom_MakeTexture();
1997 R_ResetViewRendering3D();
2000 if (r_timereport_active)
2001 R_TimeReport("clear");
2004 // restore the view settings
2005 r_view.width = oldwidth;
2006 r_view.height = oldheight;
2009 static void R_BlendView(void)
2011 if (r_bloomstate.enabled && r_bloomstate.hdr)
2013 // render high dynamic range bloom effect
2014 // the bloom texture was made earlier this render, so we just need to
2015 // blend it onto the screen...
2016 R_ResetViewRendering2D();
2017 R_Mesh_VertexPointer(r_screenvertex3f);
2018 R_Mesh_ColorPointer(NULL);
2019 GL_Color(1, 1, 1, 1);
2020 GL_BlendFunc(GL_ONE, GL_ONE);
2021 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2022 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f);
2023 R_Mesh_Draw(0, 4, 2, polygonelements);
2024 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
2026 else if (r_bloomstate.enabled)
2028 // render simple bloom effect
2029 // copy the screen and shrink it and darken it for the bloom process
2030 R_Bloom_CopyScreenTexture(r_bloom_colorscale.value);
2031 // make the bloom texture
2032 R_Bloom_MakeTexture();
2033 // put the original screen image back in place and blend the bloom
2035 R_ResetViewRendering2D();
2036 R_Mesh_VertexPointer(r_screenvertex3f);
2037 R_Mesh_ColorPointer(NULL);
2038 GL_Color(1, 1, 1, 1);
2039 GL_BlendFunc(GL_ONE, GL_ZERO);
2040 // do both in one pass if possible
2041 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2042 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f);
2043 if (r_textureunits.integer >= 2 && gl_combine.integer)
2045 R_Mesh_TexCombine(1, GL_ADD, GL_ADD, 1, 1);
2046 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_screen));
2047 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.screentexcoord2f);
2051 R_Mesh_Draw(0, 4, 2, polygonelements);
2052 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
2053 // now blend on the bloom texture
2054 GL_BlendFunc(GL_ONE, GL_ONE);
2055 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
2056 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f);
2058 R_Mesh_Draw(0, 4, 2, polygonelements);
2059 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
2061 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
2063 // apply a color tint to the whole view
2064 R_ResetViewRendering2D();
2065 R_Mesh_VertexPointer(r_screenvertex3f);
2066 R_Mesh_ColorPointer(NULL);
2067 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2068 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
2069 R_Mesh_Draw(0, 4, 2, polygonelements);
2073 void R_RenderScene(void);
2075 matrix4x4_t r_waterscrollmatrix;
2077 void R_UpdateVariables(void)
2081 r_refdef.farclip = 4096;
2082 if (r_refdef.worldmodel)
2083 r_refdef.farclip += VectorDistance(r_refdef.worldmodel->normalmins, r_refdef.worldmodel->normalmaxs);
2084 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
2086 r_refdef.polygonfactor = 0;
2087 r_refdef.polygonoffset = 0;
2088 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_shadow_polygonfactor.value;
2089 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_shadow_polygonoffset.value;
2091 r_refdef.rtworld = r_shadow_realtime_world.integer;
2092 r_refdef.rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
2093 r_refdef.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
2094 r_refdef.rtdlightshadows = r_refdef.rtdlight && (r_refdef.rtworld ? r_shadow_realtime_world_dlightshadows.integer : r_shadow_realtime_dlight_shadows.integer) && gl_stencil;
2095 r_refdef.lightmapintensity = r_refdef.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
2096 if (r_showsurfaces.integer)
2098 r_refdef.rtworld = false;
2099 r_refdef.rtworldshadows = false;
2100 r_refdef.rtdlight = false;
2101 r_refdef.rtdlightshadows = false;
2102 r_refdef.lightmapintensity = 0;
2105 if (gamemode == GAME_NEHAHRA)
2107 if (gl_fogenable.integer)
2109 r_refdef.oldgl_fogenable = true;
2110 r_refdef.fog_density = gl_fogdensity.value;
2111 r_refdef.fog_red = gl_fogred.value;
2112 r_refdef.fog_green = gl_foggreen.value;
2113 r_refdef.fog_blue = gl_fogblue.value;
2115 else if (r_refdef.oldgl_fogenable)
2117 r_refdef.oldgl_fogenable = false;
2118 r_refdef.fog_density = 0;
2119 r_refdef.fog_red = 0;
2120 r_refdef.fog_green = 0;
2121 r_refdef.fog_blue = 0;
2124 if (r_refdef.fog_density)
2126 r_refdef.fogcolor[0] = bound(0.0f, r_refdef.fog_red , 1.0f);
2127 r_refdef.fogcolor[1] = bound(0.0f, r_refdef.fog_green, 1.0f);
2128 r_refdef.fogcolor[2] = bound(0.0f, r_refdef.fog_blue , 1.0f);
2130 if (r_refdef.fog_density)
2132 r_refdef.fogenabled = true;
2133 // this is the point where the fog reaches 0.9986 alpha, which we
2134 // consider a good enough cutoff point for the texture
2135 // (0.9986 * 256 == 255.6)
2136 r_refdef.fogrange = 400 / r_refdef.fog_density;
2137 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
2138 r_refdef.fogtabledistmultiplier = FOGTABLEWIDTH * r_refdef.fograngerecip;
2139 // fog color was already set
2142 r_refdef.fogenabled = false;
2150 void R_RenderView(void)
2152 if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
2153 return; //Host_Error ("R_RenderView: NULL worldmodel");
2155 R_Shadow_UpdateWorldLightSelection();
2158 if (r_timereport_active)
2159 R_TimeReport("setup");
2162 if (r_timereport_active)
2163 R_TimeReport("visibility");
2165 R_ResetViewRendering3D();
2168 if (r_timereport_active)
2169 R_TimeReport("clear");
2171 R_Bloom_StartFrame();
2173 // this produces a bloom texture to be used in R_BlendView() later
2175 R_HDR_RenderBloomTexture();
2177 r_view.colorscale = r_hdr_scenebrightness.value;
2181 if (r_timereport_active)
2182 R_TimeReport("blendview");
2184 GL_Scissor(0, 0, vid.width, vid.height);
2185 GL_ScissorTest(false);
2189 extern void R_DrawLightningBeams (void);
2190 extern void VM_CL_AddPolygonsToMeshQueue (void);
2191 extern void R_DrawPortals (void);
2192 extern cvar_t cl_locs_show;
2193 static void R_DrawLocs(void);
2194 void R_RenderScene(void)
2196 // don't let sound skip if going slow
2197 if (r_refdef.extraupdate)
2200 R_ResetViewRendering3D();
2202 R_MeshQueue_BeginScene();
2206 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);
2208 if (cl.csqc_vidvars.drawworld)
2210 // don't let sound skip if going slow
2211 if (r_refdef.extraupdate)
2214 if (r_refdef.worldmodel && r_refdef.worldmodel->DrawSky)
2216 r_refdef.worldmodel->DrawSky(r_refdef.worldentity);
2217 if (r_timereport_active)
2218 R_TimeReport("worldsky");
2221 if (R_DrawBrushModelsSky() && r_timereport_active)
2222 R_TimeReport("bmodelsky");
2224 if (r_refdef.worldmodel && r_refdef.worldmodel->Draw)
2226 r_refdef.worldmodel->Draw(r_refdef.worldentity);
2227 if (r_timereport_active)
2228 R_TimeReport("world");
2232 // don't let sound skip if going slow
2233 if (r_refdef.extraupdate)
2237 if (r_timereport_active)
2238 R_TimeReport("models");
2240 // don't let sound skip if going slow
2241 if (r_refdef.extraupdate)
2244 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
2246 R_DrawModelShadows();
2248 R_ResetViewRendering3D();
2250 // don't let sound skip if going slow
2251 if (r_refdef.extraupdate)
2255 R_ShadowVolumeLighting(false);
2256 if (r_timereport_active)
2257 R_TimeReport("rtlights");
2259 // don't let sound skip if going slow
2260 if (r_refdef.extraupdate)
2263 if (cl.csqc_vidvars.drawworld)
2265 R_DrawLightningBeams();
2266 if (r_timereport_active)
2267 R_TimeReport("lightning");
2270 if (r_timereport_active)
2271 R_TimeReport("particles");
2274 if (r_timereport_active)
2275 R_TimeReport("explosions");
2278 if (gl_support_fragment_shader)
2280 qglUseProgramObjectARB(0);CHECKGLERROR
2282 VM_CL_AddPolygonsToMeshQueue();
2284 if (cl_locs_show.integer)
2287 if (r_timereport_active)
2288 R_TimeReport("showlocs");
2291 if (r_drawportals.integer)
2294 if (r_timereport_active)
2295 R_TimeReport("portals");
2298 if (gl_support_fragment_shader)
2300 qglUseProgramObjectARB(0);CHECKGLERROR
2302 R_MeshQueue_RenderTransparent();
2303 if (r_timereport_active)
2304 R_TimeReport("drawtrans");
2306 if (gl_support_fragment_shader)
2308 qglUseProgramObjectARB(0);CHECKGLERROR
2311 if (cl.csqc_vidvars.drawworld)
2314 if (r_timereport_active)
2315 R_TimeReport("coronas");
2318 // don't let sound skip if going slow
2319 if (r_refdef.extraupdate)
2322 R_ResetViewRendering2D();
2326 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
2329 float *v, *c, f1, f2, diff[3], vertex3f[8*3], color4f[8*4];
2330 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2331 GL_DepthMask(false);
2333 R_Mesh_Matrix(&identitymatrix);
2335 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2];
2336 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
2337 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
2338 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
2339 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
2340 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
2341 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
2342 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
2343 R_FillColors(color, 8, cr, cg, cb, ca);
2344 if (r_refdef.fogenabled)
2346 for (i = 0, v = vertex, c = color;i < 8;i++, v += 4, c += 4)
2348 f2 = VERTEXFOGTABLE(VectorDistance(v, r_view.origin));
2350 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
2351 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
2352 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
2355 R_Mesh_VertexPointer(vertex3f);
2356 R_Mesh_ColorPointer(color);
2357 R_Mesh_ResetTextureState();
2362 int nomodelelements[24] =
2374 float nomodelvertex3f[6*3] =
2384 float nomodelcolor4f[6*4] =
2386 0.0f, 0.0f, 0.5f, 1.0f,
2387 0.0f, 0.0f, 0.5f, 1.0f,
2388 0.0f, 0.5f, 0.0f, 1.0f,
2389 0.0f, 0.5f, 0.0f, 1.0f,
2390 0.5f, 0.0f, 0.0f, 1.0f,
2391 0.5f, 0.0f, 0.0f, 1.0f
2394 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
2399 // this is only called once per entity so numsurfaces is always 1, and
2400 // surfacelist is always {0}, so this code does not handle batches
2401 R_Mesh_Matrix(&ent->matrix);
2403 if (ent->flags & EF_ADDITIVE)
2405 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2406 GL_DepthMask(false);
2408 else if (ent->alpha < 1)
2410 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2411 GL_DepthMask(false);
2415 GL_BlendFunc(GL_ONE, GL_ZERO);
2418 GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
2419 GL_CullFace((ent->effects & EF_DOUBLESIDED) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
2420 R_Mesh_VertexPointer(nomodelvertex3f);
2421 if (r_refdef.fogenabled)
2424 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
2425 R_Mesh_ColorPointer(color4f);
2426 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
2427 f2 = VERTEXFOGTABLE(VectorDistance(org, r_view.origin));
2429 for (i = 0, c = color4f;i < 6;i++, c += 4)
2431 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
2432 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
2433 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
2437 else if (ent->alpha != 1)
2439 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
2440 R_Mesh_ColorPointer(color4f);
2441 for (i = 0, c = color4f;i < 6;i++, c += 4)
2445 R_Mesh_ColorPointer(nomodelcolor4f);
2446 R_Mesh_ResetTextureState();
2447 R_Mesh_Draw(0, 6, 8, nomodelelements);
2450 void R_DrawNoModel(entity_render_t *ent)
2453 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
2454 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
2455 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, r_shadow_rtlight);
2457 // R_DrawNoModelCallback(ent, 0);
2460 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
2462 vec3_t right1, right2, diff, normal;
2464 VectorSubtract (org2, org1, normal);
2466 // calculate 'right' vector for start
2467 VectorSubtract (r_view.origin, org1, diff);
2468 CrossProduct (normal, diff, right1);
2469 VectorNormalize (right1);
2471 // calculate 'right' vector for end
2472 VectorSubtract (r_view.origin, org2, diff);
2473 CrossProduct (normal, diff, right2);
2474 VectorNormalize (right2);
2476 vert[ 0] = org1[0] + width * right1[0];
2477 vert[ 1] = org1[1] + width * right1[1];
2478 vert[ 2] = org1[2] + width * right1[2];
2479 vert[ 3] = org1[0] - width * right1[0];
2480 vert[ 4] = org1[1] - width * right1[1];
2481 vert[ 5] = org1[2] - width * right1[2];
2482 vert[ 6] = org2[0] - width * right2[0];
2483 vert[ 7] = org2[1] - width * right2[1];
2484 vert[ 8] = org2[2] - width * right2[2];
2485 vert[ 9] = org2[0] + width * right2[0];
2486 vert[10] = org2[1] + width * right2[1];
2487 vert[11] = org2[2] + width * right2[2];
2490 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
2492 void R_DrawSprite(int blendfunc1, int blendfunc2, rtexture_t *texture, rtexture_t *fogtexture, int depthdisable, const vec3_t origin, const vec3_t left, const vec3_t up, float scalex1, float scalex2, float scaley1, float scaley2, float cr, float cg, float cb, float ca)
2494 float fog = 0.0f, ifog;
2497 if (r_refdef.fogenabled)
2498 fog = VERTEXFOGTABLE(VectorDistance(origin, r_view.origin));
2501 R_Mesh_Matrix(&identitymatrix);
2502 GL_BlendFunc(blendfunc1, blendfunc2);
2503 GL_DepthMask(false);
2504 GL_DepthTest(!depthdisable);
2506 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
2507 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
2508 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
2509 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
2510 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
2511 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
2512 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
2513 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
2514 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
2515 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
2516 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
2517 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
2519 R_Mesh_VertexPointer(vertex3f);
2520 R_Mesh_ColorPointer(NULL);
2521 R_Mesh_ResetTextureState();
2522 R_Mesh_TexBind(0, R_GetTexture(texture));
2523 R_Mesh_TexCoordPointer(0, 2, spritetexcoord2f);
2524 // FIXME: fixed function path can't properly handle r_view.colorscale > 1
2525 GL_Color(cr * ifog * r_view.colorscale, cg * ifog * r_view.colorscale, cb * ifog * r_view.colorscale, ca);
2526 R_Mesh_Draw(0, 4, 2, polygonelements);
2528 if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
2530 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
2531 GL_BlendFunc(blendfunc1, GL_ONE);
2532 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);
2533 R_Mesh_Draw(0, 4, 2, polygonelements);
2537 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
2542 VectorSet(v, x, y, z);
2543 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
2544 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
2546 if (i == mesh->numvertices)
2548 if (mesh->numvertices < mesh->maxvertices)
2550 VectorCopy(v, vertex3f);
2551 mesh->numvertices++;
2553 return mesh->numvertices;
2559 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
2563 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
2564 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
2565 e = mesh->element3i + mesh->numtriangles * 3;
2566 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
2568 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
2569 if (mesh->numtriangles < mesh->maxtriangles)
2574 mesh->numtriangles++;
2576 element[1] = element[2];
2580 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
2584 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
2585 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
2586 e = mesh->element3i + mesh->numtriangles * 3;
2587 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
2589 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
2590 if (mesh->numtriangles < mesh->maxtriangles)
2595 mesh->numtriangles++;
2597 element[1] = element[2];
2601 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
2602 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
2604 int planenum, planenum2;
2607 mplane_t *plane, *plane2;
2609 double temppoints[2][256*3];
2610 // figure out how large a bounding box we need to properly compute this brush
2612 for (w = 0;w < numplanes;w++)
2613 maxdist = max(maxdist, planes[w].dist);
2614 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
2615 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
2616 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
2620 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
2621 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
2623 if (planenum2 == planenum)
2625 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);
2628 if (tempnumpoints < 3)
2630 // generate elements forming a triangle fan for this polygon
2631 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
2635 static void R_DrawCollisionBrush(const colbrushf_t *brush)
2638 R_Mesh_VertexPointer(brush->points->v);
2639 i = (int)(((size_t)brush) / sizeof(colbrushf_t));
2640 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);
2641 GL_LockArrays(0, brush->numpoints);
2642 R_Mesh_Draw(0, brush->numpoints, brush->numtriangles, brush->elements);
2643 GL_LockArrays(0, 0);
2646 static void R_DrawCollisionSurface(const entity_render_t *ent, const msurface_t *surface)
2649 if (!surface->num_collisiontriangles)
2651 R_Mesh_VertexPointer(surface->data_collisionvertex3f);
2652 i = (int)(((size_t)surface) / sizeof(msurface_t));
2653 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);
2654 GL_LockArrays(0, surface->num_collisionvertices);
2655 R_Mesh_Draw(0, surface->num_collisionvertices, surface->num_collisiontriangles, surface->data_collisionelement3i);
2656 GL_LockArrays(0, 0);
2659 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)
2661 texturelayer_t *layer;
2662 layer = t->currentlayers + t->currentnumlayers++;
2664 layer->depthmask = depthmask;
2665 layer->blendfunc1 = blendfunc1;
2666 layer->blendfunc2 = blendfunc2;
2667 layer->texture = texture;
2668 layer->texmatrix = *matrix;
2669 layer->color[0] = r * r_view.colorscale;
2670 layer->color[1] = g * r_view.colorscale;
2671 layer->color[2] = b * r_view.colorscale;
2672 layer->color[3] = a;
2675 void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
2677 model_t *model = ent->model;
2679 // switch to an alternate material if this is a q1bsp animated material
2681 texture_t *texture = t;
2682 int s = ent->skinnum;
2683 if ((unsigned int)s >= (unsigned int)model->numskins)
2685 if (model->skinscenes)
2687 if (model->skinscenes[s].framecount > 1)
2688 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
2690 s = model->skinscenes[s].firstframe;
2693 t = t + s * model->num_surfaces;
2696 // use an alternate animation if the entity's frame is not 0,
2697 // and only if the texture has an alternate animation
2698 if (ent->frame != 0 && t->anim_total[1])
2699 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.time * 5.0f) % t->anim_total[1]) : 0];
2701 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.time * 5.0f) % t->anim_total[0]) : 0];
2703 texture->currentframe = t;
2706 // pick a new currentskinframe if the material is animated
2707 if (t->numskinframes >= 2)
2708 t->currentskinframe = t->skinframes + ((int)(t->skinframerate * (cl.time - ent->frame2time)) % t->numskinframes);
2709 if (t->backgroundnumskinframes >= 2)
2710 t->backgroundcurrentskinframe = t->backgroundskinframes + ((int)(t->backgroundskinframerate * (cl.time - ent->frame2time)) % t->backgroundnumskinframes);
2712 t->currentmaterialflags = t->basematerialflags;
2713 t->currentalpha = ent->alpha;
2714 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
2715 t->currentalpha *= r_wateralpha.value;
2716 if (!(ent->flags & RENDER_LIGHT))
2717 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
2718 if (ent->effects & EF_ADDITIVE)
2719 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_TRANSPARENT | MATERIALFLAG_NOSHADOW;
2720 else if (t->currentalpha < 1)
2721 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_TRANSPARENT | MATERIALFLAG_NOSHADOW;
2722 if (ent->effects & EF_DOUBLESIDED)
2723 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
2724 if (ent->effects & EF_NODEPTHTEST)
2725 t->currentmaterialflags |= MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_NOSHADOW;
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 & MATERIALFLAG_TRANSPARENT))
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 t->specularscale = 0;
2740 if (r_shadow_gloss.integer > 0)
2742 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
2744 if (r_shadow_glossintensity.value > 0)
2746 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_black;
2747 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_black;
2748 t->specularscale = r_shadow_glossintensity.value;
2751 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
2752 t->specularscale = r_shadow_gloss2intensity.value;
2755 t->currentnumlayers = 0;
2756 if (!(t->currentmaterialflags & MATERIALFLAG_NODRAW))
2758 if (gl_lightmaps.integer)
2759 R_Texture_AddLayer(t, true, GL_ONE, GL_ZERO, TEXTURELAYERTYPE_LITTEXTURE, r_texture_white, &identitymatrix, 1, 1, 1, 1);
2760 else if (!(t->currentmaterialflags & MATERIALFLAG_SKY))
2762 int blendfunc1, blendfunc2, depthmask;
2763 if (t->currentmaterialflags & MATERIALFLAG_ADD)
2765 blendfunc1 = GL_SRC_ALPHA;
2766 blendfunc2 = GL_ONE;
2768 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
2770 blendfunc1 = GL_SRC_ALPHA;
2771 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
2773 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
2775 blendfunc1 = t->customblendfunc[0];
2776 blendfunc2 = t->customblendfunc[1];
2780 blendfunc1 = GL_ONE;
2781 blendfunc2 = GL_ZERO;
2783 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
2784 if (t->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL))
2786 rtexture_t *currentbasetexture;
2788 if (r_refdef.fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED))
2789 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
2790 currentbasetexture = (VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) < (1.0f / 1048576.0f) && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
2791 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2793 // fullbright is not affected by r_refdef.lightmapintensity
2794 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
2795 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
2796 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->pants, &t->currenttexmatrix, ent->colormap_pantscolor[0] * ent->colormod[0], ent->colormap_pantscolor[1] * ent->colormod[1], ent->colormap_pantscolor[2] * ent->colormod[2], t->currentalpha);
2797 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
2798 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->shirt, &t->currenttexmatrix, ent->colormap_shirtcolor[0] * ent->colormod[0], ent->colormap_shirtcolor[1] * ent->colormod[1], ent->colormap_shirtcolor[2] * ent->colormod[2], t->currentalpha);
2804 // q3bsp has no lightmap updates, so the lightstylevalue that
2805 // would normally be baked into the lightmap must be
2806 // applied to the color
2807 if (ent->model->type == mod_brushq3)
2808 colorscale *= r_refdef.lightstylevalue[0] * (1.0f / 256.0f);
2809 colorscale *= r_refdef.lightmapintensity;
2810 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_LITTEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0] * colorscale, ent->colormod[1] * colorscale, ent->colormod[2] * colorscale, t->currentalpha);
2811 if (r_ambient.value >= (1.0f/64.0f))
2812 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0] * r_ambient.value * (1.0f / 64.0f), ent->colormod[1] * r_ambient.value * (1.0f / 64.0f), ent->colormod[2] * r_ambient.value * (1.0f / 64.0f), t->currentalpha);
2813 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
2815 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->currentskinframe->pants, &t->currenttexmatrix, ent->colormap_pantscolor[0] * ent->colormod[0] * colorscale, ent->colormap_pantscolor[1] * ent->colormod[1] * colorscale, ent->colormap_pantscolor[2] * ent->colormod[2] * colorscale, t->currentalpha);
2816 if (r_ambient.value >= (1.0f/64.0f))
2817 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->pants, &t->currenttexmatrix, ent->colormap_pantscolor[0] * ent->colormod[0] * r_ambient.value * (1.0f / 64.0f), ent->colormap_pantscolor[1] * ent->colormod[1] * r_ambient.value * (1.0f / 64.0f), ent->colormap_pantscolor[2] * ent->colormod[2] * r_ambient.value * (1.0f / 64.0f), t->currentalpha);
2819 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
2821 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->currentskinframe->shirt, &t->currenttexmatrix, ent->colormap_shirtcolor[0] * ent->colormod[0] * colorscale, ent->colormap_shirtcolor[1] * ent->colormod[1] * colorscale, ent->colormap_shirtcolor[2] * ent->colormod[2] * colorscale, t->currentalpha);
2822 if (r_ambient.value >= (1.0f/64.0f))
2823 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->shirt, &t->currenttexmatrix, ent->colormap_shirtcolor[0] * ent->colormod[0] * r_ambient.value * (1.0f / 64.0f), ent->colormap_shirtcolor[1] * ent->colormod[1] * r_ambient.value * (1.0f / 64.0f), ent->colormap_shirtcolor[2] * ent->colormod[2] * r_ambient.value * (1.0f / 64.0f), t->currentalpha);
2826 if (t->currentskinframe->glow != NULL)
2827 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->glow, &t->currenttexmatrix, r_hdr_glowintensity.value, r_hdr_glowintensity.value, r_hdr_glowintensity.value, t->currentalpha);
2828 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
2830 // if this is opaque use alpha blend which will darken the earlier
2833 // if this is an alpha blended material, all the earlier passes
2834 // were darkened by fog already, so we only need to add the fog
2835 // color ontop through the fog mask texture
2837 // if this is an additive blended material, all the earlier passes
2838 // were darkened by fog already, and we should not add fog color
2839 // (because the background was not darkened, there is no fog color
2840 // that was lost behind it).
2841 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, (t->currentmaterialflags & MATERIALFLAG_BLENDED) ? GL_ONE : GL_ONE_MINUS_SRC_ALPHA, TEXTURELAYERTYPE_FOG, t->currentskinframe->fog, &identitymatrix, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], t->currentalpha);
2848 void R_UpdateAllTextureInfo(entity_render_t *ent)
2852 for (i = 0;i < ent->model->num_textures;i++)
2853 R_UpdateTextureInfo(ent, ent->model->data_textures + i);
2856 int rsurface_array_size = 0;
2857 float *rsurface_array_modelvertex3f = NULL;
2858 float *rsurface_array_modelsvector3f = NULL;
2859 float *rsurface_array_modeltvector3f = NULL;
2860 float *rsurface_array_modelnormal3f = NULL;
2861 float *rsurface_array_deformedvertex3f = NULL;
2862 float *rsurface_array_deformedsvector3f = NULL;
2863 float *rsurface_array_deformedtvector3f = NULL;
2864 float *rsurface_array_deformednormal3f = NULL;
2865 float *rsurface_array_color4f = NULL;
2866 float *rsurface_array_texcoord3f = NULL;
2868 void R_Mesh_ResizeArrays(int newvertices)
2871 if (rsurface_array_size >= newvertices)
2873 if (rsurface_array_modelvertex3f)
2874 Mem_Free(rsurface_array_modelvertex3f);
2875 rsurface_array_size = (newvertices + 1023) & ~1023;
2876 base = (float *)Mem_Alloc(r_main_mempool, rsurface_array_size * sizeof(float[31]));
2877 rsurface_array_modelvertex3f = base + rsurface_array_size * 0;
2878 rsurface_array_modelsvector3f = base + rsurface_array_size * 3;
2879 rsurface_array_modeltvector3f = base + rsurface_array_size * 6;
2880 rsurface_array_modelnormal3f = base + rsurface_array_size * 9;
2881 rsurface_array_deformedvertex3f = base + rsurface_array_size * 12;
2882 rsurface_array_deformedsvector3f = base + rsurface_array_size * 15;
2883 rsurface_array_deformedtvector3f = base + rsurface_array_size * 18;
2884 rsurface_array_deformednormal3f = base + rsurface_array_size * 21;
2885 rsurface_array_texcoord3f = base + rsurface_array_size * 24;
2886 rsurface_array_color4f = base + rsurface_array_size * 27;
2889 float *rsurface_modelvertex3f;
2890 float *rsurface_modelsvector3f;
2891 float *rsurface_modeltvector3f;
2892 float *rsurface_modelnormal3f;
2893 float *rsurface_vertex3f;
2894 float *rsurface_svector3f;
2895 float *rsurface_tvector3f;
2896 float *rsurface_normal3f;
2897 float *rsurface_lightmapcolor4f;
2898 vec3_t rsurface_modelorg;
2899 qboolean rsurface_generatedvertex;
2900 const entity_render_t *rsurface_entity;
2901 const model_t *rsurface_model;
2902 texture_t *rsurface_texture;
2903 qboolean rsurface_uselightmaptexture;
2904 rsurfmode_t rsurface_mode;
2905 int rsurface_lightmode; // 0 = lightmap or fullbright, 1 = color array from q3bsp, 2 = vertex shaded model
2907 void RSurf_CleanUp(void)
2910 if (rsurface_mode == RSURFMODE_GLSL)
2912 qglUseProgramObjectARB(0);CHECKGLERROR
2914 GL_AlphaTest(false);
2915 rsurface_mode = RSURFMODE_NONE;
2916 rsurface_uselightmaptexture = false;
2917 rsurface_texture = NULL;
2920 void RSurf_ActiveWorldEntity(void)
2923 rsurface_entity = r_refdef.worldentity;
2924 rsurface_model = r_refdef.worldmodel;
2925 if (rsurface_array_size < rsurface_model->surfmesh.num_vertices)
2926 R_Mesh_ResizeArrays(rsurface_model->surfmesh.num_vertices);
2927 R_Mesh_Matrix(&identitymatrix);
2928 VectorCopy(r_view.origin, rsurface_modelorg);
2929 rsurface_modelvertex3f = rsurface_model->surfmesh.data_vertex3f;
2930 rsurface_modelsvector3f = rsurface_model->surfmesh.data_svector3f;
2931 rsurface_modeltvector3f = rsurface_model->surfmesh.data_tvector3f;
2932 rsurface_modelnormal3f = rsurface_model->surfmesh.data_normal3f;
2933 rsurface_generatedvertex = false;
2934 rsurface_vertex3f = rsurface_modelvertex3f;
2935 rsurface_svector3f = rsurface_modelsvector3f;
2936 rsurface_tvector3f = rsurface_modeltvector3f;
2937 rsurface_normal3f = rsurface_modelnormal3f;
2940 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
2943 rsurface_entity = ent;
2944 rsurface_model = ent->model;
2945 if (rsurface_array_size < rsurface_model->surfmesh.num_vertices)
2946 R_Mesh_ResizeArrays(rsurface_model->surfmesh.num_vertices);
2947 R_Mesh_Matrix(&ent->matrix);
2948 Matrix4x4_Transform(&ent->inversematrix, r_view.origin, rsurface_modelorg);
2949 if (rsurface_model->surfmesh.isanimated && (rsurface_entity->frameblend[0].lerp != 1 || rsurface_entity->frameblend[0].frame != 0))
2953 rsurface_modelvertex3f = rsurface_array_modelvertex3f;
2954 rsurface_modelsvector3f = rsurface_array_modelsvector3f;
2955 rsurface_modeltvector3f = rsurface_array_modeltvector3f;
2956 rsurface_modelnormal3f = rsurface_array_modelnormal3f;
2957 Mod_Alias_GetMesh_Vertices(rsurface_model, rsurface_entity->frameblend, rsurface_array_modelvertex3f, rsurface_array_modelnormal3f, rsurface_array_modelsvector3f, rsurface_array_modeltvector3f);
2959 else if (wantnormals)
2961 rsurface_modelvertex3f = rsurface_array_modelvertex3f;
2962 rsurface_modelsvector3f = NULL;
2963 rsurface_modeltvector3f = NULL;
2964 rsurface_modelnormal3f = rsurface_array_modelnormal3f;
2965 Mod_Alias_GetMesh_Vertices(rsurface_model, rsurface_entity->frameblend, rsurface_array_modelvertex3f, rsurface_array_modelnormal3f, NULL, NULL);
2969 rsurface_modelvertex3f = rsurface_array_modelvertex3f;
2970 rsurface_modelsvector3f = NULL;
2971 rsurface_modeltvector3f = NULL;
2972 rsurface_modelnormal3f = NULL;
2973 Mod_Alias_GetMesh_Vertices(rsurface_model, rsurface_entity->frameblend, rsurface_array_modelvertex3f, NULL, NULL, NULL);
2975 rsurface_generatedvertex = true;
2979 rsurface_modelvertex3f = rsurface_model->surfmesh.data_vertex3f;
2980 rsurface_modelsvector3f = rsurface_model->surfmesh.data_svector3f;
2981 rsurface_modeltvector3f = rsurface_model->surfmesh.data_tvector3f;
2982 rsurface_modelnormal3f = rsurface_model->surfmesh.data_normal3f;
2983 rsurface_generatedvertex = false;
2985 rsurface_vertex3f = rsurface_modelvertex3f;
2986 rsurface_svector3f = rsurface_modelsvector3f;
2987 rsurface_tvector3f = rsurface_modeltvector3f;
2988 rsurface_normal3f = rsurface_modelnormal3f;
2991 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, msurface_t **texturesurfacelist)
2993 // 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
2994 if (rsurface_generatedvertex)
2996 if (rsurface_texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
2997 generatetangents = true;
2998 if (generatetangents)
2999 generatenormals = true;
3000 if (generatenormals && !rsurface_modelnormal3f)
3002 rsurface_normal3f = rsurface_modelnormal3f = rsurface_array_modelnormal3f;
3003 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);
3005 if (generatetangents && !rsurface_modelsvector3f)
3007 rsurface_svector3f = rsurface_modelsvector3f = rsurface_array_modelsvector3f;
3008 rsurface_tvector3f = rsurface_modeltvector3f = rsurface_array_modeltvector3f;
3009 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);
3012 // 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)
3013 if (rsurface_texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
3015 int texturesurfaceindex;
3016 float center[3], forward[3], right[3], up[3], v[4][3];
3017 matrix4x4_t matrix1, imatrix1;
3018 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_view.forward, forward);
3019 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_view.right, right);
3020 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_view.up, up);
3021 // make deformed versions of only the model vertices used by the specified surfaces
3022 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3025 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3026 // a single autosprite surface can contain multiple sprites...
3027 for (j = 0;j < surface->num_vertices - 3;j += 4)
3029 VectorClear(center);
3030 for (i = 0;i < 4;i++)
3031 VectorAdd(center, (rsurface_modelvertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
3032 VectorScale(center, 0.25f, center);
3033 if (rsurface_texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE2)
3035 forward[0] = rsurface_modelorg[0] - center[0];
3036 forward[1] = rsurface_modelorg[1] - center[1];
3038 VectorNormalize(forward);
3039 right[0] = forward[1];
3040 right[1] = -forward[0];
3042 VectorSet(up, 0, 0, 1);
3044 // FIXME: calculate vectors from triangle edges instead of using texture vectors as an easy way out?
3045 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);
3046 Matrix4x4_Invert_Simple(&imatrix1, &matrix1);
3047 for (i = 0;i < 4;i++)
3048 Matrix4x4_Transform(&imatrix1, (rsurface_modelvertex3f + 3 * surface->num_firstvertex) + (j+i)*3, v[i]);
3049 for (i = 0;i < 4;i++)
3050 VectorMAMAMAM(1, center, v[i][0], forward, v[i][1], right, v[i][2], up, rsurface_array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
3052 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);
3053 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);
3055 rsurface_vertex3f = rsurface_array_deformedvertex3f;
3056 rsurface_svector3f = rsurface_array_deformedsvector3f;
3057 rsurface_tvector3f = rsurface_array_deformedtvector3f;
3058 rsurface_normal3f = rsurface_array_deformednormal3f;
3062 rsurface_vertex3f = rsurface_modelvertex3f;
3063 rsurface_svector3f = rsurface_modelsvector3f;
3064 rsurface_tvector3f = rsurface_modeltvector3f;
3065 rsurface_normal3f = rsurface_modelnormal3f;
3067 R_Mesh_VertexPointer(rsurface_vertex3f);
3070 void RSurf_DrawBatch_Simple(int texturenumsurfaces, msurface_t **texturesurfacelist)
3073 const msurface_t *surface = texturesurfacelist[0];
3074 const msurface_t *surface2;
3079 // TODO: lock all array ranges before render, rather than on each surface
3080 if (texturenumsurfaces == 1)
3082 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
3083 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
3085 else if (r_batchmode.integer == 2)
3087 #define MAXBATCHTRIANGLES 4096
3088 int batchtriangles = 0;
3089 int batchelements[MAXBATCHTRIANGLES*3];
3090 for (i = 0;i < texturenumsurfaces;i = j)
3092 surface = texturesurfacelist[i];
3094 if (surface->num_triangles > MAXBATCHTRIANGLES)
3096 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
3099 memcpy(batchelements, rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
3100 batchtriangles = surface->num_triangles;
3101 firstvertex = surface->num_firstvertex;
3102 endvertex = surface->num_firstvertex + surface->num_vertices;
3103 for (;j < texturenumsurfaces;j++)
3105 surface2 = texturesurfacelist[j];
3106 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
3108 memcpy(batchelements + batchtriangles * 3, rsurface_model->surfmesh.data_element3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
3109 batchtriangles += surface2->num_triangles;
3110 firstvertex = min(firstvertex, surface2->num_firstvertex);
3111 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
3113 surface2 = texturesurfacelist[j-1];
3114 numvertices = endvertex - firstvertex;
3115 R_Mesh_Draw(firstvertex, numvertices, batchtriangles, batchelements);
3118 else if (r_batchmode.integer == 1)
3120 for (i = 0;i < texturenumsurfaces;i = j)
3122 surface = texturesurfacelist[i];
3123 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
3124 if (texturesurfacelist[j] != surface2)
3126 surface2 = texturesurfacelist[j-1];
3127 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
3128 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
3129 GL_LockArrays(surface->num_firstvertex, numvertices);
3130 R_Mesh_Draw(surface->num_firstvertex, numvertices, numtriangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
3135 for (i = 0;i < texturenumsurfaces;i++)
3137 surface = texturesurfacelist[i];
3138 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
3139 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
3144 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit)
3148 const msurface_t *surface = texturesurfacelist[0];
3149 const msurface_t *surface2;
3154 // TODO: lock all array ranges before render, rather than on each surface
3155 if (texturenumsurfaces == 1)
3157 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
3158 if (deluxemaptexunit >= 0)
3159 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
3160 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
3161 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
3163 else if (r_batchmode.integer == 2)
3165 #define MAXBATCHTRIANGLES 4096
3166 int batchtriangles = 0;
3167 int batchelements[MAXBATCHTRIANGLES*3];
3168 for (i = 0;i < texturenumsurfaces;i = j)
3170 surface = texturesurfacelist[i];
3171 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
3172 if (deluxemaptexunit >= 0)
3173 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
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));
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 (surface2->lightmaptexture != surface->lightmaptexture || 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);
3199 else if (r_batchmode.integer == 1)
3202 Con_Printf("%s batch sizes ignoring lightmap:", rsurface_texture->name);
3203 for (i = 0;i < texturenumsurfaces;i = j)
3205 surface = texturesurfacelist[i];
3206 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
3207 if (texturesurfacelist[j] != surface2)
3209 Con_Printf(" %i", j - i);
3212 Con_Printf("%s batch sizes honoring lightmap:", rsurface_texture->name);
3214 for (i = 0;i < texturenumsurfaces;i = j)
3216 surface = texturesurfacelist[i];
3217 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
3218 if (deluxemaptexunit >= 0)
3219 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
3220 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
3221 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
3224 Con_Printf(" %i", j - i);
3226 surface2 = texturesurfacelist[j-1];
3227 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
3228 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
3229 GL_LockArrays(surface->num_firstvertex, numvertices);
3230 R_Mesh_Draw(surface->num_firstvertex, numvertices, numtriangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
3238 for (i = 0;i < texturenumsurfaces;i++)
3240 surface = texturesurfacelist[i];
3241 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
3242 if (deluxemaptexunit >= 0)
3243 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
3244 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
3245 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
3250 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
3253 int texturesurfaceindex;
3254 if (r_showsurfaces.integer == 2)
3256 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3258 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3259 for (j = 0;j < surface->num_triangles;j++)
3261 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_view.colorscale;
3262 GL_Color(f, f, f, 1);
3263 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, 1, (rsurface_model->surfmesh.data_element3i + 3 * (j + surface->num_firsttriangle)));
3269 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3271 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3272 int k = (int)(((size_t)surface) / sizeof(msurface_t));
3273 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);
3274 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
3275 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
3280 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, msurface_t **texturesurfacelist)
3282 int texturesurfaceindex;
3286 if (rsurface_lightmapcolor4f)
3288 // generate color arrays for the surfaces in this list
3289 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3291 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3292 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)
3294 f = 1 - VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
3304 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3306 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3307 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)
3309 f = 1 - VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
3317 rsurface_lightmapcolor4f = rsurface_array_color4f;
3320 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a)
3322 int texturesurfaceindex;
3325 if (!rsurface_lightmapcolor4f)
3327 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3329 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3330 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)
3338 rsurface_lightmapcolor4f = rsurface_array_color4f;
3341 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
3344 rsurface_lightmapcolor4f = NULL;
3345 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
3346 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
3347 R_Mesh_ColorPointer(rsurface_lightmapcolor4f);
3348 GL_Color(r, g, b, a);
3349 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 0, -1);
3352 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
3354 // TODO: optimize applyfog && applycolor case
3355 // just apply fog if necessary, and tint the fog color array if necessary
3356 rsurface_lightmapcolor4f = NULL;
3357 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
3358 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
3359 R_Mesh_ColorPointer(rsurface_lightmapcolor4f);
3360 GL_Color(r, g, b, a);
3361 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3364 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
3366 int texturesurfaceindex;
3370 if (texturesurfacelist[0]->lightmapinfo && texturesurfacelist[0]->lightmapinfo->stainsamples)
3372 // generate color arrays for the surfaces in this list
3373 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3375 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3376 for (i = 0, c = rsurface_array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
3378 if (surface->lightmapinfo->samples)
3380 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface_model->surfmesh.data_lightmapoffsets + surface->num_firstvertex)[i];
3381 float scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
3382 VectorScale(lm, scale, c);
3383 if (surface->lightmapinfo->styles[1] != 255)
3385 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
3387 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
3388 VectorMA(c, scale, lm, c);
3389 if (surface->lightmapinfo->styles[2] != 255)
3392 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
3393 VectorMA(c, scale, lm, c);
3394 if (surface->lightmapinfo->styles[3] != 255)
3397 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
3398 VectorMA(c, scale, lm, c);
3408 rsurface_lightmapcolor4f = rsurface_array_color4f;
3411 rsurface_lightmapcolor4f = rsurface_model->surfmesh.data_lightmapcolor4f;
3412 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
3413 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
3414 R_Mesh_ColorPointer(rsurface_lightmapcolor4f);
3415 GL_Color(r, g, b, a);
3416 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3419 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
3421 int texturesurfaceindex;
3425 vec3_t ambientcolor;
3426 vec3_t diffusecolor;
3430 VectorCopy(rsurface_entity->modellight_lightdir, lightdir);
3431 ambientcolor[0] = rsurface_entity->modellight_ambient[0] * r * 0.5f;
3432 ambientcolor[1] = rsurface_entity->modellight_ambient[1] * g * 0.5f;
3433 ambientcolor[2] = rsurface_entity->modellight_ambient[2] * b * 0.5f;
3434 diffusecolor[0] = rsurface_entity->modellight_diffuse[0] * r * 0.5f;
3435 diffusecolor[1] = rsurface_entity->modellight_diffuse[1] * g * 0.5f;
3436 diffusecolor[2] = rsurface_entity->modellight_diffuse[2] * b * 0.5f;
3437 if (VectorLength2(diffusecolor) > 0)
3439 // generate color arrays for the surfaces in this list
3440 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3442 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3443 int numverts = surface->num_vertices;
3444 v = rsurface_vertex3f + 3 * surface->num_firstvertex;
3445 c2 = rsurface_normal3f + 3 * surface->num_firstvertex;
3446 c = rsurface_array_color4f + 4 * surface->num_firstvertex;
3447 // q3-style directional shading
3448 for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
3450 if ((f = DotProduct(c2, lightdir)) > 0)
3451 VectorMA(ambientcolor, f, diffusecolor, c);
3453 VectorCopy(ambientcolor, c);
3462 rsurface_lightmapcolor4f = rsurface_array_color4f;
3466 r = ambientcolor[0];
3467 g = ambientcolor[1];
3468 b = ambientcolor[2];
3469 rsurface_lightmapcolor4f = NULL;
3471 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
3472 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
3473 R_Mesh_ColorPointer(rsurface_lightmapcolor4f);
3474 GL_Color(r, g, b, a);
3475 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3478 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
3480 GL_DepthTest(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
3481 GL_CullFace((rsurface_texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
3482 if (rsurface_mode != RSURFMODE_SHOWSURFACES)
3484 rsurface_mode = RSURFMODE_SHOWSURFACES;
3486 GL_BlendFunc(GL_ONE, GL_ZERO);
3487 R_Mesh_ColorPointer(NULL);
3488 R_Mesh_ResetTextureState();
3490 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
3491 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
3494 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, msurface_t **texturesurfacelist)
3496 // transparent sky would be ridiculous
3497 if ((rsurface_texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
3499 if (rsurface_mode != RSURFMODE_SKY)
3501 if (rsurface_mode == RSURFMODE_GLSL)
3503 qglUseProgramObjectARB(0);CHECKGLERROR
3505 rsurface_mode = RSURFMODE_SKY;
3509 skyrendernow = false;
3511 // restore entity matrix
3512 R_Mesh_Matrix(&rsurface_entity->matrix);
3514 GL_DepthTest(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
3515 GL_CullFace((rsurface_texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
3517 // LordHavoc: HalfLife maps have freaky skypolys so don't use
3518 // skymasking on them, and Quake3 never did sky masking (unlike
3519 // software Quake and software Quake2), so disable the sky masking
3520 // in Quake3 maps as it causes problems with q3map2 sky tricks,
3521 // and skymasking also looks very bad when noclipping outside the
3522 // level, so don't use it then either.
3523 if (rsurface_model->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_viewcache.world_novis)
3525 GL_Color(r_refdef.fogcolor[0] * r_view.colorscale, r_refdef.fogcolor[1] * r_view.colorscale, r_refdef.fogcolor[2] * r_view.colorscale, 1);
3526 R_Mesh_ColorPointer(NULL);
3527 R_Mesh_ResetTextureState();
3528 if (skyrendermasked)
3530 // depth-only (masking)
3531 GL_ColorMask(0,0,0,0);
3532 // just to make sure that braindead drivers don't draw
3533 // anything despite that colormask...
3534 GL_BlendFunc(GL_ZERO, GL_ONE);
3539 GL_BlendFunc(GL_ONE, GL_ZERO);
3541 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
3542 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3543 if (skyrendermasked)
3544 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
3548 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, msurface_t **texturesurfacelist)
3550 if (rsurface_mode != RSURFMODE_GLSL)
3552 rsurface_mode = RSURFMODE_GLSL;
3553 R_Mesh_ResetTextureState();
3556 R_SetupSurfaceShader(vec3_origin, rsurface_lightmode == 2);
3557 if (!r_glsl_permutation)
3560 if (rsurface_lightmode == 2)
3561 RSurf_PrepareVerticesForBatch(true, r_glsl_permutation->loc_Texture_Normal, texturenumsurfaces, texturesurfacelist);
3563 RSurf_PrepareVerticesForBatch(r_glsl_permutation->loc_Texture_Normal, r_glsl_permutation->loc_Texture_Normal, texturenumsurfaces, texturesurfacelist);
3564 R_Mesh_TexCoordPointer(0, 2, rsurface_model->surfmesh.data_texcoordtexture2f);
3565 R_Mesh_TexCoordPointer(1, 3, rsurface_svector3f);
3566 R_Mesh_TexCoordPointer(2, 3, rsurface_tvector3f);
3567 R_Mesh_TexCoordPointer(3, 3, rsurface_normal3f);
3568 R_Mesh_TexCoordPointer(4, 2, rsurface_model->surfmesh.data_texcoordlightmap2f);
3570 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
3572 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
3573 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
3574 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
3575 R_Mesh_ColorPointer(NULL);
3577 else if (rsurface_uselightmaptexture)
3579 R_Mesh_TexBind(7, R_GetTexture(texturesurfacelist[0]->lightmaptexture));
3580 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
3581 R_Mesh_TexBind(8, R_GetTexture(texturesurfacelist[0]->deluxemaptexture));
3582 R_Mesh_ColorPointer(NULL);
3586 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
3587 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
3588 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
3589 R_Mesh_ColorPointer(rsurface_model->surfmesh.data_lightmapcolor4f);
3592 if (rsurface_uselightmaptexture && !(rsurface_texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
3593 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 7, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? 8 : -1);
3595 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3596 if (rsurface_texture->backgroundnumskinframes && !(rsurface_texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
3601 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, msurface_t **texturesurfacelist)
3603 // OpenGL 1.3 path - anything not completely ancient
3604 int texturesurfaceindex;
3605 qboolean applycolor;
3609 const texturelayer_t *layer;
3610 if (rsurface_mode != RSURFMODE_MULTIPASS)
3611 rsurface_mode = RSURFMODE_MULTIPASS;
3612 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
3613 for (layerindex = 0, layer = rsurface_texture->currentlayers;layerindex < rsurface_texture->currentnumlayers;layerindex++, layer++)
3616 int layertexrgbscale;
3617 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
3619 if (layerindex == 0)
3623 GL_AlphaTest(false);
3624 qglDepthFunc(GL_EQUAL);CHECKGLERROR
3627 GL_DepthMask(layer->depthmask);
3628 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
3629 if ((layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2) && (gl_combine.integer || layer->depthmask))
3631 layertexrgbscale = 4;
3632 VectorScale(layer->color, 0.25f, layercolor);
3634 else if ((layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1) && (gl_combine.integer || layer->depthmask))
3636 layertexrgbscale = 2;
3637 VectorScale(layer->color, 0.5f, layercolor);
3641 layertexrgbscale = 1;
3642 VectorScale(layer->color, 1.0f, layercolor);
3644 layercolor[3] = layer->color[3];
3645 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
3646 R_Mesh_ColorPointer(NULL);
3647 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
3648 switch (layer->type)
3650 case TEXTURELAYERTYPE_LITTEXTURE:
3651 memset(&m, 0, sizeof(m));
3652 m.tex[0] = R_GetTexture(r_texture_white);
3653 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordlightmap2f;
3654 m.tex[1] = R_GetTexture(layer->texture);
3655 m.texmatrix[1] = layer->texmatrix;
3656 m.texrgbscale[1] = layertexrgbscale;
3657 m.pointer_texcoord[1] = rsurface_model->surfmesh.data_texcoordtexture2f;
3658 R_Mesh_TextureState(&m);
3659 if (rsurface_lightmode == 2)
3660 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
3661 else if (rsurface_uselightmaptexture)
3662 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
3664 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
3666 case TEXTURELAYERTYPE_TEXTURE:
3667 memset(&m, 0, sizeof(m));
3668 m.tex[0] = R_GetTexture(layer->texture);
3669 m.texmatrix[0] = layer->texmatrix;
3670 m.texrgbscale[0] = layertexrgbscale;
3671 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3672 R_Mesh_TextureState(&m);
3673 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
3675 case TEXTURELAYERTYPE_FOG:
3676 memset(&m, 0, sizeof(m));
3677 m.texrgbscale[0] = layertexrgbscale;
3680 m.tex[0] = R_GetTexture(layer->texture);
3681 m.texmatrix[0] = layer->texmatrix;
3682 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3684 R_Mesh_TextureState(&m);
3685 // generate a color array for the fog pass
3686 R_Mesh_ColorPointer(rsurface_array_color4f);
3687 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3691 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3692 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)
3694 f = VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
3695 c[0] = layercolor[0];
3696 c[1] = layercolor[1];
3697 c[2] = layercolor[2];
3698 c[3] = f * layercolor[3];
3701 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3704 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
3706 GL_LockArrays(0, 0);
3709 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
3711 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3712 GL_AlphaTest(false);
3716 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, msurface_t **texturesurfacelist)
3718 // OpenGL 1.1 - crusty old voodoo path
3719 int texturesurfaceindex;
3723 const texturelayer_t *layer;
3724 if (rsurface_mode != RSURFMODE_MULTIPASS)
3725 rsurface_mode = RSURFMODE_MULTIPASS;
3726 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
3727 for (layerindex = 0, layer = rsurface_texture->currentlayers;layerindex < rsurface_texture->currentnumlayers;layerindex++, layer++)
3729 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
3731 if (layerindex == 0)
3735 GL_AlphaTest(false);
3736 qglDepthFunc(GL_EQUAL);CHECKGLERROR
3739 GL_DepthMask(layer->depthmask);
3740 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
3741 R_Mesh_ColorPointer(NULL);
3742 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
3743 switch (layer->type)
3745 case TEXTURELAYERTYPE_LITTEXTURE:
3746 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
3748 // two-pass lit texture with 2x rgbscale
3749 // first the lightmap pass
3750 memset(&m, 0, sizeof(m));
3751 m.tex[0] = R_GetTexture(r_texture_white);
3752 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordlightmap2f;
3753 R_Mesh_TextureState(&m);
3754 if (rsurface_lightmode == 2)
3755 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
3756 else if (rsurface_uselightmaptexture)
3757 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
3759 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
3760 GL_LockArrays(0, 0);
3761 // then apply the texture to it
3762 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
3763 memset(&m, 0, sizeof(m));
3764 m.tex[0] = R_GetTexture(layer->texture);
3765 m.texmatrix[0] = layer->texmatrix;
3766 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3767 R_Mesh_TextureState(&m);
3768 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);
3772 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
3773 memset(&m, 0, sizeof(m));
3774 m.tex[0] = R_GetTexture(layer->texture);
3775 m.texmatrix[0] = layer->texmatrix;
3776 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3777 R_Mesh_TextureState(&m);
3778 if (rsurface_lightmode == 2)
3779 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);
3781 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);
3784 case TEXTURELAYERTYPE_TEXTURE:
3785 // singletexture unlit texture with transparency support
3786 memset(&m, 0, sizeof(m));
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 R_Mesh_TextureState(&m);
3791 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);
3793 case TEXTURELAYERTYPE_FOG:
3794 // singletexture fogging
3795 R_Mesh_ColorPointer(rsurface_array_color4f);
3798 memset(&m, 0, sizeof(m));
3799 m.tex[0] = R_GetTexture(layer->texture);
3800 m.texmatrix[0] = layer->texmatrix;
3801 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3802 R_Mesh_TextureState(&m);
3805 R_Mesh_ResetTextureState();
3806 // generate a color array for the fog pass
3807 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3811 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3812 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)
3814 f = VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
3815 c[0] = layer->color[0];
3816 c[1] = layer->color[1];
3817 c[2] = layer->color[2];
3818 c[3] = f * layer->color[3];
3821 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3824 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
3826 GL_LockArrays(0, 0);
3829 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
3831 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3832 GL_AlphaTest(false);
3836 static void R_DrawTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist)
3838 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_NODRAW)
3840 r_shadow_rtlight = NULL;
3841 r_refdef.stats.entities_surfaces += texturenumsurfaces;
3843 if (r_showsurfaces.integer)
3844 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
3845 else if (rsurface_texture->currentmaterialflags & MATERIALFLAG_SKY)
3846 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
3847 else if (rsurface_texture->currentnumlayers)
3849 GL_DepthTest(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
3850 GL_CullFace((rsurface_texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
3851 GL_BlendFunc(rsurface_texture->currentlayers[0].blendfunc1, rsurface_texture->currentlayers[0].blendfunc2);
3852 GL_DepthMask(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_BLENDED));
3853 GL_Color(rsurface_entity->colormod[0], rsurface_entity->colormod[1], rsurface_entity->colormod[2], rsurface_texture->currentalpha);
3854 GL_AlphaTest((rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
3855 // FIXME: identify models using a better check than rsurface_model->brush.shadowmesh
3856 rsurface_lightmode = ((rsurface_texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT) || rsurface_model->brush.shadowmesh) ? 0 : 2;
3857 if (r_glsl.integer && gl_support_fragment_shader)
3858 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist);
3859 else if (gl_combine.integer && r_textureunits.integer >= 2)
3860 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist);
3862 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist);
3865 GL_LockArrays(0, 0);
3868 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
3871 int texturenumsurfaces, endsurface;
3873 msurface_t *surface;
3874 msurface_t *texturesurfacelist[1024];
3876 // if the model is static it doesn't matter what value we give for
3877 // wantnormals and wanttangents, so this logic uses only rules applicable
3878 // to a model, knowing that they are meaningless otherwise
3879 if (ent == r_refdef.worldentity)
3880 RSurf_ActiveWorldEntity();
3881 else if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
3882 RSurf_ActiveModelEntity(ent, false, false);
3884 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
3886 for (i = 0;i < numsurfaces;i = j)
3889 surface = rsurface_model->data_surfaces + surfacelist[i];
3890 texture = surface->texture;
3891 R_UpdateTextureInfo(ent, texture);
3892 rsurface_texture = texture->currentframe;
3893 rsurface_uselightmaptexture = surface->lightmaptexture != NULL;
3894 // scan ahead until we find a different texture
3895 endsurface = min(i + 1024, numsurfaces);
3896 texturenumsurfaces = 0;
3897 texturesurfacelist[texturenumsurfaces++] = surface;
3898 for (;j < endsurface;j++)
3900 surface = rsurface_model->data_surfaces + surfacelist[j];
3901 if (texture != surface->texture || rsurface_uselightmaptexture != (surface->lightmaptexture != NULL))
3903 texturesurfacelist[texturenumsurfaces++] = surface;
3905 // render the range of surfaces
3906 R_DrawTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
3912 void R_QueueSurfaceList(int numsurfaces, msurface_t **surfacelist, int flagsmask)
3915 vec3_t tempcenter, center;
3917 // break the surface list down into batches by texture and use of lightmapping
3918 for (i = 0;i < numsurfaces;i = j)
3921 // texture is the base texture pointer, rsurface_texture is the
3922 // current frame/skin the texture is directing us to use (for example
3923 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
3924 // use skin 1 instead)
3925 texture = surfacelist[i]->texture;
3926 rsurface_texture = texture->currentframe;
3927 rsurface_uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
3928 if (!(rsurface_texture->currentmaterialflags & flagsmask))
3930 // if this texture is not the kind we want, skip ahead to the next one
3931 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
3935 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_BLENDED)
3937 // transparent surfaces get pushed off into the transparent queue
3938 const msurface_t *surface = surfacelist[i];
3939 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
3940 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
3941 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
3942 Matrix4x4_Transform(&rsurface_entity->matrix, tempcenter, center);
3943 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);
3947 // simply scan ahead until we find a different texture or lightmap state
3948 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface_uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
3950 // render the range of surfaces
3951 R_DrawTextureSurfaceList(j - i, surfacelist + i);
3956 float locboxvertex3f[6*4*3] =
3958 1,0,1, 1,0,0, 1,1,0, 1,1,1,
3959 0,1,1, 0,1,0, 0,0,0, 0,0,1,
3960 1,1,1, 1,1,0, 0,1,0, 0,1,1,
3961 0,0,1, 0,0,0, 1,0,0, 1,0,1,
3962 0,0,1, 1,0,1, 1,1,1, 0,1,1,
3963 1,0,0, 0,0,0, 0,1,0, 1,1,0
3966 int locboxelement3i[6*2*3] =
3976 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
3979 cl_locnode_t *loc = (cl_locnode_t *)ent;
3981 float vertex3f[6*4*3];
3983 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3984 GL_DepthMask(false);
3986 GL_CullFace(GL_NONE);
3987 R_Mesh_Matrix(&identitymatrix);
3989 R_Mesh_VertexPointer(vertex3f);
3990 R_Mesh_ColorPointer(NULL);
3991 R_Mesh_ResetTextureState();
3994 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_view.colorscale,
3995 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_view.colorscale,
3996 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_view.colorscale,
3997 surfacelist[0] < 0 ? 0.5f : 0.125f);
3999 if (VectorCompare(loc->mins, loc->maxs))
4001 VectorSet(size, 2, 2, 2);
4002 VectorMA(loc->mins, -0.5f, size, mins);
4006 VectorCopy(loc->mins, mins);
4007 VectorSubtract(loc->maxs, loc->mins, size);
4010 for (i = 0;i < 6*4*3;)
4011 for (j = 0;j < 3;j++, i++)
4012 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
4014 R_Mesh_Draw(0, 6*4, 6*2, locboxelement3i);
4017 void R_DrawLocs(void)
4020 cl_locnode_t *loc, *nearestloc;
4022 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
4023 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
4025 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
4026 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
4030 void R_DrawCollisionBrushes(entity_render_t *ent)
4034 msurface_t *surface;
4035 model_t *model = ent->model;
4036 if (!model->brush.num_brushes)
4039 R_Mesh_ColorPointer(NULL);
4040 R_Mesh_ResetTextureState();
4041 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
4042 GL_DepthMask(false);
4043 GL_DepthTest(!r_showdisabledepthtest.integer);
4044 qglPolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);CHECKGLERROR
4045 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
4046 if (brush->colbrushf && brush->colbrushf->numtriangles)
4047 R_DrawCollisionBrush(brush->colbrushf);
4048 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
4049 if (surface->num_collisiontriangles)
4050 R_DrawCollisionSurface(ent, surface);
4051 qglPolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR
4054 void R_DrawTrianglesAndNormals(entity_render_t *ent, qboolean drawtris, qboolean drawnormals, int flagsmask)
4057 const int *elements;
4058 msurface_t *surface;
4059 model_t *model = ent->model;
4062 GL_DepthTest(!r_showdisabledepthtest.integer);
4064 GL_BlendFunc(GL_ONE, GL_ZERO);
4065 R_Mesh_ColorPointer(NULL);
4066 R_Mesh_ResetTextureState();
4067 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
4069 if (ent == r_refdef.worldentity && !r_viewcache.world_surfacevisible[j])
4071 rsurface_texture = surface->texture->currentframe;
4072 if ((rsurface_texture->currentmaterialflags & flagsmask) && surface->num_triangles)
4074 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
4077 if (!rsurface_texture->currentlayers->depthmask)
4078 GL_Color(r_showtris.value * r_view.colorscale, 0, 0, 1);
4079 else if (ent == r_refdef.worldentity)
4080 GL_Color(r_showtris.value * r_view.colorscale, r_showtris.value * r_view.colorscale, r_showtris.value * r_view.colorscale, 1);
4082 GL_Color(0, r_showtris.value * r_view.colorscale, 0, 1);
4083 elements = (ent->model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
4086 for (k = 0;k < surface->num_triangles;k++, elements += 3)
4088 qglArrayElement(elements[0]);qglArrayElement(elements[1]);
4089 qglArrayElement(elements[1]);qglArrayElement(elements[2]);
4090 qglArrayElement(elements[2]);qglArrayElement(elements[0]);
4097 GL_Color(r_shownormals.value * r_view.colorscale, 0, 0, 1);
4099 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
4101 VectorCopy(rsurface_vertex3f + l * 3, v);
4102 qglVertex3f(v[0], v[1], v[2]);
4103 VectorMA(v, 8, rsurface_svector3f + l * 3, v);
4104 qglVertex3f(v[0], v[1], v[2]);
4108 GL_Color(0, 0, r_shownormals.value * r_view.colorscale, 1);
4110 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
4112 VectorCopy(rsurface_vertex3f + l * 3, v);
4113 qglVertex3f(v[0], v[1], v[2]);
4114 VectorMA(v, 8, rsurface_tvector3f + l * 3, v);
4115 qglVertex3f(v[0], v[1], v[2]);
4119 GL_Color(0, r_shownormals.value * r_view.colorscale, 0, 1);
4121 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
4123 VectorCopy(rsurface_vertex3f + l * 3, v);
4124 qglVertex3f(v[0], v[1], v[2]);
4125 VectorMA(v, 8, rsurface_normal3f + l * 3, v);
4126 qglVertex3f(v[0], v[1], v[2]);
4133 rsurface_texture = NULL;
4136 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
4137 void R_DrawWorldSurfaces(qboolean skysurfaces)
4139 int i, j, endj, f, flagsmask;
4140 int counttriangles = 0;
4141 msurface_t *surface, **surfacechain;
4143 model_t *model = r_refdef.worldmodel;
4144 const int maxsurfacelist = 1024;
4145 int numsurfacelist = 0;
4146 msurface_t *surfacelist[1024];
4150 RSurf_ActiveWorldEntity();
4152 // update light styles
4153 if (!skysurfaces && model->brushq1.light_styleupdatechains)
4155 for (i = 0;i < model->brushq1.light_styles;i++)
4157 if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
4159 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
4160 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
4161 for (;(surface = *surfacechain);surfacechain++)
4162 surface->cached_dlight = true;
4167 R_UpdateAllTextureInfo(r_refdef.worldentity);
4168 flagsmask = skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL);
4171 rsurface_uselightmaptexture = false;
4172 rsurface_texture = NULL;
4174 j = model->firstmodelsurface;
4175 endj = j + model->nummodelsurfaces;
4178 // quickly skip over non-visible surfaces
4179 for (;j < endj && !r_viewcache.world_surfacevisible[j];j++)
4181 // quickly iterate over visible surfaces
4182 for (;j < endj && r_viewcache.world_surfacevisible[j];j++)
4184 // process this surface
4185 surface = model->data_surfaces + j;
4186 // if this surface fits the criteria, add it to the list
4187 if (surface->num_triangles)
4189 // if lightmap parameters changed, rebuild lightmap texture
4190 if (surface->cached_dlight)
4191 R_BuildLightMap(r_refdef.worldentity, surface);
4192 // add face to draw list
4193 surfacelist[numsurfacelist++] = surface;
4194 counttriangles += surface->num_triangles;
4195 if (numsurfacelist >= maxsurfacelist)
4197 R_QueueSurfaceList(numsurfacelist, surfacelist, flagsmask);
4204 R_QueueSurfaceList(numsurfacelist, surfacelist, flagsmask);
4205 r_refdef.stats.entities_triangles += counttriangles;
4208 if (r_showcollisionbrushes.integer && !skysurfaces)
4209 R_DrawCollisionBrushes(r_refdef.worldentity);
4211 if (r_showtris.integer || r_shownormals.integer)
4212 R_DrawTrianglesAndNormals(r_refdef.worldentity, r_showtris.integer, r_shownormals.integer, flagsmask);
4215 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces)
4217 int i, f, flagsmask;
4218 int counttriangles = 0;
4219 msurface_t *surface, *endsurface, **surfacechain;
4221 model_t *model = ent->model;
4222 const int maxsurfacelist = 1024;
4223 int numsurfacelist = 0;
4224 msurface_t *surfacelist[1024];
4228 // if the model is static it doesn't matter what value we give for
4229 // wantnormals and wanttangents, so this logic uses only rules applicable
4230 // to a model, knowing that they are meaningless otherwise
4231 if (ent == r_refdef.worldentity)
4232 RSurf_ActiveWorldEntity();
4233 else if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
4234 RSurf_ActiveModelEntity(ent, false, false);
4236 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
4238 // update light styles
4239 if (!skysurfaces && model->brushq1.light_styleupdatechains)
4241 for (i = 0;i < model->brushq1.light_styles;i++)
4243 if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
4245 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
4246 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
4247 for (;(surface = *surfacechain);surfacechain++)
4248 surface->cached_dlight = true;
4253 R_UpdateAllTextureInfo(ent);
4254 flagsmask = skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL);
4257 rsurface_uselightmaptexture = false;
4258 rsurface_texture = NULL;
4260 surface = model->data_surfaces + model->firstmodelsurface;
4261 endsurface = surface + model->nummodelsurfaces;
4262 for (;surface < endsurface;surface++)
4264 // if this surface fits the criteria, add it to the list
4265 if (surface->num_triangles)
4267 // if lightmap parameters changed, rebuild lightmap texture
4268 if (surface->cached_dlight)
4269 R_BuildLightMap(ent, surface);
4270 // add face to draw list
4271 surfacelist[numsurfacelist++] = surface;
4272 counttriangles += surface->num_triangles;
4273 if (numsurfacelist >= maxsurfacelist)
4275 R_QueueSurfaceList(numsurfacelist, surfacelist, flagsmask);
4281 R_QueueSurfaceList(numsurfacelist, surfacelist, flagsmask);
4282 r_refdef.stats.entities_triangles += counttriangles;
4285 if (r_showcollisionbrushes.integer && !skysurfaces)
4286 R_DrawCollisionBrushes(ent);
4288 if (r_showtris.integer || r_shownormals.integer)
4289 R_DrawTrianglesAndNormals(ent, r_showtris.integer, r_shownormals.integer, flagsmask);