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", "shows surfaces as different colors"};
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_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
50 cvar_t r_fullbright = {0, "r_fullbright","0", "make everything bright cheat (not allowed in multiplayer)"};
51 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
52 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
53 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
54 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this)"};
55 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
56 cvar_t r_q1bsp_skymasking = {0, "r_qb1sp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
58 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
59 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
60 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
61 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
62 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
63 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
64 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
66 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)"};
68 cvar_t r_glsl = {0, "r_glsl", "1", "enables use of OpenGL 2.0 pixel shaders for lighting"};
69 cvar_t r_glsl_offsetmapping = {0, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
70 cvar_t r_glsl_offsetmapping_reliefmapping = {0, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
71 cvar_t r_glsl_offsetmapping_scale = {0, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
72 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)"};
74 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1", "enables animation smoothing on sprites (requires r_lerpmodels 1)"};
75 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
76 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
78 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
79 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
80 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "1", "how bright the glow is, after subtract/power"};
81 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
82 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
83 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
84 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0", "reduces bloom colors by a certain amount"};
86 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
87 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
88 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
89 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)"};
91 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"};
93 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"};
95 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
97 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"}; // used for testing renderer code changes, otherwise does nothing
98 cvar_t r_batchmode = {0, "r_batchmode", "1", "selects method of rendering multiple surfaces with one driver call (values are 0, 1, 2, etc...)"};
100 typedef struct r_glsl_bloomshader_s
103 int loc_Texture_Bloom;
105 r_glsl_bloomshader_t;
107 static struct r_bloomstate_s
112 int bloomwidth, bloomheight;
114 int screentexturewidth, screentextureheight;
115 rtexture_t *texture_screen;
117 int bloomtexturewidth, bloomtextureheight;
118 rtexture_t *texture_bloom;
120 r_glsl_bloomshader_t *shader;
122 // arrays for rendering the screen passes
123 float screentexcoord2f[8];
124 float bloomtexcoord2f[8];
125 float offsettexcoord2f[8];
129 rtexture_t *r_texture_blanknormalmap;
130 rtexture_t *r_texture_white;
131 rtexture_t *r_texture_black;
132 rtexture_t *r_texture_notexture;
133 rtexture_t *r_texture_whitecube;
134 rtexture_t *r_texture_normalizationcube;
135 rtexture_t *r_texture_fogattenuation;
136 //rtexture_t *r_texture_fogintensity;
138 // information about each possible shader permutation
139 r_glsl_permutation_t r_glsl_permutations[SHADERPERMUTATION_COUNT];
140 // currently selected permutation
141 r_glsl_permutation_t *r_glsl_permutation;
143 // temporary variable used by a macro
146 // vertex coordinates for a quad that covers the screen exactly
147 const static float r_screenvertex3f[12] =
155 extern void R_DrawModelShadows(void);
157 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
160 for (i = 0;i < verts;i++)
171 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
174 for (i = 0;i < verts;i++)
184 // FIXME: move this to client?
187 if (gamemode == GAME_NEHAHRA)
189 Cvar_Set("gl_fogenable", "0");
190 Cvar_Set("gl_fogdensity", "0.2");
191 Cvar_Set("gl_fogred", "0.3");
192 Cvar_Set("gl_foggreen", "0.3");
193 Cvar_Set("gl_fogblue", "0.3");
195 r_refdef.fog_density = r_refdef.fog_red = r_refdef.fog_green = r_refdef.fog_blue = 0.0f;
198 // FIXME: move this to client?
199 void FOG_registercvars(void)
204 if (gamemode == GAME_NEHAHRA)
206 Cvar_RegisterVariable (&gl_fogenable);
207 Cvar_RegisterVariable (&gl_fogdensity);
208 Cvar_RegisterVariable (&gl_fogred);
209 Cvar_RegisterVariable (&gl_foggreen);
210 Cvar_RegisterVariable (&gl_fogblue);
211 Cvar_RegisterVariable (&gl_fogstart);
212 Cvar_RegisterVariable (&gl_fogend);
215 r = (-1.0/256.0) * (FOGTABLEWIDTH * FOGTABLEWIDTH);
216 for (x = 0;x < FOGTABLEWIDTH;x++)
218 alpha = exp(r / ((double)x*(double)x));
219 if (x == FOGTABLEWIDTH - 1)
221 r_refdef.fogtable[x] = bound(0, alpha, 1);
225 static void R_BuildBlankTextures(void)
227 unsigned char data[4];
228 data[0] = 128; // normal X
229 data[1] = 128; // normal Y
230 data[2] = 255; // normal Z
231 data[3] = 128; // height
232 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
237 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
242 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
245 static void R_BuildNoTexture(void)
248 unsigned char pix[16][16][4];
249 // this makes a light grey/dark grey checkerboard texture
250 for (y = 0;y < 16;y++)
252 for (x = 0;x < 16;x++)
254 if ((y < 8) ^ (x < 8))
270 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_RGBA, TEXF_MIPMAP, NULL);
273 static void R_BuildWhiteCube(void)
275 unsigned char data[6*1*1*4];
276 data[ 0] = 255;data[ 1] = 255;data[ 2] = 255;data[ 3] = 255;
277 data[ 4] = 255;data[ 5] = 255;data[ 6] = 255;data[ 7] = 255;
278 data[ 8] = 255;data[ 9] = 255;data[10] = 255;data[11] = 255;
279 data[12] = 255;data[13] = 255;data[14] = 255;data[15] = 255;
280 data[16] = 255;data[17] = 255;data[18] = 255;data[19] = 255;
281 data[20] = 255;data[21] = 255;data[22] = 255;data[23] = 255;
282 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
285 static void R_BuildNormalizationCube(void)
289 vec_t s, t, intensity;
291 unsigned char data[6][NORMSIZE][NORMSIZE][4];
292 for (side = 0;side < 6;side++)
294 for (y = 0;y < NORMSIZE;y++)
296 for (x = 0;x < NORMSIZE;x++)
298 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
299 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
334 intensity = 127.0f / sqrt(DotProduct(v, v));
335 data[side][y][x][0] = (unsigned char)(128.0f + intensity * v[0]);
336 data[side][y][x][1] = (unsigned char)(128.0f + intensity * v[1]);
337 data[side][y][x][2] = (unsigned char)(128.0f + intensity * v[2]);
338 data[side][y][x][3] = 255;
342 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, &data[0][0][0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
345 static void R_BuildFogTexture(void)
350 unsigned char data1[FOGWIDTH][4];
351 //unsigned char data2[FOGWIDTH][4];
352 r = (-1.0/256.0) * (FOGWIDTH * FOGWIDTH);
353 for (x = 0;x < FOGWIDTH;x++)
355 alpha = exp(r / ((double)x*(double)x));
356 if (x == FOGWIDTH - 1)
358 b = (int)(256.0 * alpha);
359 b = bound(0, b, 255);
360 data1[x][0] = 255 - b;
361 data1[x][1] = 255 - b;
362 data1[x][2] = 255 - b;
369 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
370 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
373 static const char *builtinshaderstring =
374 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
375 "// written by Forest 'LordHavoc' Hale\n"
377 "// common definitions between vertex shader and fragment shader:\n"
379 "#ifdef __GLSL_CG_DATA_TYPES\n"
380 "#define myhalf half\n"
381 "#define myhvec2 hvec2\n"
382 "#define myhvec3 hvec3\n"
383 "#define myhvec4 hvec4\n"
385 "#define myhalf float\n"
386 "#define myhvec2 vec2\n"
387 "#define myhvec3 vec3\n"
388 "#define myhvec4 vec4\n"
391 "varying vec2 TexCoord;\n"
392 "varying vec2 TexCoordLightmap;\n"
394 "varying vec3 CubeVector;\n"
395 "varying vec3 LightVector;\n"
396 "varying vec3 EyeVector;\n"
398 "varying vec3 EyeVectorModelSpace;\n"
401 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
402 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
403 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
408 "// vertex shader specific:\n"
409 "#ifdef VERTEX_SHADER\n"
411 "uniform vec3 LightPosition;\n"
412 "uniform vec3 EyePosition;\n"
413 "uniform vec3 LightDir;\n"
415 "// TODO: get rid of tangentt (texcoord2) and use a crossproduct to regenerate it from tangents (texcoord1) and normal (texcoord3)\n"
419 " gl_FrontColor = gl_Color;\n"
420 " // copy the surface texcoord\n"
421 " TexCoord = vec2(gl_TextureMatrix[0] * gl_MultiTexCoord0);\n"
422 "#if !defined(MODE_LIGHTSOURCE) && !defined(MODE_LIGHTDIRECTION)\n"
423 " TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
426 "#ifdef MODE_LIGHTSOURCE\n"
427 " // transform vertex position into light attenuation/cubemap space\n"
428 " // (-1 to +1 across the light box)\n"
429 " CubeVector = vec3(gl_TextureMatrix[3] * gl_Vertex);\n"
431 " // transform unnormalized light direction into tangent space\n"
432 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
433 " // normalize it per pixel)\n"
434 " vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
435 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
436 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
437 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
440 "#ifdef MODE_LIGHTDIRECTION\n"
441 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
442 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
443 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
446 " // transform unnormalized eye direction into tangent space\n"
448 " vec3 EyeVectorModelSpace;\n"
450 " EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
451 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
452 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
453 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
455 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
456 " VectorS = gl_MultiTexCoord1.xyz;\n"
457 " VectorT = gl_MultiTexCoord2.xyz;\n"
458 " VectorR = gl_MultiTexCoord3.xyz;\n"
461 " // transform vertex to camera space, using ftransform to match non-VS\n"
463 " gl_Position = ftransform();\n"
466 "#endif // VERTEX_SHADER\n"
471 "// fragment shader specific:\n"
472 "#ifdef FRAGMENT_SHADER\n"
474 "uniform sampler2D Texture_Normal;\n"
475 "uniform sampler2D Texture_Color;\n"
476 "uniform sampler2D Texture_Gloss;\n"
477 "uniform samplerCube Texture_Cube;\n"
478 "uniform sampler2D Texture_FogMask;\n"
479 "uniform sampler2D Texture_Pants;\n"
480 "uniform sampler2D Texture_Shirt;\n"
481 "uniform sampler2D Texture_Lightmap;\n"
482 "uniform sampler2D Texture_Deluxemap;\n"
483 "uniform sampler2D Texture_Glow;\n"
485 "uniform myhvec3 LightColor;\n"
486 "uniform myhvec3 AmbientColor;\n"
487 "uniform myhvec3 DiffuseColor;\n"
488 "uniform myhvec3 SpecularColor;\n"
489 "uniform myhvec3 Color_Pants;\n"
490 "uniform myhvec3 Color_Shirt;\n"
491 "uniform myhvec3 FogColor;\n"
493 "uniform myhalf GlowScale;\n"
494 "uniform myhalf SceneBrightness;\n"
496 "uniform float OffsetMapping_Scale;\n"
497 "uniform float OffsetMapping_Bias;\n"
498 "uniform float FogRangeRecip;\n"
500 "uniform myhalf AmbientScale;\n"
501 "uniform myhalf DiffuseScale;\n"
502 "uniform myhalf SpecularScale;\n"
503 "uniform myhalf SpecularPower;\n"
507 " // apply offsetmapping\n"
508 "#ifdef USEOFFSETMAPPING\n"
509 " vec2 TexCoordOffset = TexCoord;\n"
510 "#define TexCoord TexCoordOffset\n"
512 " vec3 eyedir = vec3(normalize(EyeVector));\n"
513 " float depthbias = 1.0 - eyedir.z; // should this be a -?\n"
514 " depthbias = 1.0 - depthbias * depthbias;\n"
516 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
517 " // 14 sample relief mapping: linear search and then binary search\n"
518 " //vec3 OffsetVector = vec3(EyeVector.xy * (1.0 / EyeVector.z) * depthbias * OffsetMapping_Scale * vec2(-0.1, 0.1), -0.1);\n"
519 " //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-0.1, 0.1), -0.1);\n"
520 " vec3 OffsetVector = vec3(eyedir.xy * OffsetMapping_Scale * vec2(-0.1, 0.1), -0.1);\n"
521 " vec3 RT = vec3(TexCoord - OffsetVector.xy * 10.0, 1.0) + OffsetVector;\n"
522 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
523 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
524 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
525 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
526 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
527 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
528 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += 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;OffsetVector *= 0.5;RT -= OffsetVector;\n"
531 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;OffsetVector *= 0.5;RT -= OffsetVector;\n"
532 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;OffsetVector *= 0.5;RT -= OffsetVector;\n"
533 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;OffsetVector *= 0.5;RT -= OffsetVector;\n"
534 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;OffsetVector *= 0.5;RT -= OffsetVector;\n"
535 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;OffsetVector *= 0.5;RT -= OffsetVector;\n"
536 " TexCoord = RT.xy;\n"
538 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
539 " //vec2 OffsetVector = vec2(EyeVector.xy * (1.0 / EyeVector.z) * depthbias) * OffsetMapping_Scale * vec2(-0.333, 0.333);\n"
540 " //vec2 OffsetVector = vec2(normalize(EyeVector.xy)) * OffsetMapping_Scale * vec2(-0.333, 0.333);\n"
541 " vec2 OffsetVector = vec2(eyedir.xy) * OffsetMapping_Scale * vec2(-0.333, 0.333);\n"
542 " //TexCoord += OffsetVector * 3.0;\n"
543 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
544 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
545 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
547 " // 10 sample offset mapping\n"
548 " //vec2 OffsetVector = vec2(EyeVector.xy * (1.0 / EyeVector.z) * depthbias) * OffsetMapping_Scale * vec2(-0.333, 0.333);\n"
549 " //vec2 OffsetVector = vec2(normalize(EyeVector.xy)) * OffsetMapping_Scale * vec2(-0.333, 0.333);\n"
550 " vec2 OffsetVector = vec2(eyedir.xy) * OffsetMapping_Scale * vec2(-0.1, 0.1);\n"
551 " //TexCoord += OffsetVector * 3.0;\n"
552 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
553 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
554 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
555 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
556 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
557 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
558 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\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"
563 " // parallax mapping as described in the paper\n"
564 " // 'Parallax Mapping with Offset Limiting: A Per-Pixel Approximation of Uneven Surfaces' by Terry Welsh\n"
565 " // The paper provides code in the ARB fragment program assembly language\n"
566 " // I translated it to GLSL but may have done something wrong - SavageX\n"
567 " // LordHavoc: removed bias and simplified to one line\n"
568 " // LordHavoc: this is just a single sample offsetmapping...\n"
569 " TexCoordOffset += vec2(eyedir.x, -1.0 * eyedir.y) * OffsetMapping_Scale * texture2D(Texture_Normal, TexCoord).a;\n"
571 " // parallax mapping as described in the paper\n"
572 " // 'Parallax Mapping with Offset Limiting: A Per-Pixel Approximation of Uneven Surfaces' by Terry Welsh\n"
573 " // The paper provides code in the ARB fragment program assembly language\n"
574 " // I translated it to GLSL but may have done something wrong - SavageX\n"
575 " float height = texture2D(Texture_Normal, TexCoord).a;\n"
576 " height = (height - 0.5) * OffsetMapping_Scale; // bias and scale\n"
577 " TexCoordOffset += height * vec2(eyedir.x, -1.0 * eyedir.y);\n"
581 " // combine the diffuse textures (base, pants, shirt)\n"
582 " myhvec4 color = myhvec4(texture2D(Texture_Color, TexCoord));\n"
583 "#ifdef USECOLORMAPPING\n"
584 " color.rgb += myhvec3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhvec3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
590 "#ifdef MODE_LIGHTSOURCE\n"
593 " // get the surface normal and light normal\n"
594 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
595 " myhvec3 diffusenormal = myhvec3(normalize(LightVector));\n"
597 " // calculate directional shading\n"
598 " color.rgb *= AmbientScale + DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
599 "#ifdef USESPECULAR\n"
600 " myhvec3 specularnormal = normalize(diffusenormal + myhvec3(normalize(EyeVector)));\n"
601 " color.rgb += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
604 "#ifdef USECUBEFILTER\n"
605 " // apply light cubemap filter\n"
606 " //color.rgb *= normalize(CubeVector) * 0.5 + 0.5;//vec3(textureCube(Texture_Cube, CubeVector));\n"
607 " color.rgb *= myhvec3(textureCube(Texture_Cube, CubeVector));\n"
610 " // apply light color\n"
611 " color.rgb *= LightColor;\n"
613 " // apply attenuation\n"
615 " // the attenuation is (1-(x*x+y*y+z*z)) which gives a large bright\n"
616 " // center and sharp falloff at the edge, this is about the most efficient\n"
617 " // we can get away with as far as providing illumination.\n"
619 " // pow(1-(x*x+y*y+z*z), 4) is far more realistic but needs large lights to\n"
620 " // provide significant illumination, large = slow = pain.\n"
621 " color.rgb *= myhalf(max(1.0 - dot(CubeVector, CubeVector), 0.0));\n"
626 "#elif defined(MODE_LIGHTDIRECTION)\n"
627 " // directional model lighting\n"
629 " // get the surface normal and light normal\n"
630 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
631 " myhvec3 diffusenormal = myhvec3(normalize(LightVector));\n"
633 " // calculate directional shading\n"
634 " color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
635 "#ifdef USESPECULAR\n"
636 " myhvec3 specularnormal = normalize(diffusenormal + myhvec3(normalize(EyeVector)));\n"
637 " color.rgb += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
643 "#elif defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
644 " // deluxemap lightmapping using light vectors in modelspace (evil q3map2)\n"
646 " // get the surface normal and light normal\n"
647 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
649 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
650 " myhvec3 diffusenormal_modelspace = myhvec3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - myhvec3(0.5);\n"
651 " myhvec3 diffusenormal = normalize(myhvec3(dot(diffusenormal_modelspace, myhvec3(VectorS)), dot(diffusenormal_modelspace, myhvec3(VectorT)), dot(diffusenormal_modelspace, myhvec3(VectorR))));\n"
653 " myhvec3 diffusenormal = normalize(myhvec3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - myhvec3(0.5));\n"
655 " // calculate directional shading\n"
656 " myhvec3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0)));\n"
657 "#ifdef USESPECULAR\n"
658 " myhvec3 specularnormal = myhvec3(normalize(diffusenormal + myhvec3(normalize(EyeVector))));\n"
659 " tempcolor += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
662 " // apply lightmap color\n"
663 " color.rgb = tempcolor * myhvec3(texture2D(Texture_Lightmap, TexCoordLightmap)) + color.rgb * AmbientScale;\n"
666 "#else // MODE none (lightmap)\n"
667 " // apply lightmap color\n"
668 " color.rgb *= myhvec3(texture2D(Texture_Lightmap, TexCoordLightmap)) * DiffuseScale + myhvec3(AmbientScale);\n"
671 " color *= myhvec4(gl_Color);\n"
674 " color.rgb += myhvec3(texture2D(Texture_Glow, TexCoord)) * GlowScale;\n"
679 " myhalf fog = myhalf(texture2D(Texture_FogMask, myhvec2(length(EyeVectorModelSpace)*FogRangeRecip, 0.0)).x);\n"
680 " color.rgb = color.rgb * fog + FogColor * (1.0 - fog);\n"
683 " color.rgb *= SceneBrightness;\n"
685 " gl_FragColor = vec4(color);\n"
688 "#endif // FRAGMENT_SHADER\n"
691 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
692 const char *permutationinfo[][2] =
694 {"#define MODE_LIGHTSOURCE\n", " lightsource"},
695 {"#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
696 {"#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
697 {"#define MODE_LIGHTDIRECTION\n", " lightdirection"},
698 {"#define USEGLOW\n", " glow"},
699 {"#define USEFOG\n", " fog"},
700 {"#define USECOLORMAPPING\n", " colormapping"},
701 {"#define USESPECULAR\n", " specular"},
702 {"#define USECUBEFILTER\n", " cubefilter"},
703 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
704 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
708 void R_GLSL_CompilePermutation(int permutation)
711 r_glsl_permutation_t *p = r_glsl_permutations + permutation;
712 int vertstrings_count;
713 int fragstrings_count;
715 const char *vertstrings_list[SHADERPERMUTATION_COUNT+1];
716 const char *fragstrings_list[SHADERPERMUTATION_COUNT+1];
717 char permutationname[256];
721 vertstrings_list[0] = "#define VERTEX_SHADER\n";
722 fragstrings_list[0] = "#define FRAGMENT_SHADER\n";
723 vertstrings_count = 1;
724 fragstrings_count = 1;
725 permutationname[0] = 0;
726 for (i = 0;permutationinfo[i][0];i++)
728 if (permutation & (1<<i))
730 vertstrings_list[vertstrings_count++] = permutationinfo[i][0];
731 fragstrings_list[fragstrings_count++] = permutationinfo[i][0];
732 strlcat(permutationname, permutationinfo[i][1], sizeof(permutationname));
736 // keep line numbers correct
737 vertstrings_list[vertstrings_count++] = "\n";
738 fragstrings_list[fragstrings_count++] = "\n";
741 shaderstring = (char *)FS_LoadFile("glsl/default.glsl", r_main_mempool, false, NULL);
744 Con_DPrintf("GLSL shader text loaded from disk\n");
745 vertstrings_list[vertstrings_count++] = shaderstring;
746 fragstrings_list[fragstrings_count++] = shaderstring;
750 vertstrings_list[vertstrings_count++] = builtinshaderstring;
751 fragstrings_list[fragstrings_count++] = builtinshaderstring;
753 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, fragstrings_count, fragstrings_list);
757 qglUseProgramObjectARB(p->program);CHECKGLERROR
758 p->loc_Texture_Normal = qglGetUniformLocationARB(p->program, "Texture_Normal");
759 p->loc_Texture_Color = qglGetUniformLocationARB(p->program, "Texture_Color");
760 p->loc_Texture_Gloss = qglGetUniformLocationARB(p->program, "Texture_Gloss");
761 p->loc_Texture_Cube = qglGetUniformLocationARB(p->program, "Texture_Cube");
762 p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
763 p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
764 p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
765 p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
766 p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
767 p->loc_Texture_Glow = qglGetUniformLocationARB(p->program, "Texture_Glow");
768 p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
769 p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
770 p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
771 p->loc_LightColor = qglGetUniformLocationARB(p->program, "LightColor");
772 p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants");
773 p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt");
774 p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip");
775 p->loc_AmbientScale = qglGetUniformLocationARB(p->program, "AmbientScale");
776 p->loc_DiffuseScale = qglGetUniformLocationARB(p->program, "DiffuseScale");
777 p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
778 p->loc_SpecularScale = qglGetUniformLocationARB(p->program, "SpecularScale");
779 p->loc_GlowScale = qglGetUniformLocationARB(p->program, "GlowScale");
780 p->loc_SceneBrightness = qglGetUniformLocationARB(p->program, "SceneBrightness");
781 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
782 p->loc_AmbientColor = qglGetUniformLocationARB(p->program, "AmbientColor");
783 p->loc_DiffuseColor = qglGetUniformLocationARB(p->program, "DiffuseColor");
784 p->loc_SpecularColor = qglGetUniformLocationARB(p->program, "SpecularColor");
785 p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
786 if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal, 0);
787 if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color, 1);
788 if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss, 2);
789 if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube, 3);
790 if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask, 4);
791 if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants, 5);
792 if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt, 6);
793 if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap, 7);
794 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap, 8);
795 if (p->loc_Texture_Glow >= 0) qglUniform1iARB(p->loc_Texture_Glow, 9);
797 qglUseProgramObjectARB(0);CHECKGLERROR
800 Con_Printf("permutation%s failed for shader %s, some features may not work properly!\n", permutationname, "glsl/default.glsl");
802 Mem_Free(shaderstring);
805 void R_GLSL_Restart_f(void)
808 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
809 if (r_glsl_permutations[i].program)
810 GL_Backend_FreeProgram(r_glsl_permutations[i].program);
811 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
814 int R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting)
816 // select a permutation of the lighting shader appropriate to this
817 // combination of texture, entity, light source, and fogging, only use the
818 // minimum features necessary to avoid wasting rendering time in the
819 // fragment shader on features that are not being used
821 float specularscale = rsurface_texture->specularscale;
822 r_glsl_permutation = NULL;
823 if (r_shadow_rtlight)
825 permutation |= SHADERPERMUTATION_MODE_LIGHTSOURCE;
826 specularscale *= r_shadow_rtlight->specularscale;
827 if (r_shadow_rtlight->currentcubemap != r_texture_whitecube)
828 permutation |= SHADERPERMUTATION_CUBEFILTER;
832 if (!(rsurface_texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
835 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTION;
836 else if (r_glsl_deluxemapping.integer >= 1 && rsurface_lightmaptexture)
838 if (r_refdef.worldmodel && r_refdef.worldmodel->brushq3.deluxemapping)
840 if (r_refdef.worldmodel->brushq3.deluxemapping_modelspace)
841 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_MODELSPACE;
843 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
845 else if (r_glsl_deluxemapping.integer >= 2) // fake mode
846 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
849 if (rsurface_texture->currentskinframe->glow)
850 permutation |= SHADERPERMUTATION_GLOW;
852 if (specularscale > 0)
853 permutation |= SHADERPERMUTATION_SPECULAR;
854 if (r_refdef.fogenabled)
855 permutation |= SHADERPERMUTATION_FOG;
856 if (rsurface_texture->colormapping)
857 permutation |= SHADERPERMUTATION_COLORMAPPING;
858 if (r_glsl_offsetmapping.integer)
860 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
861 if (r_glsl_offsetmapping_reliefmapping.integer)
862 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
864 if (!r_glsl_permutations[permutation].program)
866 if (!r_glsl_permutations[permutation].compiled)
867 R_GLSL_CompilePermutation(permutation);
868 if (!r_glsl_permutations[permutation].program)
870 // remove features until we find a valid permutation
872 for (i = SHADERPERMUTATION_COUNT-1;;i>>=1)
874 // reduce i more quickly whenever it would not remove any bits
878 if (!r_glsl_permutations[permutation].compiled)
879 R_GLSL_CompilePermutation(permutation);
880 if (r_glsl_permutations[permutation].program)
883 return 0; // utterly failed
887 r_glsl_permutation = r_glsl_permutations + permutation;
889 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
890 R_Mesh_TexMatrix(0, &rsurface_texture->currenttexmatrix);
891 if (permutation & SHADERPERMUTATION_MODE_LIGHTSOURCE)
893 if (r_glsl_permutation->loc_Texture_Cube >= 0 && r_shadow_rtlight) R_Mesh_TexBindCubeMap(3, R_GetTexture(r_shadow_rtlight->currentcubemap));
894 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]);
895 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
896 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_shadow_rtlight->ambientscale);
897 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_shadow_rtlight->diffusescale);
898 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, specularscale);
900 else if (permutation & SHADERPERMUTATION_MODE_LIGHTDIRECTION)
902 if (r_glsl_permutation->loc_AmbientColor >= 0)
903 qglUniform3fARB(r_glsl_permutation->loc_AmbientColor, rsurface_entity->modellight_ambient[0], rsurface_entity->modellight_ambient[1], rsurface_entity->modellight_ambient[2]);
904 if (r_glsl_permutation->loc_DiffuseColor >= 0)
905 qglUniform3fARB(r_glsl_permutation->loc_DiffuseColor, rsurface_entity->modellight_diffuse[0], rsurface_entity->modellight_diffuse[1], rsurface_entity->modellight_diffuse[2]);
906 if (r_glsl_permutation->loc_SpecularColor >= 0)
907 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);
908 if (r_glsl_permutation->loc_LightDir >= 0)
909 qglUniform3fARB(r_glsl_permutation->loc_LightDir, rsurface_entity->modellight_lightdir[0], rsurface_entity->modellight_lightdir[1], rsurface_entity->modellight_lightdir[2]);
913 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_ambient.value * 2.0f / 128.0f);
914 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_refdef.lightmapintensity * 2.0f);
915 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, r_refdef.lightmapintensity * specularscale * 2.0f);
917 if (r_glsl_permutation->loc_Texture_Normal >= 0) R_Mesh_TexBind(0, R_GetTexture(rsurface_texture->currentskinframe->nmap));
918 if (r_glsl_permutation->loc_Texture_Color >= 0) R_Mesh_TexBind(1, R_GetTexture(rsurface_texture->basetexture));
919 if (r_glsl_permutation->loc_Texture_Gloss >= 0) R_Mesh_TexBind(2, R_GetTexture(rsurface_texture->glosstexture));
920 //if (r_glsl_permutation->loc_Texture_Cube >= 0 && permutation & SHADERPERMUTATION_MODE_LIGHTSOURCE) R_Mesh_TexBindCubeMap(3, R_GetTexture(r_shadow_rtlight->currentcubemap));
921 if (r_glsl_permutation->loc_Texture_FogMask >= 0) R_Mesh_TexBind(4, R_GetTexture(r_texture_fogattenuation));
922 if (r_glsl_permutation->loc_Texture_Pants >= 0) R_Mesh_TexBind(5, R_GetTexture(rsurface_texture->currentskinframe->pants));
923 if (r_glsl_permutation->loc_Texture_Shirt >= 0) R_Mesh_TexBind(6, R_GetTexture(rsurface_texture->currentskinframe->shirt));
924 //if (r_glsl_permutation->loc_Texture_Lightmap >= 0) R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
925 //if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
926 if (r_glsl_permutation->loc_Texture_Glow >= 0) R_Mesh_TexBind(9, R_GetTexture(rsurface_texture->currentskinframe->glow));
927 if (r_glsl_permutation->loc_GlowScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_GlowScale, r_hdr_glowintensity.value);
928 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_view.colorscale);
929 if (r_glsl_permutation->loc_FogColor >= 0)
931 // additive passes are only darkened by fog, not tinted
932 if (r_shadow_rtlight || (rsurface_texture->currentmaterialflags & MATERIALFLAG_ADD))
933 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
935 qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
937 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface_modelorg[0], rsurface_modelorg[1], rsurface_modelorg[2]);
938 if (r_glsl_permutation->loc_Color_Pants >= 0)
940 if (rsurface_texture->currentskinframe->pants)
941 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface_entity->colormap_pantscolor[0], rsurface_entity->colormap_pantscolor[1], rsurface_entity->colormap_pantscolor[2]);
943 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
945 if (r_glsl_permutation->loc_Color_Shirt >= 0)
947 if (rsurface_texture->currentskinframe->shirt)
948 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface_entity->colormap_shirtcolor[0], rsurface_entity->colormap_shirtcolor[1], rsurface_entity->colormap_shirtcolor[2]);
950 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
952 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, r_refdef.fograngerecip);
953 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface_texture->specularpower);
954 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
959 void R_SwitchSurfaceShader(int permutation)
961 if (r_glsl_permutation != r_glsl_permutations + permutation)
963 r_glsl_permutation = r_glsl_permutations + permutation;
965 qglUseProgramObjectARB(r_glsl_permutation->program);
970 void gl_main_start(void)
972 r_main_texturepool = R_AllocTexturePool();
973 R_BuildBlankTextures();
975 if (gl_texturecubemap)
978 R_BuildNormalizationCube();
981 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
982 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
985 void gl_main_shutdown(void)
987 R_FreeTexturePool(&r_main_texturepool);
988 r_texture_blanknormalmap = NULL;
989 r_texture_white = NULL;
990 r_texture_black = NULL;
991 r_texture_whitecube = NULL;
992 r_texture_normalizationcube = NULL;
993 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
997 extern void CL_ParseEntityLump(char *entitystring);
998 void gl_main_newmap(void)
1000 // FIXME: move this code to client
1002 char *entities, entname[MAX_QPATH];
1005 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
1006 l = (int)strlen(entname) - 4;
1007 if (l >= 0 && !strcmp(entname + l, ".bsp"))
1009 memcpy(entname + l, ".ent", 5);
1010 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
1012 CL_ParseEntityLump(entities);
1017 if (cl.worldmodel->brush.entities)
1018 CL_ParseEntityLump(cl.worldmodel->brush.entities);
1022 void GL_Main_Init(void)
1024 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
1026 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed\n");
1027 FOG_registercvars(); // FIXME: move this fog stuff to client?
1028 Cvar_RegisterVariable(&r_nearclip);
1029 Cvar_RegisterVariable(&r_showsurfaces);
1030 Cvar_RegisterVariable(&r_showtris);
1031 Cvar_RegisterVariable(&r_shownormals);
1032 Cvar_RegisterVariable(&r_showlighting);
1033 Cvar_RegisterVariable(&r_showshadowvolumes);
1034 Cvar_RegisterVariable(&r_showcollisionbrushes);
1035 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
1036 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
1037 Cvar_RegisterVariable(&r_showdisabledepthtest);
1038 Cvar_RegisterVariable(&r_drawportals);
1039 Cvar_RegisterVariable(&r_drawentities);
1040 Cvar_RegisterVariable(&r_drawviewmodel);
1041 Cvar_RegisterVariable(&r_speeds);
1042 Cvar_RegisterVariable(&r_fullbrights);
1043 Cvar_RegisterVariable(&r_wateralpha);
1044 Cvar_RegisterVariable(&r_dynamic);
1045 Cvar_RegisterVariable(&r_fullbright);
1046 Cvar_RegisterVariable(&r_shadows);
1047 Cvar_RegisterVariable(&r_shadows_throwdistance);
1048 Cvar_RegisterVariable(&r_q1bsp_skymasking);
1049 Cvar_RegisterVariable(&r_textureunits);
1050 Cvar_RegisterVariable(&r_glsl);
1051 Cvar_RegisterVariable(&r_glsl_offsetmapping);
1052 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
1053 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
1054 Cvar_RegisterVariable(&r_glsl_deluxemapping);
1055 Cvar_RegisterVariable(&r_lerpsprites);
1056 Cvar_RegisterVariable(&r_lerpmodels);
1057 Cvar_RegisterVariable(&r_waterscroll);
1058 Cvar_RegisterVariable(&r_bloom);
1059 Cvar_RegisterVariable(&r_bloom_colorscale);
1060 Cvar_RegisterVariable(&r_bloom_brighten);
1061 Cvar_RegisterVariable(&r_bloom_blur);
1062 Cvar_RegisterVariable(&r_bloom_resolution);
1063 Cvar_RegisterVariable(&r_bloom_colorexponent);
1064 Cvar_RegisterVariable(&r_bloom_colorsubtract);
1065 Cvar_RegisterVariable(&r_hdr);
1066 Cvar_RegisterVariable(&r_hdr_scenebrightness);
1067 Cvar_RegisterVariable(&r_hdr_glowintensity);
1068 Cvar_RegisterVariable(&r_hdr_range);
1069 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
1070 Cvar_RegisterVariable(&developer_texturelogging);
1071 Cvar_RegisterVariable(&gl_lightmaps);
1072 Cvar_RegisterVariable(&r_test);
1073 Cvar_RegisterVariable(&r_batchmode);
1074 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
1075 Cvar_SetValue("r_fullbrights", 0);
1076 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
1079 extern void R_Textures_Init(void);
1080 extern void GL_Draw_Init(void);
1081 extern void GL_Main_Init(void);
1082 extern void R_Shadow_Init(void);
1083 extern void R_Sky_Init(void);
1084 extern void GL_Surf_Init(void);
1085 extern void R_Light_Init(void);
1086 extern void R_Particles_Init(void);
1087 extern void R_Explosion_Init(void);
1088 extern void gl_backend_init(void);
1089 extern void Sbar_Init(void);
1090 extern void R_LightningBeams_Init(void);
1091 extern void Mod_RenderInit(void);
1093 void Render_Init(void)
1106 R_LightningBeams_Init();
1115 extern char *ENGINE_EXTENSIONS;
1118 VID_CheckExtensions();
1120 // LordHavoc: report supported extensions
1121 Con_DPrintf("\nengine extensions: %s\n", vm_sv_extensions );
1123 // clear to black (loading plaque will be seen over this)
1125 qglClearColor(0,0,0,1);CHECKGLERROR
1126 qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
1129 int R_CullBox(const vec3_t mins, const vec3_t maxs)
1133 for (i = 0;i < 4;i++)
1135 p = r_view.frustum + i;
1140 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1144 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1148 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1152 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1156 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1160 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1164 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1168 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1176 //==================================================================================
1178 static void R_UpdateEntityLighting(entity_render_t *ent)
1180 vec3_t tempdiffusenormal;
1182 // fetch the lighting from the worldmodel data
1183 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));
1184 VectorClear(ent->modellight_diffuse);
1185 VectorClear(tempdiffusenormal);
1186 if ((ent->flags & RENDER_LIGHT) && r_refdef.worldmodel && r_refdef.worldmodel->brush.LightPoint)
1189 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
1190 r_refdef.worldmodel->brush.LightPoint(r_refdef.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
1193 VectorSet(ent->modellight_ambient, 1, 1, 1);
1195 // move the light direction into modelspace coordinates for lighting code
1196 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
1197 VectorNormalize(ent->modellight_lightdir);
1199 // scale ambient and directional light contributions according to rendering variables
1200 ent->modellight_ambient[0] *= ent->colormod[0] * r_refdef.lightmapintensity;
1201 ent->modellight_ambient[1] *= ent->colormod[1] * r_refdef.lightmapintensity;
1202 ent->modellight_ambient[2] *= ent->colormod[2] * r_refdef.lightmapintensity;
1203 ent->modellight_diffuse[0] *= ent->colormod[0] * r_refdef.lightmapintensity;
1204 ent->modellight_diffuse[1] *= ent->colormod[1] * r_refdef.lightmapintensity;
1205 ent->modellight_diffuse[2] *= ent->colormod[2] * r_refdef.lightmapintensity;
1208 static void R_View_UpdateEntityVisible (void)
1211 entity_render_t *ent;
1213 if (!r_drawentities.integer)
1216 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : (chase_active.integer ? 0 : RENDER_EXTERIORMODEL);
1217 if (r_refdef.worldmodel && r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs)
1219 // worldmodel can check visibility
1220 for (i = 0;i < r_refdef.numentities;i++)
1222 ent = r_refdef.entities[i];
1223 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));
1228 // no worldmodel or it can't check visibility
1229 for (i = 0;i < r_refdef.numentities;i++)
1231 ent = r_refdef.entities[i];
1232 r_viewcache.entityvisible[i] = !(ent->flags & renderimask) && !R_CullBox(ent->mins, ent->maxs);
1236 // update entity lighting (even on hidden entities for r_shadows)
1237 for (i = 0;i < r_refdef.numentities;i++)
1238 R_UpdateEntityLighting(r_refdef.entities[i]);
1241 // only used if skyrendermasked, and normally returns false
1242 int R_DrawBrushModelsSky (void)
1245 entity_render_t *ent;
1247 if (!r_drawentities.integer)
1251 for (i = 0;i < r_refdef.numentities;i++)
1253 if (!r_viewcache.entityvisible[i])
1255 ent = r_refdef.entities[i];
1256 if (!ent->model || !ent->model->DrawSky)
1258 ent->model->DrawSky(ent);
1264 void R_DrawNoModel(entity_render_t *ent);
1265 void R_DrawModels(void)
1268 entity_render_t *ent;
1270 if (!r_drawentities.integer)
1273 for (i = 0;i < r_refdef.numentities;i++)
1275 if (!r_viewcache.entityvisible[i])
1277 ent = r_refdef.entities[i];
1278 r_refdef.stats.entities++;
1279 if (ent->model && ent->model->Draw != NULL)
1280 ent->model->Draw(ent);
1286 static void R_View_SetFrustum(void)
1288 // break apart the view matrix into vectors for various purposes
1289 Matrix4x4_ToVectors(&r_view.matrix, r_view.forward, r_view.left, r_view.up, r_view.origin);
1290 VectorNegate(r_view.left, r_view.right);
1293 r_view.frustum[0].normal[0] = 0 - 1.0 / r_view.frustum_x;
1294 r_view.frustum[0].normal[1] = 0 - 0;
1295 r_view.frustum[0].normal[2] = -1 - 0;
1296 r_view.frustum[1].normal[0] = 0 + 1.0 / r_view.frustum_x;
1297 r_view.frustum[1].normal[1] = 0 + 0;
1298 r_view.frustum[1].normal[2] = -1 + 0;
1299 r_view.frustum[2].normal[0] = 0 - 0;
1300 r_view.frustum[2].normal[1] = 0 - 1.0 / r_view.frustum_y;
1301 r_view.frustum[2].normal[2] = -1 - 0;
1302 r_view.frustum[3].normal[0] = 0 + 0;
1303 r_view.frustum[3].normal[1] = 0 + 1.0 / r_view.frustum_y;
1304 r_view.frustum[3].normal[2] = -1 + 0;
1308 zNear = r_refdef.nearclip;
1309 nudge = 1.0 - 1.0 / (1<<23);
1310 r_view.frustum[4].normal[0] = 0 - 0;
1311 r_view.frustum[4].normal[1] = 0 - 0;
1312 r_view.frustum[4].normal[2] = -1 - -nudge;
1313 r_view.frustum[4].dist = 0 - -2 * zNear * nudge;
1314 r_view.frustum[5].normal[0] = 0 + 0;
1315 r_view.frustum[5].normal[1] = 0 + 0;
1316 r_view.frustum[5].normal[2] = -1 + -nudge;
1317 r_view.frustum[5].dist = 0 + -2 * zNear * nudge;
1323 r_view.frustum[0].normal[0] = m[3] - m[0];
1324 r_view.frustum[0].normal[1] = m[7] - m[4];
1325 r_view.frustum[0].normal[2] = m[11] - m[8];
1326 r_view.frustum[0].dist = m[15] - m[12];
1328 r_view.frustum[1].normal[0] = m[3] + m[0];
1329 r_view.frustum[1].normal[1] = m[7] + m[4];
1330 r_view.frustum[1].normal[2] = m[11] + m[8];
1331 r_view.frustum[1].dist = m[15] + m[12];
1333 r_view.frustum[2].normal[0] = m[3] - m[1];
1334 r_view.frustum[2].normal[1] = m[7] - m[5];
1335 r_view.frustum[2].normal[2] = m[11] - m[9];
1336 r_view.frustum[2].dist = m[15] - m[13];
1338 r_view.frustum[3].normal[0] = m[3] + m[1];
1339 r_view.frustum[3].normal[1] = m[7] + m[5];
1340 r_view.frustum[3].normal[2] = m[11] + m[9];
1341 r_view.frustum[3].dist = m[15] + m[13];
1343 r_view.frustum[4].normal[0] = m[3] - m[2];
1344 r_view.frustum[4].normal[1] = m[7] - m[6];
1345 r_view.frustum[4].normal[2] = m[11] - m[10];
1346 r_view.frustum[4].dist = m[15] - m[14];
1348 r_view.frustum[5].normal[0] = m[3] + m[2];
1349 r_view.frustum[5].normal[1] = m[7] + m[6];
1350 r_view.frustum[5].normal[2] = m[11] + m[10];
1351 r_view.frustum[5].dist = m[15] + m[14];
1356 VectorMAM(1, r_view.forward, 1.0 / -r_view.frustum_x, r_view.left, r_view.frustum[0].normal);
1357 VectorMAM(1, r_view.forward, 1.0 / r_view.frustum_x, r_view.left, r_view.frustum[1].normal);
1358 VectorMAM(1, r_view.forward, 1.0 / -r_view.frustum_y, r_view.up, r_view.frustum[2].normal);
1359 VectorMAM(1, r_view.forward, 1.0 / r_view.frustum_y, r_view.up, r_view.frustum[3].normal);
1360 VectorCopy(r_view.forward, r_view.frustum[4].normal);
1361 VectorNormalize(r_view.frustum[0].normal);
1362 VectorNormalize(r_view.frustum[1].normal);
1363 VectorNormalize(r_view.frustum[2].normal);
1364 VectorNormalize(r_view.frustum[3].normal);
1365 r_view.frustum[0].dist = DotProduct (r_view.origin, r_view.frustum[0].normal);
1366 r_view.frustum[1].dist = DotProduct (r_view.origin, r_view.frustum[1].normal);
1367 r_view.frustum[2].dist = DotProduct (r_view.origin, r_view.frustum[2].normal);
1368 r_view.frustum[3].dist = DotProduct (r_view.origin, r_view.frustum[3].normal);
1369 r_view.frustum[4].dist = DotProduct (r_view.origin, r_view.frustum[4].normal) + r_refdef.nearclip;
1370 PlaneClassify(&r_view.frustum[0]);
1371 PlaneClassify(&r_view.frustum[1]);
1372 PlaneClassify(&r_view.frustum[2]);
1373 PlaneClassify(&r_view.frustum[3]);
1374 PlaneClassify(&r_view.frustum[4]);
1376 // LordHavoc: note to all quake engine coders, Quake had a special case
1377 // for 90 degrees which assumed a square view (wrong), so I removed it,
1378 // Quake2 has it disabled as well.
1380 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
1381 //RotatePointAroundVector( r_view.frustum[0].normal, r_view.up, r_view.forward, -(90 - r_refdef.fov_x / 2));
1382 //r_view.frustum[0].dist = DotProduct (r_view.origin, frustum[0].normal);
1383 //PlaneClassify(&frustum[0]);
1385 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
1386 //RotatePointAroundVector( r_view.frustum[1].normal, r_view.up, r_view.forward, (90 - r_refdef.fov_x / 2));
1387 //r_view.frustum[1].dist = DotProduct (r_view.origin, frustum[1].normal);
1388 //PlaneClassify(&frustum[1]);
1390 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
1391 //RotatePointAroundVector( r_view.frustum[2].normal, r_view.left, r_view.forward, -(90 - r_refdef.fov_y / 2));
1392 //r_view.frustum[2].dist = DotProduct (r_view.origin, frustum[2].normal);
1393 //PlaneClassify(&frustum[2]);
1395 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
1396 //RotatePointAroundVector( r_view.frustum[3].normal, r_view.left, r_view.forward, (90 - r_refdef.fov_y / 2));
1397 //r_view.frustum[3].dist = DotProduct (r_view.origin, frustum[3].normal);
1398 //PlaneClassify(&frustum[3]);
1401 //VectorCopy(r_view.forward, r_view.frustum[4].normal);
1402 //r_view.frustum[4].dist = DotProduct (r_view.origin, frustum[4].normal) + r_nearclip.value;
1403 //PlaneClassify(&frustum[4]);
1406 void R_View_Update(void)
1408 R_View_SetFrustum();
1409 R_View_WorldVisibility();
1410 R_View_UpdateEntityVisible();
1413 void R_SetupView(const matrix4x4_t *matrix)
1415 if (r_refdef.rtworldshadows || r_refdef.rtdlightshadows)
1416 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_view.frustum_x, r_view.frustum_y, r_refdef.nearclip);
1418 GL_SetupView_Mode_Perspective(r_view.frustum_x, r_view.frustum_y, r_refdef.nearclip, r_refdef.farclip);
1420 GL_SetupView_Orientation_FromEntity(matrix);
1423 void R_ResetViewRendering2D(void)
1425 if (gl_support_fragment_shader)
1427 qglUseProgramObjectARB(0);CHECKGLERROR
1432 // GL is weird because it's bottom to top, r_view.y is top to bottom
1433 qglViewport(r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
1434 GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
1435 GL_Scissor(r_view.x, r_view.y, r_view.width, r_view.height);
1436 GL_Color(1, 1, 1, 1);
1437 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
1438 GL_BlendFunc(GL_ONE, GL_ZERO);
1439 GL_AlphaTest(false);
1440 GL_ScissorTest(false);
1441 GL_DepthMask(false);
1442 GL_DepthTest(false);
1443 R_Mesh_Matrix(&identitymatrix);
1444 R_Mesh_ResetTextureState();
1445 qglPolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR
1446 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
1447 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
1448 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
1449 qglStencilMask(~0);CHECKGLERROR
1450 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
1451 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
1452 GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
1455 void R_ResetViewRendering3D(void)
1457 if (gl_support_fragment_shader)
1459 qglUseProgramObjectARB(0);CHECKGLERROR
1464 // GL is weird because it's bottom to top, r_view.y is top to bottom
1465 qglViewport(r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
1466 R_SetupView(&r_view.matrix);
1467 GL_Scissor(r_view.x, r_view.y, r_view.width, r_view.height);
1468 GL_Color(1, 1, 1, 1);
1469 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
1470 GL_BlendFunc(GL_ONE, GL_ZERO);
1471 GL_AlphaTest(false);
1472 GL_ScissorTest(true);
1475 R_Mesh_Matrix(&identitymatrix);
1476 R_Mesh_ResetTextureState();
1477 qglPolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR
1478 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
1479 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
1480 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
1481 qglStencilMask(~0);CHECKGLERROR
1482 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
1483 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
1484 GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
1488 R_Bloom_SetupShader(
1490 "// written by Forest 'LordHavoc' Hale\n"
1492 "// common definitions between vertex shader and fragment shader:\n"
1494 "#ifdef __GLSL_CG_DATA_TYPES\n"
1495 "#define myhalf half\n"
1496 "#define myhvec2 hvec2\n"
1497 "#define myhvec3 hvec3\n"
1498 "#define myhvec4 hvec4\n"
1500 "#define myhalf float\n"
1501 "#define myhvec2 vec2\n"
1502 "#define myhvec3 vec3\n"
1503 "#define myhvec4 vec4\n"
1506 "varying vec2 ScreenTexCoord;\n"
1507 "varying vec2 BloomTexCoord;\n"
1512 "// vertex shader specific:\n"
1513 "#ifdef VERTEX_SHADER\n"
1517 " ScreenTexCoord = vec2(gl_MultiTexCoord0);\n"
1518 " BloomTexCoord = vec2(gl_MultiTexCoord1);\n"
1519 " // transform vertex to camera space, using ftransform to match non-VS\n"
1521 " gl_Position = ftransform();\n"
1524 "#endif // VERTEX_SHADER\n"
1529 "// fragment shader specific:\n"
1530 "#ifdef FRAGMENT_SHADER\n"
1535 " myhvec3 color = myhvec3(texture2D(Texture_Screen, ScreenTexCoord));\n"
1536 " for (x = -BLUR_X;x <= BLUR_X;x++)
1537 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
1538 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
1539 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
1540 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
1542 " gl_FragColor = vec4(color);\n"
1545 "#endif // FRAGMENT_SHADER\n"
1548 void R_RenderScene(void);
1550 void R_Bloom_StartFrame(void)
1552 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
1554 // set bloomwidth and bloomheight to the bloom resolution that will be
1555 // used (often less than the screen resolution for faster rendering)
1556 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_view.width);
1557 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_view.height / r_view.width;
1558 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_view.height);
1560 // calculate desired texture sizes
1561 if (gl_support_arb_texture_non_power_of_two)
1563 screentexturewidth = r_view.width;
1564 screentextureheight = r_view.height;
1565 bloomtexturewidth = r_bloomstate.bloomwidth;
1566 bloomtextureheight = r_bloomstate.bloomheight;
1570 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
1571 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
1572 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
1573 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
1578 screentexturewidth = screentextureheight = 0;
1580 else if (r_bloom.integer)
1585 screentexturewidth = screentextureheight = 0;
1586 bloomtexturewidth = bloomtextureheight = 0;
1589 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)
1591 // can't use bloom if the parameters are too weird
1592 // can't use bloom if the card does not support the texture size
1593 if (r_bloomstate.texture_screen)
1594 R_FreeTexture(r_bloomstate.texture_screen);
1595 if (r_bloomstate.texture_bloom)
1596 R_FreeTexture(r_bloomstate.texture_bloom);
1597 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
1601 r_bloomstate.enabled = true;
1602 r_bloomstate.hdr = r_hdr.integer != 0;
1604 // allocate textures as needed
1605 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
1607 if (r_bloomstate.texture_screen)
1608 R_FreeTexture(r_bloomstate.texture_screen);
1609 r_bloomstate.texture_screen = NULL;
1610 r_bloomstate.screentexturewidth = screentexturewidth;
1611 r_bloomstate.screentextureheight = screentextureheight;
1612 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
1613 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);
1615 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
1617 if (r_bloomstate.texture_bloom)
1618 R_FreeTexture(r_bloomstate.texture_bloom);
1619 r_bloomstate.texture_bloom = NULL;
1620 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
1621 r_bloomstate.bloomtextureheight = bloomtextureheight;
1622 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
1623 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);
1626 // set up a texcoord array for the full resolution screen image
1627 // (we have to keep this around to copy back during final render)
1628 r_bloomstate.screentexcoord2f[0] = 0;
1629 r_bloomstate.screentexcoord2f[1] = (float)r_view.height / (float)r_bloomstate.screentextureheight;
1630 r_bloomstate.screentexcoord2f[2] = (float)r_view.width / (float)r_bloomstate.screentexturewidth;
1631 r_bloomstate.screentexcoord2f[3] = (float)r_view.height / (float)r_bloomstate.screentextureheight;
1632 r_bloomstate.screentexcoord2f[4] = (float)r_view.width / (float)r_bloomstate.screentexturewidth;
1633 r_bloomstate.screentexcoord2f[5] = 0;
1634 r_bloomstate.screentexcoord2f[6] = 0;
1635 r_bloomstate.screentexcoord2f[7] = 0;
1637 // set up a texcoord array for the reduced resolution bloom image
1638 // (which will be additive blended over the screen image)
1639 r_bloomstate.bloomtexcoord2f[0] = 0;
1640 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
1641 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
1642 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
1643 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
1644 r_bloomstate.bloomtexcoord2f[5] = 0;
1645 r_bloomstate.bloomtexcoord2f[6] = 0;
1646 r_bloomstate.bloomtexcoord2f[7] = 0;
1649 void R_Bloom_CopyScreenTexture(float colorscale)
1651 r_refdef.stats.bloom++;
1653 R_ResetViewRendering2D();
1654 R_Mesh_VertexPointer(r_screenvertex3f);
1655 R_Mesh_ColorPointer(NULL);
1656 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f);
1657 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
1659 // copy view into the screen texture
1660 GL_ActiveTexture(0);
1662 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
1663 r_refdef.stats.bloom_copypixels += r_view.width * r_view.height;
1665 // now scale it down to the bloom texture size
1667 qglViewport(r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
1668 GL_BlendFunc(GL_ONE, GL_ZERO);
1669 GL_Color(colorscale, colorscale, colorscale, 1);
1670 // TODO: optimize with multitexture or GLSL
1671 R_Mesh_Draw(0, 4, 2, polygonelements);
1672 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
1674 // we now have a bloom image in the framebuffer
1675 // copy it into the bloom image texture for later processing
1676 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
1677 GL_ActiveTexture(0);
1679 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
1680 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
1683 void R_Bloom_CopyHDRTexture(void)
1685 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
1686 GL_ActiveTexture(0);
1688 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
1689 r_refdef.stats.bloom_copypixels += r_view.width * r_view.height;
1692 void R_Bloom_MakeTexture(void)
1695 float xoffset, yoffset, r, brighten;
1697 r_refdef.stats.bloom++;
1699 R_ResetViewRendering2D();
1700 R_Mesh_VertexPointer(r_screenvertex3f);
1701 R_Mesh_ColorPointer(NULL);
1703 // we have a bloom image in the framebuffer
1705 qglViewport(r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
1707 for (x = 1;x < r_bloom_colorexponent.value;)
1710 r = bound(0, r_bloom_colorexponent.value / x, 1);
1711 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
1712 GL_Color(r, r, r, 1);
1713 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
1714 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f);
1715 R_Mesh_Draw(0, 4, 2, polygonelements);
1716 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
1718 // copy the vertically blurred bloom view to a texture
1719 GL_ActiveTexture(0);
1721 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
1722 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
1725 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
1726 brighten = r_bloom_brighten.value;
1728 brighten *= r_hdr_range.value;
1729 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
1730 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f);
1732 for (dir = 0;dir < 2;dir++)
1734 // blend on at multiple vertical offsets to achieve a vertical blur
1735 // TODO: do offset blends using GLSL
1736 GL_BlendFunc(GL_ONE, GL_ZERO);
1737 for (x = -range;x <= range;x++)
1739 if (!dir){xoffset = 0;yoffset = x;}
1740 else {xoffset = x;yoffset = 0;}
1741 xoffset /= (float)r_bloomstate.bloomtexturewidth;
1742 yoffset /= (float)r_bloomstate.bloomtextureheight;
1743 // compute a texcoord array with the specified x and y offset
1744 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
1745 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
1746 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
1747 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
1748 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
1749 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
1750 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
1751 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
1752 // this r value looks like a 'dot' particle, fading sharply to
1753 // black at the edges
1754 // (probably not realistic but looks good enough)
1755 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
1756 //r = (dir ? 1.0f : brighten)/(range*2+1);
1757 r = (dir ? 1.0f : brighten)/(range*2+1)*(1 - x*x/(float)(range*range));
1758 GL_Color(r, r, r, 1);
1759 R_Mesh_Draw(0, 4, 2, polygonelements);
1760 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
1761 GL_BlendFunc(GL_ONE, GL_ONE);
1764 // copy the vertically blurred bloom view to a texture
1765 GL_ActiveTexture(0);
1767 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
1768 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
1771 // apply subtract last
1772 // (just like it would be in a GLSL shader)
1773 if (r_bloom_colorsubtract.value > 0 && gl_support_ext_blend_subtract)
1775 GL_BlendFunc(GL_ONE, GL_ZERO);
1776 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
1777 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f);
1778 GL_Color(1, 1, 1, 1);
1779 R_Mesh_Draw(0, 4, 2, polygonelements);
1780 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
1782 GL_BlendFunc(GL_ONE, GL_ONE);
1783 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
1784 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
1785 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f);
1786 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
1787 R_Mesh_Draw(0, 4, 2, polygonelements);
1788 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
1789 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
1791 // copy the darkened bloom view to a texture
1792 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
1793 GL_ActiveTexture(0);
1795 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
1796 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
1800 void R_HDR_RenderBloomTexture(void)
1802 int oldwidth, oldheight;
1804 oldwidth = r_view.width;
1805 oldheight = r_view.height;
1806 r_view.width = r_bloomstate.bloomwidth;
1807 r_view.height = r_bloomstate.bloomheight;
1809 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
1810 // TODO: add exposure compensation features
1811 // TODO: add fp16 framebuffer support
1813 r_view.colorscale = r_bloom_colorscale.value * r_hdr_scenebrightness.value;
1815 r_view.colorscale /= r_hdr_range.value;
1818 R_ResetViewRendering2D();
1820 R_Bloom_CopyHDRTexture();
1821 R_Bloom_MakeTexture();
1823 R_ResetViewRendering3D();
1826 if (r_timereport_active)
1827 R_TimeReport("clear");
1830 // restore the view settings
1831 r_view.width = oldwidth;
1832 r_view.height = oldheight;
1835 static void R_BlendView(void)
1837 if (r_bloomstate.enabled && r_bloomstate.hdr)
1839 // render high dynamic range bloom effect
1840 // the bloom texture was made earlier this render, so we just need to
1841 // blend it onto the screen...
1842 R_ResetViewRendering2D();
1843 R_Mesh_VertexPointer(r_screenvertex3f);
1844 R_Mesh_ColorPointer(NULL);
1845 GL_Color(1, 1, 1, 1);
1846 GL_BlendFunc(GL_ONE, GL_ONE);
1847 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
1848 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f);
1849 R_Mesh_Draw(0, 4, 2, polygonelements);
1850 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
1852 else if (r_bloomstate.enabled)
1854 // render simple bloom effect
1855 // copy the screen and shrink it and darken it for the bloom process
1856 R_Bloom_CopyScreenTexture(r_bloom_colorscale.value);
1857 // make the bloom texture
1858 R_Bloom_MakeTexture();
1859 // put the original screen image back in place and blend the bloom
1861 R_ResetViewRendering2D();
1862 R_Mesh_VertexPointer(r_screenvertex3f);
1863 R_Mesh_ColorPointer(NULL);
1864 GL_Color(1, 1, 1, 1);
1865 GL_BlendFunc(GL_ONE, GL_ZERO);
1866 // do both in one pass if possible
1867 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
1868 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f);
1869 if (r_textureunits.integer >= 2 && gl_combine.integer)
1871 R_Mesh_TexCombine(1, GL_ADD, GL_ADD, 1, 1);
1872 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_screen));
1873 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.screentexcoord2f);
1877 R_Mesh_Draw(0, 4, 2, polygonelements);
1878 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
1879 // now blend on the bloom texture
1880 GL_BlendFunc(GL_ONE, GL_ONE);
1881 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
1882 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f);
1884 R_Mesh_Draw(0, 4, 2, polygonelements);
1885 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
1887 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
1889 // apply a color tint to the whole view
1890 R_ResetViewRendering2D();
1891 R_Mesh_VertexPointer(r_screenvertex3f);
1892 R_Mesh_ColorPointer(NULL);
1893 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1894 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
1895 R_Mesh_Draw(0, 4, 2, polygonelements);
1899 void R_RenderScene(void);
1901 matrix4x4_t r_waterscrollmatrix;
1903 void R_UpdateVariables(void)
1907 r_refdef.farclip = 4096;
1908 if (r_refdef.worldmodel)
1909 r_refdef.farclip += VectorDistance(r_refdef.worldmodel->normalmins, r_refdef.worldmodel->normalmaxs);
1910 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
1912 r_refdef.polygonfactor = 0;
1913 r_refdef.polygonoffset = 0;
1914 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_shadow_polygonfactor.value;
1915 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_shadow_polygonoffset.value;
1917 r_refdef.rtworld = r_shadow_realtime_world.integer;
1918 r_refdef.rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
1919 r_refdef.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer;
1920 r_refdef.rtdlightshadows = r_refdef.rtdlight && (r_refdef.rtworld ? r_shadow_realtime_world_dlightshadows.integer : r_shadow_realtime_dlight_shadows.integer) && gl_stencil;
1921 r_refdef.lightmapintensity = r_refdef.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
1922 if (r_showsurfaces.integer)
1924 r_refdef.rtworld = false;
1925 r_refdef.rtworldshadows = false;
1926 r_refdef.rtdlight = false;
1927 r_refdef.rtdlightshadows = false;
1928 r_refdef.lightmapintensity = 0;
1931 if (gamemode == GAME_NEHAHRA)
1933 if (gl_fogenable.integer)
1935 r_refdef.oldgl_fogenable = true;
1936 r_refdef.fog_density = gl_fogdensity.value;
1937 r_refdef.fog_red = gl_fogred.value;
1938 r_refdef.fog_green = gl_foggreen.value;
1939 r_refdef.fog_blue = gl_fogblue.value;
1941 else if (r_refdef.oldgl_fogenable)
1943 r_refdef.oldgl_fogenable = false;
1944 r_refdef.fog_density = 0;
1945 r_refdef.fog_red = 0;
1946 r_refdef.fog_green = 0;
1947 r_refdef.fog_blue = 0;
1950 if (r_refdef.fog_density)
1952 r_refdef.fogcolor[0] = bound(0.0f, r_refdef.fog_red , 1.0f);
1953 r_refdef.fogcolor[1] = bound(0.0f, r_refdef.fog_green, 1.0f);
1954 r_refdef.fogcolor[2] = bound(0.0f, r_refdef.fog_blue , 1.0f);
1956 if (r_refdef.fog_density)
1958 r_refdef.fogenabled = true;
1959 // this is the point where the fog reaches 0.9986 alpha, which we
1960 // consider a good enough cutoff point for the texture
1961 // (0.9986 * 256 == 255.6)
1962 r_refdef.fogrange = 400 / r_refdef.fog_density;
1963 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
1964 r_refdef.fogtabledistmultiplier = FOGTABLEWIDTH * r_refdef.fograngerecip;
1965 // fog color was already set
1968 r_refdef.fogenabled = false;
1976 void R_RenderView(void)
1978 if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
1979 return; //Host_Error ("R_RenderView: NULL worldmodel");
1981 R_Shadow_UpdateWorldLightSelection();
1984 if (r_timereport_active)
1985 R_TimeReport("setup");
1988 if (r_timereport_active)
1989 R_TimeReport("visibility");
1991 R_ResetViewRendering3D();
1994 if (r_timereport_active)
1995 R_TimeReport("clear");
1997 R_Bloom_StartFrame();
1999 // this produces a bloom texture to be used in R_BlendView() later
2001 R_HDR_RenderBloomTexture();
2003 r_view.colorscale = r_hdr_scenebrightness.value;
2007 if (r_timereport_active)
2008 R_TimeReport("blendview");
2010 GL_Scissor(0, 0, vid.width, vid.height);
2011 GL_ScissorTest(false);
2015 extern void R_DrawLightningBeams (void);
2016 extern void VM_AddPolygonsToMeshQueue (void);
2017 extern void R_DrawPortals (void);
2018 void R_RenderScene(void)
2020 // don't let sound skip if going slow
2021 if (r_refdef.extraupdate)
2024 R_ResetViewRendering3D();
2026 R_MeshQueue_BeginScene();
2030 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);
2032 if (cl.csqc_vidvars.drawworld)
2034 // don't let sound skip if going slow
2035 if (r_refdef.extraupdate)
2038 if (r_refdef.worldmodel && r_refdef.worldmodel->DrawSky)
2040 r_refdef.worldmodel->DrawSky(r_refdef.worldentity);
2041 if (r_timereport_active)
2042 R_TimeReport("worldsky");
2045 if (R_DrawBrushModelsSky() && r_timereport_active)
2046 R_TimeReport("bmodelsky");
2048 if (r_refdef.worldmodel && r_refdef.worldmodel->Draw)
2050 r_refdef.worldmodel->Draw(r_refdef.worldentity);
2051 if (r_timereport_active)
2052 R_TimeReport("world");
2056 // don't let sound skip if going slow
2057 if (r_refdef.extraupdate)
2061 if (r_timereport_active)
2062 R_TimeReport("models");
2064 // don't let sound skip if going slow
2065 if (r_refdef.extraupdate)
2068 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
2070 R_DrawModelShadows();
2072 R_ResetViewRendering3D();
2074 // don't let sound skip if going slow
2075 if (r_refdef.extraupdate)
2079 R_ShadowVolumeLighting(false);
2080 if (r_timereport_active)
2081 R_TimeReport("rtlights");
2083 // don't let sound skip if going slow
2084 if (r_refdef.extraupdate)
2087 if (cl.csqc_vidvars.drawworld)
2089 R_DrawLightningBeams();
2090 if (r_timereport_active)
2091 R_TimeReport("lightning");
2094 if (r_timereport_active)
2095 R_TimeReport("particles");
2098 if (r_timereport_active)
2099 R_TimeReport("explosions");
2102 if (gl_support_fragment_shader)
2104 qglUseProgramObjectARB(0);CHECKGLERROR
2106 VM_AddPolygonsToMeshQueue();
2108 if (r_drawportals.integer)
2111 if (r_timereport_active)
2112 R_TimeReport("portals");
2115 if (gl_support_fragment_shader)
2117 qglUseProgramObjectARB(0);CHECKGLERROR
2119 R_MeshQueue_RenderTransparent();
2120 if (r_timereport_active)
2121 R_TimeReport("drawtrans");
2123 if (gl_support_fragment_shader)
2125 qglUseProgramObjectARB(0);CHECKGLERROR
2128 if (cl.csqc_vidvars.drawworld)
2131 if (r_timereport_active)
2132 R_TimeReport("coronas");
2135 // don't let sound skip if going slow
2136 if (r_refdef.extraupdate)
2139 R_ResetViewRendering2D();
2143 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
2146 float *v, *c, f1, f2, diff[3], vertex3f[8*3], color4f[8*4];
2147 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2148 GL_DepthMask(false);
2150 R_Mesh_Matrix(&identitymatrix);
2152 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2];
2153 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
2154 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
2155 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
2156 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
2157 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
2158 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
2159 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
2160 R_FillColors(color, 8, cr, cg, cb, ca);
2161 if (r_refdef.fogenabled)
2163 for (i = 0, v = vertex, c = color;i < 8;i++, v += 4, c += 4)
2165 f2 = VERTEXFOGTABLE(VectorDistance(v, r_view.origin));
2167 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
2168 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
2169 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
2172 R_Mesh_VertexPointer(vertex3f);
2173 R_Mesh_ColorPointer(color);
2174 R_Mesh_ResetTextureState();
2179 int nomodelelements[24] =
2191 float nomodelvertex3f[6*3] =
2201 float nomodelcolor4f[6*4] =
2203 0.0f, 0.0f, 0.5f, 1.0f,
2204 0.0f, 0.0f, 0.5f, 1.0f,
2205 0.0f, 0.5f, 0.0f, 1.0f,
2206 0.0f, 0.5f, 0.0f, 1.0f,
2207 0.5f, 0.0f, 0.0f, 1.0f,
2208 0.5f, 0.0f, 0.0f, 1.0f
2211 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
2216 // this is only called once per entity so numsurfaces is always 1, and
2217 // surfacelist is always {0}, so this code does not handle batches
2218 R_Mesh_Matrix(&ent->matrix);
2220 if (ent->flags & EF_ADDITIVE)
2222 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2223 GL_DepthMask(false);
2225 else if (ent->alpha < 1)
2227 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2228 GL_DepthMask(false);
2232 GL_BlendFunc(GL_ONE, GL_ZERO);
2235 GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
2236 GL_CullFace((ent->flags & RENDER_NOCULLFACE) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
2237 R_Mesh_VertexPointer(nomodelvertex3f);
2238 if (r_refdef.fogenabled)
2241 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
2242 R_Mesh_ColorPointer(color4f);
2243 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
2244 f2 = VERTEXFOGTABLE(VectorDistance(org, r_view.origin));
2246 for (i = 0, c = color4f;i < 6;i++, c += 4)
2248 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
2249 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
2250 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
2254 else if (ent->alpha != 1)
2256 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
2257 R_Mesh_ColorPointer(color4f);
2258 for (i = 0, c = color4f;i < 6;i++, c += 4)
2262 R_Mesh_ColorPointer(nomodelcolor4f);
2263 R_Mesh_ResetTextureState();
2264 R_Mesh_Draw(0, 6, 8, nomodelelements);
2267 void R_DrawNoModel(entity_render_t *ent)
2270 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
2271 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
2272 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, r_shadow_rtlight);
2274 // R_DrawNoModelCallback(ent, 0);
2277 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
2279 vec3_t right1, right2, diff, normal;
2281 VectorSubtract (org2, org1, normal);
2283 // calculate 'right' vector for start
2284 VectorSubtract (r_view.origin, org1, diff);
2285 CrossProduct (normal, diff, right1);
2286 VectorNormalize (right1);
2288 // calculate 'right' vector for end
2289 VectorSubtract (r_view.origin, org2, diff);
2290 CrossProduct (normal, diff, right2);
2291 VectorNormalize (right2);
2293 vert[ 0] = org1[0] + width * right1[0];
2294 vert[ 1] = org1[1] + width * right1[1];
2295 vert[ 2] = org1[2] + width * right1[2];
2296 vert[ 3] = org1[0] - width * right1[0];
2297 vert[ 4] = org1[1] - width * right1[1];
2298 vert[ 5] = org1[2] - width * right1[2];
2299 vert[ 6] = org2[0] - width * right2[0];
2300 vert[ 7] = org2[1] - width * right2[1];
2301 vert[ 8] = org2[2] - width * right2[2];
2302 vert[ 9] = org2[0] + width * right2[0];
2303 vert[10] = org2[1] + width * right2[1];
2304 vert[11] = org2[2] + width * right2[2];
2307 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
2309 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)
2311 float fog = 0.0f, ifog;
2314 if (r_refdef.fogenabled)
2315 fog = VERTEXFOGTABLE(VectorDistance(origin, r_view.origin));
2318 R_Mesh_Matrix(&identitymatrix);
2319 GL_BlendFunc(blendfunc1, blendfunc2);
2320 GL_DepthMask(false);
2321 GL_DepthTest(!depthdisable);
2323 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
2324 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
2325 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
2326 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
2327 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
2328 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
2329 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
2330 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
2331 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
2332 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
2333 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
2334 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
2336 R_Mesh_VertexPointer(vertex3f);
2337 R_Mesh_ColorPointer(NULL);
2338 R_Mesh_ResetTextureState();
2339 R_Mesh_TexBind(0, R_GetTexture(texture));
2340 R_Mesh_TexCoordPointer(0, 2, spritetexcoord2f);
2341 // FIXME: fixed function path can't properly handle r_view.colorscale > 1
2342 GL_Color(cr * ifog * r_view.colorscale, cg * ifog * r_view.colorscale, cb * ifog * r_view.colorscale, ca);
2343 R_Mesh_Draw(0, 4, 2, polygonelements);
2345 if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
2347 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
2348 GL_BlendFunc(blendfunc1, GL_ONE);
2349 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);
2350 R_Mesh_Draw(0, 4, 2, polygonelements);
2354 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
2359 VectorSet(v, x, y, z);
2360 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
2361 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
2363 if (i == mesh->numvertices)
2365 if (mesh->numvertices < mesh->maxvertices)
2367 VectorCopy(v, vertex3f);
2368 mesh->numvertices++;
2370 return mesh->numvertices;
2376 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
2380 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
2381 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
2382 e = mesh->element3i + mesh->numtriangles * 3;
2383 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
2385 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
2386 if (mesh->numtriangles < mesh->maxtriangles)
2391 mesh->numtriangles++;
2393 element[1] = element[2];
2397 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
2401 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
2402 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
2403 e = mesh->element3i + mesh->numtriangles * 3;
2404 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
2406 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
2407 if (mesh->numtriangles < mesh->maxtriangles)
2412 mesh->numtriangles++;
2414 element[1] = element[2];
2418 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
2419 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
2421 int planenum, planenum2;
2424 mplane_t *plane, *plane2;
2426 double temppoints[2][256*3];
2427 // figure out how large a bounding box we need to properly compute this brush
2429 for (w = 0;w < numplanes;w++)
2430 maxdist = max(maxdist, planes[w].dist);
2431 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
2432 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
2433 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
2437 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
2438 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
2440 if (planenum2 == planenum)
2442 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);
2445 if (tempnumpoints < 3)
2447 // generate elements forming a triangle fan for this polygon
2448 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
2452 static void R_DrawCollisionBrush(const colbrushf_t *brush)
2455 R_Mesh_VertexPointer(brush->points->v);
2456 i = (int)(((size_t)brush) / sizeof(colbrushf_t));
2457 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);
2458 GL_LockArrays(0, brush->numpoints);
2459 R_Mesh_Draw(0, brush->numpoints, brush->numtriangles, brush->elements);
2460 GL_LockArrays(0, 0);
2463 static void R_DrawCollisionSurface(const entity_render_t *ent, const msurface_t *surface)
2466 if (!surface->num_collisiontriangles)
2468 R_Mesh_VertexPointer(surface->data_collisionvertex3f);
2469 i = (int)(((size_t)surface) / sizeof(msurface_t));
2470 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);
2471 GL_LockArrays(0, surface->num_collisionvertices);
2472 R_Mesh_Draw(0, surface->num_collisionvertices, surface->num_collisiontriangles, surface->data_collisionelement3i);
2473 GL_LockArrays(0, 0);
2476 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)
2478 texturelayer_t *layer;
2479 layer = t->currentlayers + t->currentnumlayers++;
2481 layer->depthmask = depthmask;
2482 layer->blendfunc1 = blendfunc1;
2483 layer->blendfunc2 = blendfunc2;
2484 layer->texture = texture;
2485 layer->texmatrix = *matrix;
2486 layer->color[0] = r * r_view.colorscale;
2487 layer->color[1] = g * r_view.colorscale;
2488 layer->color[2] = b * r_view.colorscale;
2489 layer->color[3] = a;
2492 void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
2494 model_t *model = ent->model;
2496 // FIXME: identify models using a better check than ent->model->brush.shadowmesh
2497 //int lightmode = ((ent->effects & EF_FULLBRIGHT) || ent->model->brush.shadowmesh) ? 0 : 2;
2499 // switch to an alternate material if this is a q1bsp animated material
2501 texture_t *texture = t;
2502 int s = ent->skinnum;
2503 if ((unsigned int)s >= (unsigned int)model->numskins)
2505 if (model->skinscenes)
2507 if (model->skinscenes[s].framecount > 1)
2508 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
2510 s = model->skinscenes[s].firstframe;
2513 t = t + s * model->num_surfaces;
2516 // use an alternate animation if the entity's frame is not 0,
2517 // and only if the texture has an alternate animation
2518 if (ent->frame != 0 && t->anim_total[1])
2519 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.time * 5.0f) % t->anim_total[1]) : 0];
2521 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.time * 5.0f) % t->anim_total[0]) : 0];
2523 texture->currentframe = t;
2526 // pick a new currentskinframe if the material is animated
2527 if (t->numskinframes >= 2)
2528 t->currentskinframe = t->skinframes + ((int)(t->skinframerate * (cl.time - ent->frame2time)) % t->numskinframes);
2530 t->currentmaterialflags = t->basematerialflags;
2531 t->currentalpha = ent->alpha;
2532 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
2533 t->currentalpha *= r_wateralpha.value;
2534 if (!(ent->flags & RENDER_LIGHT))
2535 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
2536 if (ent->effects & EF_ADDITIVE)
2537 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_TRANSPARENT;
2538 else if (t->currentalpha < 1)
2539 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_TRANSPARENT;
2540 if (ent->effects & EF_NODEPTHTEST)
2541 t->currentmaterialflags |= MATERIALFLAG_NODEPTHTEST;
2542 if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
2543 t->currenttexmatrix = r_waterscrollmatrix;
2545 t->currenttexmatrix = identitymatrix;
2547 t->colormapping = VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f);
2548 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
2549 t->glosstexture = r_texture_white;
2550 t->specularpower = r_shadow_glossexponent.value;
2551 t->specularscale = 0;
2552 if (r_shadow_gloss.integer > 0)
2554 if (t->currentskinframe->gloss)
2556 if (r_shadow_glossintensity.value > 0)
2558 t->glosstexture = t->currentskinframe->gloss;
2559 t->specularscale = r_shadow_glossintensity.value;
2562 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
2563 t->specularscale = r_shadow_gloss2intensity.value;
2566 t->currentnumlayers = 0;
2567 if (!(t->currentmaterialflags & MATERIALFLAG_NODRAW))
2569 if (gl_lightmaps.integer)
2570 R_Texture_AddLayer(t, true, GL_ONE, GL_ZERO, TEXTURELAYERTYPE_LITTEXTURE, r_texture_white, &identitymatrix, 1, 1, 1, 1);
2571 else if (!(t->currentmaterialflags & MATERIALFLAG_SKY))
2573 int blendfunc1, blendfunc2, depthmask;
2574 if (t->currentmaterialflags & MATERIALFLAG_ADD)
2576 blendfunc1 = GL_SRC_ALPHA;
2577 blendfunc2 = GL_ONE;
2579 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
2581 blendfunc1 = GL_SRC_ALPHA;
2582 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
2584 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
2586 blendfunc1 = t->customblendfunc[0];
2587 blendfunc2 = t->customblendfunc[1];
2591 blendfunc1 = GL_ONE;
2592 blendfunc2 = GL_ZERO;
2594 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
2595 if (t->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL))
2597 rtexture_t *currentbasetexture;
2599 if (r_refdef.fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED))
2600 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
2601 currentbasetexture = (VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) < (1.0f / 1048576.0f) && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
2602 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2604 // fullbright is not affected by r_refdef.lightmapintensity
2605 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
2606 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
2607 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);
2608 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
2609 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);
2615 // q3bsp has no lightmap updates, so the lightstylevalue that
2616 // would normally be baked into the lightmap must be
2617 // applied to the color
2618 if (ent->model->type == mod_brushq3)
2619 colorscale *= r_refdef.lightstylevalue[0] * (1.0f / 256.0f);
2620 colorscale *= r_refdef.lightmapintensity;
2621 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);
2622 if (r_ambient.value >= (1.0f/64.0f))
2623 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);
2624 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
2626 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);
2627 if (r_ambient.value >= (1.0f/64.0f))
2628 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);
2630 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
2632 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);
2633 if (r_ambient.value >= (1.0f/64.0f))
2634 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);
2637 if (t->currentskinframe->glow != NULL)
2638 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);
2639 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
2641 // if this is opaque use alpha blend which will darken the earlier
2644 // if this is an alpha blended material, all the earlier passes
2645 // were darkened by fog already, so we only need to add the fog
2646 // color ontop through the fog mask texture
2648 // if this is an additive blended material, all the earlier passes
2649 // were darkened by fog already, and we should not add fog color
2650 // (because the background was not darkened, there is no fog color
2651 // that was lost behind it).
2652 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);
2659 void R_UpdateAllTextureInfo(entity_render_t *ent)
2663 for (i = 0;i < ent->model->num_textures;i++)
2664 R_UpdateTextureInfo(ent, ent->model->data_textures + i);
2667 int rsurface_array_size = 0;
2668 float *rsurface_array_modelvertex3f = NULL;
2669 float *rsurface_array_modelsvector3f = NULL;
2670 float *rsurface_array_modeltvector3f = NULL;
2671 float *rsurface_array_modelnormal3f = NULL;
2672 float *rsurface_array_deformedvertex3f = NULL;
2673 float *rsurface_array_deformedsvector3f = NULL;
2674 float *rsurface_array_deformedtvector3f = NULL;
2675 float *rsurface_array_deformednormal3f = NULL;
2676 float *rsurface_array_color4f = NULL;
2677 float *rsurface_array_texcoord3f = NULL;
2679 void R_Mesh_ResizeArrays(int newvertices)
2682 if (rsurface_array_size >= newvertices)
2684 if (rsurface_array_modelvertex3f)
2685 Mem_Free(rsurface_array_modelvertex3f);
2686 rsurface_array_size = (newvertices + 1023) & ~1023;
2687 base = (float *)Mem_Alloc(r_main_mempool, rsurface_array_size * sizeof(float[31]));
2688 rsurface_array_modelvertex3f = base + rsurface_array_size * 0;
2689 rsurface_array_modelsvector3f = base + rsurface_array_size * 3;
2690 rsurface_array_modeltvector3f = base + rsurface_array_size * 6;
2691 rsurface_array_modelnormal3f = base + rsurface_array_size * 9;
2692 rsurface_array_deformedvertex3f = base + rsurface_array_size * 12;
2693 rsurface_array_deformedsvector3f = base + rsurface_array_size * 15;
2694 rsurface_array_deformedtvector3f = base + rsurface_array_size * 18;
2695 rsurface_array_deformednormal3f = base + rsurface_array_size * 21;
2696 rsurface_array_texcoord3f = base + rsurface_array_size * 24;
2697 rsurface_array_color4f = base + rsurface_array_size * 27;
2700 float *rsurface_modelvertex3f;
2701 float *rsurface_modelsvector3f;
2702 float *rsurface_modeltvector3f;
2703 float *rsurface_modelnormal3f;
2704 float *rsurface_vertex3f;
2705 float *rsurface_svector3f;
2706 float *rsurface_tvector3f;
2707 float *rsurface_normal3f;
2708 float *rsurface_lightmapcolor4f;
2709 vec3_t rsurface_modelorg;
2710 qboolean rsurface_generatedvertex;
2711 const entity_render_t *rsurface_entity;
2712 const model_t *rsurface_model;
2713 texture_t *rsurface_texture;
2714 rtexture_t *rsurface_lightmaptexture;
2715 rsurfmode_t rsurface_mode;
2716 texture_t *rsurface_glsl_texture;
2717 qboolean rsurface_glsl_uselightmap;
2719 void RSurf_CleanUp(void)
2722 if (rsurface_mode == RSURFMODE_GLSL)
2724 qglUseProgramObjectARB(0);CHECKGLERROR
2726 GL_AlphaTest(false);
2727 rsurface_mode = RSURFMODE_NONE;
2728 rsurface_lightmaptexture = NULL;
2729 rsurface_texture = NULL;
2730 rsurface_glsl_texture = NULL;
2731 rsurface_glsl_uselightmap = false;
2734 void RSurf_ActiveEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
2737 Matrix4x4_Transform(&ent->inversematrix, r_view.origin, rsurface_modelorg);
2738 rsurface_entity = ent;
2739 rsurface_model = ent->model;
2740 if (rsurface_array_size < rsurface_model->surfmesh.num_vertices)
2741 R_Mesh_ResizeArrays(rsurface_model->surfmesh.num_vertices);
2742 R_Mesh_Matrix(&ent->matrix);
2743 Matrix4x4_Transform(&ent->inversematrix, r_view.origin, rsurface_modelorg);
2744 if ((rsurface_entity->frameblend[0].lerp != 1 || rsurface_entity->frameblend[0].frame != 0) && rsurface_model->surfmesh.isanimated)
2748 rsurface_modelvertex3f = rsurface_array_modelvertex3f;
2749 rsurface_modelsvector3f = rsurface_array_modelsvector3f;
2750 rsurface_modeltvector3f = rsurface_array_modeltvector3f;
2751 rsurface_modelnormal3f = rsurface_array_modelnormal3f;
2752 Mod_Alias_GetMesh_Vertices(rsurface_model, rsurface_entity->frameblend, rsurface_array_modelvertex3f, rsurface_array_modelnormal3f, rsurface_array_modelsvector3f, rsurface_array_modeltvector3f);
2754 else if (wantnormals)
2756 rsurface_modelvertex3f = rsurface_array_modelvertex3f;
2757 rsurface_modelsvector3f = NULL;
2758 rsurface_modeltvector3f = NULL;
2759 rsurface_modelnormal3f = rsurface_array_modelnormal3f;
2760 Mod_Alias_GetMesh_Vertices(rsurface_model, rsurface_entity->frameblend, rsurface_array_modelvertex3f, rsurface_array_modelnormal3f, NULL, NULL);
2764 rsurface_modelvertex3f = rsurface_array_modelvertex3f;
2765 rsurface_modelsvector3f = NULL;
2766 rsurface_modeltvector3f = NULL;
2767 rsurface_modelnormal3f = NULL;
2768 Mod_Alias_GetMesh_Vertices(rsurface_model, rsurface_entity->frameblend, rsurface_array_modelvertex3f, NULL, NULL, NULL);
2770 rsurface_generatedvertex = true;
2774 rsurface_modelvertex3f = rsurface_model->surfmesh.data_vertex3f;
2775 rsurface_modelsvector3f = rsurface_model->surfmesh.data_svector3f;
2776 rsurface_modeltvector3f = rsurface_model->surfmesh.data_tvector3f;
2777 rsurface_modelnormal3f = rsurface_model->surfmesh.data_normal3f;
2778 rsurface_generatedvertex = false;
2780 rsurface_vertex3f = rsurface_modelvertex3f;
2781 rsurface_svector3f = rsurface_modelsvector3f;
2782 rsurface_tvector3f = rsurface_modeltvector3f;
2783 rsurface_normal3f = rsurface_modelnormal3f;
2786 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, msurface_t **texturesurfacelist)
2788 // 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
2789 if (rsurface_generatedvertex)
2791 if (rsurface_texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
2792 generatetangents = true;
2793 if (generatetangents)
2794 generatenormals = true;
2795 if (generatenormals && !rsurface_modelnormal3f)
2797 rsurface_normal3f = rsurface_modelnormal3f = rsurface_array_modelnormal3f;
2798 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);
2800 if (generatetangents && !rsurface_modelsvector3f)
2802 rsurface_svector3f = rsurface_modelsvector3f = rsurface_array_modelsvector3f;
2803 rsurface_tvector3f = rsurface_modeltvector3f = rsurface_array_modeltvector3f;
2804 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);
2807 // 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)
2808 if (rsurface_texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
2810 int texturesurfaceindex;
2811 float center[3], forward[3], right[3], up[3], v[4][3];
2812 matrix4x4_t matrix1, imatrix1;
2813 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_view.forward, forward);
2814 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_view.right, right);
2815 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_view.up, up);
2816 // make deformed versions of only the model vertices used by the specified surfaces
2817 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2820 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2821 // a single autosprite surface can contain multiple sprites...
2822 for (j = 0;j < surface->num_vertices - 3;j += 4)
2824 VectorClear(center);
2825 for (i = 0;i < 4;i++)
2826 VectorAdd(center, (rsurface_modelvertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
2827 VectorScale(center, 0.25f, center);
2828 if (rsurface_texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE2)
2830 forward[0] = rsurface_modelorg[0] - center[0];
2831 forward[1] = rsurface_modelorg[1] - center[1];
2833 VectorNormalize(forward);
2834 right[0] = forward[1];
2835 right[1] = -forward[0];
2837 VectorSet(up, 0, 0, 1);
2839 // FIXME: calculate vectors from triangle edges instead of using texture vectors as an easy way out?
2840 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);
2841 Matrix4x4_Invert_Simple(&imatrix1, &matrix1);
2842 for (i = 0;i < 4;i++)
2843 Matrix4x4_Transform(&imatrix1, (rsurface_modelvertex3f + 3 * surface->num_firstvertex) + (j+i)*3, v[i]);
2844 for (i = 0;i < 4;i++)
2845 VectorMAMAMAM(1, center, v[i][0], forward, v[i][1], right, v[i][2], up, rsurface_array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
2847 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);
2848 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);
2850 rsurface_vertex3f = rsurface_array_deformedvertex3f;
2851 rsurface_svector3f = rsurface_array_deformedsvector3f;
2852 rsurface_tvector3f = rsurface_array_deformedtvector3f;
2853 rsurface_normal3f = rsurface_array_deformednormal3f;
2857 rsurface_vertex3f = rsurface_modelvertex3f;
2858 rsurface_svector3f = rsurface_modelsvector3f;
2859 rsurface_tvector3f = rsurface_modeltvector3f;
2860 rsurface_normal3f = rsurface_modelnormal3f;
2862 R_Mesh_VertexPointer(rsurface_vertex3f);
2865 void RSurf_DrawBatch_Simple(int texturenumsurfaces, msurface_t **texturesurfacelist)
2867 int texturesurfaceindex;
2868 const msurface_t *surface = texturesurfacelist[0];
2869 int firstvertex = surface->num_firstvertex;
2870 int endvertex = surface->num_firstvertex + surface->num_vertices;
2871 if (texturenumsurfaces == 1)
2873 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2874 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
2876 else if (r_batchmode.integer == 2)
2878 #define MAXBATCHTRIANGLES 4096
2879 int batchtriangles = 0;
2880 int batchelements[MAXBATCHTRIANGLES*3];
2881 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2883 surface = texturesurfacelist[texturesurfaceindex];
2884 if (surface->num_triangles >= 256 || (batchtriangles == 0 && texturesurfaceindex + 1 >= texturenumsurfaces))
2886 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
2889 if (batchtriangles + surface->num_triangles > MAXBATCHTRIANGLES)
2891 R_Mesh_Draw(firstvertex, endvertex - firstvertex, batchtriangles, batchelements);
2893 firstvertex = surface->num_firstvertex;
2894 endvertex = surface->num_firstvertex + surface->num_vertices;
2898 firstvertex = min(firstvertex, surface->num_firstvertex);
2899 endvertex = max(endvertex, surface->num_firstvertex + surface->num_vertices);
2901 memcpy(batchelements + batchtriangles * 3, rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
2902 batchtriangles += surface->num_triangles;
2905 R_Mesh_Draw(firstvertex, endvertex - firstvertex, batchtriangles, batchelements);
2907 else if (r_batchmode.integer == 1)
2909 int firsttriangle = 0;
2910 int endtriangle = -1;
2911 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2913 surface = texturesurfacelist[texturesurfaceindex];
2914 if (surface->num_firsttriangle != endtriangle)
2916 if (endtriangle > firsttriangle)
2918 GL_LockArrays(firstvertex, endvertex - firstvertex);
2919 R_Mesh_Draw(firstvertex, endvertex - firstvertex, endtriangle - firsttriangle, (rsurface_model->surfmesh.data_element3i + 3 * firsttriangle));
2921 firstvertex = surface->num_firstvertex;
2922 endvertex = surface->num_firstvertex + surface->num_vertices;
2923 firsttriangle = surface->num_firsttriangle;
2927 firstvertex = min(firstvertex, surface->num_firstvertex);
2928 endvertex = max(endvertex, surface->num_firstvertex + surface->num_vertices);
2930 endtriangle = surface->num_firsttriangle + surface->num_triangles;
2932 if (endtriangle > firsttriangle)
2934 GL_LockArrays(firstvertex, endvertex - firstvertex);
2935 R_Mesh_Draw(firstvertex, endvertex - firstvertex, endtriangle - firsttriangle, (rsurface_model->surfmesh.data_element3i + 3 * firsttriangle));
2940 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2942 surface = texturesurfacelist[texturesurfaceindex];
2943 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2944 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
2949 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
2951 int texturesurfaceindex;
2952 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2954 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2955 int k = (int)(((size_t)surface) / sizeof(msurface_t));
2956 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, 0.2f);
2957 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2958 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
2962 static void RSurf_DrawBatch_Lightmap(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, int lightmode, qboolean applycolor, qboolean applyfog)
2964 int texturesurfaceindex;
2972 vec3_t ambientcolor;
2973 vec3_t diffusecolor;
2975 VectorCopy(rsurface_entity->modellight_lightdir, lightdir);
2976 ambientcolor[0] = rsurface_entity->modellight_ambient[0] * r * 0.5f;
2977 ambientcolor[1] = rsurface_entity->modellight_ambient[1] * g * 0.5f;
2978 ambientcolor[2] = rsurface_entity->modellight_ambient[2] * b * 0.5f;
2979 diffusecolor[0] = rsurface_entity->modellight_diffuse[0] * r * 0.5f;
2980 diffusecolor[1] = rsurface_entity->modellight_diffuse[1] * g * 0.5f;
2981 diffusecolor[2] = rsurface_entity->modellight_diffuse[2] * b * 0.5f;
2982 if (VectorLength2(diffusecolor) > 0)
2984 // generate color arrays for the surfaces in this list
2985 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2987 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2988 int numverts = surface->num_vertices;
2989 v = rsurface_vertex3f + 3 * surface->num_firstvertex;
2990 c2 = rsurface_normal3f + 3 * surface->num_firstvertex;
2991 c = rsurface_array_color4f + 4 * surface->num_firstvertex;
2992 // q3-style directional shading
2993 for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
2995 if ((f = DotProduct(c2, lightdir)) > 0)
2996 VectorMA(ambientcolor, f, diffusecolor, c);
2998 VectorCopy(ambientcolor, c);
3007 rsurface_lightmapcolor4f = rsurface_array_color4f;
3011 r = ambientcolor[0];
3012 g = ambientcolor[1];
3013 b = ambientcolor[2];
3014 rsurface_lightmapcolor4f = NULL;
3017 else if (lightmode >= 1 || !rsurface_lightmaptexture)
3019 if (texturesurfacelist[0]->lightmapinfo && texturesurfacelist[0]->lightmapinfo->stainsamples)
3021 // generate color arrays for the surfaces in this list
3022 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3024 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3025 for (i = 0, c = rsurface_array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
3027 if (surface->lightmapinfo->samples)
3029 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface_model->surfmesh.data_lightmapoffsets + surface->num_firstvertex)[i];
3030 float scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
3031 VectorScale(lm, scale, c);
3032 if (surface->lightmapinfo->styles[1] != 255)
3034 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
3036 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
3037 VectorMA(c, scale, lm, c);
3038 if (surface->lightmapinfo->styles[2] != 255)
3041 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
3042 VectorMA(c, scale, lm, c);
3043 if (surface->lightmapinfo->styles[3] != 255)
3046 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
3047 VectorMA(c, scale, lm, c);
3057 rsurface_lightmapcolor4f = rsurface_array_color4f;
3060 rsurface_lightmapcolor4f = rsurface_model->surfmesh.data_lightmapcolor4f;
3065 rsurface_lightmapcolor4f = NULL;
3069 if (rsurface_lightmapcolor4f)
3071 // generate color arrays for the surfaces in this list
3072 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3074 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3075 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)
3077 f = 1 - VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
3087 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3089 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3090 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)
3092 f = 1 - VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
3100 rsurface_lightmapcolor4f = rsurface_array_color4f;
3102 if (applycolor && rsurface_lightmapcolor4f)
3104 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3106 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3107 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)
3115 rsurface_lightmapcolor4f = rsurface_array_color4f;
3117 R_Mesh_ColorPointer(rsurface_lightmapcolor4f);
3118 GL_Color(r, g, b, a);
3119 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3122 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
3124 if (rsurface_mode != RSURFMODE_SHOWSURFACES)
3126 rsurface_mode = RSURFMODE_SHOWSURFACES;
3128 GL_BlendFunc(GL_ONE, GL_ZERO);
3129 R_Mesh_ColorPointer(NULL);
3130 R_Mesh_ResetTextureState();
3132 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
3133 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
3136 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, msurface_t **texturesurfacelist)
3138 // transparent sky would be ridiculous
3139 if ((rsurface_texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
3141 if (rsurface_mode != RSURFMODE_SKY)
3143 if (rsurface_mode == RSURFMODE_GLSL)
3145 qglUseProgramObjectARB(0);CHECKGLERROR
3147 rsurface_mode = RSURFMODE_SKY;
3151 skyrendernow = false;
3153 // restore entity matrix
3154 R_Mesh_Matrix(&rsurface_entity->matrix);
3157 // LordHavoc: HalfLife maps have freaky skypolys so don't use
3158 // skymasking on them, and Quake3 never did sky masking (unlike
3159 // software Quake and software Quake2), so disable the sky masking
3160 // in Quake3 maps as it causes problems with q3map2 sky tricks,
3161 // and skymasking also looks very bad when noclipping outside the
3162 // level, so don't use it then either.
3163 if (rsurface_model->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_viewcache.world_novis)
3165 GL_Color(r_refdef.fogcolor[0] * r_view.colorscale, r_refdef.fogcolor[1] * r_view.colorscale, r_refdef.fogcolor[2] * r_view.colorscale, 1);
3166 R_Mesh_ColorPointer(NULL);
3167 R_Mesh_ResetTextureState();
3168 if (skyrendermasked)
3170 // depth-only (masking)
3171 GL_ColorMask(0,0,0,0);
3172 // just to make sure that braindead drivers don't draw
3173 // anything despite that colormask...
3174 GL_BlendFunc(GL_ZERO, GL_ONE);
3179 GL_BlendFunc(GL_ONE, GL_ZERO);
3181 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
3182 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3183 if (skyrendermasked)
3184 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
3188 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, msurface_t **texturesurfacelist)
3191 // FIXME: identify models using a better check than rsurface_model->brush.shadowmesh
3192 lightmode = ((rsurface_entity->effects & EF_FULLBRIGHT) || rsurface_model->brush.shadowmesh) ? 0 : 2;
3193 if (rsurface_mode != RSURFMODE_GLSL)
3195 rsurface_mode = RSURFMODE_GLSL;
3196 rsurface_glsl_texture = NULL;
3197 rsurface_glsl_uselightmap = false;
3198 R_Mesh_ResetTextureState();
3200 if (rsurface_glsl_texture != rsurface_texture || rsurface_glsl_uselightmap != (rsurface_lightmaptexture != NULL))
3202 rsurface_glsl_texture = rsurface_texture;
3203 rsurface_glsl_uselightmap = rsurface_lightmaptexture != NULL;
3204 GL_BlendFunc(rsurface_texture->currentlayers[0].blendfunc1, rsurface_texture->currentlayers[0].blendfunc2);
3205 GL_DepthMask(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_BLENDED));
3206 GL_Color(rsurface_entity->colormod[0], rsurface_entity->colormod[1], rsurface_entity->colormod[2], rsurface_texture->currentalpha);
3207 R_SetupSurfaceShader(vec3_origin, lightmode == 2);
3208 //permutation_deluxemapping = permutation_lightmapping = R_SetupSurfaceShader(vec3_origin, lightmode == 2, false);
3209 //if (r_glsl_deluxemapping.integer)
3210 // permutation_deluxemapping = R_SetupSurfaceShader(vec3_origin, lightmode == 2, true);
3211 R_Mesh_TexCoordPointer(0, 2, rsurface_model->surfmesh.data_texcoordtexture2f);
3212 R_Mesh_TexCoordPointer(4, 2, rsurface_model->surfmesh.data_texcoordlightmap2f);
3213 GL_AlphaTest((rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
3215 if (!r_glsl_permutation)
3217 RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
3218 R_Mesh_TexCoordPointer(1, 3, rsurface_svector3f);
3219 R_Mesh_TexCoordPointer(2, 3, rsurface_tvector3f);
3220 R_Mesh_TexCoordPointer(3, 3, rsurface_normal3f);
3221 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
3223 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
3224 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
3225 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
3226 R_Mesh_ColorPointer(NULL);
3228 else if (rsurface_lightmaptexture)
3230 R_Mesh_TexBind(7, R_GetTexture(rsurface_lightmaptexture));
3231 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
3232 R_Mesh_TexBind(8, R_GetTexture(texturesurfacelist[0]->deluxemaptexture));
3233 R_Mesh_ColorPointer(NULL);
3237 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
3238 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
3239 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
3240 R_Mesh_ColorPointer(rsurface_model->surfmesh.data_lightmapcolor4f);
3242 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3245 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, msurface_t **texturesurfacelist)
3247 // OpenGL 1.3 path - anything not completely ancient
3248 int texturesurfaceindex;
3250 qboolean applycolor;
3254 const texturelayer_t *layer;
3256 // FIXME: identify models using a better check than rsurface_model->brush.shadowmesh
3257 lightmode = ((rsurface_entity->effects & EF_FULLBRIGHT) || rsurface_model->brush.shadowmesh) ? 0 : 2;
3258 if (rsurface_mode != RSURFMODE_MULTIPASS)
3259 rsurface_mode = RSURFMODE_MULTIPASS;
3260 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
3261 for (layerindex = 0, layer = rsurface_texture->currentlayers;layerindex < rsurface_texture->currentnumlayers;layerindex++, layer++)
3264 int layertexrgbscale;
3265 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
3267 if (layerindex == 0)
3271 GL_AlphaTest(false);
3272 qglDepthFunc(GL_EQUAL);CHECKGLERROR
3275 GL_DepthMask(layer->depthmask);
3276 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
3277 if ((layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2) && (gl_combine.integer || layer->depthmask))
3279 layertexrgbscale = 4;
3280 VectorScale(layer->color, 0.25f, layercolor);
3282 else if ((layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1) && (gl_combine.integer || layer->depthmask))
3284 layertexrgbscale = 2;
3285 VectorScale(layer->color, 0.5f, layercolor);
3289 layertexrgbscale = 1;
3290 VectorScale(layer->color, 1.0f, layercolor);
3292 layercolor[3] = layer->color[3];
3293 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
3294 R_Mesh_ColorPointer(NULL);
3295 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
3296 switch (layer->type)
3298 case TEXTURELAYERTYPE_LITTEXTURE:
3299 memset(&m, 0, sizeof(m));
3300 if (lightmode >= 1 || !rsurface_lightmaptexture)
3301 m.tex[0] = R_GetTexture(r_texture_white);
3303 m.tex[0] = R_GetTexture(rsurface_lightmaptexture);
3304 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordlightmap2f;
3305 m.tex[1] = R_GetTexture(layer->texture);
3306 m.texmatrix[1] = layer->texmatrix;
3307 m.texrgbscale[1] = layertexrgbscale;
3308 m.pointer_texcoord[1] = rsurface_model->surfmesh.data_texcoordtexture2f;
3309 R_Mesh_TextureState(&m);
3310 RSurf_DrawBatch_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], lightmode, applycolor, applyfog);
3312 case TEXTURELAYERTYPE_TEXTURE:
3313 memset(&m, 0, sizeof(m));
3314 m.tex[0] = R_GetTexture(layer->texture);
3315 m.texmatrix[0] = layer->texmatrix;
3316 m.texrgbscale[0] = layertexrgbscale;
3317 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3318 R_Mesh_TextureState(&m);
3319 RSurf_DrawBatch_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, applyfog);
3321 case TEXTURELAYERTYPE_FOG:
3322 memset(&m, 0, sizeof(m));
3323 m.texrgbscale[0] = layertexrgbscale;
3326 m.tex[0] = R_GetTexture(layer->texture);
3327 m.texmatrix[0] = layer->texmatrix;
3328 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3330 R_Mesh_TextureState(&m);
3331 // generate a color array for the fog pass
3332 R_Mesh_ColorPointer(rsurface_array_color4f);
3333 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3337 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3338 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)
3340 f = VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
3341 c[0] = layercolor[0];
3342 c[1] = layercolor[1];
3343 c[2] = layercolor[2];
3344 c[3] = f * layercolor[3];
3347 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3350 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
3352 GL_LockArrays(0, 0);
3355 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
3357 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3358 GL_AlphaTest(false);
3362 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, msurface_t **texturesurfacelist)
3364 // OpenGL 1.1 - crusty old voodoo path
3365 int texturesurfaceindex;
3370 const texturelayer_t *layer;
3372 // FIXME: identify models using a better check than rsurface_model->brush.shadowmesh
3373 lightmode = ((rsurface_entity->effects & EF_FULLBRIGHT) || rsurface_model->brush.shadowmesh) ? 0 : 2;
3374 if (rsurface_mode != RSURFMODE_MULTIPASS)
3375 rsurface_mode = RSURFMODE_MULTIPASS;
3376 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
3377 for (layerindex = 0, layer = rsurface_texture->currentlayers;layerindex < rsurface_texture->currentnumlayers;layerindex++, layer++)
3379 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
3381 if (layerindex == 0)
3385 GL_AlphaTest(false);
3386 qglDepthFunc(GL_EQUAL);CHECKGLERROR
3389 GL_DepthMask(layer->depthmask);
3390 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
3391 R_Mesh_ColorPointer(NULL);
3392 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
3393 switch (layer->type)
3395 case TEXTURELAYERTYPE_LITTEXTURE:
3396 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
3398 // two-pass lit texture with 2x rgbscale
3399 // first the lightmap pass
3400 memset(&m, 0, sizeof(m));
3401 if (lightmode >= 1 || !rsurface_lightmaptexture)
3402 m.tex[0] = R_GetTexture(r_texture_white);
3404 m.tex[0] = R_GetTexture(rsurface_lightmaptexture);
3405 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordlightmap2f;
3406 R_Mesh_TextureState(&m);
3407 RSurf_DrawBatch_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, lightmode, false, false);
3408 GL_LockArrays(0, 0);
3409 // then apply the texture to it
3410 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
3411 memset(&m, 0, sizeof(m));
3412 m.tex[0] = R_GetTexture(layer->texture);
3413 m.texmatrix[0] = layer->texmatrix;
3414 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3415 R_Mesh_TextureState(&m);
3416 RSurf_DrawBatch_Lightmap(texturenumsurfaces, texturesurfacelist, layer->color[0] * 0.5f, layer->color[1] * 0.5f, layer->color[2] * 0.5f, layer->color[3], 0, layer->color[0] != 2 || layer->color[1] != 2 || layer->color[2] != 2 || layer->color[3] != 1, false);
3420 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
3421 memset(&m, 0, sizeof(m));
3422 m.tex[0] = R_GetTexture(layer->texture);
3423 m.texmatrix[0] = layer->texmatrix;
3424 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3425 R_Mesh_TextureState(&m);
3426 RSurf_DrawBatch_Lightmap(texturenumsurfaces, texturesurfacelist, layer->color[0], layer->color[1], layer->color[2], layer->color[3], lightmode == 2 ? 2 : 1, layer->color[0] != 1 || layer->color[1] != 1 || layer->color[2] != 1 || layer->color[3] != 1, applyfog);
3429 case TEXTURELAYERTYPE_TEXTURE:
3430 // singletexture unlit texture with transparency support
3431 memset(&m, 0, sizeof(m));
3432 m.tex[0] = R_GetTexture(layer->texture);
3433 m.texmatrix[0] = layer->texmatrix;
3434 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3435 R_Mesh_TextureState(&m);
3436 RSurf_DrawBatch_Lightmap(texturenumsurfaces, texturesurfacelist, layer->color[0], layer->color[1], layer->color[2], layer->color[3], 0, layer->color[0] != 1 || layer->color[1] != 1 || layer->color[2] != 1 || layer->color[3] != 1, applyfog);
3438 case TEXTURELAYERTYPE_FOG:
3439 // singletexture fogging
3440 R_Mesh_ColorPointer(rsurface_array_color4f);
3443 memset(&m, 0, sizeof(m));
3444 m.tex[0] = R_GetTexture(layer->texture);
3445 m.texmatrix[0] = layer->texmatrix;
3446 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3447 R_Mesh_TextureState(&m);
3450 R_Mesh_ResetTextureState();
3451 // generate a color array for the fog pass
3452 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3456 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3457 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)
3459 f = VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
3460 c[0] = layer->color[0];
3461 c[1] = layer->color[1];
3462 c[2] = layer->color[2];
3463 c[3] = f * layer->color[3];
3466 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3469 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
3471 GL_LockArrays(0, 0);
3474 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
3476 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3477 GL_AlphaTest(false);
3481 static void R_DrawTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist)
3483 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_NODRAW)
3485 r_shadow_rtlight = NULL;
3486 r_refdef.stats.entities_surfaces += texturenumsurfaces;
3488 GL_DepthTest(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
3489 GL_CullFace(((rsurface_texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (rsurface_entity->flags & RENDER_NOCULLFACE)) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
3490 if (r_showsurfaces.integer)
3491 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
3492 else if (rsurface_texture->currentmaterialflags & MATERIALFLAG_SKY)
3493 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
3494 else if (rsurface_texture->currentnumlayers)
3496 if (r_glsl.integer && gl_support_fragment_shader)
3497 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist);
3498 else if (gl_combine.integer && r_textureunits.integer >= 2)
3499 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist);
3501 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist);
3504 GL_LockArrays(0, 0);
3507 #define BATCHSIZE 256
3508 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
3510 int surfacelistindex;
3513 msurface_t *texturesurfacelist[BATCHSIZE];
3514 // if the model is static it doesn't matter what value we give for
3515 // wantnormals and wanttangents, so this logic uses only rules applicable
3516 // to a model, knowing that they are meaningless otherwise
3517 if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
3518 RSurf_ActiveEntity(ent, false, false);
3520 RSurf_ActiveEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
3523 for (surfacelistindex = 0;surfacelistindex < numsurfaces;surfacelistindex++)
3525 msurface_t *surface = ent->model->data_surfaces + surfacelist[surfacelistindex];
3527 if (t != surface->texture || rsurface_lightmaptexture != surface->lightmaptexture)
3530 if (!(rsurface_texture->currentmaterialflags & MATERIALFLAG_SKY)) // transparent sky is too difficult
3531 R_DrawTextureSurfaceList(batchcount, texturesurfacelist);
3533 t = surface->texture;
3534 rsurface_lightmaptexture = surface->lightmaptexture;
3535 R_UpdateTextureInfo(ent, t);
3536 rsurface_texture = t->currentframe;
3539 texturesurfacelist[batchcount++] = surface;
3542 if (!(rsurface_texture->currentmaterialflags & MATERIALFLAG_SKY)) // transparent sky is too difficult
3543 R_DrawTextureSurfaceList(batchcount, texturesurfacelist);
3547 void R_QueueTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist)
3549 int texturesurfaceindex;
3550 vec3_t tempcenter, center;
3551 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_BLENDED)
3553 // drawing sky transparently would be too difficult
3554 if (!(rsurface_texture->currentmaterialflags & MATERIALFLAG_SKY))
3556 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3558 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3559 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
3560 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
3561 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
3562 Matrix4x4_Transform(&rsurface_entity->matrix, tempcenter, center);
3563 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);
3568 R_DrawTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
3571 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
3572 void R_DrawSurfaces(entity_render_t *ent, qboolean skysurfaces)
3574 int i, j, f, flagsmask;
3575 int counttriangles = 0;
3577 model_t *model = ent->model;
3578 const int maxsurfacelist = 1024;
3579 int numsurfacelist = 0;
3580 msurface_t *surfacelist[1024];
3584 // if the model is static it doesn't matter what value we give for
3585 // wantnormals and wanttangents, so this logic uses only rules applicable
3586 // to a model, knowing that they are meaningless otherwise
3587 if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
3588 RSurf_ActiveEntity(ent, false, false);
3590 RSurf_ActiveEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
3592 // update light styles
3593 if (!skysurfaces && model->brushq1.light_styleupdatechains)
3595 msurface_t *surface, **surfacechain;
3596 for (i = 0;i < model->brushq1.light_styles;i++)
3598 if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
3600 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
3601 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
3602 for (;(surface = *surfacechain);surfacechain++)
3603 surface->cached_dlight = true;
3608 R_UpdateAllTextureInfo(ent);
3609 flagsmask = skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL);
3612 rsurface_lightmaptexture = NULL;
3613 rsurface_texture = NULL;
3615 if (ent == r_refdef.worldentity)
3617 msurface_t *surface;
3618 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
3620 if (!r_viewcache.world_surfacevisible[j])
3622 if (t != surface->texture || rsurface_lightmaptexture != surface->lightmaptexture)
3626 R_QueueTextureSurfaceList(numsurfacelist, surfacelist);
3629 t = surface->texture;
3630 rsurface_lightmaptexture = surface->lightmaptexture;
3631 rsurface_texture = t->currentframe;
3632 f = rsurface_texture->currentmaterialflags & flagsmask;
3634 if (f && surface->num_triangles)
3636 // if lightmap parameters changed, rebuild lightmap texture
3637 if (surface->cached_dlight)
3638 R_BuildLightMap(ent, surface);
3639 // add face to draw list
3640 surfacelist[numsurfacelist++] = surface;
3641 counttriangles += surface->num_triangles;
3642 if (numsurfacelist >= maxsurfacelist)
3644 R_QueueTextureSurfaceList(numsurfacelist, surfacelist);
3652 msurface_t *surface;
3653 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
3655 if (t != surface->texture || rsurface_lightmaptexture != surface->lightmaptexture)
3659 R_QueueTextureSurfaceList(numsurfacelist, surfacelist);
3662 t = surface->texture;
3663 rsurface_lightmaptexture = surface->lightmaptexture;
3664 rsurface_texture = t->currentframe;
3665 f = rsurface_texture->currentmaterialflags & flagsmask;
3667 if (f && surface->num_triangles)
3669 // if lightmap parameters changed, rebuild lightmap texture
3670 if (surface->cached_dlight)
3671 R_BuildLightMap(ent, surface);
3672 // add face to draw list
3673 surfacelist[numsurfacelist++] = surface;
3674 counttriangles += surface->num_triangles;
3675 if (numsurfacelist >= maxsurfacelist)
3677 R_QueueTextureSurfaceList(numsurfacelist, surfacelist);
3684 R_QueueTextureSurfaceList(numsurfacelist, surfacelist);
3685 r_refdef.stats.entities_triangles += counttriangles;
3688 if (r_showcollisionbrushes.integer && model->brush.num_brushes && !skysurfaces)
3691 const msurface_t *surface;
3694 R_Mesh_Matrix(&ent->matrix);
3695 R_Mesh_ColorPointer(NULL);
3696 R_Mesh_ResetTextureState();
3697 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
3698 GL_DepthMask(false);
3699 GL_DepthTest(!r_showdisabledepthtest.integer);
3700 qglPolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);CHECKGLERROR
3701 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
3702 if (brush->colbrushf && brush->colbrushf->numtriangles)
3703 R_DrawCollisionBrush(brush->colbrushf);
3704 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
3705 if (surface->num_collisiontriangles)
3706 R_DrawCollisionSurface(ent, surface);
3707 qglPolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR
3710 if (r_showtris.integer || r_shownormals.integer)
3713 msurface_t *surface;
3714 const int *elements;
3717 GL_DepthTest(!r_showdisabledepthtest.integer);
3719 GL_BlendFunc(GL_ONE, GL_ZERO);
3720 R_Mesh_ColorPointer(NULL);
3721 R_Mesh_ResetTextureState();
3722 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
3724 if (ent == r_refdef.worldentity && !r_viewcache.world_surfacevisible[j])
3726 rsurface_texture = surface->texture->currentframe;
3727 if ((rsurface_texture->currentmaterialflags & flagsmask) && surface->num_triangles)
3729 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
3730 if (r_showtris.integer)
3732 if (!rsurface_texture->currentlayers->depthmask)
3733 GL_Color(r_showtris.value * r_view.colorscale, 0, 0, 1);
3734 else if (ent == r_refdef.worldentity)
3735 GL_Color(r_showtris.value * r_view.colorscale, r_showtris.value * r_view.colorscale, r_showtris.value * r_view.colorscale, 1);
3737 GL_Color(0, r_showtris.value * r_view.colorscale, 0, 1);
3738 elements = (ent->model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
3741 for (k = 0;k < surface->num_triangles;k++, elements += 3)
3743 qglArrayElement(elements[0]);qglArrayElement(elements[1]);
3744 qglArrayElement(elements[1]);qglArrayElement(elements[2]);
3745 qglArrayElement(elements[2]);qglArrayElement(elements[0]);
3750 if (r_shownormals.integer)
3752 GL_Color(r_shownormals.value * r_view.colorscale, 0, 0, 1);
3754 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
3756 VectorCopy(rsurface_vertex3f + l * 3, v);
3757 qglVertex3f(v[0], v[1], v[2]);
3758 VectorMA(v, 8, rsurface_svector3f + l * 3, v);
3759 qglVertex3f(v[0], v[1], v[2]);
3763 GL_Color(0, 0, r_shownormals.value * r_view.colorscale, 1);
3765 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
3767 VectorCopy(rsurface_vertex3f + l * 3, v);
3768 qglVertex3f(v[0], v[1], v[2]);
3769 VectorMA(v, 8, rsurface_tvector3f + l * 3, v);
3770 qglVertex3f(v[0], v[1], v[2]);
3774 GL_Color(0, r_shownormals.value * r_view.colorscale, 0, 1);
3776 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
3778 VectorCopy(rsurface_vertex3f + l * 3, v);
3779 qglVertex3f(v[0], v[1], v[2]);
3780 VectorMA(v, 8, rsurface_normal3f + l * 3, v);
3781 qglVertex3f(v[0], v[1], v[2]);
3788 rsurface_texture = NULL;