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(const char *filename, int permutation)
711 qboolean shaderfound;
712 r_glsl_permutation_t *p = r_glsl_permutations + (permutation & SHADERPERMUTATION_COUNTMASK);
713 int vertstrings_count;
714 int geomstrings_count;
715 int fragstrings_count;
717 const char *vertstrings_list[SHADERPERMUTATION_COUNT+1];
718 const char *geomstrings_list[SHADERPERMUTATION_COUNT+1];
719 const char *fragstrings_list[SHADERPERMUTATION_COUNT+1];
720 char permutationname[256];
725 vertstrings_list[0] = "#define VERTEX_SHADER\n";
726 geomstrings_list[0] = "#define GEOMETRY_SHADER\n";
727 fragstrings_list[0] = "#define FRAGMENT_SHADER\n";
728 vertstrings_count = 1;
729 geomstrings_count = 1;
730 fragstrings_count = 1;
731 permutationname[0] = 0;
732 for (i = 0;permutationinfo[i][0];i++)
734 if (permutation & (1<<i))
736 vertstrings_list[vertstrings_count++] = permutationinfo[i][0];
737 geomstrings_list[geomstrings_count++] = permutationinfo[i][0];
738 fragstrings_list[fragstrings_count++] = permutationinfo[i][0];
739 strlcat(permutationname, permutationinfo[i][1], sizeof(permutationname));
743 // keep line numbers correct
744 vertstrings_list[vertstrings_count++] = "\n";
745 geomstrings_list[geomstrings_count++] = "\n";
746 fragstrings_list[fragstrings_count++] = "\n";
749 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
753 Con_DPrintf("GLSL shader text for \"%s\" loaded from disk\n", filename);
754 vertstrings_list[vertstrings_count++] = shaderstring;
755 geomstrings_list[geomstrings_count++] = shaderstring;
756 fragstrings_list[fragstrings_count++] = shaderstring;
759 else if (!strcmp(filename, "glsl/default.glsl"))
761 Con_DPrintf("GLSL shader text for \"%s\" loaded from engine\n", filename);
762 vertstrings_list[vertstrings_count++] = builtinshaderstring;
763 geomstrings_list[geomstrings_count++] = builtinshaderstring;
764 fragstrings_list[fragstrings_count++] = builtinshaderstring;
767 // clear any lists that are not needed by this shader
768 if (!(permutation & SHADERPERMUTATION_USES_VERTEXSHADER))
769 vertstrings_count = 0;
770 if (!(permutation & SHADERPERMUTATION_USES_GEOMETRYSHADER))
771 geomstrings_count = 0;
772 if (!(permutation & SHADERPERMUTATION_USES_FRAGMENTSHADER))
773 fragstrings_count = 0;
774 // compile the shader program
775 if (shaderfound && vertstrings_count + geomstrings_count + fragstrings_count)
776 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
780 qglUseProgramObjectARB(p->program);CHECKGLERROR
781 // look up all the uniform variable names we care about, so we don't
782 // have to look them up every time we set them
783 p->loc_Texture_Normal = qglGetUniformLocationARB(p->program, "Texture_Normal");
784 p->loc_Texture_Color = qglGetUniformLocationARB(p->program, "Texture_Color");
785 p->loc_Texture_Gloss = qglGetUniformLocationARB(p->program, "Texture_Gloss");
786 p->loc_Texture_Cube = qglGetUniformLocationARB(p->program, "Texture_Cube");
787 p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
788 p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
789 p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
790 p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
791 p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
792 p->loc_Texture_Glow = qglGetUniformLocationARB(p->program, "Texture_Glow");
793 p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
794 p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
795 p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
796 p->loc_LightColor = qglGetUniformLocationARB(p->program, "LightColor");
797 p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants");
798 p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt");
799 p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip");
800 p->loc_AmbientScale = qglGetUniformLocationARB(p->program, "AmbientScale");
801 p->loc_DiffuseScale = qglGetUniformLocationARB(p->program, "DiffuseScale");
802 p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
803 p->loc_SpecularScale = qglGetUniformLocationARB(p->program, "SpecularScale");
804 p->loc_GlowScale = qglGetUniformLocationARB(p->program, "GlowScale");
805 p->loc_SceneBrightness = qglGetUniformLocationARB(p->program, "SceneBrightness");
806 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
807 p->loc_AmbientColor = qglGetUniformLocationARB(p->program, "AmbientColor");
808 p->loc_DiffuseColor = qglGetUniformLocationARB(p->program, "DiffuseColor");
809 p->loc_SpecularColor = qglGetUniformLocationARB(p->program, "SpecularColor");
810 p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
811 // initialize the samplers to refer to the texture units we use
812 if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal, 0);
813 if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color, 1);
814 if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss, 2);
815 if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube, 3);
816 if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask, 4);
817 if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants, 5);
818 if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt, 6);
819 if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap, 7);
820 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap, 8);
821 if (p->loc_Texture_Glow >= 0) qglUniform1iARB(p->loc_Texture_Glow, 9);
823 qglUseProgramObjectARB(0);CHECKGLERROR
826 Con_Printf("permutation%s failed for shader %s, some features may not work properly!\n", permutationname, "glsl/default.glsl");
828 Mem_Free(shaderstring);
831 void R_GLSL_Restart_f(void)
834 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
835 if (r_glsl_permutations[i].program)
836 GL_Backend_FreeProgram(r_glsl_permutations[i].program);
837 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
840 int R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting)
842 // select a permutation of the lighting shader appropriate to this
843 // combination of texture, entity, light source, and fogging, only use the
844 // minimum features necessary to avoid wasting rendering time in the
845 // fragment shader on features that are not being used
846 const char *shaderfilename = NULL;
848 float specularscale = rsurface_texture->specularscale;
849 r_glsl_permutation = NULL;
850 // TODO: implement geometry-shader based shadow volumes someday
851 if (r_shadow_rtlight)
854 shaderfilename = "glsl/default.glsl";
855 permutation = SHADERPERMUTATION_MODE_LIGHTSOURCE | SHADERPERMUTATION_USES_VERTEXSHADER | SHADERPERMUTATION_USES_FRAGMENTSHADER;
856 specularscale *= r_shadow_rtlight->specularscale;
857 if (r_shadow_rtlight->currentcubemap != r_texture_whitecube)
858 permutation |= SHADERPERMUTATION_CUBEFILTER;
859 if (specularscale > 0)
860 permutation |= SHADERPERMUTATION_SPECULAR;
861 if (r_refdef.fogenabled)
862 permutation |= SHADERPERMUTATION_FOG;
863 if (rsurface_texture->colormapping)
864 permutation |= SHADERPERMUTATION_COLORMAPPING;
865 if (r_glsl_offsetmapping.integer)
867 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
868 if (r_glsl_offsetmapping_reliefmapping.integer)
869 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
872 else if (rsurface_texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
874 // bright unshaded geometry
875 shaderfilename = "glsl/default.glsl";
876 permutation = SHADERPERMUTATION_USES_VERTEXSHADER | SHADERPERMUTATION_USES_FRAGMENTSHADER;
877 if (rsurface_texture->currentskinframe->glow)
878 permutation |= SHADERPERMUTATION_GLOW;
879 if (r_refdef.fogenabled)
880 permutation |= SHADERPERMUTATION_FOG;
881 if (rsurface_texture->colormapping)
882 permutation |= SHADERPERMUTATION_COLORMAPPING;
883 if (r_glsl_offsetmapping.integer)
885 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
886 if (r_glsl_offsetmapping_reliefmapping.integer)
887 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
890 else if (modellighting)
892 // directional model lighting
893 shaderfilename = "glsl/default.glsl";
894 permutation = SHADERPERMUTATION_USES_VERTEXSHADER | SHADERPERMUTATION_USES_FRAGMENTSHADER;
895 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTION;
896 if (rsurface_texture->currentskinframe->glow)
897 permutation |= SHADERPERMUTATION_GLOW;
898 if (specularscale > 0)
899 permutation |= SHADERPERMUTATION_SPECULAR;
900 if (r_refdef.fogenabled)
901 permutation |= SHADERPERMUTATION_FOG;
902 if (rsurface_texture->colormapping)
903 permutation |= SHADERPERMUTATION_COLORMAPPING;
904 if (r_glsl_offsetmapping.integer)
906 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
907 if (r_glsl_offsetmapping_reliefmapping.integer)
908 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
914 shaderfilename = "glsl/default.glsl";
915 permutation = SHADERPERMUTATION_USES_VERTEXSHADER | SHADERPERMUTATION_USES_FRAGMENTSHADER;
916 if (r_glsl_deluxemapping.integer >= 1 && rsurface_lightmaptexture && r_refdef.worldmodel && r_refdef.worldmodel->brushq3.deluxemapping)
918 // deluxemapping (light direction texture)
919 if (rsurface_lightmaptexture && r_refdef.worldmodel && r_refdef.worldmodel->brushq3.deluxemapping && r_refdef.worldmodel->brushq3.deluxemapping_modelspace)
920 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_MODELSPACE;
922 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
923 if (specularscale > 0)
924 permutation |= SHADERPERMUTATION_SPECULAR;
926 else if (r_glsl_deluxemapping.integer >= 2)
928 // fake deluxemapping (uniform light direction in tangentspace)
929 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
930 if (specularscale > 0)
931 permutation |= SHADERPERMUTATION_SPECULAR;
935 // ordinary lightmapping
938 if (rsurface_texture->currentskinframe->glow)
939 permutation |= SHADERPERMUTATION_GLOW;
940 if (r_refdef.fogenabled)
941 permutation |= SHADERPERMUTATION_FOG;
942 if (rsurface_texture->colormapping)
943 permutation |= SHADERPERMUTATION_COLORMAPPING;
944 if (r_glsl_offsetmapping.integer)
946 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
947 if (r_glsl_offsetmapping_reliefmapping.integer)
948 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
951 if (!r_glsl_permutations[permutation & SHADERPERMUTATION_COUNTMASK].program)
953 if (!r_glsl_permutations[permutation & SHADERPERMUTATION_COUNTMASK].compiled)
954 R_GLSL_CompilePermutation(shaderfilename, permutation);
955 if (!r_glsl_permutations[permutation & SHADERPERMUTATION_COUNTMASK].program)
957 // remove features until we find a valid permutation
959 for (i = SHADERPERMUTATION_COUNT-1;;i>>=1)
961 // reduce i more quickly whenever it would not remove any bits
965 if (!r_glsl_permutations[permutation & SHADERPERMUTATION_COUNTMASK].compiled)
966 R_GLSL_CompilePermutation(shaderfilename, permutation);
967 if (r_glsl_permutations[permutation & SHADERPERMUTATION_COUNTMASK].program)
970 return 0; // utterly failed
974 r_glsl_permutation = r_glsl_permutations + (permutation & SHADERPERMUTATION_COUNTMASK);
976 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
977 R_Mesh_TexMatrix(0, &rsurface_texture->currenttexmatrix);
978 if (permutation & SHADERPERMUTATION_MODE_LIGHTSOURCE)
980 if (r_glsl_permutation->loc_Texture_Cube >= 0 && r_shadow_rtlight) R_Mesh_TexBindCubeMap(3, R_GetTexture(r_shadow_rtlight->currentcubemap));
981 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]);
982 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
983 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_shadow_rtlight->ambientscale);
984 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_shadow_rtlight->diffusescale);
985 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, specularscale);
987 else if (permutation & SHADERPERMUTATION_MODE_LIGHTDIRECTION)
989 if (r_glsl_permutation->loc_AmbientColor >= 0)
990 qglUniform3fARB(r_glsl_permutation->loc_AmbientColor, rsurface_entity->modellight_ambient[0], rsurface_entity->modellight_ambient[1], rsurface_entity->modellight_ambient[2]);
991 if (r_glsl_permutation->loc_DiffuseColor >= 0)
992 qglUniform3fARB(r_glsl_permutation->loc_DiffuseColor, rsurface_entity->modellight_diffuse[0], rsurface_entity->modellight_diffuse[1], rsurface_entity->modellight_diffuse[2]);
993 if (r_glsl_permutation->loc_SpecularColor >= 0)
994 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);
995 if (r_glsl_permutation->loc_LightDir >= 0)
996 qglUniform3fARB(r_glsl_permutation->loc_LightDir, rsurface_entity->modellight_lightdir[0], rsurface_entity->modellight_lightdir[1], rsurface_entity->modellight_lightdir[2]);
1000 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_ambient.value * 2.0f / 128.0f);
1001 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_refdef.lightmapintensity * 2.0f);
1002 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, r_refdef.lightmapintensity * specularscale * 2.0f);
1004 if (r_glsl_permutation->loc_Texture_Normal >= 0) R_Mesh_TexBind(0, R_GetTexture(rsurface_texture->currentskinframe->nmap));
1005 if (r_glsl_permutation->loc_Texture_Color >= 0) R_Mesh_TexBind(1, R_GetTexture(rsurface_texture->basetexture));
1006 if (r_glsl_permutation->loc_Texture_Gloss >= 0) R_Mesh_TexBind(2, R_GetTexture(rsurface_texture->glosstexture));
1007 //if (r_glsl_permutation->loc_Texture_Cube >= 0 && permutation & SHADERPERMUTATION_MODE_LIGHTSOURCE) R_Mesh_TexBindCubeMap(3, R_GetTexture(r_shadow_rtlight->currentcubemap));
1008 if (r_glsl_permutation->loc_Texture_FogMask >= 0) R_Mesh_TexBind(4, R_GetTexture(r_texture_fogattenuation));
1009 if (r_glsl_permutation->loc_Texture_Pants >= 0) R_Mesh_TexBind(5, R_GetTexture(rsurface_texture->currentskinframe->pants));
1010 if (r_glsl_permutation->loc_Texture_Shirt >= 0) R_Mesh_TexBind(6, R_GetTexture(rsurface_texture->currentskinframe->shirt));
1011 //if (r_glsl_permutation->loc_Texture_Lightmap >= 0) R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
1012 //if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
1013 if (r_glsl_permutation->loc_Texture_Glow >= 0) R_Mesh_TexBind(9, R_GetTexture(rsurface_texture->currentskinframe->glow));
1014 if (r_glsl_permutation->loc_GlowScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_GlowScale, r_hdr_glowintensity.value);
1015 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_view.colorscale);
1016 if (r_glsl_permutation->loc_FogColor >= 0)
1018 // additive passes are only darkened by fog, not tinted
1019 if (r_shadow_rtlight || (rsurface_texture->currentmaterialflags & MATERIALFLAG_ADD))
1020 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
1022 qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
1024 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface_modelorg[0], rsurface_modelorg[1], rsurface_modelorg[2]);
1025 if (r_glsl_permutation->loc_Color_Pants >= 0)
1027 if (rsurface_texture->currentskinframe->pants)
1028 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface_entity->colormap_pantscolor[0], rsurface_entity->colormap_pantscolor[1], rsurface_entity->colormap_pantscolor[2]);
1030 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
1032 if (r_glsl_permutation->loc_Color_Shirt >= 0)
1034 if (rsurface_texture->currentskinframe->shirt)
1035 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface_entity->colormap_shirtcolor[0], rsurface_entity->colormap_shirtcolor[1], rsurface_entity->colormap_shirtcolor[2]);
1037 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
1039 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, r_refdef.fograngerecip);
1040 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface_texture->specularpower);
1041 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
1046 void R_SwitchSurfaceShader(int permutation)
1048 if (r_glsl_permutation != r_glsl_permutations + (permutation & SHADERPERMUTATION_COUNTMASK))
1050 r_glsl_permutation = r_glsl_permutations + (permutation & SHADERPERMUTATION_COUNTMASK);
1052 qglUseProgramObjectARB(r_glsl_permutation->program);
1057 void gl_main_start(void)
1059 r_main_texturepool = R_AllocTexturePool();
1060 R_BuildBlankTextures();
1062 if (gl_texturecubemap)
1065 R_BuildNormalizationCube();
1067 R_BuildFogTexture();
1068 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
1069 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
1072 void gl_main_shutdown(void)
1074 R_FreeTexturePool(&r_main_texturepool);
1075 r_texture_blanknormalmap = NULL;
1076 r_texture_white = NULL;
1077 r_texture_black = NULL;
1078 r_texture_whitecube = NULL;
1079 r_texture_normalizationcube = NULL;
1080 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
1084 extern void CL_ParseEntityLump(char *entitystring);
1085 void gl_main_newmap(void)
1087 // FIXME: move this code to client
1089 char *entities, entname[MAX_QPATH];
1092 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
1093 l = (int)strlen(entname) - 4;
1094 if (l >= 0 && !strcmp(entname + l, ".bsp"))
1096 memcpy(entname + l, ".ent", 5);
1097 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
1099 CL_ParseEntityLump(entities);
1104 if (cl.worldmodel->brush.entities)
1105 CL_ParseEntityLump(cl.worldmodel->brush.entities);
1109 void GL_Main_Init(void)
1111 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
1113 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed\n");
1114 FOG_registercvars(); // FIXME: move this fog stuff to client?
1115 Cvar_RegisterVariable(&r_nearclip);
1116 Cvar_RegisterVariable(&r_showsurfaces);
1117 Cvar_RegisterVariable(&r_showtris);
1118 Cvar_RegisterVariable(&r_shownormals);
1119 Cvar_RegisterVariable(&r_showlighting);
1120 Cvar_RegisterVariable(&r_showshadowvolumes);
1121 Cvar_RegisterVariable(&r_showcollisionbrushes);
1122 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
1123 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
1124 Cvar_RegisterVariable(&r_showdisabledepthtest);
1125 Cvar_RegisterVariable(&r_drawportals);
1126 Cvar_RegisterVariable(&r_drawentities);
1127 Cvar_RegisterVariable(&r_drawviewmodel);
1128 Cvar_RegisterVariable(&r_speeds);
1129 Cvar_RegisterVariable(&r_fullbrights);
1130 Cvar_RegisterVariable(&r_wateralpha);
1131 Cvar_RegisterVariable(&r_dynamic);
1132 Cvar_RegisterVariable(&r_fullbright);
1133 Cvar_RegisterVariable(&r_shadows);
1134 Cvar_RegisterVariable(&r_shadows_throwdistance);
1135 Cvar_RegisterVariable(&r_q1bsp_skymasking);
1136 Cvar_RegisterVariable(&r_textureunits);
1137 Cvar_RegisterVariable(&r_glsl);
1138 Cvar_RegisterVariable(&r_glsl_offsetmapping);
1139 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
1140 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
1141 Cvar_RegisterVariable(&r_glsl_deluxemapping);
1142 Cvar_RegisterVariable(&r_lerpsprites);
1143 Cvar_RegisterVariable(&r_lerpmodels);
1144 Cvar_RegisterVariable(&r_waterscroll);
1145 Cvar_RegisterVariable(&r_bloom);
1146 Cvar_RegisterVariable(&r_bloom_colorscale);
1147 Cvar_RegisterVariable(&r_bloom_brighten);
1148 Cvar_RegisterVariable(&r_bloom_blur);
1149 Cvar_RegisterVariable(&r_bloom_resolution);
1150 Cvar_RegisterVariable(&r_bloom_colorexponent);
1151 Cvar_RegisterVariable(&r_bloom_colorsubtract);
1152 Cvar_RegisterVariable(&r_hdr);
1153 Cvar_RegisterVariable(&r_hdr_scenebrightness);
1154 Cvar_RegisterVariable(&r_hdr_glowintensity);
1155 Cvar_RegisterVariable(&r_hdr_range);
1156 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
1157 Cvar_RegisterVariable(&developer_texturelogging);
1158 Cvar_RegisterVariable(&gl_lightmaps);
1159 Cvar_RegisterVariable(&r_test);
1160 Cvar_RegisterVariable(&r_batchmode);
1161 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
1162 Cvar_SetValue("r_fullbrights", 0);
1163 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
1166 extern void R_Textures_Init(void);
1167 extern void GL_Draw_Init(void);
1168 extern void GL_Main_Init(void);
1169 extern void R_Shadow_Init(void);
1170 extern void R_Sky_Init(void);
1171 extern void GL_Surf_Init(void);
1172 extern void R_Light_Init(void);
1173 extern void R_Particles_Init(void);
1174 extern void R_Explosion_Init(void);
1175 extern void gl_backend_init(void);
1176 extern void Sbar_Init(void);
1177 extern void R_LightningBeams_Init(void);
1178 extern void Mod_RenderInit(void);
1180 void Render_Init(void)
1193 R_LightningBeams_Init();
1202 extern char *ENGINE_EXTENSIONS;
1205 VID_CheckExtensions();
1207 // LordHavoc: report supported extensions
1208 Con_DPrintf("\nengine extensions: %s\n", vm_sv_extensions );
1210 // clear to black (loading plaque will be seen over this)
1212 qglClearColor(0,0,0,1);CHECKGLERROR
1213 qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
1216 int R_CullBox(const vec3_t mins, const vec3_t maxs)
1220 for (i = 0;i < 4;i++)
1222 p = r_view.frustum + i;
1227 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1231 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1235 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1239 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1243 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1247 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1251 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1255 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1263 //==================================================================================
1265 static void R_UpdateEntityLighting(entity_render_t *ent)
1267 vec3_t tempdiffusenormal;
1269 // fetch the lighting from the worldmodel data
1270 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));
1271 VectorClear(ent->modellight_diffuse);
1272 VectorClear(tempdiffusenormal);
1273 if ((ent->flags & RENDER_LIGHT) && r_refdef.worldmodel && r_refdef.worldmodel->brush.LightPoint)
1276 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
1277 r_refdef.worldmodel->brush.LightPoint(r_refdef.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
1280 VectorSet(ent->modellight_ambient, 1, 1, 1);
1282 // move the light direction into modelspace coordinates for lighting code
1283 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
1284 VectorNormalize(ent->modellight_lightdir);
1286 // scale ambient and directional light contributions according to rendering variables
1287 ent->modellight_ambient[0] *= ent->colormod[0] * r_refdef.lightmapintensity;
1288 ent->modellight_ambient[1] *= ent->colormod[1] * r_refdef.lightmapintensity;
1289 ent->modellight_ambient[2] *= ent->colormod[2] * r_refdef.lightmapintensity;
1290 ent->modellight_diffuse[0] *= ent->colormod[0] * r_refdef.lightmapintensity;
1291 ent->modellight_diffuse[1] *= ent->colormod[1] * r_refdef.lightmapintensity;
1292 ent->modellight_diffuse[2] *= ent->colormod[2] * r_refdef.lightmapintensity;
1295 static void R_View_UpdateEntityVisible (void)
1298 entity_render_t *ent;
1300 if (!r_drawentities.integer)
1303 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : (chase_active.integer ? 0 : RENDER_EXTERIORMODEL);
1304 if (r_refdef.worldmodel && r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs)
1306 // worldmodel can check visibility
1307 for (i = 0;i < r_refdef.numentities;i++)
1309 ent = r_refdef.entities[i];
1310 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));
1315 // no worldmodel or it can't check visibility
1316 for (i = 0;i < r_refdef.numentities;i++)
1318 ent = r_refdef.entities[i];
1319 r_viewcache.entityvisible[i] = !(ent->flags & renderimask) && !R_CullBox(ent->mins, ent->maxs);
1323 // update entity lighting (even on hidden entities for r_shadows)
1324 for (i = 0;i < r_refdef.numentities;i++)
1325 R_UpdateEntityLighting(r_refdef.entities[i]);
1328 // only used if skyrendermasked, and normally returns false
1329 int R_DrawBrushModelsSky (void)
1332 entity_render_t *ent;
1334 if (!r_drawentities.integer)
1338 for (i = 0;i < r_refdef.numentities;i++)
1340 if (!r_viewcache.entityvisible[i])
1342 ent = r_refdef.entities[i];
1343 if (!ent->model || !ent->model->DrawSky)
1345 ent->model->DrawSky(ent);
1351 void R_DrawNoModel(entity_render_t *ent);
1352 void R_DrawModels(void)
1355 entity_render_t *ent;
1357 if (!r_drawentities.integer)
1360 for (i = 0;i < r_refdef.numentities;i++)
1362 if (!r_viewcache.entityvisible[i])
1364 ent = r_refdef.entities[i];
1365 r_refdef.stats.entities++;
1366 if (ent->model && ent->model->Draw != NULL)
1367 ent->model->Draw(ent);
1373 static void R_View_SetFrustum(void)
1375 // break apart the view matrix into vectors for various purposes
1376 Matrix4x4_ToVectors(&r_view.matrix, r_view.forward, r_view.left, r_view.up, r_view.origin);
1377 VectorNegate(r_view.left, r_view.right);
1380 r_view.frustum[0].normal[0] = 0 - 1.0 / r_view.frustum_x;
1381 r_view.frustum[0].normal[1] = 0 - 0;
1382 r_view.frustum[0].normal[2] = -1 - 0;
1383 r_view.frustum[1].normal[0] = 0 + 1.0 / r_view.frustum_x;
1384 r_view.frustum[1].normal[1] = 0 + 0;
1385 r_view.frustum[1].normal[2] = -1 + 0;
1386 r_view.frustum[2].normal[0] = 0 - 0;
1387 r_view.frustum[2].normal[1] = 0 - 1.0 / r_view.frustum_y;
1388 r_view.frustum[2].normal[2] = -1 - 0;
1389 r_view.frustum[3].normal[0] = 0 + 0;
1390 r_view.frustum[3].normal[1] = 0 + 1.0 / r_view.frustum_y;
1391 r_view.frustum[3].normal[2] = -1 + 0;
1395 zNear = r_refdef.nearclip;
1396 nudge = 1.0 - 1.0 / (1<<23);
1397 r_view.frustum[4].normal[0] = 0 - 0;
1398 r_view.frustum[4].normal[1] = 0 - 0;
1399 r_view.frustum[4].normal[2] = -1 - -nudge;
1400 r_view.frustum[4].dist = 0 - -2 * zNear * nudge;
1401 r_view.frustum[5].normal[0] = 0 + 0;
1402 r_view.frustum[5].normal[1] = 0 + 0;
1403 r_view.frustum[5].normal[2] = -1 + -nudge;
1404 r_view.frustum[5].dist = 0 + -2 * zNear * nudge;
1410 r_view.frustum[0].normal[0] = m[3] - m[0];
1411 r_view.frustum[0].normal[1] = m[7] - m[4];
1412 r_view.frustum[0].normal[2] = m[11] - m[8];
1413 r_view.frustum[0].dist = m[15] - m[12];
1415 r_view.frustum[1].normal[0] = m[3] + m[0];
1416 r_view.frustum[1].normal[1] = m[7] + m[4];
1417 r_view.frustum[1].normal[2] = m[11] + m[8];
1418 r_view.frustum[1].dist = m[15] + m[12];
1420 r_view.frustum[2].normal[0] = m[3] - m[1];
1421 r_view.frustum[2].normal[1] = m[7] - m[5];
1422 r_view.frustum[2].normal[2] = m[11] - m[9];
1423 r_view.frustum[2].dist = m[15] - m[13];
1425 r_view.frustum[3].normal[0] = m[3] + m[1];
1426 r_view.frustum[3].normal[1] = m[7] + m[5];
1427 r_view.frustum[3].normal[2] = m[11] + m[9];
1428 r_view.frustum[3].dist = m[15] + m[13];
1430 r_view.frustum[4].normal[0] = m[3] - m[2];
1431 r_view.frustum[4].normal[1] = m[7] - m[6];
1432 r_view.frustum[4].normal[2] = m[11] - m[10];
1433 r_view.frustum[4].dist = m[15] - m[14];
1435 r_view.frustum[5].normal[0] = m[3] + m[2];
1436 r_view.frustum[5].normal[1] = m[7] + m[6];
1437 r_view.frustum[5].normal[2] = m[11] + m[10];
1438 r_view.frustum[5].dist = m[15] + m[14];
1443 VectorMAM(1, r_view.forward, 1.0 / -r_view.frustum_x, r_view.left, r_view.frustum[0].normal);
1444 VectorMAM(1, r_view.forward, 1.0 / r_view.frustum_x, r_view.left, r_view.frustum[1].normal);
1445 VectorMAM(1, r_view.forward, 1.0 / -r_view.frustum_y, r_view.up, r_view.frustum[2].normal);
1446 VectorMAM(1, r_view.forward, 1.0 / r_view.frustum_y, r_view.up, r_view.frustum[3].normal);
1447 VectorCopy(r_view.forward, r_view.frustum[4].normal);
1448 VectorNormalize(r_view.frustum[0].normal);
1449 VectorNormalize(r_view.frustum[1].normal);
1450 VectorNormalize(r_view.frustum[2].normal);
1451 VectorNormalize(r_view.frustum[3].normal);
1452 r_view.frustum[0].dist = DotProduct (r_view.origin, r_view.frustum[0].normal);
1453 r_view.frustum[1].dist = DotProduct (r_view.origin, r_view.frustum[1].normal);
1454 r_view.frustum[2].dist = DotProduct (r_view.origin, r_view.frustum[2].normal);
1455 r_view.frustum[3].dist = DotProduct (r_view.origin, r_view.frustum[3].normal);
1456 r_view.frustum[4].dist = DotProduct (r_view.origin, r_view.frustum[4].normal) + r_refdef.nearclip;
1457 PlaneClassify(&r_view.frustum[0]);
1458 PlaneClassify(&r_view.frustum[1]);
1459 PlaneClassify(&r_view.frustum[2]);
1460 PlaneClassify(&r_view.frustum[3]);
1461 PlaneClassify(&r_view.frustum[4]);
1463 // LordHavoc: note to all quake engine coders, Quake had a special case
1464 // for 90 degrees which assumed a square view (wrong), so I removed it,
1465 // Quake2 has it disabled as well.
1467 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
1468 //RotatePointAroundVector( r_view.frustum[0].normal, r_view.up, r_view.forward, -(90 - r_refdef.fov_x / 2));
1469 //r_view.frustum[0].dist = DotProduct (r_view.origin, frustum[0].normal);
1470 //PlaneClassify(&frustum[0]);
1472 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
1473 //RotatePointAroundVector( r_view.frustum[1].normal, r_view.up, r_view.forward, (90 - r_refdef.fov_x / 2));
1474 //r_view.frustum[1].dist = DotProduct (r_view.origin, frustum[1].normal);
1475 //PlaneClassify(&frustum[1]);
1477 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
1478 //RotatePointAroundVector( r_view.frustum[2].normal, r_view.left, r_view.forward, -(90 - r_refdef.fov_y / 2));
1479 //r_view.frustum[2].dist = DotProduct (r_view.origin, frustum[2].normal);
1480 //PlaneClassify(&frustum[2]);
1482 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
1483 //RotatePointAroundVector( r_view.frustum[3].normal, r_view.left, r_view.forward, (90 - r_refdef.fov_y / 2));
1484 //r_view.frustum[3].dist = DotProduct (r_view.origin, frustum[3].normal);
1485 //PlaneClassify(&frustum[3]);
1488 //VectorCopy(r_view.forward, r_view.frustum[4].normal);
1489 //r_view.frustum[4].dist = DotProduct (r_view.origin, frustum[4].normal) + r_nearclip.value;
1490 //PlaneClassify(&frustum[4]);
1493 void R_View_Update(void)
1495 R_View_SetFrustum();
1496 R_View_WorldVisibility();
1497 R_View_UpdateEntityVisible();
1500 void R_SetupView(const matrix4x4_t *matrix)
1502 if (r_refdef.rtworldshadows || r_refdef.rtdlightshadows)
1503 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_view.frustum_x, r_view.frustum_y, r_refdef.nearclip);
1505 GL_SetupView_Mode_Perspective(r_view.frustum_x, r_view.frustum_y, r_refdef.nearclip, r_refdef.farclip);
1507 GL_SetupView_Orientation_FromEntity(matrix);
1510 void R_ResetViewRendering2D(void)
1512 if (gl_support_fragment_shader)
1514 qglUseProgramObjectARB(0);CHECKGLERROR
1519 // GL is weird because it's bottom to top, r_view.y is top to bottom
1520 qglViewport(r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
1521 GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
1522 GL_Scissor(r_view.x, r_view.y, r_view.width, r_view.height);
1523 GL_Color(1, 1, 1, 1);
1524 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
1525 GL_BlendFunc(GL_ONE, GL_ZERO);
1526 GL_AlphaTest(false);
1527 GL_ScissorTest(false);
1528 GL_DepthMask(false);
1529 GL_DepthTest(false);
1530 R_Mesh_Matrix(&identitymatrix);
1531 R_Mesh_ResetTextureState();
1532 qglPolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR
1533 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
1534 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
1535 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
1536 qglStencilMask(~0);CHECKGLERROR
1537 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
1538 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
1539 GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
1542 void R_ResetViewRendering3D(void)
1544 if (gl_support_fragment_shader)
1546 qglUseProgramObjectARB(0);CHECKGLERROR
1551 // GL is weird because it's bottom to top, r_view.y is top to bottom
1552 qglViewport(r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
1553 R_SetupView(&r_view.matrix);
1554 GL_Scissor(r_view.x, r_view.y, r_view.width, r_view.height);
1555 GL_Color(1, 1, 1, 1);
1556 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
1557 GL_BlendFunc(GL_ONE, GL_ZERO);
1558 GL_AlphaTest(false);
1559 GL_ScissorTest(true);
1562 R_Mesh_Matrix(&identitymatrix);
1563 R_Mesh_ResetTextureState();
1564 qglPolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR
1565 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
1566 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
1567 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
1568 qglStencilMask(~0);CHECKGLERROR
1569 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
1570 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
1571 GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
1575 R_Bloom_SetupShader(
1577 "// written by Forest 'LordHavoc' Hale\n"
1579 "// common definitions between vertex shader and fragment shader:\n"
1581 "#ifdef __GLSL_CG_DATA_TYPES\n"
1582 "#define myhalf half\n"
1583 "#define myhvec2 hvec2\n"
1584 "#define myhvec3 hvec3\n"
1585 "#define myhvec4 hvec4\n"
1587 "#define myhalf float\n"
1588 "#define myhvec2 vec2\n"
1589 "#define myhvec3 vec3\n"
1590 "#define myhvec4 vec4\n"
1593 "varying vec2 ScreenTexCoord;\n"
1594 "varying vec2 BloomTexCoord;\n"
1599 "// vertex shader specific:\n"
1600 "#ifdef VERTEX_SHADER\n"
1604 " ScreenTexCoord = vec2(gl_MultiTexCoord0);\n"
1605 " BloomTexCoord = vec2(gl_MultiTexCoord1);\n"
1606 " // transform vertex to camera space, using ftransform to match non-VS\n"
1608 " gl_Position = ftransform();\n"
1611 "#endif // VERTEX_SHADER\n"
1616 "// fragment shader specific:\n"
1617 "#ifdef FRAGMENT_SHADER\n"
1622 " myhvec3 color = myhvec3(texture2D(Texture_Screen, ScreenTexCoord));\n"
1623 " for (x = -BLUR_X;x <= BLUR_X;x++)
1624 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
1625 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
1626 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
1627 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
1629 " gl_FragColor = vec4(color);\n"
1632 "#endif // FRAGMENT_SHADER\n"
1635 void R_RenderScene(void);
1637 void R_Bloom_StartFrame(void)
1639 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
1641 // set bloomwidth and bloomheight to the bloom resolution that will be
1642 // used (often less than the screen resolution for faster rendering)
1643 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_view.width);
1644 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_view.height / r_view.width;
1645 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_view.height);
1647 // calculate desired texture sizes
1648 if (gl_support_arb_texture_non_power_of_two)
1650 screentexturewidth = r_view.width;
1651 screentextureheight = r_view.height;
1652 bloomtexturewidth = r_bloomstate.bloomwidth;
1653 bloomtextureheight = r_bloomstate.bloomheight;
1657 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
1658 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
1659 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
1660 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
1665 screentexturewidth = screentextureheight = 0;
1667 else if (r_bloom.integer)
1672 screentexturewidth = screentextureheight = 0;
1673 bloomtexturewidth = bloomtextureheight = 0;
1676 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)
1678 // can't use bloom if the parameters are too weird
1679 // can't use bloom if the card does not support the texture size
1680 if (r_bloomstate.texture_screen)
1681 R_FreeTexture(r_bloomstate.texture_screen);
1682 if (r_bloomstate.texture_bloom)
1683 R_FreeTexture(r_bloomstate.texture_bloom);
1684 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
1688 r_bloomstate.enabled = true;
1689 r_bloomstate.hdr = r_hdr.integer != 0;
1691 // allocate textures as needed
1692 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
1694 if (r_bloomstate.texture_screen)
1695 R_FreeTexture(r_bloomstate.texture_screen);
1696 r_bloomstate.texture_screen = NULL;
1697 r_bloomstate.screentexturewidth = screentexturewidth;
1698 r_bloomstate.screentextureheight = screentextureheight;
1699 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
1700 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);
1702 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
1704 if (r_bloomstate.texture_bloom)
1705 R_FreeTexture(r_bloomstate.texture_bloom);
1706 r_bloomstate.texture_bloom = NULL;
1707 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
1708 r_bloomstate.bloomtextureheight = bloomtextureheight;
1709 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
1710 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);
1713 // set up a texcoord array for the full resolution screen image
1714 // (we have to keep this around to copy back during final render)
1715 r_bloomstate.screentexcoord2f[0] = 0;
1716 r_bloomstate.screentexcoord2f[1] = (float)r_view.height / (float)r_bloomstate.screentextureheight;
1717 r_bloomstate.screentexcoord2f[2] = (float)r_view.width / (float)r_bloomstate.screentexturewidth;
1718 r_bloomstate.screentexcoord2f[3] = (float)r_view.height / (float)r_bloomstate.screentextureheight;
1719 r_bloomstate.screentexcoord2f[4] = (float)r_view.width / (float)r_bloomstate.screentexturewidth;
1720 r_bloomstate.screentexcoord2f[5] = 0;
1721 r_bloomstate.screentexcoord2f[6] = 0;
1722 r_bloomstate.screentexcoord2f[7] = 0;
1724 // set up a texcoord array for the reduced resolution bloom image
1725 // (which will be additive blended over the screen image)
1726 r_bloomstate.bloomtexcoord2f[0] = 0;
1727 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
1728 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
1729 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
1730 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
1731 r_bloomstate.bloomtexcoord2f[5] = 0;
1732 r_bloomstate.bloomtexcoord2f[6] = 0;
1733 r_bloomstate.bloomtexcoord2f[7] = 0;
1736 void R_Bloom_CopyScreenTexture(float colorscale)
1738 r_refdef.stats.bloom++;
1740 R_ResetViewRendering2D();
1741 R_Mesh_VertexPointer(r_screenvertex3f);
1742 R_Mesh_ColorPointer(NULL);
1743 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f);
1744 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
1746 // copy view into the screen texture
1747 GL_ActiveTexture(0);
1749 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
1750 r_refdef.stats.bloom_copypixels += r_view.width * r_view.height;
1752 // now scale it down to the bloom texture size
1754 qglViewport(r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
1755 GL_BlendFunc(GL_ONE, GL_ZERO);
1756 GL_Color(colorscale, colorscale, colorscale, 1);
1757 // TODO: optimize with multitexture or GLSL
1758 R_Mesh_Draw(0, 4, 2, polygonelements);
1759 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
1761 // we now have a bloom image in the framebuffer
1762 // copy it into the bloom image texture for later processing
1763 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
1764 GL_ActiveTexture(0);
1766 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
1767 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
1770 void R_Bloom_CopyHDRTexture(void)
1772 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
1773 GL_ActiveTexture(0);
1775 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
1776 r_refdef.stats.bloom_copypixels += r_view.width * r_view.height;
1779 void R_Bloom_MakeTexture(void)
1782 float xoffset, yoffset, r, brighten;
1784 r_refdef.stats.bloom++;
1786 R_ResetViewRendering2D();
1787 R_Mesh_VertexPointer(r_screenvertex3f);
1788 R_Mesh_ColorPointer(NULL);
1790 // we have a bloom image in the framebuffer
1792 qglViewport(r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
1794 for (x = 1;x < r_bloom_colorexponent.value;)
1797 r = bound(0, r_bloom_colorexponent.value / x, 1);
1798 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
1799 GL_Color(r, r, r, 1);
1800 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
1801 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f);
1802 R_Mesh_Draw(0, 4, 2, polygonelements);
1803 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
1805 // copy the vertically blurred bloom view to a texture
1806 GL_ActiveTexture(0);
1808 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
1809 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
1812 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
1813 brighten = r_bloom_brighten.value;
1815 brighten *= r_hdr_range.value;
1816 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
1817 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f);
1819 for (dir = 0;dir < 2;dir++)
1821 // blend on at multiple vertical offsets to achieve a vertical blur
1822 // TODO: do offset blends using GLSL
1823 GL_BlendFunc(GL_ONE, GL_ZERO);
1824 for (x = -range;x <= range;x++)
1826 if (!dir){xoffset = 0;yoffset = x;}
1827 else {xoffset = x;yoffset = 0;}
1828 xoffset /= (float)r_bloomstate.bloomtexturewidth;
1829 yoffset /= (float)r_bloomstate.bloomtextureheight;
1830 // compute a texcoord array with the specified x and y offset
1831 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
1832 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
1833 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
1834 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
1835 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
1836 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
1837 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
1838 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
1839 // this r value looks like a 'dot' particle, fading sharply to
1840 // black at the edges
1841 // (probably not realistic but looks good enough)
1842 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
1843 //r = (dir ? 1.0f : brighten)/(range*2+1);
1844 r = (dir ? 1.0f : brighten)/(range*2+1)*(1 - x*x/(float)(range*range));
1845 GL_Color(r, r, r, 1);
1846 R_Mesh_Draw(0, 4, 2, polygonelements);
1847 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
1848 GL_BlendFunc(GL_ONE, GL_ONE);
1851 // copy the vertically blurred bloom view to a texture
1852 GL_ActiveTexture(0);
1854 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
1855 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
1858 // apply subtract last
1859 // (just like it would be in a GLSL shader)
1860 if (r_bloom_colorsubtract.value > 0 && gl_support_ext_blend_subtract)
1862 GL_BlendFunc(GL_ONE, GL_ZERO);
1863 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
1864 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f);
1865 GL_Color(1, 1, 1, 1);
1866 R_Mesh_Draw(0, 4, 2, polygonelements);
1867 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
1869 GL_BlendFunc(GL_ONE, GL_ONE);
1870 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
1871 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
1872 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f);
1873 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
1874 R_Mesh_Draw(0, 4, 2, polygonelements);
1875 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
1876 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
1878 // copy the darkened bloom view to a texture
1879 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
1880 GL_ActiveTexture(0);
1882 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
1883 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
1887 void R_HDR_RenderBloomTexture(void)
1889 int oldwidth, oldheight;
1891 oldwidth = r_view.width;
1892 oldheight = r_view.height;
1893 r_view.width = r_bloomstate.bloomwidth;
1894 r_view.height = r_bloomstate.bloomheight;
1896 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
1897 // TODO: add exposure compensation features
1898 // TODO: add fp16 framebuffer support
1900 r_view.colorscale = r_bloom_colorscale.value * r_hdr_scenebrightness.value;
1902 r_view.colorscale /= r_hdr_range.value;
1905 R_ResetViewRendering2D();
1907 R_Bloom_CopyHDRTexture();
1908 R_Bloom_MakeTexture();
1910 R_ResetViewRendering3D();
1913 if (r_timereport_active)
1914 R_TimeReport("clear");
1917 // restore the view settings
1918 r_view.width = oldwidth;
1919 r_view.height = oldheight;
1922 static void R_BlendView(void)
1924 if (r_bloomstate.enabled && r_bloomstate.hdr)
1926 // render high dynamic range bloom effect
1927 // the bloom texture was made earlier this render, so we just need to
1928 // blend it onto the screen...
1929 R_ResetViewRendering2D();
1930 R_Mesh_VertexPointer(r_screenvertex3f);
1931 R_Mesh_ColorPointer(NULL);
1932 GL_Color(1, 1, 1, 1);
1933 GL_BlendFunc(GL_ONE, GL_ONE);
1934 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
1935 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f);
1936 R_Mesh_Draw(0, 4, 2, polygonelements);
1937 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
1939 else if (r_bloomstate.enabled)
1941 // render simple bloom effect
1942 // copy the screen and shrink it and darken it for the bloom process
1943 R_Bloom_CopyScreenTexture(r_bloom_colorscale.value);
1944 // make the bloom texture
1945 R_Bloom_MakeTexture();
1946 // put the original screen image back in place and blend the bloom
1948 R_ResetViewRendering2D();
1949 R_Mesh_VertexPointer(r_screenvertex3f);
1950 R_Mesh_ColorPointer(NULL);
1951 GL_Color(1, 1, 1, 1);
1952 GL_BlendFunc(GL_ONE, GL_ZERO);
1953 // do both in one pass if possible
1954 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
1955 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f);
1956 if (r_textureunits.integer >= 2 && gl_combine.integer)
1958 R_Mesh_TexCombine(1, GL_ADD, GL_ADD, 1, 1);
1959 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_screen));
1960 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.screentexcoord2f);
1964 R_Mesh_Draw(0, 4, 2, polygonelements);
1965 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
1966 // now blend on the bloom texture
1967 GL_BlendFunc(GL_ONE, GL_ONE);
1968 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
1969 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f);
1971 R_Mesh_Draw(0, 4, 2, polygonelements);
1972 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
1974 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
1976 // apply a color tint to the whole view
1977 R_ResetViewRendering2D();
1978 R_Mesh_VertexPointer(r_screenvertex3f);
1979 R_Mesh_ColorPointer(NULL);
1980 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1981 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
1982 R_Mesh_Draw(0, 4, 2, polygonelements);
1986 void R_RenderScene(void);
1988 matrix4x4_t r_waterscrollmatrix;
1990 void R_UpdateVariables(void)
1994 r_refdef.farclip = 4096;
1995 if (r_refdef.worldmodel)
1996 r_refdef.farclip += VectorDistance(r_refdef.worldmodel->normalmins, r_refdef.worldmodel->normalmaxs);
1997 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
1999 r_refdef.polygonfactor = 0;
2000 r_refdef.polygonoffset = 0;
2001 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_shadow_polygonfactor.value;
2002 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_shadow_polygonoffset.value;
2004 r_refdef.rtworld = r_shadow_realtime_world.integer;
2005 r_refdef.rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
2006 r_refdef.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer;
2007 r_refdef.rtdlightshadows = r_refdef.rtdlight && (r_refdef.rtworld ? r_shadow_realtime_world_dlightshadows.integer : r_shadow_realtime_dlight_shadows.integer) && gl_stencil;
2008 r_refdef.lightmapintensity = r_refdef.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
2009 if (r_showsurfaces.integer)
2011 r_refdef.rtworld = false;
2012 r_refdef.rtworldshadows = false;
2013 r_refdef.rtdlight = false;
2014 r_refdef.rtdlightshadows = false;
2015 r_refdef.lightmapintensity = 0;
2018 if (gamemode == GAME_NEHAHRA)
2020 if (gl_fogenable.integer)
2022 r_refdef.oldgl_fogenable = true;
2023 r_refdef.fog_density = gl_fogdensity.value;
2024 r_refdef.fog_red = gl_fogred.value;
2025 r_refdef.fog_green = gl_foggreen.value;
2026 r_refdef.fog_blue = gl_fogblue.value;
2028 else if (r_refdef.oldgl_fogenable)
2030 r_refdef.oldgl_fogenable = false;
2031 r_refdef.fog_density = 0;
2032 r_refdef.fog_red = 0;
2033 r_refdef.fog_green = 0;
2034 r_refdef.fog_blue = 0;
2037 if (r_refdef.fog_density)
2039 r_refdef.fogcolor[0] = bound(0.0f, r_refdef.fog_red , 1.0f);
2040 r_refdef.fogcolor[1] = bound(0.0f, r_refdef.fog_green, 1.0f);
2041 r_refdef.fogcolor[2] = bound(0.0f, r_refdef.fog_blue , 1.0f);
2043 if (r_refdef.fog_density)
2045 r_refdef.fogenabled = true;
2046 // this is the point where the fog reaches 0.9986 alpha, which we
2047 // consider a good enough cutoff point for the texture
2048 // (0.9986 * 256 == 255.6)
2049 r_refdef.fogrange = 400 / r_refdef.fog_density;
2050 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
2051 r_refdef.fogtabledistmultiplier = FOGTABLEWIDTH * r_refdef.fograngerecip;
2052 // fog color was already set
2055 r_refdef.fogenabled = false;
2063 void R_RenderView(void)
2065 if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
2066 return; //Host_Error ("R_RenderView: NULL worldmodel");
2068 R_Shadow_UpdateWorldLightSelection();
2071 if (r_timereport_active)
2072 R_TimeReport("setup");
2075 if (r_timereport_active)
2076 R_TimeReport("visibility");
2078 R_ResetViewRendering3D();
2081 if (r_timereport_active)
2082 R_TimeReport("clear");
2084 R_Bloom_StartFrame();
2086 // this produces a bloom texture to be used in R_BlendView() later
2088 R_HDR_RenderBloomTexture();
2090 r_view.colorscale = r_hdr_scenebrightness.value;
2094 if (r_timereport_active)
2095 R_TimeReport("blendview");
2097 GL_Scissor(0, 0, vid.width, vid.height);
2098 GL_ScissorTest(false);
2102 extern void R_DrawLightningBeams (void);
2103 extern void VM_AddPolygonsToMeshQueue (void);
2104 extern void R_DrawPortals (void);
2105 void R_RenderScene(void)
2107 // don't let sound skip if going slow
2108 if (r_refdef.extraupdate)
2111 R_ResetViewRendering3D();
2113 R_MeshQueue_BeginScene();
2117 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);
2119 if (cl.csqc_vidvars.drawworld)
2121 // don't let sound skip if going slow
2122 if (r_refdef.extraupdate)
2125 if (r_refdef.worldmodel && r_refdef.worldmodel->DrawSky)
2127 r_refdef.worldmodel->DrawSky(r_refdef.worldentity);
2128 if (r_timereport_active)
2129 R_TimeReport("worldsky");
2132 if (R_DrawBrushModelsSky() && r_timereport_active)
2133 R_TimeReport("bmodelsky");
2135 if (r_refdef.worldmodel && r_refdef.worldmodel->Draw)
2137 r_refdef.worldmodel->Draw(r_refdef.worldentity);
2138 if (r_timereport_active)
2139 R_TimeReport("world");
2143 // don't let sound skip if going slow
2144 if (r_refdef.extraupdate)
2148 if (r_timereport_active)
2149 R_TimeReport("models");
2151 // don't let sound skip if going slow
2152 if (r_refdef.extraupdate)
2155 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
2157 R_DrawModelShadows();
2159 R_ResetViewRendering3D();
2161 // don't let sound skip if going slow
2162 if (r_refdef.extraupdate)
2166 R_ShadowVolumeLighting(false);
2167 if (r_timereport_active)
2168 R_TimeReport("rtlights");
2170 // don't let sound skip if going slow
2171 if (r_refdef.extraupdate)
2174 if (cl.csqc_vidvars.drawworld)
2176 R_DrawLightningBeams();
2177 if (r_timereport_active)
2178 R_TimeReport("lightning");
2181 if (r_timereport_active)
2182 R_TimeReport("particles");
2185 if (r_timereport_active)
2186 R_TimeReport("explosions");
2189 if (gl_support_fragment_shader)
2191 qglUseProgramObjectARB(0);CHECKGLERROR
2193 VM_AddPolygonsToMeshQueue();
2195 if (r_drawportals.integer)
2198 if (r_timereport_active)
2199 R_TimeReport("portals");
2202 if (gl_support_fragment_shader)
2204 qglUseProgramObjectARB(0);CHECKGLERROR
2206 R_MeshQueue_RenderTransparent();
2207 if (r_timereport_active)
2208 R_TimeReport("drawtrans");
2210 if (gl_support_fragment_shader)
2212 qglUseProgramObjectARB(0);CHECKGLERROR
2215 if (cl.csqc_vidvars.drawworld)
2218 if (r_timereport_active)
2219 R_TimeReport("coronas");
2222 // don't let sound skip if going slow
2223 if (r_refdef.extraupdate)
2226 R_ResetViewRendering2D();
2230 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
2233 float *v, *c, f1, f2, diff[3], vertex3f[8*3], color4f[8*4];
2234 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2235 GL_DepthMask(false);
2237 R_Mesh_Matrix(&identitymatrix);
2239 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2];
2240 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
2241 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
2242 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
2243 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
2244 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
2245 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
2246 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
2247 R_FillColors(color, 8, cr, cg, cb, ca);
2248 if (r_refdef.fogenabled)
2250 for (i = 0, v = vertex, c = color;i < 8;i++, v += 4, c += 4)
2252 f2 = VERTEXFOGTABLE(VectorDistance(v, r_view.origin));
2254 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
2255 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
2256 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
2259 R_Mesh_VertexPointer(vertex3f);
2260 R_Mesh_ColorPointer(color);
2261 R_Mesh_ResetTextureState();
2266 int nomodelelements[24] =
2278 float nomodelvertex3f[6*3] =
2288 float nomodelcolor4f[6*4] =
2290 0.0f, 0.0f, 0.5f, 1.0f,
2291 0.0f, 0.0f, 0.5f, 1.0f,
2292 0.0f, 0.5f, 0.0f, 1.0f,
2293 0.0f, 0.5f, 0.0f, 1.0f,
2294 0.5f, 0.0f, 0.0f, 1.0f,
2295 0.5f, 0.0f, 0.0f, 1.0f
2298 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
2303 // this is only called once per entity so numsurfaces is always 1, and
2304 // surfacelist is always {0}, so this code does not handle batches
2305 R_Mesh_Matrix(&ent->matrix);
2307 if (ent->flags & EF_ADDITIVE)
2309 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2310 GL_DepthMask(false);
2312 else if (ent->alpha < 1)
2314 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2315 GL_DepthMask(false);
2319 GL_BlendFunc(GL_ONE, GL_ZERO);
2322 GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
2323 GL_CullFace((ent->flags & RENDER_NOCULLFACE) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
2324 R_Mesh_VertexPointer(nomodelvertex3f);
2325 if (r_refdef.fogenabled)
2328 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
2329 R_Mesh_ColorPointer(color4f);
2330 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
2331 f2 = VERTEXFOGTABLE(VectorDistance(org, r_view.origin));
2333 for (i = 0, c = color4f;i < 6;i++, c += 4)
2335 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
2336 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
2337 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
2341 else if (ent->alpha != 1)
2343 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
2344 R_Mesh_ColorPointer(color4f);
2345 for (i = 0, c = color4f;i < 6;i++, c += 4)
2349 R_Mesh_ColorPointer(nomodelcolor4f);
2350 R_Mesh_ResetTextureState();
2351 R_Mesh_Draw(0, 6, 8, nomodelelements);
2354 void R_DrawNoModel(entity_render_t *ent)
2357 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
2358 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
2359 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, r_shadow_rtlight);
2361 // R_DrawNoModelCallback(ent, 0);
2364 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
2366 vec3_t right1, right2, diff, normal;
2368 VectorSubtract (org2, org1, normal);
2370 // calculate 'right' vector for start
2371 VectorSubtract (r_view.origin, org1, diff);
2372 CrossProduct (normal, diff, right1);
2373 VectorNormalize (right1);
2375 // calculate 'right' vector for end
2376 VectorSubtract (r_view.origin, org2, diff);
2377 CrossProduct (normal, diff, right2);
2378 VectorNormalize (right2);
2380 vert[ 0] = org1[0] + width * right1[0];
2381 vert[ 1] = org1[1] + width * right1[1];
2382 vert[ 2] = org1[2] + width * right1[2];
2383 vert[ 3] = org1[0] - width * right1[0];
2384 vert[ 4] = org1[1] - width * right1[1];
2385 vert[ 5] = org1[2] - width * right1[2];
2386 vert[ 6] = org2[0] - width * right2[0];
2387 vert[ 7] = org2[1] - width * right2[1];
2388 vert[ 8] = org2[2] - width * right2[2];
2389 vert[ 9] = org2[0] + width * right2[0];
2390 vert[10] = org2[1] + width * right2[1];
2391 vert[11] = org2[2] + width * right2[2];
2394 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
2396 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)
2398 float fog = 0.0f, ifog;
2401 if (r_refdef.fogenabled)
2402 fog = VERTEXFOGTABLE(VectorDistance(origin, r_view.origin));
2405 R_Mesh_Matrix(&identitymatrix);
2406 GL_BlendFunc(blendfunc1, blendfunc2);
2407 GL_DepthMask(false);
2408 GL_DepthTest(!depthdisable);
2410 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
2411 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
2412 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
2413 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
2414 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
2415 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
2416 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
2417 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
2418 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
2419 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
2420 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
2421 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
2423 R_Mesh_VertexPointer(vertex3f);
2424 R_Mesh_ColorPointer(NULL);
2425 R_Mesh_ResetTextureState();
2426 R_Mesh_TexBind(0, R_GetTexture(texture));
2427 R_Mesh_TexCoordPointer(0, 2, spritetexcoord2f);
2428 // FIXME: fixed function path can't properly handle r_view.colorscale > 1
2429 GL_Color(cr * ifog * r_view.colorscale, cg * ifog * r_view.colorscale, cb * ifog * r_view.colorscale, ca);
2430 R_Mesh_Draw(0, 4, 2, polygonelements);
2432 if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
2434 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
2435 GL_BlendFunc(blendfunc1, GL_ONE);
2436 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);
2437 R_Mesh_Draw(0, 4, 2, polygonelements);
2441 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
2446 VectorSet(v, x, y, z);
2447 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
2448 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
2450 if (i == mesh->numvertices)
2452 if (mesh->numvertices < mesh->maxvertices)
2454 VectorCopy(v, vertex3f);
2455 mesh->numvertices++;
2457 return mesh->numvertices;
2463 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
2467 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
2468 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
2469 e = mesh->element3i + mesh->numtriangles * 3;
2470 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
2472 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
2473 if (mesh->numtriangles < mesh->maxtriangles)
2478 mesh->numtriangles++;
2480 element[1] = element[2];
2484 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
2488 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
2489 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
2490 e = mesh->element3i + mesh->numtriangles * 3;
2491 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
2493 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
2494 if (mesh->numtriangles < mesh->maxtriangles)
2499 mesh->numtriangles++;
2501 element[1] = element[2];
2505 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
2506 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
2508 int planenum, planenum2;
2511 mplane_t *plane, *plane2;
2513 double temppoints[2][256*3];
2514 // figure out how large a bounding box we need to properly compute this brush
2516 for (w = 0;w < numplanes;w++)
2517 maxdist = max(maxdist, planes[w].dist);
2518 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
2519 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
2520 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
2524 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
2525 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
2527 if (planenum2 == planenum)
2529 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);
2532 if (tempnumpoints < 3)
2534 // generate elements forming a triangle fan for this polygon
2535 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
2539 static void R_DrawCollisionBrush(const colbrushf_t *brush)
2542 R_Mesh_VertexPointer(brush->points->v);
2543 i = (int)(((size_t)brush) / sizeof(colbrushf_t));
2544 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);
2545 GL_LockArrays(0, brush->numpoints);
2546 R_Mesh_Draw(0, brush->numpoints, brush->numtriangles, brush->elements);
2547 GL_LockArrays(0, 0);
2550 static void R_DrawCollisionSurface(const entity_render_t *ent, const msurface_t *surface)
2553 if (!surface->num_collisiontriangles)
2555 R_Mesh_VertexPointer(surface->data_collisionvertex3f);
2556 i = (int)(((size_t)surface) / sizeof(msurface_t));
2557 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);
2558 GL_LockArrays(0, surface->num_collisionvertices);
2559 R_Mesh_Draw(0, surface->num_collisionvertices, surface->num_collisiontriangles, surface->data_collisionelement3i);
2560 GL_LockArrays(0, 0);
2563 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)
2565 texturelayer_t *layer;
2566 layer = t->currentlayers + t->currentnumlayers++;
2568 layer->depthmask = depthmask;
2569 layer->blendfunc1 = blendfunc1;
2570 layer->blendfunc2 = blendfunc2;
2571 layer->texture = texture;
2572 layer->texmatrix = *matrix;
2573 layer->color[0] = r * r_view.colorscale;
2574 layer->color[1] = g * r_view.colorscale;
2575 layer->color[2] = b * r_view.colorscale;
2576 layer->color[3] = a;
2579 void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
2581 model_t *model = ent->model;
2583 // FIXME: identify models using a better check than ent->model->brush.shadowmesh
2584 //int lightmode = ((ent->effects & EF_FULLBRIGHT) || ent->model->brush.shadowmesh) ? 0 : 2;
2586 // switch to an alternate material if this is a q1bsp animated material
2588 texture_t *texture = t;
2589 int s = ent->skinnum;
2590 if ((unsigned int)s >= (unsigned int)model->numskins)
2592 if (model->skinscenes)
2594 if (model->skinscenes[s].framecount > 1)
2595 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
2597 s = model->skinscenes[s].firstframe;
2600 t = t + s * model->num_surfaces;
2603 // use an alternate animation if the entity's frame is not 0,
2604 // and only if the texture has an alternate animation
2605 if (ent->frame != 0 && t->anim_total[1])
2606 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.time * 5.0f) % t->anim_total[1]) : 0];
2608 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.time * 5.0f) % t->anim_total[0]) : 0];
2610 texture->currentframe = t;
2613 // pick a new currentskinframe if the material is animated
2614 if (t->numskinframes >= 2)
2615 t->currentskinframe = t->skinframes + ((int)(t->skinframerate * (cl.time - ent->frame2time)) % t->numskinframes);
2617 t->currentmaterialflags = t->basematerialflags;
2618 t->currentalpha = ent->alpha;
2619 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
2620 t->currentalpha *= r_wateralpha.value;
2621 if (!(ent->flags & RENDER_LIGHT))
2622 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
2623 if (ent->effects & EF_ADDITIVE)
2624 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_TRANSPARENT;
2625 else if (t->currentalpha < 1)
2626 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_TRANSPARENT;
2627 if (ent->effects & EF_NODEPTHTEST)
2628 t->currentmaterialflags |= MATERIALFLAG_NODEPTHTEST;
2629 if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
2630 t->currenttexmatrix = r_waterscrollmatrix;
2632 t->currenttexmatrix = identitymatrix;
2634 t->colormapping = VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f);
2635 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
2636 t->glosstexture = r_texture_white;
2637 t->specularpower = r_shadow_glossexponent.value;
2638 t->specularscale = 0;
2639 if (r_shadow_gloss.integer > 0)
2641 if (t->currentskinframe->gloss)
2643 if (r_shadow_glossintensity.value > 0)
2645 t->glosstexture = t->currentskinframe->gloss;
2646 t->specularscale = r_shadow_glossintensity.value;
2649 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
2650 t->specularscale = r_shadow_gloss2intensity.value;
2653 t->currentnumlayers = 0;
2654 if (!(t->currentmaterialflags & MATERIALFLAG_NODRAW))
2656 if (gl_lightmaps.integer)
2657 R_Texture_AddLayer(t, true, GL_ONE, GL_ZERO, TEXTURELAYERTYPE_LITTEXTURE, r_texture_white, &identitymatrix, 1, 1, 1, 1);
2658 else if (!(t->currentmaterialflags & MATERIALFLAG_SKY))
2660 int blendfunc1, blendfunc2, depthmask;
2661 if (t->currentmaterialflags & MATERIALFLAG_ADD)
2663 blendfunc1 = GL_SRC_ALPHA;
2664 blendfunc2 = GL_ONE;
2666 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
2668 blendfunc1 = GL_SRC_ALPHA;
2669 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
2671 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
2673 blendfunc1 = t->customblendfunc[0];
2674 blendfunc2 = t->customblendfunc[1];
2678 blendfunc1 = GL_ONE;
2679 blendfunc2 = GL_ZERO;
2681 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
2682 if (t->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL))
2684 rtexture_t *currentbasetexture;
2686 if (r_refdef.fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED))
2687 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
2688 currentbasetexture = (VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) < (1.0f / 1048576.0f) && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
2689 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2691 // fullbright is not affected by r_refdef.lightmapintensity
2692 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
2693 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
2694 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);
2695 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
2696 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);
2702 // q3bsp has no lightmap updates, so the lightstylevalue that
2703 // would normally be baked into the lightmap must be
2704 // applied to the color
2705 if (ent->model->type == mod_brushq3)
2706 colorscale *= r_refdef.lightstylevalue[0] * (1.0f / 256.0f);
2707 colorscale *= r_refdef.lightmapintensity;
2708 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);
2709 if (r_ambient.value >= (1.0f/64.0f))
2710 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);
2711 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
2713 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);
2714 if (r_ambient.value >= (1.0f/64.0f))
2715 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);
2717 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
2719 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);
2720 if (r_ambient.value >= (1.0f/64.0f))
2721 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);
2724 if (t->currentskinframe->glow != NULL)
2725 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);
2726 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
2728 // if this is opaque use alpha blend which will darken the earlier
2731 // if this is an alpha blended material, all the earlier passes
2732 // were darkened by fog already, so we only need to add the fog
2733 // color ontop through the fog mask texture
2735 // if this is an additive blended material, all the earlier passes
2736 // were darkened by fog already, and we should not add fog color
2737 // (because the background was not darkened, there is no fog color
2738 // that was lost behind it).
2739 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);
2746 void R_UpdateAllTextureInfo(entity_render_t *ent)
2750 for (i = 0;i < ent->model->num_textures;i++)
2751 R_UpdateTextureInfo(ent, ent->model->data_textures + i);
2754 int rsurface_array_size = 0;
2755 float *rsurface_array_modelvertex3f = NULL;
2756 float *rsurface_array_modelsvector3f = NULL;
2757 float *rsurface_array_modeltvector3f = NULL;
2758 float *rsurface_array_modelnormal3f = NULL;
2759 float *rsurface_array_deformedvertex3f = NULL;
2760 float *rsurface_array_deformedsvector3f = NULL;
2761 float *rsurface_array_deformedtvector3f = NULL;
2762 float *rsurface_array_deformednormal3f = NULL;
2763 float *rsurface_array_color4f = NULL;
2764 float *rsurface_array_texcoord3f = NULL;
2766 void R_Mesh_ResizeArrays(int newvertices)
2769 if (rsurface_array_size >= newvertices)
2771 if (rsurface_array_modelvertex3f)
2772 Mem_Free(rsurface_array_modelvertex3f);
2773 rsurface_array_size = (newvertices + 1023) & ~1023;
2774 base = (float *)Mem_Alloc(r_main_mempool, rsurface_array_size * sizeof(float[31]));
2775 rsurface_array_modelvertex3f = base + rsurface_array_size * 0;
2776 rsurface_array_modelsvector3f = base + rsurface_array_size * 3;
2777 rsurface_array_modeltvector3f = base + rsurface_array_size * 6;
2778 rsurface_array_modelnormal3f = base + rsurface_array_size * 9;
2779 rsurface_array_deformedvertex3f = base + rsurface_array_size * 12;
2780 rsurface_array_deformedsvector3f = base + rsurface_array_size * 15;
2781 rsurface_array_deformedtvector3f = base + rsurface_array_size * 18;
2782 rsurface_array_deformednormal3f = base + rsurface_array_size * 21;
2783 rsurface_array_texcoord3f = base + rsurface_array_size * 24;
2784 rsurface_array_color4f = base + rsurface_array_size * 27;
2787 float *rsurface_modelvertex3f;
2788 float *rsurface_modelsvector3f;
2789 float *rsurface_modeltvector3f;
2790 float *rsurface_modelnormal3f;
2791 float *rsurface_vertex3f;
2792 float *rsurface_svector3f;
2793 float *rsurface_tvector3f;
2794 float *rsurface_normal3f;
2795 float *rsurface_lightmapcolor4f;
2796 vec3_t rsurface_modelorg;
2797 qboolean rsurface_generatedvertex;
2798 const entity_render_t *rsurface_entity;
2799 const model_t *rsurface_model;
2800 texture_t *rsurface_texture;
2801 rtexture_t *rsurface_lightmaptexture;
2802 rsurfmode_t rsurface_mode;
2803 texture_t *rsurface_glsl_texture;
2804 qboolean rsurface_glsl_uselightmap;
2806 void RSurf_CleanUp(void)
2809 if (rsurface_mode == RSURFMODE_GLSL)
2811 qglUseProgramObjectARB(0);CHECKGLERROR
2813 GL_AlphaTest(false);
2814 rsurface_mode = RSURFMODE_NONE;
2815 rsurface_lightmaptexture = NULL;
2816 rsurface_texture = NULL;
2817 rsurface_glsl_texture = NULL;
2818 rsurface_glsl_uselightmap = false;
2821 void RSurf_ActiveEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
2824 Matrix4x4_Transform(&ent->inversematrix, r_view.origin, rsurface_modelorg);
2825 rsurface_entity = ent;
2826 rsurface_model = ent->model;
2827 if (rsurface_array_size < rsurface_model->surfmesh.num_vertices)
2828 R_Mesh_ResizeArrays(rsurface_model->surfmesh.num_vertices);
2829 R_Mesh_Matrix(&ent->matrix);
2830 Matrix4x4_Transform(&ent->inversematrix, r_view.origin, rsurface_modelorg);
2831 if ((rsurface_entity->frameblend[0].lerp != 1 || rsurface_entity->frameblend[0].frame != 0) && rsurface_model->surfmesh.isanimated)
2835 rsurface_modelvertex3f = rsurface_array_modelvertex3f;
2836 rsurface_modelsvector3f = rsurface_array_modelsvector3f;
2837 rsurface_modeltvector3f = rsurface_array_modeltvector3f;
2838 rsurface_modelnormal3f = rsurface_array_modelnormal3f;
2839 Mod_Alias_GetMesh_Vertices(rsurface_model, rsurface_entity->frameblend, rsurface_array_modelvertex3f, rsurface_array_modelnormal3f, rsurface_array_modelsvector3f, rsurface_array_modeltvector3f);
2841 else if (wantnormals)
2843 rsurface_modelvertex3f = rsurface_array_modelvertex3f;
2844 rsurface_modelsvector3f = NULL;
2845 rsurface_modeltvector3f = NULL;
2846 rsurface_modelnormal3f = rsurface_array_modelnormal3f;
2847 Mod_Alias_GetMesh_Vertices(rsurface_model, rsurface_entity->frameblend, rsurface_array_modelvertex3f, rsurface_array_modelnormal3f, NULL, NULL);
2851 rsurface_modelvertex3f = rsurface_array_modelvertex3f;
2852 rsurface_modelsvector3f = NULL;
2853 rsurface_modeltvector3f = NULL;
2854 rsurface_modelnormal3f = NULL;
2855 Mod_Alias_GetMesh_Vertices(rsurface_model, rsurface_entity->frameblend, rsurface_array_modelvertex3f, NULL, NULL, NULL);
2857 rsurface_generatedvertex = true;
2861 rsurface_modelvertex3f = rsurface_model->surfmesh.data_vertex3f;
2862 rsurface_modelsvector3f = rsurface_model->surfmesh.data_svector3f;
2863 rsurface_modeltvector3f = rsurface_model->surfmesh.data_tvector3f;
2864 rsurface_modelnormal3f = rsurface_model->surfmesh.data_normal3f;
2865 rsurface_generatedvertex = false;
2867 rsurface_vertex3f = rsurface_modelvertex3f;
2868 rsurface_svector3f = rsurface_modelsvector3f;
2869 rsurface_tvector3f = rsurface_modeltvector3f;
2870 rsurface_normal3f = rsurface_modelnormal3f;
2873 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, msurface_t **texturesurfacelist)
2875 // 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
2876 if (rsurface_generatedvertex)
2878 if (rsurface_texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
2879 generatetangents = true;
2880 if (generatetangents)
2881 generatenormals = true;
2882 if (generatenormals && !rsurface_modelnormal3f)
2884 rsurface_normal3f = rsurface_modelnormal3f = rsurface_array_modelnormal3f;
2885 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);
2887 if (generatetangents && !rsurface_modelsvector3f)
2889 rsurface_svector3f = rsurface_modelsvector3f = rsurface_array_modelsvector3f;
2890 rsurface_tvector3f = rsurface_modeltvector3f = rsurface_array_modeltvector3f;
2891 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);
2894 // 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)
2895 if (rsurface_texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
2897 int texturesurfaceindex;
2898 float center[3], forward[3], right[3], up[3], v[4][3];
2899 matrix4x4_t matrix1, imatrix1;
2900 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_view.forward, forward);
2901 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_view.right, right);
2902 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_view.up, up);
2903 // make deformed versions of only the model vertices used by the specified surfaces
2904 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2907 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2908 // a single autosprite surface can contain multiple sprites...
2909 for (j = 0;j < surface->num_vertices - 3;j += 4)
2911 VectorClear(center);
2912 for (i = 0;i < 4;i++)
2913 VectorAdd(center, (rsurface_modelvertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
2914 VectorScale(center, 0.25f, center);
2915 if (rsurface_texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE2)
2917 forward[0] = rsurface_modelorg[0] - center[0];
2918 forward[1] = rsurface_modelorg[1] - center[1];
2920 VectorNormalize(forward);
2921 right[0] = forward[1];
2922 right[1] = -forward[0];
2924 VectorSet(up, 0, 0, 1);
2926 // FIXME: calculate vectors from triangle edges instead of using texture vectors as an easy way out?
2927 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);
2928 Matrix4x4_Invert_Simple(&imatrix1, &matrix1);
2929 for (i = 0;i < 4;i++)
2930 Matrix4x4_Transform(&imatrix1, (rsurface_modelvertex3f + 3 * surface->num_firstvertex) + (j+i)*3, v[i]);
2931 for (i = 0;i < 4;i++)
2932 VectorMAMAMAM(1, center, v[i][0], forward, v[i][1], right, v[i][2], up, rsurface_array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
2934 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);
2935 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);
2937 rsurface_vertex3f = rsurface_array_deformedvertex3f;
2938 rsurface_svector3f = rsurface_array_deformedsvector3f;
2939 rsurface_tvector3f = rsurface_array_deformedtvector3f;
2940 rsurface_normal3f = rsurface_array_deformednormal3f;
2944 rsurface_vertex3f = rsurface_modelvertex3f;
2945 rsurface_svector3f = rsurface_modelsvector3f;
2946 rsurface_tvector3f = rsurface_modeltvector3f;
2947 rsurface_normal3f = rsurface_modelnormal3f;
2949 R_Mesh_VertexPointer(rsurface_vertex3f);
2952 void RSurf_DrawBatch_Simple(int texturenumsurfaces, msurface_t **texturesurfacelist)
2954 int texturesurfaceindex;
2955 const msurface_t *surface = texturesurfacelist[0];
2956 int firstvertex = surface->num_firstvertex;
2957 int endvertex = surface->num_firstvertex + surface->num_vertices;
2958 if (texturenumsurfaces == 1)
2960 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2961 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
2963 else if (r_batchmode.integer == 2)
2965 #define MAXBATCHTRIANGLES 4096
2966 int batchtriangles = 0;
2967 int batchelements[MAXBATCHTRIANGLES*3];
2968 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2970 surface = texturesurfacelist[texturesurfaceindex];
2971 if (surface->num_triangles >= 256 || (batchtriangles == 0 && texturesurfaceindex + 1 >= texturenumsurfaces))
2973 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
2976 if (batchtriangles + surface->num_triangles > MAXBATCHTRIANGLES)
2978 R_Mesh_Draw(firstvertex, endvertex - firstvertex, batchtriangles, batchelements);
2980 firstvertex = surface->num_firstvertex;
2981 endvertex = surface->num_firstvertex + surface->num_vertices;
2985 firstvertex = min(firstvertex, surface->num_firstvertex);
2986 endvertex = max(endvertex, surface->num_firstvertex + surface->num_vertices);
2988 memcpy(batchelements + batchtriangles * 3, rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
2989 batchtriangles += surface->num_triangles;
2992 R_Mesh_Draw(firstvertex, endvertex - firstvertex, batchtriangles, batchelements);
2994 else if (r_batchmode.integer == 1)
2996 int firsttriangle = 0;
2997 int endtriangle = -1;
2998 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3000 surface = texturesurfacelist[texturesurfaceindex];
3001 if (surface->num_firsttriangle != endtriangle)
3003 if (endtriangle > firsttriangle)
3005 GL_LockArrays(firstvertex, endvertex - firstvertex);
3006 R_Mesh_Draw(firstvertex, endvertex - firstvertex, endtriangle - firsttriangle, (rsurface_model->surfmesh.data_element3i + 3 * firsttriangle));
3008 firstvertex = surface->num_firstvertex;
3009 endvertex = surface->num_firstvertex + surface->num_vertices;
3010 firsttriangle = surface->num_firsttriangle;
3014 firstvertex = min(firstvertex, surface->num_firstvertex);
3015 endvertex = max(endvertex, surface->num_firstvertex + surface->num_vertices);
3017 endtriangle = surface->num_firsttriangle + surface->num_triangles;
3019 if (endtriangle > firsttriangle)
3021 GL_LockArrays(firstvertex, endvertex - firstvertex);
3022 R_Mesh_Draw(firstvertex, endvertex - firstvertex, endtriangle - firsttriangle, (rsurface_model->surfmesh.data_element3i + 3 * firsttriangle));
3027 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3029 surface = texturesurfacelist[texturesurfaceindex];
3030 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
3031 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
3036 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
3038 int texturesurfaceindex;
3039 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3041 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3042 int k = (int)(((size_t)surface) / sizeof(msurface_t));
3043 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);
3044 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
3045 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
3049 static void RSurf_DrawBatch_Lightmap(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, int lightmode, qboolean applycolor, qboolean applyfog)
3051 int texturesurfaceindex;
3059 vec3_t ambientcolor;
3060 vec3_t diffusecolor;
3062 VectorCopy(rsurface_entity->modellight_lightdir, lightdir);
3063 ambientcolor[0] = rsurface_entity->modellight_ambient[0] * r * 0.5f;
3064 ambientcolor[1] = rsurface_entity->modellight_ambient[1] * g * 0.5f;
3065 ambientcolor[2] = rsurface_entity->modellight_ambient[2] * b * 0.5f;
3066 diffusecolor[0] = rsurface_entity->modellight_diffuse[0] * r * 0.5f;
3067 diffusecolor[1] = rsurface_entity->modellight_diffuse[1] * g * 0.5f;
3068 diffusecolor[2] = rsurface_entity->modellight_diffuse[2] * b * 0.5f;
3069 if (VectorLength2(diffusecolor) > 0)
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 int numverts = surface->num_vertices;
3076 v = rsurface_vertex3f + 3 * surface->num_firstvertex;
3077 c2 = rsurface_normal3f + 3 * surface->num_firstvertex;
3078 c = rsurface_array_color4f + 4 * surface->num_firstvertex;
3079 // q3-style directional shading
3080 for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
3082 if ((f = DotProduct(c2, lightdir)) > 0)
3083 VectorMA(ambientcolor, f, diffusecolor, c);
3085 VectorCopy(ambientcolor, c);
3094 rsurface_lightmapcolor4f = rsurface_array_color4f;
3098 r = ambientcolor[0];
3099 g = ambientcolor[1];
3100 b = ambientcolor[2];
3101 rsurface_lightmapcolor4f = NULL;
3104 else if (lightmode >= 1 || !rsurface_lightmaptexture)
3106 if (texturesurfacelist[0]->lightmapinfo && texturesurfacelist[0]->lightmapinfo->stainsamples)
3108 // generate color arrays for the surfaces in this list
3109 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3111 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3112 for (i = 0, c = rsurface_array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
3114 if (surface->lightmapinfo->samples)
3116 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface_model->surfmesh.data_lightmapoffsets + surface->num_firstvertex)[i];
3117 float scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
3118 VectorScale(lm, scale, c);
3119 if (surface->lightmapinfo->styles[1] != 255)
3121 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
3123 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
3124 VectorMA(c, scale, lm, c);
3125 if (surface->lightmapinfo->styles[2] != 255)
3128 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
3129 VectorMA(c, scale, lm, c);
3130 if (surface->lightmapinfo->styles[3] != 255)
3133 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
3134 VectorMA(c, scale, lm, c);
3144 rsurface_lightmapcolor4f = rsurface_array_color4f;
3147 rsurface_lightmapcolor4f = rsurface_model->surfmesh.data_lightmapcolor4f;
3152 rsurface_lightmapcolor4f = NULL;
3156 if (rsurface_lightmapcolor4f)
3158 // generate color arrays for the surfaces in this list
3159 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3161 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3162 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)
3164 f = 1 - VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
3174 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3176 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3177 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)
3179 f = 1 - VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
3187 rsurface_lightmapcolor4f = rsurface_array_color4f;
3189 if (applycolor && rsurface_lightmapcolor4f)
3191 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3193 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3194 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)
3202 rsurface_lightmapcolor4f = rsurface_array_color4f;
3204 R_Mesh_ColorPointer(rsurface_lightmapcolor4f);
3205 GL_Color(r, g, b, a);
3206 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3209 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
3211 if (rsurface_mode != RSURFMODE_SHOWSURFACES)
3213 rsurface_mode = RSURFMODE_SHOWSURFACES;
3215 GL_BlendFunc(GL_ONE, GL_ZERO);
3216 R_Mesh_ColorPointer(NULL);
3217 R_Mesh_ResetTextureState();
3219 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
3220 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
3223 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, msurface_t **texturesurfacelist)
3225 // transparent sky would be ridiculous
3226 if ((rsurface_texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
3228 if (rsurface_mode != RSURFMODE_SKY)
3230 if (rsurface_mode == RSURFMODE_GLSL)
3232 qglUseProgramObjectARB(0);CHECKGLERROR
3234 rsurface_mode = RSURFMODE_SKY;
3238 skyrendernow = false;
3240 // restore entity matrix
3241 R_Mesh_Matrix(&rsurface_entity->matrix);
3244 // LordHavoc: HalfLife maps have freaky skypolys so don't use
3245 // skymasking on them, and Quake3 never did sky masking (unlike
3246 // software Quake and software Quake2), so disable the sky masking
3247 // in Quake3 maps as it causes problems with q3map2 sky tricks,
3248 // and skymasking also looks very bad when noclipping outside the
3249 // level, so don't use it then either.
3250 if (rsurface_model->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_viewcache.world_novis)
3252 GL_Color(r_refdef.fogcolor[0] * r_view.colorscale, r_refdef.fogcolor[1] * r_view.colorscale, r_refdef.fogcolor[2] * r_view.colorscale, 1);
3253 R_Mesh_ColorPointer(NULL);
3254 R_Mesh_ResetTextureState();
3255 if (skyrendermasked)
3257 // depth-only (masking)
3258 GL_ColorMask(0,0,0,0);
3259 // just to make sure that braindead drivers don't draw
3260 // anything despite that colormask...
3261 GL_BlendFunc(GL_ZERO, GL_ONE);
3266 GL_BlendFunc(GL_ONE, GL_ZERO);
3268 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
3269 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3270 if (skyrendermasked)
3271 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
3275 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, msurface_t **texturesurfacelist)
3278 // FIXME: identify models using a better check than rsurface_model->brush.shadowmesh
3279 lightmode = ((rsurface_entity->effects & EF_FULLBRIGHT) || rsurface_model->brush.shadowmesh) ? 0 : 2;
3280 if (rsurface_mode != RSURFMODE_GLSL)
3282 rsurface_mode = RSURFMODE_GLSL;
3283 rsurface_glsl_texture = NULL;
3284 rsurface_glsl_uselightmap = false;
3285 R_Mesh_ResetTextureState();
3287 if (rsurface_glsl_texture != rsurface_texture || rsurface_glsl_uselightmap != (rsurface_lightmaptexture != NULL))
3289 rsurface_glsl_texture = rsurface_texture;
3290 rsurface_glsl_uselightmap = rsurface_lightmaptexture != NULL;
3291 GL_BlendFunc(rsurface_texture->currentlayers[0].blendfunc1, rsurface_texture->currentlayers[0].blendfunc2);
3292 GL_DepthMask(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_BLENDED));
3293 GL_Color(rsurface_entity->colormod[0], rsurface_entity->colormod[1], rsurface_entity->colormod[2], rsurface_texture->currentalpha);
3294 R_SetupSurfaceShader(vec3_origin, lightmode == 2);
3295 //permutation_deluxemapping = permutation_lightmapping = R_SetupSurfaceShader(vec3_origin, lightmode == 2, false);
3296 //if (r_glsl_deluxemapping.integer)
3297 // permutation_deluxemapping = R_SetupSurfaceShader(vec3_origin, lightmode == 2, true);
3298 R_Mesh_TexCoordPointer(0, 2, rsurface_model->surfmesh.data_texcoordtexture2f);
3299 R_Mesh_TexCoordPointer(4, 2, rsurface_model->surfmesh.data_texcoordlightmap2f);
3300 GL_AlphaTest((rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
3302 if (!r_glsl_permutation)
3304 RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
3305 R_Mesh_TexCoordPointer(1, 3, rsurface_svector3f);
3306 R_Mesh_TexCoordPointer(2, 3, rsurface_tvector3f);
3307 R_Mesh_TexCoordPointer(3, 3, rsurface_normal3f);
3308 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
3310 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
3311 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
3312 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
3313 R_Mesh_ColorPointer(NULL);
3315 else if (rsurface_lightmaptexture)
3317 R_Mesh_TexBind(7, R_GetTexture(rsurface_lightmaptexture));
3318 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
3319 R_Mesh_TexBind(8, R_GetTexture(texturesurfacelist[0]->deluxemaptexture));
3320 R_Mesh_ColorPointer(NULL);
3324 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
3325 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
3326 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
3327 R_Mesh_ColorPointer(rsurface_model->surfmesh.data_lightmapcolor4f);
3329 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3332 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, msurface_t **texturesurfacelist)
3334 // OpenGL 1.3 path - anything not completely ancient
3335 int texturesurfaceindex;
3337 qboolean applycolor;
3341 const texturelayer_t *layer;
3343 // FIXME: identify models using a better check than rsurface_model->brush.shadowmesh
3344 lightmode = ((rsurface_entity->effects & EF_FULLBRIGHT) || rsurface_model->brush.shadowmesh) ? 0 : 2;
3345 if (rsurface_mode != RSURFMODE_MULTIPASS)
3346 rsurface_mode = RSURFMODE_MULTIPASS;
3347 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
3348 for (layerindex = 0, layer = rsurface_texture->currentlayers;layerindex < rsurface_texture->currentnumlayers;layerindex++, layer++)
3351 int layertexrgbscale;
3352 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
3354 if (layerindex == 0)
3358 GL_AlphaTest(false);
3359 qglDepthFunc(GL_EQUAL);CHECKGLERROR
3362 GL_DepthMask(layer->depthmask);
3363 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
3364 if ((layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2) && (gl_combine.integer || layer->depthmask))
3366 layertexrgbscale = 4;
3367 VectorScale(layer->color, 0.25f, layercolor);
3369 else if ((layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1) && (gl_combine.integer || layer->depthmask))
3371 layertexrgbscale = 2;
3372 VectorScale(layer->color, 0.5f, layercolor);
3376 layertexrgbscale = 1;
3377 VectorScale(layer->color, 1.0f, layercolor);
3379 layercolor[3] = layer->color[3];
3380 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
3381 R_Mesh_ColorPointer(NULL);
3382 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
3383 switch (layer->type)
3385 case TEXTURELAYERTYPE_LITTEXTURE:
3386 memset(&m, 0, sizeof(m));
3387 if (lightmode >= 1 || !rsurface_lightmaptexture)
3388 m.tex[0] = R_GetTexture(r_texture_white);
3390 m.tex[0] = R_GetTexture(rsurface_lightmaptexture);
3391 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordlightmap2f;
3392 m.tex[1] = R_GetTexture(layer->texture);
3393 m.texmatrix[1] = layer->texmatrix;
3394 m.texrgbscale[1] = layertexrgbscale;
3395 m.pointer_texcoord[1] = rsurface_model->surfmesh.data_texcoordtexture2f;
3396 R_Mesh_TextureState(&m);
3397 RSurf_DrawBatch_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], lightmode, applycolor, applyfog);
3399 case TEXTURELAYERTYPE_TEXTURE:
3400 memset(&m, 0, sizeof(m));
3401 m.tex[0] = R_GetTexture(layer->texture);
3402 m.texmatrix[0] = layer->texmatrix;
3403 m.texrgbscale[0] = layertexrgbscale;
3404 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3405 R_Mesh_TextureState(&m);
3406 RSurf_DrawBatch_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, applyfog);
3408 case TEXTURELAYERTYPE_FOG:
3409 memset(&m, 0, sizeof(m));
3410 m.texrgbscale[0] = layertexrgbscale;
3413 m.tex[0] = R_GetTexture(layer->texture);
3414 m.texmatrix[0] = layer->texmatrix;
3415 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3417 R_Mesh_TextureState(&m);
3418 // generate a color array for the fog pass
3419 R_Mesh_ColorPointer(rsurface_array_color4f);
3420 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3424 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3425 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)
3427 f = VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
3428 c[0] = layercolor[0];
3429 c[1] = layercolor[1];
3430 c[2] = layercolor[2];
3431 c[3] = f * layercolor[3];
3434 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3437 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
3439 GL_LockArrays(0, 0);
3442 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
3444 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3445 GL_AlphaTest(false);
3449 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, msurface_t **texturesurfacelist)
3451 // OpenGL 1.1 - crusty old voodoo path
3452 int texturesurfaceindex;
3457 const texturelayer_t *layer;
3459 // FIXME: identify models using a better check than rsurface_model->brush.shadowmesh
3460 lightmode = ((rsurface_entity->effects & EF_FULLBRIGHT) || rsurface_model->brush.shadowmesh) ? 0 : 2;
3461 if (rsurface_mode != RSURFMODE_MULTIPASS)
3462 rsurface_mode = RSURFMODE_MULTIPASS;
3463 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
3464 for (layerindex = 0, layer = rsurface_texture->currentlayers;layerindex < rsurface_texture->currentnumlayers;layerindex++, layer++)
3466 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
3468 if (layerindex == 0)
3472 GL_AlphaTest(false);
3473 qglDepthFunc(GL_EQUAL);CHECKGLERROR
3476 GL_DepthMask(layer->depthmask);
3477 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
3478 R_Mesh_ColorPointer(NULL);
3479 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
3480 switch (layer->type)
3482 case TEXTURELAYERTYPE_LITTEXTURE:
3483 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
3485 // two-pass lit texture with 2x rgbscale
3486 // first the lightmap pass
3487 memset(&m, 0, sizeof(m));
3488 if (lightmode >= 1 || !rsurface_lightmaptexture)
3489 m.tex[0] = R_GetTexture(r_texture_white);
3491 m.tex[0] = R_GetTexture(rsurface_lightmaptexture);
3492 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordlightmap2f;
3493 R_Mesh_TextureState(&m);
3494 RSurf_DrawBatch_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, lightmode, false, false);
3495 GL_LockArrays(0, 0);
3496 // then apply the texture to it
3497 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
3498 memset(&m, 0, sizeof(m));
3499 m.tex[0] = R_GetTexture(layer->texture);
3500 m.texmatrix[0] = layer->texmatrix;
3501 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3502 R_Mesh_TextureState(&m);
3503 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);
3507 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
3508 memset(&m, 0, sizeof(m));
3509 m.tex[0] = R_GetTexture(layer->texture);
3510 m.texmatrix[0] = layer->texmatrix;
3511 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3512 R_Mesh_TextureState(&m);
3513 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);
3516 case TEXTURELAYERTYPE_TEXTURE:
3517 // singletexture unlit texture with transparency support
3518 memset(&m, 0, sizeof(m));
3519 m.tex[0] = R_GetTexture(layer->texture);
3520 m.texmatrix[0] = layer->texmatrix;
3521 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3522 R_Mesh_TextureState(&m);
3523 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);
3525 case TEXTURELAYERTYPE_FOG:
3526 // singletexture fogging
3527 R_Mesh_ColorPointer(rsurface_array_color4f);
3530 memset(&m, 0, sizeof(m));
3531 m.tex[0] = R_GetTexture(layer->texture);
3532 m.texmatrix[0] = layer->texmatrix;
3533 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3534 R_Mesh_TextureState(&m);
3537 R_Mesh_ResetTextureState();
3538 // generate a color array for the fog pass
3539 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3543 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3544 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)
3546 f = VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
3547 c[0] = layer->color[0];
3548 c[1] = layer->color[1];
3549 c[2] = layer->color[2];
3550 c[3] = f * layer->color[3];
3553 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3556 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
3558 GL_LockArrays(0, 0);
3561 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
3563 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3564 GL_AlphaTest(false);
3568 static void R_DrawTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist)
3570 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_NODRAW)
3572 r_shadow_rtlight = NULL;
3573 r_refdef.stats.entities_surfaces += texturenumsurfaces;
3575 GL_DepthTest(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
3576 GL_CullFace(((rsurface_texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (rsurface_entity->flags & RENDER_NOCULLFACE)) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
3577 if (r_showsurfaces.integer)
3578 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
3579 else if (rsurface_texture->currentmaterialflags & MATERIALFLAG_SKY)
3580 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
3581 else if (rsurface_texture->currentnumlayers)
3583 if (r_glsl.integer && gl_support_fragment_shader)
3584 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist);
3585 else if (gl_combine.integer && r_textureunits.integer >= 2)
3586 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist);
3588 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist);
3591 GL_LockArrays(0, 0);
3594 #define BATCHSIZE 256
3595 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
3597 int surfacelistindex;
3600 msurface_t *texturesurfacelist[BATCHSIZE];
3601 // if the model is static it doesn't matter what value we give for
3602 // wantnormals and wanttangents, so this logic uses only rules applicable
3603 // to a model, knowing that they are meaningless otherwise
3604 if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
3605 RSurf_ActiveEntity(ent, false, false);
3607 RSurf_ActiveEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
3610 for (surfacelistindex = 0;surfacelistindex < numsurfaces;surfacelistindex++)
3612 msurface_t *surface = ent->model->data_surfaces + surfacelist[surfacelistindex];
3614 if (t != surface->texture || rsurface_lightmaptexture != surface->lightmaptexture)
3617 if (!(rsurface_texture->currentmaterialflags & MATERIALFLAG_SKY)) // transparent sky is too difficult
3618 R_DrawTextureSurfaceList(batchcount, texturesurfacelist);
3620 t = surface->texture;
3621 rsurface_lightmaptexture = surface->lightmaptexture;
3622 R_UpdateTextureInfo(ent, t);
3623 rsurface_texture = t->currentframe;
3626 texturesurfacelist[batchcount++] = surface;
3629 if (!(rsurface_texture->currentmaterialflags & MATERIALFLAG_SKY)) // transparent sky is too difficult
3630 R_DrawTextureSurfaceList(batchcount, texturesurfacelist);
3634 void R_QueueTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist)
3636 int texturesurfaceindex;
3637 vec3_t tempcenter, center;
3638 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_BLENDED)
3640 // drawing sky transparently would be too difficult
3641 if (!(rsurface_texture->currentmaterialflags & MATERIALFLAG_SKY))
3643 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3645 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3646 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
3647 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
3648 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
3649 Matrix4x4_Transform(&rsurface_entity->matrix, tempcenter, center);
3650 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);
3655 R_DrawTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
3658 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
3659 void R_DrawSurfaces(entity_render_t *ent, qboolean skysurfaces)
3661 int i, j, f, flagsmask;
3662 int counttriangles = 0;
3664 model_t *model = ent->model;
3665 const int maxsurfacelist = 1024;
3666 int numsurfacelist = 0;
3667 msurface_t *surfacelist[1024];
3671 // if the model is static it doesn't matter what value we give for
3672 // wantnormals and wanttangents, so this logic uses only rules applicable
3673 // to a model, knowing that they are meaningless otherwise
3674 if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
3675 RSurf_ActiveEntity(ent, false, false);
3677 RSurf_ActiveEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
3679 // update light styles
3680 if (!skysurfaces && model->brushq1.light_styleupdatechains)
3682 msurface_t *surface, **surfacechain;
3683 for (i = 0;i < model->brushq1.light_styles;i++)
3685 if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
3687 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
3688 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
3689 for (;(surface = *surfacechain);surfacechain++)
3690 surface->cached_dlight = true;
3695 R_UpdateAllTextureInfo(ent);
3696 flagsmask = skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL);
3699 rsurface_lightmaptexture = NULL;
3700 rsurface_texture = NULL;
3702 if (ent == r_refdef.worldentity)
3704 msurface_t *surface;
3705 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
3707 if (!r_viewcache.world_surfacevisible[j])
3709 if (t != surface->texture || rsurface_lightmaptexture != surface->lightmaptexture)
3713 R_QueueTextureSurfaceList(numsurfacelist, surfacelist);
3716 t = surface->texture;
3717 rsurface_lightmaptexture = surface->lightmaptexture;
3718 rsurface_texture = t->currentframe;
3719 f = rsurface_texture->currentmaterialflags & flagsmask;
3721 if (f && surface->num_triangles)
3723 // if lightmap parameters changed, rebuild lightmap texture
3724 if (surface->cached_dlight)
3725 R_BuildLightMap(ent, surface);
3726 // add face to draw list
3727 surfacelist[numsurfacelist++] = surface;
3728 counttriangles += surface->num_triangles;
3729 if (numsurfacelist >= maxsurfacelist)
3731 R_QueueTextureSurfaceList(numsurfacelist, surfacelist);
3739 msurface_t *surface;
3740 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
3742 if (t != surface->texture || rsurface_lightmaptexture != surface->lightmaptexture)
3746 R_QueueTextureSurfaceList(numsurfacelist, surfacelist);
3749 t = surface->texture;
3750 rsurface_lightmaptexture = surface->lightmaptexture;
3751 rsurface_texture = t->currentframe;
3752 f = rsurface_texture->currentmaterialflags & flagsmask;
3754 if (f && surface->num_triangles)
3756 // if lightmap parameters changed, rebuild lightmap texture
3757 if (surface->cached_dlight)
3758 R_BuildLightMap(ent, surface);
3759 // add face to draw list
3760 surfacelist[numsurfacelist++] = surface;
3761 counttriangles += surface->num_triangles;
3762 if (numsurfacelist >= maxsurfacelist)
3764 R_QueueTextureSurfaceList(numsurfacelist, surfacelist);
3771 R_QueueTextureSurfaceList(numsurfacelist, surfacelist);
3772 r_refdef.stats.entities_triangles += counttriangles;
3775 if (r_showcollisionbrushes.integer && model->brush.num_brushes && !skysurfaces)
3778 const msurface_t *surface;
3781 R_Mesh_Matrix(&ent->matrix);
3782 R_Mesh_ColorPointer(NULL);
3783 R_Mesh_ResetTextureState();
3784 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
3785 GL_DepthMask(false);
3786 GL_DepthTest(!r_showdisabledepthtest.integer);
3787 qglPolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);CHECKGLERROR
3788 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
3789 if (brush->colbrushf && brush->colbrushf->numtriangles)
3790 R_DrawCollisionBrush(brush->colbrushf);
3791 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
3792 if (surface->num_collisiontriangles)
3793 R_DrawCollisionSurface(ent, surface);
3794 qglPolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR
3797 if (r_showtris.integer || r_shownormals.integer)
3800 msurface_t *surface;
3801 const int *elements;
3804 GL_DepthTest(!r_showdisabledepthtest.integer);
3806 GL_BlendFunc(GL_ONE, GL_ZERO);
3807 R_Mesh_ColorPointer(NULL);
3808 R_Mesh_ResetTextureState();
3809 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
3811 if (ent == r_refdef.worldentity && !r_viewcache.world_surfacevisible[j])
3813 rsurface_texture = surface->texture->currentframe;
3814 if ((rsurface_texture->currentmaterialflags & flagsmask) && surface->num_triangles)
3816 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
3817 if (r_showtris.integer)
3819 if (!rsurface_texture->currentlayers->depthmask)
3820 GL_Color(r_showtris.value * r_view.colorscale, 0, 0, 1);
3821 else if (ent == r_refdef.worldentity)
3822 GL_Color(r_showtris.value * r_view.colorscale, r_showtris.value * r_view.colorscale, r_showtris.value * r_view.colorscale, 1);
3824 GL_Color(0, r_showtris.value * r_view.colorscale, 0, 1);
3825 elements = (ent->model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
3828 for (k = 0;k < surface->num_triangles;k++, elements += 3)
3830 qglArrayElement(elements[0]);qglArrayElement(elements[1]);
3831 qglArrayElement(elements[1]);qglArrayElement(elements[2]);
3832 qglArrayElement(elements[2]);qglArrayElement(elements[0]);
3837 if (r_shownormals.integer)
3839 GL_Color(r_shownormals.value * r_view.colorscale, 0, 0, 1);
3841 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
3843 VectorCopy(rsurface_vertex3f + l * 3, v);
3844 qglVertex3f(v[0], v[1], v[2]);
3845 VectorMA(v, 8, rsurface_svector3f + l * 3, v);
3846 qglVertex3f(v[0], v[1], v[2]);
3850 GL_Color(0, 0, r_shownormals.value * r_view.colorscale, 1);
3852 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
3854 VectorCopy(rsurface_vertex3f + l * 3, v);
3855 qglVertex3f(v[0], v[1], v[2]);
3856 VectorMA(v, 8, rsurface_tvector3f + l * 3, v);
3857 qglVertex3f(v[0], v[1], v[2]);
3861 GL_Color(0, r_shownormals.value * r_view.colorscale, 0, 1);
3863 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
3865 VectorCopy(rsurface_vertex3f + l * 3, v);
3866 qglVertex3f(v[0], v[1], v[2]);
3867 VectorMA(v, 8, rsurface_normal3f + l * 3, v);
3868 qglVertex3f(v[0], v[1], v[2]);
3875 rsurface_texture = NULL;