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_q1bsp_skymasking = {0, "r_qb1sp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
56 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
57 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
58 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
59 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
60 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
61 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
62 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
64 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)"};
66 cvar_t r_glsl = {0, "r_glsl", "1", "enables use of OpenGL 2.0 pixel shaders for lighting"};
67 cvar_t r_glsl_offsetmapping = {0, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
68 cvar_t r_glsl_offsetmapping_reliefmapping = {0, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
69 cvar_t r_glsl_offsetmapping_scale = {0, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
70 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)"};
72 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1", "enables animation smoothing on sprites (requires r_lerpmodels 1)"};
73 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
74 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
76 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
77 cvar_t r_bloom_intensity = {CVAR_SAVE, "r_bloom_intensity", "1.5", "how bright the glow is"};
78 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
79 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
80 cvar_t r_bloom_power = {CVAR_SAVE, "r_bloom_power", "2", "how much to darken the image before blurring to make the bloom effect"};
82 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"};
84 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"};
86 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
88 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
89 cvar_t r_batchmode = {0, "r_batchmode", "1", "selects method of rendering multiple surfaces with one driver call (values are 0, 1, 2, etc...)"};
91 rtexture_t *r_bloom_texture_screen;
92 rtexture_t *r_bloom_texture_bloom;
93 rtexture_t *r_texture_blanknormalmap;
94 rtexture_t *r_texture_white;
95 rtexture_t *r_texture_black;
96 rtexture_t *r_texture_notexture;
97 rtexture_t *r_texture_whitecube;
98 rtexture_t *r_texture_normalizationcube;
99 rtexture_t *r_texture_fogattenuation;
100 //rtexture_t *r_texture_fogintensity;
102 // information about each possible shader permutation
103 r_glsl_permutation_t r_glsl_permutations[SHADERPERMUTATION_COUNT];
104 // currently selected permutation
105 r_glsl_permutation_t *r_glsl_permutation;
107 // temporary variable used by a macro
110 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
113 for (i = 0;i < verts;i++)
124 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
127 for (i = 0;i < verts;i++)
137 // FIXME: move this to client?
140 if (gamemode == GAME_NEHAHRA)
142 Cvar_Set("gl_fogenable", "0");
143 Cvar_Set("gl_fogdensity", "0.2");
144 Cvar_Set("gl_fogred", "0.3");
145 Cvar_Set("gl_foggreen", "0.3");
146 Cvar_Set("gl_fogblue", "0.3");
148 r_refdef.fog_density = r_refdef.fog_red = r_refdef.fog_green = r_refdef.fog_blue = 0.0f;
151 // FIXME: move this to client?
152 void FOG_registercvars(void)
157 if (gamemode == GAME_NEHAHRA)
159 Cvar_RegisterVariable (&gl_fogenable);
160 Cvar_RegisterVariable (&gl_fogdensity);
161 Cvar_RegisterVariable (&gl_fogred);
162 Cvar_RegisterVariable (&gl_foggreen);
163 Cvar_RegisterVariable (&gl_fogblue);
164 Cvar_RegisterVariable (&gl_fogstart);
165 Cvar_RegisterVariable (&gl_fogend);
168 r = (-1.0/256.0) * (FOGTABLEWIDTH * FOGTABLEWIDTH);
169 for (x = 0;x < FOGTABLEWIDTH;x++)
171 alpha = exp(r / ((double)x*(double)x));
172 if (x == FOGTABLEWIDTH - 1)
174 r_refdef.fogtable[x] = bound(0, alpha, 1);
178 static void R_BuildBlankTextures(void)
180 unsigned char data[4];
181 data[0] = 128; // normal X
182 data[1] = 128; // normal Y
183 data[2] = 255; // normal Z
184 data[3] = 128; // height
185 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
190 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
195 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
198 static void R_BuildNoTexture(void)
201 unsigned char pix[16][16][4];
202 // this makes a light grey/dark grey checkerboard texture
203 for (y = 0;y < 16;y++)
205 for (x = 0;x < 16;x++)
207 if ((y < 8) ^ (x < 8))
223 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_RGBA, TEXF_MIPMAP, NULL);
226 static void R_BuildWhiteCube(void)
228 unsigned char data[6*1*1*4];
229 data[ 0] = 255;data[ 1] = 255;data[ 2] = 255;data[ 3] = 255;
230 data[ 4] = 255;data[ 5] = 255;data[ 6] = 255;data[ 7] = 255;
231 data[ 8] = 255;data[ 9] = 255;data[10] = 255;data[11] = 255;
232 data[12] = 255;data[13] = 255;data[14] = 255;data[15] = 255;
233 data[16] = 255;data[17] = 255;data[18] = 255;data[19] = 255;
234 data[20] = 255;data[21] = 255;data[22] = 255;data[23] = 255;
235 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
238 static void R_BuildNormalizationCube(void)
242 vec_t s, t, intensity;
244 unsigned char data[6][NORMSIZE][NORMSIZE][4];
245 for (side = 0;side < 6;side++)
247 for (y = 0;y < NORMSIZE;y++)
249 for (x = 0;x < NORMSIZE;x++)
251 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
252 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
287 intensity = 127.0f / sqrt(DotProduct(v, v));
288 data[side][y][x][0] = (unsigned char)(128.0f + intensity * v[0]);
289 data[side][y][x][1] = (unsigned char)(128.0f + intensity * v[1]);
290 data[side][y][x][2] = (unsigned char)(128.0f + intensity * v[2]);
291 data[side][y][x][3] = 255;
295 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, &data[0][0][0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
298 static void R_BuildFogTexture(void)
303 unsigned char data1[FOGWIDTH][4];
304 //unsigned char data2[FOGWIDTH][4];
305 r = (-1.0/256.0) * (FOGWIDTH * FOGWIDTH);
306 for (x = 0;x < FOGWIDTH;x++)
308 alpha = exp(r / ((double)x*(double)x));
309 if (x == FOGWIDTH - 1)
311 b = (int)(256.0 * alpha);
312 b = bound(0, b, 255);
313 data1[x][0] = 255 - b;
314 data1[x][1] = 255 - b;
315 data1[x][2] = 255 - b;
322 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
323 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
326 static const char *builtinshaderstring =
327 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
328 "// written by Forest 'LordHavoc' Hale\n"
330 "// common definitions between vertex shader and fragment shader:\n"
332 "varying vec2 TexCoord;\n"
333 "varying vec2 TexCoordLightmap;\n"
335 "varying vec3 CubeVector;\n"
336 "varying vec3 LightVector;\n"
337 "varying vec3 EyeVector;\n"
339 "varying vec3 EyeVectorModelSpace;\n"
342 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
343 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
344 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
349 "// vertex shader specific:\n"
350 "#ifdef VERTEX_SHADER\n"
352 "uniform vec3 LightPosition;\n"
353 "uniform vec3 EyePosition;\n"
354 "uniform vec3 LightDir;\n"
356 "// TODO: get rid of tangentt (texcoord2) and use a crossproduct to regenerate it from tangents (texcoord1) and normal (texcoord3)\n"
360 " gl_FrontColor = gl_Color;\n"
361 " // copy the surface texcoord\n"
362 " TexCoord = vec2(gl_TextureMatrix[0] * gl_MultiTexCoord0);\n"
363 "#if !defined(MODE_LIGHTSOURCE) && !defined(MODE_LIGHTDIRECTION)\n"
364 " TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
367 "#ifdef MODE_LIGHTSOURCE\n"
368 " // transform vertex position into light attenuation/cubemap space\n"
369 " // (-1 to +1 across the light box)\n"
370 " CubeVector = vec3(gl_TextureMatrix[3] * gl_Vertex);\n"
372 " // transform unnormalized light direction into tangent space\n"
373 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
374 " // normalize it per pixel)\n"
375 " vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
376 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
377 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
378 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
381 "#ifdef MODE_LIGHTDIRECTION\n"
382 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
383 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
384 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
387 " // transform unnormalized eye direction into tangent space\n"
389 " vec3 EyeVectorModelSpace;\n"
391 " EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
392 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
393 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
394 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
396 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
397 " VectorS = gl_MultiTexCoord1.xyz;\n"
398 " VectorT = gl_MultiTexCoord2.xyz;\n"
399 " VectorR = gl_MultiTexCoord3.xyz;\n"
402 " // transform vertex to camera space, using ftransform to match non-VS\n"
404 " gl_Position = ftransform();\n"
407 "#endif // VERTEX_SHADER\n"
412 "// fragment shader specific:\n"
413 "#ifdef FRAGMENT_SHADER\n"
415 "uniform sampler2D Texture_Normal;\n"
416 "uniform sampler2D Texture_Color;\n"
417 "uniform sampler2D Texture_Gloss;\n"
418 "uniform samplerCube Texture_Cube;\n"
419 "uniform sampler2D Texture_FogMask;\n"
420 "uniform sampler2D Texture_Pants;\n"
421 "uniform sampler2D Texture_Shirt;\n"
422 "uniform sampler2D Texture_Lightmap;\n"
423 "uniform sampler2D Texture_Deluxemap;\n"
424 "uniform sampler2D Texture_Glow;\n"
426 "uniform vec3 LightColor;\n"
427 "uniform vec3 AmbientColor;\n"
428 "uniform vec3 DiffuseColor;\n"
429 "uniform vec3 SpecularColor;\n"
430 "uniform vec3 Color_Pants;\n"
431 "uniform vec3 Color_Shirt;\n"
432 "uniform vec3 FogColor;\n"
434 "uniform float OffsetMapping_Scale;\n"
435 "uniform float OffsetMapping_Bias;\n"
436 "uniform float FogRangeRecip;\n"
438 "uniform float AmbientScale;\n"
439 "uniform float DiffuseScale;\n"
440 "uniform float SpecularScale;\n"
441 "uniform float SpecularPower;\n"
445 " // apply offsetmapping\n"
446 "#ifdef USEOFFSETMAPPING\n"
447 " vec2 TexCoordOffset = TexCoord;\n"
448 "#define TexCoord TexCoordOffset\n"
450 " vec3 eyedir = vec3(normalize(EyeVector));\n"
451 " float depthbias = 1.0 - eyedir.z; // should this be a -?\n"
452 " depthbias = 1.0 - depthbias * depthbias;\n"
454 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
455 " // 14 sample relief mapping: linear search and then binary search\n"
456 " vec3 OffsetVector = vec3(EyeVector.xy * (1.0 / EyeVector.z) * depthbias * OffsetMapping_Scale * vec2(-0.1, 0.1), -0.1);\n"
457 " vec3 RT = vec3(TexCoord - OffsetVector.xy * 10.0, 1.0) + OffsetVector;\n"
458 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
459 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
460 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
461 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
462 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
463 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
464 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
465 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
466 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;OffsetVector *= 0.5;RT -= OffsetVector;\n"
467 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;OffsetVector *= 0.5;RT -= OffsetVector;\n"
468 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;OffsetVector *= 0.5;RT -= OffsetVector;\n"
469 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;OffsetVector *= 0.5;RT -= OffsetVector;\n"
470 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;OffsetVector *= 0.5;RT -= OffsetVector;\n"
471 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;OffsetVector *= 0.5;RT -= OffsetVector;\n"
472 " TexCoord = RT.xy;\n"
474 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
475 " vec2 OffsetVector = vec2((EyeVector.xy * (1.0 / EyeVector.z) * depthbias) * OffsetMapping_Scale * vec2(-0.333, 0.333));\n"
476 " //TexCoord += OffsetVector * 3.0;\n"
477 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
478 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
479 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
483 " // combine the diffuse textures (base, pants, shirt)\n"
484 " vec4 color = vec4(texture2D(Texture_Color, TexCoord));\n"
485 "#ifdef USECOLORMAPPING\n"
486 " color.rgb += vec3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + vec3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
492 "#ifdef MODE_LIGHTSOURCE\n"
495 " // get the surface normal and light normal\n"
496 " vec3 surfacenormal = normalize(vec3(texture2D(Texture_Normal, TexCoord)) - 0.5);\n"
497 " vec3 diffusenormal = vec3(normalize(LightVector));\n"
499 " // calculate directional shading\n"
500 " color.rgb *= (AmbientScale + DiffuseScale * max(dot(surfacenormal, diffusenormal), 0.0));\n"
501 "#ifdef USESPECULAR\n"
502 " vec3 specularnormal = vec3(normalize(diffusenormal + vec3(normalize(EyeVector))));\n"
503 " color.rgb += vec3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(max(dot(surfacenormal, specularnormal), 0.0), SpecularPower);\n"
506 "#ifdef USECUBEFILTER\n"
507 " // apply light cubemap filter\n"
508 " //color.rgb *= normalize(CubeVector) * 0.5 + 0.5;//vec3(textureCube(Texture_Cube, CubeVector));\n"
509 " color.rgb *= vec3(textureCube(Texture_Cube, CubeVector));\n"
512 " // apply light color\n"
513 " color.rgb *= LightColor;\n"
515 " // apply attenuation\n"
517 " // the attenuation is (1-(x*x+y*y+z*z)) which gives a large bright\n"
518 " // center and sharp falloff at the edge, this is about the most efficient\n"
519 " // we can get away with as far as providing illumination.\n"
521 " // pow(1-(x*x+y*y+z*z), 4) is far more realistic but needs large lights to\n"
522 " // provide significant illumination, large = slow = pain.\n"
523 " color.rgb *= max(1.0 - dot(CubeVector, CubeVector), 0.0);\n"
528 "#elif defined(MODE_LIGHTDIRECTION)\n"
529 " // directional model lighting\n"
531 " // get the surface normal and light normal\n"
532 " vec3 surfacenormal = normalize(vec3(texture2D(Texture_Normal, TexCoord)) - 0.5);\n"
533 " vec3 diffusenormal = vec3(normalize(LightVector));\n"
535 " // calculate directional shading\n"
536 " color.rgb *= AmbientColor + DiffuseColor * max(dot(surfacenormal, diffusenormal), 0.0);\n"
537 "#ifdef USESPECULAR\n"
538 " vec3 specularnormal = vec3(normalize(diffusenormal + vec3(normalize(EyeVector))));\n"
539 " color.rgb += vec3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(max(dot(surfacenormal, specularnormal), 0.0), SpecularPower);\n"
545 "#elif defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE)\n"
546 " // deluxemap lightmapping using light vectors in modelspace (evil q3map2)\n"
548 " // get the surface normal and light normal\n"
549 " vec3 surfacenormal = normalize(vec3(texture2D(Texture_Normal, TexCoord)) - 0.5);\n"
550 " vec3 diffusenormal_modelspace = vec3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - 0.5;\n"
551 " vec3 diffusenormal = normalize(vec3(dot(diffusenormal_modelspace, VectorS), dot(diffusenormal_modelspace, VectorT), dot(diffusenormal_modelspace, VectorR)));\n"
553 " // calculate directional shading\n"
554 " vec3 tempcolor = color.rgb * (DiffuseScale * max(dot(surfacenormal, diffusenormal), 0.0));\n"
555 "#ifdef USESPECULAR\n"
556 " vec3 specularnormal = vec3(normalize(diffusenormal + vec3(normalize(EyeVector))));\n"
557 " tempcolor += vec3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(max(dot(surfacenormal, specularnormal), 0.0), SpecularPower);\n"
560 " // apply lightmap color\n"
561 " color.rgb = tempcolor * vec3(texture2D(Texture_Lightmap, TexCoordLightmap)) + color.rgb * vec3(AmbientScale);\n"
566 "#elif defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
567 " // deluxemap lightmapping using light vectors in tangentspace\n"
569 " // get the surface normal and light normal\n"
570 " vec3 surfacenormal = normalize(vec3(texture2D(Texture_Normal, TexCoord)) - 0.5);\n"
571 " vec3 diffusenormal = normalize(vec3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - 0.5);\n"
573 " // calculate directional shading\n"
574 " vec3 tempcolor = color.rgb * (DiffuseScale * max(dot(surfacenormal, diffusenormal), 0.0));\n"
575 "#ifdef USESPECULAR\n"
576 " vec3 specularnormal = vec3(normalize(diffusenormal + vec3(normalize(EyeVector))));\n"
577 " tempcolor += vec3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(max(dot(surfacenormal, specularnormal), 0.0), SpecularPower);\n"
580 " // apply lightmap color\n"
581 " color.rgb = tempcolor * vec3(texture2D(Texture_Lightmap, TexCoordLightmap)) + color.rgb * vec3(AmbientScale);\n"
586 "#else // MODE none (lightmap)\n"
587 " // apply lightmap color\n"
588 " color.rgb *= vec3(texture2D(Texture_Lightmap, TexCoordLightmap)) * DiffuseScale + vec3(AmbientScale);\n"
591 " color *= gl_Color;\n"
594 " color.rgb += vec3(texture2D(Texture_Glow, TexCoord));\n"
599 " float fog = texture2D(Texture_FogMask, vec2(length(EyeVectorModelSpace)*FogRangeRecip, 0.0)).x;\n"
600 " color.rgb = color.rgb * fog + FogColor * (1.0 - fog);\n"
603 " gl_FragColor = color;\n"
606 "#endif // FRAGMENT_SHADER\n"
609 void R_GLSL_CompilePermutation(int permutation)
611 r_glsl_permutation_t *p = r_glsl_permutations + permutation;
612 int vertstrings_count;
613 int fragstrings_count;
615 const char *vertstrings_list[SHADERPERMUTATION_COUNT+1];
616 const char *fragstrings_list[SHADERPERMUTATION_COUNT+1];
617 char permutationname[256];
621 vertstrings_list[0] = "#define VERTEX_SHADER\n";
622 fragstrings_list[0] = "#define FRAGMENT_SHADER\n";
623 vertstrings_count = 1;
624 fragstrings_count = 1;
625 permutationname[0] = 0;
626 if (permutation & SHADERPERMUTATION_MODE_LIGHTSOURCE)
628 vertstrings_list[vertstrings_count++] = "#define MODE_LIGHTSOURCE\n";
629 fragstrings_list[fragstrings_count++] = "#define MODE_LIGHTSOURCE\n";
630 strlcat(permutationname, " lightsource", sizeof(permutationname));
632 if (permutation & SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_MODELSPACE)
634 vertstrings_list[vertstrings_count++] = "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n";
635 fragstrings_list[fragstrings_count++] = "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n";
636 strlcat(permutationname, " lightdirectionmap_modelspace", sizeof(permutationname));
638 if (permutation & SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)
640 vertstrings_list[vertstrings_count++] = "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n";
641 fragstrings_list[fragstrings_count++] = "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n";
642 strlcat(permutationname, " lightdirectionmap_tangentspace", sizeof(permutationname));
644 if (permutation & SHADERPERMUTATION_MODE_LIGHTDIRECTION)
646 vertstrings_list[vertstrings_count++] = "#define MODE_LIGHTDIRECTION\n";
647 fragstrings_list[fragstrings_count++] = "#define MODE_LIGHTDIRECTION\n";
648 strlcat(permutationname, " lightdirection", sizeof(permutationname));
650 if (permutation & SHADERPERMUTATION_GLOW)
652 vertstrings_list[vertstrings_count++] = "#define USEGLOW\n";
653 fragstrings_list[fragstrings_count++] = "#define USEGLOW\n";
654 strlcat(permutationname, " glow", sizeof(permutationname));
656 if (permutation & SHADERPERMUTATION_COLORMAPPING)
658 vertstrings_list[vertstrings_count++] = "#define USECOLORMAPPING\n";
659 fragstrings_list[fragstrings_count++] = "#define USECOLORMAPPING\n";
660 strlcat(permutationname, " colormapping", sizeof(permutationname));
662 if (permutation & SHADERPERMUTATION_SPECULAR)
664 vertstrings_list[vertstrings_count++] = "#define USESPECULAR\n";
665 fragstrings_list[fragstrings_count++] = "#define USESPECULAR\n";
666 strlcat(permutationname, " specular", sizeof(permutationname));
668 if (permutation & SHADERPERMUTATION_FOG)
670 vertstrings_list[vertstrings_count++] = "#define USEFOG\n";
671 fragstrings_list[fragstrings_count++] = "#define USEFOG\n";
672 strlcat(permutationname, " fog", sizeof(permutationname));
674 if (permutation & SHADERPERMUTATION_CUBEFILTER)
676 vertstrings_list[vertstrings_count++] = "#define USECUBEFILTER\n";
677 fragstrings_list[fragstrings_count++] = "#define USECUBEFILTER\n";
678 strlcat(permutationname, " cubefilter", sizeof(permutationname));
680 if (permutation & SHADERPERMUTATION_OFFSETMAPPING)
682 vertstrings_list[vertstrings_count++] = "#define USEOFFSETMAPPING\n";
683 fragstrings_list[fragstrings_count++] = "#define USEOFFSETMAPPING\n";
684 strlcat(permutationname, " offsetmapping", sizeof(permutationname));
686 if (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING)
688 vertstrings_list[vertstrings_count++] = "#define USEOFFSETMAPPING_RELIEFMAPPING\n";
689 fragstrings_list[fragstrings_count++] = "#define USEOFFSETMAPPING_RELIEFMAPPING\n";
690 strlcat(permutationname, " OFFSETMAPPING_RELIEFMAPPING", sizeof(permutationname));
692 shaderstring = (char *)FS_LoadFile("glsl/default.glsl", r_main_mempool, false, NULL);
695 Con_DPrintf("GLSL shader text loaded from disk\n");
696 vertstrings_list[vertstrings_count++] = shaderstring;
697 fragstrings_list[fragstrings_count++] = shaderstring;
701 vertstrings_list[vertstrings_count++] = builtinshaderstring;
702 fragstrings_list[fragstrings_count++] = builtinshaderstring;
704 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, fragstrings_count, fragstrings_list);
708 qglUseProgramObjectARB(p->program);CHECKGLERROR
709 p->loc_Texture_Normal = qglGetUniformLocationARB(p->program, "Texture_Normal");
710 p->loc_Texture_Color = qglGetUniformLocationARB(p->program, "Texture_Color");
711 p->loc_Texture_Gloss = qglGetUniformLocationARB(p->program, "Texture_Gloss");
712 p->loc_Texture_Cube = qglGetUniformLocationARB(p->program, "Texture_Cube");
713 p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
714 p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
715 p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
716 p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
717 p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
718 p->loc_Texture_Glow = qglGetUniformLocationARB(p->program, "Texture_Glow");
719 p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
720 p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
721 p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
722 p->loc_LightColor = qglGetUniformLocationARB(p->program, "LightColor");
723 p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants");
724 p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt");
725 p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip");
726 p->loc_AmbientScale = qglGetUniformLocationARB(p->program, "AmbientScale");
727 p->loc_DiffuseScale = qglGetUniformLocationARB(p->program, "DiffuseScale");
728 p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
729 p->loc_SpecularScale = qglGetUniformLocationARB(p->program, "SpecularScale");
730 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
731 p->loc_AmbientColor = qglGetUniformLocationARB(p->program, "AmbientColor");
732 p->loc_DiffuseColor = qglGetUniformLocationARB(p->program, "DiffuseColor");
733 p->loc_SpecularColor = qglGetUniformLocationARB(p->program, "SpecularColor");
734 p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
735 if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal, 0);
736 if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color, 1);
737 if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss, 2);
738 if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube, 3);
739 if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask, 4);
740 if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants, 5);
741 if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt, 6);
742 if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap, 7);
743 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap, 8);
744 if (p->loc_Texture_Glow >= 0) qglUniform1iARB(p->loc_Texture_Glow, 9);
746 qglUseProgramObjectARB(0);CHECKGLERROR
749 Con_Printf("permutation%s failed for shader %s, some features may not work properly!\n", permutationname, "glsl/default.glsl");
751 Mem_Free(shaderstring);
754 void R_GLSL_Restart_f(void)
757 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
758 if (r_glsl_permutations[i].program)
759 GL_Backend_FreeProgram(r_glsl_permutations[i].program);
760 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
763 int R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting)
765 // select a permutation of the lighting shader appropriate to this
766 // combination of texture, entity, light source, and fogging, only use the
767 // minimum features necessary to avoid wasting rendering time in the
768 // fragment shader on features that are not being used
770 float specularscale = rsurface_texture->specularscale;
771 r_glsl_permutation = NULL;
772 if (r_shadow_rtlight)
774 permutation |= SHADERPERMUTATION_MODE_LIGHTSOURCE;
775 specularscale *= r_shadow_rtlight->specularscale;
776 if (r_shadow_rtlight->currentcubemap != r_texture_whitecube)
777 permutation |= SHADERPERMUTATION_CUBEFILTER;
781 if (!(rsurface_texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
784 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTION;
787 if (r_glsl_deluxemapping.integer >= 1 && r_refdef.worldmodel && r_refdef.worldmodel->brushq3.deluxemapping && rsurface_lightmaptexture)
789 if (r_refdef.worldmodel->brushq3.deluxemapping_modelspace)
790 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_MODELSPACE;
792 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
794 else if (r_glsl_deluxemapping.integer >= 2) // fake mode
795 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
798 if (rsurface_texture->skin.glow)
799 permutation |= SHADERPERMUTATION_GLOW;
801 if (specularscale > 0)
802 permutation |= SHADERPERMUTATION_SPECULAR;
803 if (r_refdef.fogenabled)
804 permutation |= SHADERPERMUTATION_FOG;
805 if (rsurface_texture->colormapping)
806 permutation |= SHADERPERMUTATION_COLORMAPPING;
807 if (r_glsl_offsetmapping.integer)
809 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
810 if (r_glsl_offsetmapping_reliefmapping.integer)
811 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
813 if (!r_glsl_permutations[permutation].program)
815 if (!r_glsl_permutations[permutation].compiled)
816 R_GLSL_CompilePermutation(permutation);
817 if (!r_glsl_permutations[permutation].program)
819 // remove features until we find a valid permutation
821 for (i = SHADERPERMUTATION_COUNT-1;;i>>=1)
823 // reduce i more quickly whenever it would not remove any bits
827 if (!r_glsl_permutations[permutation].compiled)
828 R_GLSL_CompilePermutation(permutation);
829 if (r_glsl_permutations[permutation].program)
832 return 0; // utterly failed
836 r_glsl_permutation = r_glsl_permutations + permutation;
838 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
839 R_Mesh_TexMatrix(0, &rsurface_texture->currenttexmatrix);
840 if (permutation & SHADERPERMUTATION_MODE_LIGHTSOURCE)
842 if (r_glsl_permutation->loc_Texture_Cube >= 0 && r_shadow_rtlight) R_Mesh_TexBindCubeMap(3, R_GetTexture(r_shadow_rtlight->currentcubemap));
843 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]);
844 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
845 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_shadow_rtlight->ambientscale);
846 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_shadow_rtlight->diffusescale);
847 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, specularscale);
849 else if (permutation & SHADERPERMUTATION_MODE_LIGHTDIRECTION)
851 if (r_glsl_permutation->loc_AmbientColor >= 0)
852 qglUniform3fARB(r_glsl_permutation->loc_AmbientColor, rsurface_entity->modellight_ambient[0], rsurface_entity->modellight_ambient[1], rsurface_entity->modellight_ambient[2]);
853 if (r_glsl_permutation->loc_DiffuseColor >= 0)
854 qglUniform3fARB(r_glsl_permutation->loc_DiffuseColor, rsurface_entity->modellight_diffuse[0], rsurface_entity->modellight_diffuse[1], rsurface_entity->modellight_diffuse[2]);
855 if (r_glsl_permutation->loc_SpecularColor >= 0)
856 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);
857 if (r_glsl_permutation->loc_LightDir >= 0)
858 qglUniform3fARB(r_glsl_permutation->loc_LightDir, rsurface_entity->modellight_lightdir[0], rsurface_entity->modellight_lightdir[1], rsurface_entity->modellight_lightdir[2]);
862 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_ambient.value * 2.0f / 128.0f);
863 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_refdef.lightmapintensity * 2.0f);
864 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, r_refdef.lightmapintensity * specularscale * 2.0f);
866 if (r_glsl_permutation->loc_Texture_Normal >= 0) R_Mesh_TexBind(0, R_GetTexture(rsurface_texture->skin.nmap));
867 if (r_glsl_permutation->loc_Texture_Color >= 0) R_Mesh_TexBind(1, R_GetTexture(rsurface_texture->basetexture));
868 if (r_glsl_permutation->loc_Texture_Gloss >= 0) R_Mesh_TexBind(2, R_GetTexture(rsurface_texture->glosstexture));
869 //if (r_glsl_permutation->loc_Texture_Cube >= 0 && permutation & SHADERPERMUTATION_MODE_LIGHTSOURCE) R_Mesh_TexBindCubeMap(3, R_GetTexture(r_shadow_rtlight->currentcubemap));
870 if (r_glsl_permutation->loc_Texture_FogMask >= 0) R_Mesh_TexBind(4, R_GetTexture(r_texture_fogattenuation));
871 if (r_glsl_permutation->loc_Texture_Pants >= 0) R_Mesh_TexBind(5, R_GetTexture(rsurface_texture->skin.pants));
872 if (r_glsl_permutation->loc_Texture_Shirt >= 0) R_Mesh_TexBind(6, R_GetTexture(rsurface_texture->skin.shirt));
873 //if (r_glsl_permutation->loc_Texture_Lightmap >= 0) R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
874 //if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
875 if (r_glsl_permutation->loc_Texture_Glow >= 0) R_Mesh_TexBind(9, R_GetTexture(rsurface_texture->skin.glow));
876 if (r_glsl_permutation->loc_FogColor >= 0)
878 // additive passes are only darkened by fog, not tinted
879 if (r_shadow_rtlight || (rsurface_texture->currentmaterialflags & MATERIALFLAG_ADD))
880 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
882 qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
884 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface_modelorg[0], rsurface_modelorg[1], rsurface_modelorg[2]);
885 if (r_glsl_permutation->loc_Color_Pants >= 0)
887 if (rsurface_texture->skin.pants)
888 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface_entity->colormap_pantscolor[0], rsurface_entity->colormap_pantscolor[1], rsurface_entity->colormap_pantscolor[2]);
890 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
892 if (r_glsl_permutation->loc_Color_Shirt >= 0)
894 if (rsurface_texture->skin.shirt)
895 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface_entity->colormap_shirtcolor[0], rsurface_entity->colormap_shirtcolor[1], rsurface_entity->colormap_shirtcolor[2]);
897 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
899 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, r_refdef.fograngerecip);
900 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface_texture->specularpower);
901 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
906 void R_SwitchSurfaceShader(int permutation)
908 if (r_glsl_permutation != r_glsl_permutations + permutation)
910 r_glsl_permutation = r_glsl_permutations + permutation;
912 qglUseProgramObjectARB(r_glsl_permutation->program);
917 void gl_main_start(void)
919 r_main_texturepool = R_AllocTexturePool();
920 r_bloom_texture_screen = NULL;
921 r_bloom_texture_bloom = NULL;
922 R_BuildBlankTextures();
924 if (gl_texturecubemap)
927 R_BuildNormalizationCube();
930 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
933 void gl_main_shutdown(void)
935 R_FreeTexturePool(&r_main_texturepool);
936 r_bloom_texture_screen = NULL;
937 r_bloom_texture_bloom = NULL;
938 r_texture_blanknormalmap = NULL;
939 r_texture_white = NULL;
940 r_texture_black = NULL;
941 r_texture_whitecube = NULL;
942 r_texture_normalizationcube = NULL;
946 extern void CL_ParseEntityLump(char *entitystring);
947 void gl_main_newmap(void)
949 // FIXME: move this code to client
951 char *entities, entname[MAX_QPATH];
954 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
955 l = (int)strlen(entname) - 4;
956 if (l >= 0 && !strcmp(entname + l, ".bsp"))
958 strcpy(entname + l, ".ent");
959 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
961 CL_ParseEntityLump(entities);
966 if (cl.worldmodel->brush.entities)
967 CL_ParseEntityLump(cl.worldmodel->brush.entities);
971 void GL_Main_Init(void)
973 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
975 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed\n");
976 FOG_registercvars(); // FIXME: move this fog stuff to client?
977 Cvar_RegisterVariable(&r_nearclip);
978 Cvar_RegisterVariable(&r_showsurfaces);
979 Cvar_RegisterVariable(&r_showtris);
980 Cvar_RegisterVariable(&r_shownormals);
981 Cvar_RegisterVariable(&r_showlighting);
982 Cvar_RegisterVariable(&r_showshadowvolumes);
983 Cvar_RegisterVariable(&r_showcollisionbrushes);
984 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
985 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
986 Cvar_RegisterVariable(&r_showdisabledepthtest);
987 Cvar_RegisterVariable(&r_drawportals);
988 Cvar_RegisterVariable(&r_drawentities);
989 Cvar_RegisterVariable(&r_drawviewmodel);
990 Cvar_RegisterVariable(&r_speeds);
991 Cvar_RegisterVariable(&r_fullbrights);
992 Cvar_RegisterVariable(&r_wateralpha);
993 Cvar_RegisterVariable(&r_dynamic);
994 Cvar_RegisterVariable(&r_fullbright);
995 Cvar_RegisterVariable(&r_q1bsp_skymasking);
996 Cvar_RegisterVariable(&r_textureunits);
997 Cvar_RegisterVariable(&r_glsl);
998 Cvar_RegisterVariable(&r_glsl_offsetmapping);
999 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
1000 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
1001 Cvar_RegisterVariable(&r_glsl_deluxemapping);
1002 Cvar_RegisterVariable(&r_lerpsprites);
1003 Cvar_RegisterVariable(&r_lerpmodels);
1004 Cvar_RegisterVariable(&r_waterscroll);
1005 Cvar_RegisterVariable(&r_bloom);
1006 Cvar_RegisterVariable(&r_bloom_intensity);
1007 Cvar_RegisterVariable(&r_bloom_blur);
1008 Cvar_RegisterVariable(&r_bloom_resolution);
1009 Cvar_RegisterVariable(&r_bloom_power);
1010 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
1011 Cvar_RegisterVariable(&developer_texturelogging);
1012 Cvar_RegisterVariable(&gl_lightmaps);
1013 Cvar_RegisterVariable(&r_test);
1014 Cvar_RegisterVariable(&r_batchmode);
1015 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
1016 Cvar_SetValue("r_fullbrights", 0);
1017 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
1020 extern void R_Textures_Init(void);
1021 extern void GL_Draw_Init(void);
1022 extern void GL_Main_Init(void);
1023 extern void R_Shadow_Init(void);
1024 extern void R_Sky_Init(void);
1025 extern void GL_Surf_Init(void);
1026 extern void R_Crosshairs_Init(void);
1027 extern void R_Light_Init(void);
1028 extern void R_Particles_Init(void);
1029 extern void R_Explosion_Init(void);
1030 extern void gl_backend_init(void);
1031 extern void Sbar_Init(void);
1032 extern void R_LightningBeams_Init(void);
1033 extern void Mod_RenderInit(void);
1035 void Render_Init(void)
1044 R_Crosshairs_Init();
1049 R_LightningBeams_Init();
1058 extern char *ENGINE_EXTENSIONS;
1061 VID_CheckExtensions();
1063 // LordHavoc: report supported extensions
1064 Con_DPrintf("\nengine extensions: %s\n", vm_sv_extensions );
1066 // clear to black (loading plaque will be seen over this)
1068 qglClearColor(0,0,0,1);CHECKGLERROR
1069 qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
1072 int R_CullBox(const vec3_t mins, const vec3_t maxs)
1076 for (i = 0;i < 4;i++)
1078 p = r_view.frustum + i;
1083 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1087 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1091 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1095 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1099 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1103 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1107 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1111 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1119 //==================================================================================
1121 static void R_UpdateEntityLighting(entity_render_t *ent)
1123 vec3_t tempdiffusenormal;
1124 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));
1125 VectorClear(ent->modellight_diffuse);
1126 VectorClear(ent->modellight_lightdir);
1127 if ((ent->flags & RENDER_LIGHT) && r_refdef.worldmodel && r_refdef.worldmodel->brush.LightPoint)
1128 r_refdef.worldmodel->brush.LightPoint(r_refdef.worldmodel, ent->origin, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
1130 VectorSet(ent->modellight_ambient, 1, 1, 1);
1131 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
1132 VectorNormalize(ent->modellight_lightdir);
1133 ent->modellight_ambient[0] *= ent->colormod[0] * r_refdef.lightmapintensity;
1134 ent->modellight_ambient[1] *= ent->colormod[1] * r_refdef.lightmapintensity;
1135 ent->modellight_ambient[2] *= ent->colormod[2] * r_refdef.lightmapintensity;
1136 ent->modellight_diffuse[0] *= ent->colormod[0] * r_refdef.lightmapintensity;
1137 ent->modellight_diffuse[1] *= ent->colormod[1] * r_refdef.lightmapintensity;
1138 ent->modellight_diffuse[2] *= ent->colormod[2] * r_refdef.lightmapintensity;
1141 static void R_View_UpdateEntityVisible (void)
1144 entity_render_t *ent;
1146 if (!r_drawentities.integer)
1149 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : (chase_active.integer ? 0 : RENDER_EXTERIORMODEL);
1150 if (r_refdef.worldmodel && r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs)
1152 // worldmodel can check visibility
1153 for (i = 0;i < r_refdef.numentities;i++)
1155 ent = r_refdef.entities[i];
1156 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));
1161 // no worldmodel or it can't check visibility
1162 for (i = 0;i < r_refdef.numentities;i++)
1164 ent = r_refdef.entities[i];
1165 r_viewcache.entityvisible[i] = !(ent->flags & renderimask) && !R_CullBox(ent->mins, ent->maxs) && (ent->effects & EF_NODEPTHTEST);
1170 // only used if skyrendermasked, and normally returns false
1171 int R_DrawBrushModelsSky (void)
1174 entity_render_t *ent;
1176 if (!r_drawentities.integer)
1180 for (i = 0;i < r_refdef.numentities;i++)
1182 if (!r_viewcache.entityvisible[i])
1184 ent = r_refdef.entities[i];
1185 if (!ent->model || !ent->model->DrawSky)
1187 ent->model->DrawSky(ent);
1193 void R_DrawNoModel(entity_render_t *ent);
1194 void R_DrawModels(void)
1197 entity_render_t *ent;
1199 if (!r_drawentities.integer)
1202 for (i = 0;i < r_refdef.numentities;i++)
1204 if (!r_viewcache.entityvisible[i])
1206 ent = r_refdef.entities[i];
1207 r_refdef.stats.entities++;
1208 if (ent->model && ent->model->Draw != NULL)
1209 ent->model->Draw(ent);
1215 static void R_View_SetFrustum(void)
1217 // break apart the view matrix into vectors for various purposes
1218 Matrix4x4_ToVectors(&r_view.matrix, r_view.forward, r_view.left, r_view.up, r_view.origin);
1219 VectorNegate(r_view.left, r_view.right);
1222 r_view.frustum[0].normal[0] = 0 - 1.0 / r_view.frustum_x;
1223 r_view.frustum[0].normal[1] = 0 - 0;
1224 r_view.frustum[0].normal[2] = -1 - 0;
1225 r_view.frustum[1].normal[0] = 0 + 1.0 / r_view.frustum_x;
1226 r_view.frustum[1].normal[1] = 0 + 0;
1227 r_view.frustum[1].normal[2] = -1 + 0;
1228 r_view.frustum[2].normal[0] = 0 - 0;
1229 r_view.frustum[2].normal[1] = 0 - 1.0 / r_view.frustum_y;
1230 r_view.frustum[2].normal[2] = -1 - 0;
1231 r_view.frustum[3].normal[0] = 0 + 0;
1232 r_view.frustum[3].normal[1] = 0 + 1.0 / r_view.frustum_y;
1233 r_view.frustum[3].normal[2] = -1 + 0;
1237 zNear = r_refdef.nearclip;
1238 nudge = 1.0 - 1.0 / (1<<23);
1239 r_view.frustum[4].normal[0] = 0 - 0;
1240 r_view.frustum[4].normal[1] = 0 - 0;
1241 r_view.frustum[4].normal[2] = -1 - -nudge;
1242 r_view.frustum[4].dist = 0 - -2 * zNear * nudge;
1243 r_view.frustum[5].normal[0] = 0 + 0;
1244 r_view.frustum[5].normal[1] = 0 + 0;
1245 r_view.frustum[5].normal[2] = -1 + -nudge;
1246 r_view.frustum[5].dist = 0 + -2 * zNear * nudge;
1252 r_view.frustum[0].normal[0] = m[3] - m[0];
1253 r_view.frustum[0].normal[1] = m[7] - m[4];
1254 r_view.frustum[0].normal[2] = m[11] - m[8];
1255 r_view.frustum[0].dist = m[15] - m[12];
1257 r_view.frustum[1].normal[0] = m[3] + m[0];
1258 r_view.frustum[1].normal[1] = m[7] + m[4];
1259 r_view.frustum[1].normal[2] = m[11] + m[8];
1260 r_view.frustum[1].dist = m[15] + m[12];
1262 r_view.frustum[2].normal[0] = m[3] - m[1];
1263 r_view.frustum[2].normal[1] = m[7] - m[5];
1264 r_view.frustum[2].normal[2] = m[11] - m[9];
1265 r_view.frustum[2].dist = m[15] - m[13];
1267 r_view.frustum[3].normal[0] = m[3] + m[1];
1268 r_view.frustum[3].normal[1] = m[7] + m[5];
1269 r_view.frustum[3].normal[2] = m[11] + m[9];
1270 r_view.frustum[3].dist = m[15] + m[13];
1272 r_view.frustum[4].normal[0] = m[3] - m[2];
1273 r_view.frustum[4].normal[1] = m[7] - m[6];
1274 r_view.frustum[4].normal[2] = m[11] - m[10];
1275 r_view.frustum[4].dist = m[15] - m[14];
1277 r_view.frustum[5].normal[0] = m[3] + m[2];
1278 r_view.frustum[5].normal[1] = m[7] + m[6];
1279 r_view.frustum[5].normal[2] = m[11] + m[10];
1280 r_view.frustum[5].dist = m[15] + m[14];
1285 VectorMAM(1, r_view.forward, 1.0 / -r_view.frustum_x, r_view.left, r_view.frustum[0].normal);
1286 VectorMAM(1, r_view.forward, 1.0 / r_view.frustum_x, r_view.left, r_view.frustum[1].normal);
1287 VectorMAM(1, r_view.forward, 1.0 / -r_view.frustum_y, r_view.up, r_view.frustum[2].normal);
1288 VectorMAM(1, r_view.forward, 1.0 / r_view.frustum_y, r_view.up, r_view.frustum[3].normal);
1289 VectorCopy(r_view.forward, r_view.frustum[4].normal);
1290 VectorNormalize(r_view.frustum[0].normal);
1291 VectorNormalize(r_view.frustum[1].normal);
1292 VectorNormalize(r_view.frustum[2].normal);
1293 VectorNormalize(r_view.frustum[3].normal);
1294 r_view.frustum[0].dist = DotProduct (r_view.origin, r_view.frustum[0].normal);
1295 r_view.frustum[1].dist = DotProduct (r_view.origin, r_view.frustum[1].normal);
1296 r_view.frustum[2].dist = DotProduct (r_view.origin, r_view.frustum[2].normal);
1297 r_view.frustum[3].dist = DotProduct (r_view.origin, r_view.frustum[3].normal);
1298 r_view.frustum[4].dist = DotProduct (r_view.origin, r_view.frustum[4].normal) + r_refdef.nearclip;
1299 PlaneClassify(&r_view.frustum[0]);
1300 PlaneClassify(&r_view.frustum[1]);
1301 PlaneClassify(&r_view.frustum[2]);
1302 PlaneClassify(&r_view.frustum[3]);
1303 PlaneClassify(&r_view.frustum[4]);
1305 // LordHavoc: note to all quake engine coders, Quake had a special case
1306 // for 90 degrees which assumed a square view (wrong), so I removed it,
1307 // Quake2 has it disabled as well.
1309 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
1310 //RotatePointAroundVector( r_view.frustum[0].normal, r_view.up, r_view.forward, -(90 - r_refdef.fov_x / 2));
1311 //r_view.frustum[0].dist = DotProduct (r_view.origin, frustum[0].normal);
1312 //PlaneClassify(&frustum[0]);
1314 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
1315 //RotatePointAroundVector( r_view.frustum[1].normal, r_view.up, r_view.forward, (90 - r_refdef.fov_x / 2));
1316 //r_view.frustum[1].dist = DotProduct (r_view.origin, frustum[1].normal);
1317 //PlaneClassify(&frustum[1]);
1319 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
1320 //RotatePointAroundVector( r_view.frustum[2].normal, r_view.left, r_view.forward, -(90 - r_refdef.fov_y / 2));
1321 //r_view.frustum[2].dist = DotProduct (r_view.origin, frustum[2].normal);
1322 //PlaneClassify(&frustum[2]);
1324 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
1325 //RotatePointAroundVector( r_view.frustum[3].normal, r_view.left, r_view.forward, (90 - r_refdef.fov_y / 2));
1326 //r_view.frustum[3].dist = DotProduct (r_view.origin, frustum[3].normal);
1327 //PlaneClassify(&frustum[3]);
1330 //VectorCopy(r_view.forward, r_view.frustum[4].normal);
1331 //r_view.frustum[4].dist = DotProduct (r_view.origin, frustum[4].normal) + r_nearclip.value;
1332 //PlaneClassify(&frustum[4]);
1335 void R_View_Update(void)
1337 // GL is weird because it's bottom to top, r_view.y is top to bottom
1338 qglViewport(r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
1339 GL_Scissor(r_view.x, r_view.y, r_view.width, r_view.height);
1340 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
1341 R_View_SetFrustum();
1342 R_View_WorldVisibility();
1343 R_View_UpdateEntityVisible();
1346 static void R_BlendView(void)
1348 int screenwidth, screenheight;
1352 float texcoord2f[3][8];
1354 // set the (poorly named) screenwidth and screenheight variables to
1355 // a power of 2 at least as large as the screen, these will define the
1356 // size of the texture to allocate
1357 for (screenwidth = 1;screenwidth < vid.width;screenwidth *= 2);
1358 for (screenheight = 1;screenheight < vid.height;screenheight *= 2);
1360 doblend = r_refdef.viewblend[3] >= 0.01f;
1361 dobloom = r_bloom.integer && screenwidth <= gl_max_texture_size && screenheight <= gl_max_texture_size && r_bloom_resolution.value >= 32 && r_bloom_power.integer >= 1 && r_bloom_power.integer < 100 && r_bloom_blur.value >= 0 && r_bloom_blur.value < 512;
1363 if (!dobloom && !doblend)
1366 GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
1368 GL_DepthTest(false);
1369 R_Mesh_Matrix(&identitymatrix);
1370 // vertex coordinates for a quad that covers the screen exactly
1371 vertex3f[0] = 0;vertex3f[1] = 0;vertex3f[2] = 0;
1372 vertex3f[3] = 1;vertex3f[4] = 0;vertex3f[5] = 0;
1373 vertex3f[6] = 1;vertex3f[7] = 1;vertex3f[8] = 0;
1374 vertex3f[9] = 0;vertex3f[10] = 1;vertex3f[11] = 0;
1375 R_Mesh_VertexPointer(vertex3f);
1376 R_Mesh_ColorPointer(NULL);
1377 R_Mesh_ResetTextureState();
1380 int bloomwidth, bloomheight, x, range;
1381 float xoffset, yoffset, r;
1382 r_refdef.stats.bloom++;
1383 // allocate textures as needed
1384 if (!r_bloom_texture_screen)
1385 r_bloom_texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", screenwidth, screenheight, NULL, TEXTYPE_RGBA, TEXF_FORCENEAREST | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
1386 if (!r_bloom_texture_bloom)
1387 r_bloom_texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", screenwidth, screenheight, NULL, TEXTYPE_RGBA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
1388 // set bloomwidth and bloomheight to the bloom resolution that will be
1389 // used (often less than the screen resolution for faster rendering)
1390 bloomwidth = min(r_view.width, r_bloom_resolution.integer);
1391 bloomheight = min(r_view.height, bloomwidth * r_view.height / r_view.width);
1392 // set up a texcoord array for the full resolution screen image
1393 // (we have to keep this around to copy back during final render)
1394 texcoord2f[0][0] = 0;
1395 texcoord2f[0][1] = (float)r_view.height / (float)screenheight;
1396 texcoord2f[0][2] = (float)r_view.width / (float)screenwidth;
1397 texcoord2f[0][3] = (float)r_view.height / (float)screenheight;
1398 texcoord2f[0][4] = (float)r_view.width / (float)screenwidth;
1399 texcoord2f[0][5] = 0;
1400 texcoord2f[0][6] = 0;
1401 texcoord2f[0][7] = 0;
1402 // set up a texcoord array for the reduced resolution bloom image
1403 // (which will be additive blended over the screen image)
1404 texcoord2f[1][0] = 0;
1405 texcoord2f[1][1] = (float)bloomheight / (float)screenheight;
1406 texcoord2f[1][2] = (float)bloomwidth / (float)screenwidth;
1407 texcoord2f[1][3] = (float)bloomheight / (float)screenheight;
1408 texcoord2f[1][4] = (float)bloomwidth / (float)screenwidth;
1409 texcoord2f[1][5] = 0;
1410 texcoord2f[1][6] = 0;
1411 texcoord2f[1][7] = 0;
1412 R_Mesh_TexCoordPointer(0, 2, texcoord2f[0]);
1413 R_Mesh_TexBind(0, R_GetTexture(r_bloom_texture_screen));
1414 // copy view into the full resolution screen image texture
1415 GL_ActiveTexture(0);
1417 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
1418 r_refdef.stats.bloom_copypixels += r_view.width * r_view.height;
1419 // now scale it down to the bloom size and raise to a power of itself
1420 // to darken it (this leaves the really bright stuff bright, and
1421 // everything else becomes very dark)
1422 // TODO: optimize with multitexture or GLSL
1424 qglViewport(r_view.x, vid.height - (r_view.y + bloomheight), bloomwidth, bloomheight);CHECKGLERROR
1425 GL_BlendFunc(GL_ONE, GL_ZERO);
1426 GL_Color(1, 1, 1, 1);
1427 R_Mesh_Draw(0, 4, 2, polygonelements);
1428 r_refdef.stats.bloom_drawpixels += bloomwidth * bloomheight;
1429 // render multiple times with a multiply blendfunc to raise to a power
1430 GL_BlendFunc(GL_DST_COLOR, GL_ZERO);
1431 for (x = 1;x < r_bloom_power.integer;x++)
1433 R_Mesh_Draw(0, 4, 2, polygonelements);
1434 r_refdef.stats.bloom_drawpixels += bloomwidth * bloomheight;
1436 // we now have a darkened bloom image in the framebuffer, copy it into
1437 // the bloom image texture for more processing
1438 R_Mesh_TexBind(0, R_GetTexture(r_bloom_texture_bloom));
1439 R_Mesh_TexCoordPointer(0, 2, texcoord2f[2]);
1440 GL_ActiveTexture(0);
1442 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view.x, vid.height - (r_view.y + bloomheight), bloomwidth, bloomheight);CHECKGLERROR
1443 r_refdef.stats.bloom_copypixels += bloomwidth * bloomheight;
1444 // blend on at multiple vertical offsets to achieve a vertical blur
1445 // TODO: do offset blends using GLSL
1446 range = r_bloom_blur.integer * bloomwidth / 320;
1447 GL_BlendFunc(GL_ONE, GL_ZERO);
1448 for (x = -range;x <= range;x++)
1450 xoffset = 0 / (float)bloomwidth * (float)bloomwidth / (float)screenwidth;
1451 yoffset = x / (float)bloomheight * (float)bloomheight / (float)screenheight;
1452 // compute a texcoord array with the specified x and y offset
1453 texcoord2f[2][0] = xoffset+0;
1454 texcoord2f[2][1] = yoffset+(float)bloomheight / (float)screenheight;
1455 texcoord2f[2][2] = xoffset+(float)bloomwidth / (float)screenwidth;
1456 texcoord2f[2][3] = yoffset+(float)bloomheight / (float)screenheight;
1457 texcoord2f[2][4] = xoffset+(float)bloomwidth / (float)screenwidth;
1458 texcoord2f[2][5] = yoffset+0;
1459 texcoord2f[2][6] = xoffset+0;
1460 texcoord2f[2][7] = yoffset+0;
1461 // this r value looks like a 'dot' particle, fading sharply to
1462 // black at the edges
1463 // (probably not realistic but looks good enough)
1464 r = r_bloom_intensity.value/(range*2+1)*(1 - x*x/(float)(range*range));
1467 GL_Color(r, r, r, 1);
1468 R_Mesh_Draw(0, 4, 2, polygonelements);
1469 r_refdef.stats.bloom_drawpixels += bloomwidth * bloomheight;
1470 GL_BlendFunc(GL_ONE, GL_ONE);
1472 // copy the vertically blurred bloom view to a texture
1473 GL_ActiveTexture(0);
1475 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view.x, vid.height - (r_view.y + bloomheight), bloomwidth, bloomheight);CHECKGLERROR
1476 r_refdef.stats.bloom_copypixels += bloomwidth * bloomheight;
1477 // blend the vertically blurred image at multiple offsets horizontally
1478 // to finish the blur effect
1479 // TODO: do offset blends using GLSL
1480 range = r_bloom_blur.integer * bloomwidth / 320;
1481 GL_BlendFunc(GL_ONE, GL_ZERO);
1482 for (x = -range;x <= range;x++)
1484 xoffset = x / (float)bloomwidth * (float)bloomwidth / (float)screenwidth;
1485 yoffset = 0 / (float)bloomheight * (float)bloomheight / (float)screenheight;
1486 // compute a texcoord array with the specified x and y offset
1487 texcoord2f[2][0] = xoffset+0;
1488 texcoord2f[2][1] = yoffset+(float)bloomheight / (float)screenheight;
1489 texcoord2f[2][2] = xoffset+(float)bloomwidth / (float)screenwidth;
1490 texcoord2f[2][3] = yoffset+(float)bloomheight / (float)screenheight;
1491 texcoord2f[2][4] = xoffset+(float)bloomwidth / (float)screenwidth;
1492 texcoord2f[2][5] = yoffset+0;
1493 texcoord2f[2][6] = xoffset+0;
1494 texcoord2f[2][7] = yoffset+0;
1495 // this r value looks like a 'dot' particle, fading sharply to
1496 // black at the edges
1497 // (probably not realistic but looks good enough)
1498 r = r_bloom_intensity.value/(range*2+1)*(1 - x*x/(float)(range*range));
1501 GL_Color(r, r, r, 1);
1502 R_Mesh_Draw(0, 4, 2, polygonelements);
1503 r_refdef.stats.bloom_drawpixels += bloomwidth * bloomheight;
1504 GL_BlendFunc(GL_ONE, GL_ONE);
1506 // copy the blurred bloom view to a texture
1507 GL_ActiveTexture(0);
1509 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view.x, vid.height - (r_view.y + bloomheight), bloomwidth, bloomheight);CHECKGLERROR
1510 r_refdef.stats.bloom_copypixels += bloomwidth * bloomheight;
1511 // go back to full view area
1512 qglViewport(r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
1513 // put the original screen image back in place and blend the bloom
1516 GL_BlendFunc(GL_ONE, GL_ZERO);
1517 // do both in one pass if possible
1518 R_Mesh_TexBind(0, R_GetTexture(r_bloom_texture_screen));
1519 R_Mesh_TexCoordPointer(0, 2, texcoord2f[0]);
1520 if (r_textureunits.integer >= 2 && gl_combine.integer)
1522 R_Mesh_TexCombine(1, GL_ADD, GL_ADD, 1, 1);
1523 R_Mesh_TexBind(1, R_GetTexture(r_bloom_texture_bloom));
1524 R_Mesh_TexCoordPointer(1, 2, texcoord2f[1]);
1528 R_Mesh_Draw(0, 4, 2, polygonelements);
1529 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
1530 // now blend on the bloom texture
1531 GL_BlendFunc(GL_ONE, GL_ONE);
1532 R_Mesh_TexBind(0, R_GetTexture(r_bloom_texture_bloom));
1533 R_Mesh_TexCoordPointer(0, 2, texcoord2f[1]);
1535 R_Mesh_Draw(0, 4, 2, polygonelements);
1536 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
1540 // apply a color tint to the whole view
1541 R_Mesh_ResetTextureState();
1542 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1543 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
1544 R_Mesh_Draw(0, 4, 2, polygonelements);
1548 void R_RenderScene(void);
1550 matrix4x4_t r_waterscrollmatrix;
1552 void R_UpdateVariables(void)
1558 r_refdef.farclip = 4096;
1559 if (r_refdef.worldmodel)
1560 r_refdef.farclip += VectorDistance(r_refdef.worldmodel->normalmins, r_refdef.worldmodel->normalmaxs);
1561 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
1563 r_refdef.polygonfactor = 0;
1564 r_refdef.polygonoffset = 0;
1565 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_shadow_polygonfactor.value;
1566 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_shadow_polygonoffset.value;
1568 r_refdef.rtworld = r_shadow_realtime_world.integer;
1569 r_refdef.rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
1570 r_refdef.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer;
1571 r_refdef.rtdlightshadows = r_refdef.rtdlight && (r_refdef.rtworld ? r_shadow_realtime_world_dlightshadows.integer : r_shadow_realtime_dlight_shadows.integer) && gl_stencil;
1572 r_refdef.lightmapintensity = r_refdef.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
1573 if (r_showsurfaces.integer)
1575 r_refdef.rtworld = false;
1576 r_refdef.rtworldshadows = false;
1577 r_refdef.rtdlight = false;
1578 r_refdef.rtdlightshadows = false;
1579 r_refdef.lightmapintensity = 0;
1582 if (gamemode == GAME_NEHAHRA)
1584 if (gl_fogenable.integer)
1586 r_refdef.oldgl_fogenable = true;
1587 r_refdef.fog_density = gl_fogdensity.value;
1588 r_refdef.fog_red = gl_fogred.value;
1589 r_refdef.fog_green = gl_foggreen.value;
1590 r_refdef.fog_blue = gl_fogblue.value;
1592 else if (r_refdef.oldgl_fogenable)
1594 r_refdef.oldgl_fogenable = false;
1595 r_refdef.fog_density = 0;
1596 r_refdef.fog_red = 0;
1597 r_refdef.fog_green = 0;
1598 r_refdef.fog_blue = 0;
1601 if (r_refdef.fog_density)
1603 r_refdef.fogcolor[0] = bound(0.0f, r_refdef.fog_red , 1.0f);
1604 r_refdef.fogcolor[1] = bound(0.0f, r_refdef.fog_green, 1.0f);
1605 r_refdef.fogcolor[2] = bound(0.0f, r_refdef.fog_blue , 1.0f);
1607 if (r_refdef.fog_density)
1609 r_refdef.fogenabled = true;
1610 // this is the point where the fog reaches 0.9986 alpha, which we
1611 // consider a good enough cutoff point for the texture
1612 // (0.9986 * 256 == 255.6)
1613 r_refdef.fogrange = 400 / r_refdef.fog_density;
1614 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
1615 r_refdef.fogtabledistmultiplier = FOGTABLEWIDTH * r_refdef.fograngerecip;
1616 // fog color was already set
1619 r_refdef.fogenabled = false;
1621 // update some cached entity properties...
1622 for (i = 0;i < r_refdef.numentities;i++)
1624 entity_render_t *ent = r_refdef.entities[i];
1625 // some of the renderer still relies on origin...
1626 Matrix4x4_OriginFromMatrix(&ent->matrix, ent->origin);
1627 // some of the renderer still relies on scale...
1628 ent->scale = Matrix4x4_ScaleFromMatrix(&ent->matrix);
1629 R_UpdateEntityLighting(ent);
1638 void R_RenderView(void)
1640 if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
1641 return; //Host_Error ("R_RenderView: NULL worldmodel");
1644 GL_ScissorTest(true);
1646 if (r_timereport_active)
1647 R_TimeReport("setup");
1650 if (r_timereport_active)
1651 R_TimeReport("visibility");
1654 if (r_timereport_active)
1655 R_TimeReport("clear");
1660 if (r_timereport_active)
1661 R_TimeReport("blendview");
1663 GL_Scissor(0, 0, vid.width, vid.height);
1664 GL_ScissorTest(false);
1669 void CSQC_R_ClearScreen (void)
1671 if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
1672 return; //Host_Error ("R_RenderView: NULL worldmodel");
1675 GL_ScissorTest(true);
1677 if (r_timereport_active)
1678 R_TimeReport("setup");
1681 if (r_timereport_active)
1682 R_TimeReport("visibility");
1685 if (r_timereport_active)
1686 R_TimeReport("clear");
1691 void CSQC_R_RenderScene (void)
1696 if (r_timereport_active)
1697 R_TimeReport("blendview");
1699 GL_Scissor(0, 0, vid.width, vid.height);
1700 GL_ScissorTest(false);
1704 extern void R_DrawLightningBeams (void);
1705 extern void VM_AddPolygonsToMeshQueue (void);
1706 extern void R_DrawPortals (void);
1707 void R_RenderScene(void)
1709 // don't let sound skip if going slow
1710 if (r_refdef.extraupdate)
1714 if (gl_support_fragment_shader)
1716 qglUseProgramObjectARB(0);CHECKGLERROR
1718 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
1719 qglPolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR
1720 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
1722 R_MeshQueue_BeginScene();
1724 if (r_refdef.rtworldshadows || r_refdef.rtdlightshadows)
1725 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_view.frustum_x, r_view.frustum_y, r_refdef.nearclip);
1727 GL_SetupView_Mode_Perspective(r_view.frustum_x, r_view.frustum_y, r_refdef.nearclip, r_refdef.farclip);
1729 GL_SetupView_Orientation_FromEntity(&r_view.matrix);
1731 R_Shadow_UpdateWorldLightSelection();
1735 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);
1737 if (cl.csqc_vidvars.drawworld)
1739 // don't let sound skip if going slow
1740 if (r_refdef.extraupdate)
1743 if (r_refdef.worldmodel && r_refdef.worldmodel->DrawSky)
1745 r_refdef.worldmodel->DrawSky(r_refdef.worldentity);
1746 if (r_timereport_active)
1747 R_TimeReport("worldsky");
1750 if (R_DrawBrushModelsSky() && r_timereport_active)
1751 R_TimeReport("bmodelsky");
1753 if (r_refdef.worldmodel && r_refdef.worldmodel->Draw)
1755 r_refdef.worldmodel->Draw(r_refdef.worldentity);
1756 if (r_timereport_active)
1757 R_TimeReport("world");
1761 // don't let sound skip if going slow
1762 if (r_refdef.extraupdate)
1766 if (r_timereport_active)
1767 R_TimeReport("models");
1769 // don't let sound skip if going slow
1770 if (r_refdef.extraupdate)
1773 R_ShadowVolumeLighting(false);
1774 if (r_timereport_active)
1775 R_TimeReport("rtlights");
1777 // don't let sound skip if going slow
1778 if (r_refdef.extraupdate)
1781 if (cl.csqc_vidvars.drawworld)
1783 R_DrawLightningBeams();
1784 if (r_timereport_active)
1785 R_TimeReport("lightning");
1788 if (r_timereport_active)
1789 R_TimeReport("particles");
1792 if (r_timereport_active)
1793 R_TimeReport("explosions");
1796 if (gl_support_fragment_shader)
1798 qglUseProgramObjectARB(0);CHECKGLERROR
1800 VM_AddPolygonsToMeshQueue();
1802 if (r_drawportals.integer)
1805 if (r_timereport_active)
1806 R_TimeReport("portals");
1809 if (gl_support_fragment_shader)
1811 qglUseProgramObjectARB(0);CHECKGLERROR
1813 R_MeshQueue_RenderTransparent();
1814 if (r_timereport_active)
1815 R_TimeReport("drawtrans");
1817 if (gl_support_fragment_shader)
1819 qglUseProgramObjectARB(0);CHECKGLERROR
1822 if (cl.csqc_vidvars.drawworld)
1825 if (r_timereport_active)
1826 R_TimeReport("coronas");
1828 if(cl.csqc_vidvars.drawcrosshair)
1830 R_DrawWorldCrosshair();
1831 if (r_timereport_active)
1832 R_TimeReport("crosshair");
1835 // don't let sound skip if going slow
1836 if (r_refdef.extraupdate)
1840 if (gl_support_fragment_shader)
1842 qglUseProgramObjectARB(0);CHECKGLERROR
1844 qglPolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR
1845 qglDisable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
1849 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
1852 float *v, *c, f1, f2, diff[3], vertex3f[8*3], color4f[8*4];
1853 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1854 GL_DepthMask(false);
1856 R_Mesh_Matrix(&identitymatrix);
1858 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2];
1859 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
1860 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
1861 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
1862 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
1863 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
1864 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
1865 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
1866 R_FillColors(color, 8, cr, cg, cb, ca);
1867 if (r_refdef.fogenabled)
1869 for (i = 0, v = vertex, c = color;i < 8;i++, v += 4, c += 4)
1871 f2 = VERTEXFOGTABLE(VectorDistance(v, r_view.origin));
1873 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
1874 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
1875 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
1878 R_Mesh_VertexPointer(vertex3f);
1879 R_Mesh_ColorPointer(color);
1880 R_Mesh_ResetTextureState();
1885 int nomodelelements[24] =
1897 float nomodelvertex3f[6*3] =
1907 float nomodelcolor4f[6*4] =
1909 0.0f, 0.0f, 0.5f, 1.0f,
1910 0.0f, 0.0f, 0.5f, 1.0f,
1911 0.0f, 0.5f, 0.0f, 1.0f,
1912 0.0f, 0.5f, 0.0f, 1.0f,
1913 0.5f, 0.0f, 0.0f, 1.0f,
1914 0.5f, 0.0f, 0.0f, 1.0f
1917 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
1922 // this is only called once per entity so numsurfaces is always 1, and
1923 // surfacelist is always {0}, so this code does not handle batches
1924 R_Mesh_Matrix(&ent->matrix);
1926 if (ent->flags & EF_ADDITIVE)
1928 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
1929 GL_DepthMask(false);
1931 else if (ent->alpha < 1)
1933 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1934 GL_DepthMask(false);
1938 GL_BlendFunc(GL_ONE, GL_ZERO);
1941 GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
1942 R_Mesh_VertexPointer(nomodelvertex3f);
1943 if (r_refdef.fogenabled)
1945 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
1946 R_Mesh_ColorPointer(color4f);
1947 f2 = VERTEXFOGTABLE(VectorDistance(ent->origin, r_view.origin));
1949 for (i = 0, c = color4f;i < 6;i++, c += 4)
1951 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
1952 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
1953 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
1957 else if (ent->alpha != 1)
1959 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
1960 R_Mesh_ColorPointer(color4f);
1961 for (i = 0, c = color4f;i < 6;i++, c += 4)
1965 R_Mesh_ColorPointer(nomodelcolor4f);
1966 R_Mesh_ResetTextureState();
1967 R_Mesh_Draw(0, 6, 8, nomodelelements);
1970 void R_DrawNoModel(entity_render_t *ent)
1972 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
1973 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_view.origin : ent->origin, R_DrawNoModel_TransparentCallback, ent, 0, r_shadow_rtlight);
1975 // R_DrawNoModelCallback(ent, 0);
1978 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
1980 vec3_t right1, right2, diff, normal;
1982 VectorSubtract (org2, org1, normal);
1984 // calculate 'right' vector for start
1985 VectorSubtract (r_view.origin, org1, diff);
1986 CrossProduct (normal, diff, right1);
1987 VectorNormalize (right1);
1989 // calculate 'right' vector for end
1990 VectorSubtract (r_view.origin, org2, diff);
1991 CrossProduct (normal, diff, right2);
1992 VectorNormalize (right2);
1994 vert[ 0] = org1[0] + width * right1[0];
1995 vert[ 1] = org1[1] + width * right1[1];
1996 vert[ 2] = org1[2] + width * right1[2];
1997 vert[ 3] = org1[0] - width * right1[0];
1998 vert[ 4] = org1[1] - width * right1[1];
1999 vert[ 5] = org1[2] - width * right1[2];
2000 vert[ 6] = org2[0] - width * right2[0];
2001 vert[ 7] = org2[1] - width * right2[1];
2002 vert[ 8] = org2[2] - width * right2[2];
2003 vert[ 9] = org2[0] + width * right2[0];
2004 vert[10] = org2[1] + width * right2[1];
2005 vert[11] = org2[2] + width * right2[2];
2008 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
2010 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)
2012 float fog = 0.0f, ifog;
2015 if (r_refdef.fogenabled)
2016 fog = VERTEXFOGTABLE(VectorDistance(origin, r_view.origin));
2019 R_Mesh_Matrix(&identitymatrix);
2020 GL_BlendFunc(blendfunc1, blendfunc2);
2021 GL_DepthMask(false);
2022 GL_DepthTest(!depthdisable);
2024 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
2025 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
2026 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
2027 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
2028 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
2029 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
2030 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
2031 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
2032 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
2033 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
2034 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
2035 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
2037 R_Mesh_VertexPointer(vertex3f);
2038 R_Mesh_ColorPointer(NULL);
2039 R_Mesh_ResetTextureState();
2040 R_Mesh_TexBind(0, R_GetTexture(texture));
2041 R_Mesh_TexCoordPointer(0, 2, spritetexcoord2f);
2042 GL_Color(cr * ifog, cg * ifog, cb * ifog, ca);
2043 R_Mesh_Draw(0, 4, 2, polygonelements);
2045 if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
2047 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
2048 GL_BlendFunc(blendfunc1, GL_ONE);
2049 GL_Color(r_refdef.fogcolor[0] * fog, r_refdef.fogcolor[1] * fog, r_refdef.fogcolor[2] * fog, ca);
2050 R_Mesh_Draw(0, 4, 2, polygonelements);
2054 int R_Mesh_AddVertex3f(rmesh_t *mesh, const float *v)
2058 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
2059 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
2061 if (i == mesh->numvertices)
2063 if (mesh->numvertices < mesh->maxvertices)
2065 VectorCopy(v, vertex3f);
2066 mesh->numvertices++;
2068 return mesh->numvertices;
2074 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
2078 element[0] = R_Mesh_AddVertex3f(mesh, vertex3f);vertex3f += 3;
2079 element[1] = R_Mesh_AddVertex3f(mesh, vertex3f);vertex3f += 3;
2080 e = mesh->element3i + mesh->numtriangles * 3;
2081 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
2083 element[2] = R_Mesh_AddVertex3f(mesh, vertex3f);
2084 if (mesh->numtriangles < mesh->maxtriangles)
2089 mesh->numtriangles++;
2091 element[1] = element[2];
2095 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
2097 int planenum, planenum2;
2100 mplane_t *plane, *plane2;
2101 float temppoints[2][256*3];
2102 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
2106 PolygonF_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->normal[3], 1024.0*1024.0*1024.0);
2107 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
2109 if (planenum2 == planenum)
2111 PolygonF_Divide(tempnumpoints, temppoints[w], plane2->normal[0], plane2->normal[1], plane2->normal[2], plane2->dist, 1.0/32.0, 0, NULL, NULL, 256, temppoints[!w], &tempnumpoints, NULL);
2114 if (tempnumpoints < 3)
2116 // generate elements forming a triangle fan for this polygon
2117 R_Mesh_AddPolygon3f(mesh, tempnumpoints, temppoints[w]);
2121 static void R_DrawCollisionBrush(const colbrushf_t *brush)
2124 R_Mesh_VertexPointer(brush->points->v);
2125 i = (int)(((size_t)brush) / sizeof(colbrushf_t));
2126 GL_Color((i & 31) * (1.0f / 32.0f), ((i >> 5) & 31) * (1.0f / 32.0f), ((i >> 10) & 31) * (1.0f / 32.0f), 0.2f);
2127 GL_LockArrays(0, brush->numpoints);
2128 R_Mesh_Draw(0, brush->numpoints, brush->numtriangles, brush->elements);
2129 GL_LockArrays(0, 0);
2132 static void R_DrawCollisionSurface(const entity_render_t *ent, const msurface_t *surface)
2135 if (!surface->num_collisiontriangles)
2137 R_Mesh_VertexPointer(surface->data_collisionvertex3f);
2138 i = (int)(((size_t)surface) / sizeof(msurface_t));
2139 GL_Color((i & 31) * (1.0f / 32.0f), ((i >> 5) & 31) * (1.0f / 32.0f), ((i >> 10) & 31) * (1.0f / 32.0f), 0.2f);
2140 GL_LockArrays(0, surface->num_collisionvertices);
2141 R_Mesh_Draw(0, surface->num_collisionvertices, surface->num_collisiontriangles, surface->data_collisionelement3i);
2142 GL_LockArrays(0, 0);
2145 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)
2147 texturelayer_t *layer;
2148 layer = t->currentlayers + t->currentnumlayers++;
2150 layer->depthmask = depthmask;
2151 layer->blendfunc1 = blendfunc1;
2152 layer->blendfunc2 = blendfunc2;
2153 layer->texture = texture;
2154 layer->texmatrix = *matrix;
2155 layer->color[0] = r;
2156 layer->color[1] = g;
2157 layer->color[2] = b;
2158 layer->color[3] = a;
2161 void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
2163 // FIXME: identify models using a better check than ent->model->brush.shadowmesh
2164 //int lightmode = ((ent->effects & EF_FULLBRIGHT) || ent->model->brush.shadowmesh) ? 0 : 2;
2167 texture_t *texture = t;
2168 model_t *model = ent->model;
2169 int s = ent->skinnum;
2170 if ((unsigned int)s >= (unsigned int)model->numskins)
2172 if (model->skinscenes)
2174 if (model->skinscenes[s].framecount > 1)
2175 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
2177 s = model->skinscenes[s].firstframe;
2180 t = t + s * model->num_surfaces;
2183 // use an alternate animation if the entity's frame is not 0,
2184 // and only if the texture has an alternate animation
2185 if (ent->frame != 0 && t->anim_total[1])
2186 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.time * 5.0f) % t->anim_total[1]) : 0];
2188 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.time * 5.0f) % t->anim_total[0]) : 0];
2190 texture->currentframe = t;
2193 t->currentmaterialflags = t->basematerialflags;
2194 t->currentalpha = ent->alpha;
2195 if (t->basematerialflags & MATERIALFLAG_WATERALPHA)
2196 t->currentalpha *= r_wateralpha.value;
2197 if (!(ent->flags & RENDER_LIGHT))
2198 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
2199 if (ent->effects & EF_ADDITIVE)
2200 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_TRANSPARENT;
2201 else if (t->currentalpha < 1)
2202 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_TRANSPARENT;
2203 if (ent->effects & EF_NODEPTHTEST)
2204 t->currentmaterialflags |= MATERIALFLAG_NODEPTHTEST;
2205 if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
2206 t->currenttexmatrix = r_waterscrollmatrix;
2208 t->currenttexmatrix = identitymatrix;
2210 t->colormapping = VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f);
2211 t->basetexture = (!t->colormapping && t->skin.merged) ? t->skin.merged : t->skin.base;
2212 t->glosstexture = r_texture_white;
2213 t->specularpower = 8;
2214 t->specularscale = 0;
2215 if (r_shadow_gloss.integer > 0)
2219 if (r_shadow_glossintensity.value > 0)
2221 t->glosstexture = t->skin.gloss;
2222 t->specularscale = r_shadow_glossintensity.value;
2225 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
2226 t->specularscale = r_shadow_gloss2intensity.value;
2229 t->currentnumlayers = 0;
2230 if (!(t->currentmaterialflags & MATERIALFLAG_NODRAW))
2232 if (gl_lightmaps.integer)
2233 R_Texture_AddLayer(t, true, GL_ONE, GL_ZERO, TEXTURELAYERTYPE_LITTEXTURE, r_texture_white, &identitymatrix, 1, 1, 1, 1);
2234 else if (!(t->currentmaterialflags & MATERIALFLAG_SKY))
2236 int blendfunc1, blendfunc2, depthmask;
2237 if (t->currentmaterialflags & MATERIALFLAG_ADD)
2239 blendfunc1 = GL_SRC_ALPHA;
2240 blendfunc2 = GL_ONE;
2242 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
2244 blendfunc1 = GL_SRC_ALPHA;
2245 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
2247 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
2249 blendfunc1 = t->customblendfunc[0];
2250 blendfunc2 = t->customblendfunc[1];
2254 blendfunc1 = GL_ONE;
2255 blendfunc2 = GL_ZERO;
2257 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
2258 if (t->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL))
2260 rtexture_t *currentbasetexture;
2262 if (r_refdef.fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED))
2263 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
2264 currentbasetexture = (VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) < (1.0f / 1048576.0f) && t->skin.merged) ? t->skin.merged : t->skin.base;
2265 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2267 // fullbright is not affected by r_refdef.lightmapintensity
2268 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
2269 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->skin.pants)
2270 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.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);
2271 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->skin.shirt)
2272 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.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);
2278 // q3bsp has no lightmap updates, so the lightstylevalue that
2279 // would normally be baked into the lightmap must be
2280 // applied to the color
2281 if (ent->model->type == mod_brushq3)
2282 colorscale *= r_refdef.lightstylevalue[0] * (1.0f / 256.0f);
2283 colorscale *= r_refdef.lightmapintensity;
2284 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);
2285 if (r_ambient.value >= (1.0f/64.0f))
2286 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);
2287 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->skin.pants)
2289 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->skin.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);
2290 if (r_ambient.value >= (1.0f/64.0f))
2291 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.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);
2293 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->skin.shirt)
2295 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->skin.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);
2296 if (r_ambient.value >= (1.0f/64.0f))
2297 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.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);
2300 if (t->skin.glow != NULL)
2301 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.glow, &t->currenttexmatrix, 1, 1, 1, t->currentalpha);
2302 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
2304 // if this is opaque use alpha blend which will darken the earlier
2307 // if this is an alpha blended material, all the earlier passes
2308 // were darkened by fog already, so we only need to add the fog
2309 // color ontop through the fog mask texture
2311 // if this is an additive blended material, all the earlier passes
2312 // were darkened by fog already, and we should not add fog color
2313 // (because the background was not darkened, there is no fog color
2314 // that was lost behind it).
2315 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, (t->currentmaterialflags & MATERIALFLAG_BLENDED) ? GL_ONE : GL_ONE_MINUS_SRC_ALPHA, TEXTURELAYERTYPE_FOG, t->skin.fog, &identitymatrix, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], t->currentalpha);
2322 void R_UpdateAllTextureInfo(entity_render_t *ent)
2326 for (i = 0;i < ent->model->num_textures;i++)
2327 R_UpdateTextureInfo(ent, ent->model->data_textures + i);
2330 int rsurface_array_size = 0;
2331 float *rsurface_array_modelvertex3f = NULL;
2332 float *rsurface_array_modelsvector3f = NULL;
2333 float *rsurface_array_modeltvector3f = NULL;
2334 float *rsurface_array_modelnormal3f = NULL;
2335 float *rsurface_array_deformedvertex3f = NULL;
2336 float *rsurface_array_deformedsvector3f = NULL;
2337 float *rsurface_array_deformedtvector3f = NULL;
2338 float *rsurface_array_deformednormal3f = NULL;
2339 float *rsurface_array_color4f = NULL;
2340 float *rsurface_array_texcoord3f = NULL;
2342 void R_Mesh_ResizeArrays(int newvertices)
2345 if (rsurface_array_size >= newvertices)
2347 if (rsurface_array_modelvertex3f)
2348 Mem_Free(rsurface_array_modelvertex3f);
2349 rsurface_array_size = (newvertices + 1023) & ~1023;
2350 base = (float *)Mem_Alloc(r_main_mempool, rsurface_array_size * sizeof(float[31]));
2351 rsurface_array_modelvertex3f = base + rsurface_array_size * 0;
2352 rsurface_array_modelsvector3f = base + rsurface_array_size * 3;
2353 rsurface_array_modeltvector3f = base + rsurface_array_size * 6;
2354 rsurface_array_modelnormal3f = base + rsurface_array_size * 9;
2355 rsurface_array_deformedvertex3f = base + rsurface_array_size * 12;
2356 rsurface_array_deformedsvector3f = base + rsurface_array_size * 15;
2357 rsurface_array_deformedtvector3f = base + rsurface_array_size * 18;
2358 rsurface_array_deformednormal3f = base + rsurface_array_size * 21;
2359 rsurface_array_texcoord3f = base + rsurface_array_size * 24;
2360 rsurface_array_color4f = base + rsurface_array_size * 27;
2363 float *rsurface_modelvertex3f;
2364 float *rsurface_modelsvector3f;
2365 float *rsurface_modeltvector3f;
2366 float *rsurface_modelnormal3f;
2367 float *rsurface_vertex3f;
2368 float *rsurface_svector3f;
2369 float *rsurface_tvector3f;
2370 float *rsurface_normal3f;
2371 float *rsurface_lightmapcolor4f;
2372 vec3_t rsurface_modelorg;
2373 qboolean rsurface_generatedvertex;
2374 const entity_render_t *rsurface_entity;
2375 const model_t *rsurface_model;
2376 texture_t *rsurface_texture;
2377 rtexture_t *rsurface_lightmaptexture;
2378 rsurfmode_t rsurface_mode;
2379 texture_t *rsurface_glsl_texture;
2380 qboolean rsurface_glsl_uselightmap;
2382 void RSurf_ActiveEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
2384 Matrix4x4_Transform(&ent->inversematrix, r_view.origin, rsurface_modelorg);
2385 rsurface_entity = ent;
2386 rsurface_model = ent->model;
2387 if (rsurface_array_size < rsurface_model->surfmesh.num_vertices)
2388 R_Mesh_ResizeArrays(rsurface_model->surfmesh.num_vertices);
2389 R_Mesh_Matrix(&ent->matrix);
2390 Matrix4x4_Transform(&ent->inversematrix, r_view.origin, rsurface_modelorg);
2391 if ((rsurface_entity->frameblend[0].lerp != 1 || rsurface_entity->frameblend[0].frame != 0) && rsurface_model->surfmesh.isanimated)
2395 rsurface_modelvertex3f = rsurface_array_modelvertex3f;
2396 rsurface_modelsvector3f = rsurface_array_modelsvector3f;
2397 rsurface_modeltvector3f = rsurface_array_modeltvector3f;
2398 rsurface_modelnormal3f = rsurface_array_modelnormal3f;
2399 Mod_Alias_GetMesh_Vertices(rsurface_model, rsurface_entity->frameblend, rsurface_array_modelvertex3f, rsurface_array_modelnormal3f, rsurface_array_modelsvector3f, rsurface_array_modeltvector3f);
2401 else if (wantnormals)
2403 rsurface_modelvertex3f = rsurface_array_modelvertex3f;
2404 rsurface_modelsvector3f = NULL;
2405 rsurface_modeltvector3f = NULL;
2406 rsurface_modelnormal3f = rsurface_array_modelnormal3f;
2407 Mod_Alias_GetMesh_Vertices(rsurface_model, rsurface_entity->frameblend, rsurface_array_modelvertex3f, rsurface_array_modelnormal3f, NULL, NULL);
2411 rsurface_modelvertex3f = rsurface_array_modelvertex3f;
2412 rsurface_modelsvector3f = NULL;
2413 rsurface_modeltvector3f = NULL;
2414 rsurface_modelnormal3f = NULL;
2415 Mod_Alias_GetMesh_Vertices(rsurface_model, rsurface_entity->frameblend, rsurface_array_modelvertex3f, NULL, NULL, NULL);
2417 rsurface_generatedvertex = true;
2421 rsurface_modelvertex3f = rsurface_model->surfmesh.data_vertex3f;
2422 rsurface_modelsvector3f = rsurface_model->surfmesh.data_svector3f;
2423 rsurface_modeltvector3f = rsurface_model->surfmesh.data_tvector3f;
2424 rsurface_modelnormal3f = rsurface_model->surfmesh.data_normal3f;
2425 rsurface_generatedvertex = false;
2427 rsurface_vertex3f = rsurface_modelvertex3f;
2428 rsurface_svector3f = rsurface_modelsvector3f;
2429 rsurface_tvector3f = rsurface_modeltvector3f;
2430 rsurface_normal3f = rsurface_modelnormal3f;
2431 rsurface_mode = RSURFMODE_NONE;
2432 rsurface_lightmaptexture = NULL;
2433 rsurface_texture = NULL;
2434 rsurface_glsl_texture = NULL;
2435 rsurface_glsl_uselightmap = false;
2438 void RSurf_CleanUp(void)
2441 if (rsurface_mode == RSURFMODE_GLSL)
2443 qglUseProgramObjectARB(0);CHECKGLERROR
2445 GL_AlphaTest(false);
2446 rsurface_mode = RSURFMODE_NONE;
2447 rsurface_lightmaptexture = NULL;
2448 rsurface_texture = NULL;
2449 rsurface_glsl_texture = NULL;
2450 rsurface_glsl_uselightmap = false;
2453 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, msurface_t **texturesurfacelist)
2455 if (rsurface_generatedvertex)
2457 if (rsurface_texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
2458 generatetangents = true;
2459 if (generatetangents)
2460 generatenormals = true;
2461 if (generatenormals && !rsurface_modelnormal3f)
2463 rsurface_normal3f = rsurface_modelnormal3f = rsurface_array_modelnormal3f;
2464 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);
2466 if (generatetangents && !rsurface_modelsvector3f)
2468 rsurface_svector3f = rsurface_modelsvector3f = rsurface_array_modelsvector3f;
2469 rsurface_tvector3f = rsurface_modeltvector3f = rsurface_array_modeltvector3f;
2470 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);
2473 if (rsurface_texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
2475 int texturesurfaceindex;
2476 float center[3], forward[3], right[3], up[3], v[4][3];
2477 matrix4x4_t matrix1, imatrix1;
2478 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_view.forward, forward);
2479 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_view.right, right);
2480 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_view.up, up);
2481 // make deformed versions of only the vertices used by the specified surfaces
2482 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2485 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2486 // a single autosprite surface can contain multiple sprites...
2487 for (j = 0;j < surface->num_vertices - 3;j += 4)
2489 VectorClear(center);
2490 for (i = 0;i < 4;i++)
2491 VectorAdd(center, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
2492 VectorScale(center, 0.25f, center);
2493 if (rsurface_texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE2)
2495 forward[0] = rsurface_modelorg[0] - center[0];
2496 forward[1] = rsurface_modelorg[1] - center[1];
2498 VectorNormalize(forward);
2499 right[0] = forward[1];
2500 right[1] = -forward[0];
2502 VectorSet(up, 0, 0, 1);
2504 // FIXME: calculate vectors from triangle edges instead of using texture vectors as an easy way out?
2505 Matrix4x4_FromVectors(&matrix1, (rsurface_normal3f + 3 * surface->num_firstvertex) + j*3, (rsurface_svector3f + 3 * surface->num_firstvertex) + j*3, (rsurface_tvector3f + 3 * surface->num_firstvertex) + j*3, center);
2506 Matrix4x4_Invert_Simple(&imatrix1, &matrix1);
2507 for (i = 0;i < 4;i++)
2508 Matrix4x4_Transform(&imatrix1, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, v[i]);
2509 for (i = 0;i < 4;i++)
2510 VectorMAMAMAM(1, center, v[i][0], forward, v[i][1], right, v[i][2], up, rsurface_array_modelvertex3f + (surface->num_firstvertex+i+j) * 3);
2512 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);
2513 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);
2515 rsurface_vertex3f = rsurface_array_deformedvertex3f;
2516 rsurface_svector3f = rsurface_array_deformedsvector3f;
2517 rsurface_tvector3f = rsurface_array_deformedtvector3f;
2518 rsurface_normal3f = rsurface_array_deformednormal3f;
2520 R_Mesh_VertexPointer(rsurface_vertex3f);
2523 void RSurf_DrawBatch_Simple(int texturenumsurfaces, msurface_t **texturesurfacelist)
2525 int texturesurfaceindex;
2526 const msurface_t *surface = texturesurfacelist[0];
2527 int firstvertex = surface->num_firstvertex;
2528 int endvertex = surface->num_firstvertex + surface->num_vertices;
2529 if (texturenumsurfaces == 1)
2531 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2532 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
2534 else if (r_batchmode.integer == 2)
2536 #define MAXBATCHTRIANGLES 4096
2537 int batchtriangles = 0;
2538 int batchelements[MAXBATCHTRIANGLES*3];
2539 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2541 surface = texturesurfacelist[texturesurfaceindex];
2542 if (surface->num_triangles >= 256 || (batchtriangles == 0 && texturesurfaceindex + 1 >= texturenumsurfaces))
2544 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
2547 if (batchtriangles + surface->num_triangles > MAXBATCHTRIANGLES)
2549 R_Mesh_Draw(firstvertex, endvertex - firstvertex, batchtriangles, batchelements);
2551 firstvertex = surface->num_firstvertex;
2552 endvertex = surface->num_firstvertex + surface->num_vertices;
2556 firstvertex = min(firstvertex, surface->num_firstvertex);
2557 endvertex = max(endvertex, surface->num_firstvertex + surface->num_vertices);
2559 memcpy(batchelements + batchtriangles * 3, rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
2560 batchtriangles += surface->num_triangles;
2563 R_Mesh_Draw(firstvertex, endvertex - firstvertex, batchtriangles, batchelements);
2565 else if (r_batchmode.integer == 1)
2567 int firsttriangle = 0;
2568 int endtriangle = -1;
2569 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2571 surface = texturesurfacelist[texturesurfaceindex];
2572 if (surface->num_firsttriangle != endtriangle)
2574 if (endtriangle > firsttriangle)
2576 GL_LockArrays(firstvertex, endvertex - firstvertex);
2577 R_Mesh_Draw(firstvertex, endvertex - firstvertex, endtriangle - firsttriangle, (rsurface_model->surfmesh.data_element3i + 3 * firsttriangle));
2579 firstvertex = surface->num_firstvertex;
2580 endvertex = surface->num_firstvertex + surface->num_vertices;
2581 firsttriangle = surface->num_firsttriangle;
2585 firstvertex = min(firstvertex, surface->num_firstvertex);
2586 endvertex = max(endvertex, surface->num_firstvertex + surface->num_vertices);
2588 endtriangle = surface->num_firsttriangle + surface->num_triangles;
2590 if (endtriangle > firsttriangle)
2592 GL_LockArrays(firstvertex, endvertex - firstvertex);
2593 R_Mesh_Draw(firstvertex, endvertex - firstvertex, endtriangle - firsttriangle, (rsurface_model->surfmesh.data_element3i + 3 * firsttriangle));
2598 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2600 surface = texturesurfacelist[texturesurfaceindex];
2601 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2602 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
2607 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
2609 int texturesurfaceindex;
2610 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2612 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2613 int k = (int)(((size_t)surface) / sizeof(msurface_t));
2614 GL_Color((k & 15) * (1.0f / 16.0f), ((k >> 4) & 15) * (1.0f / 16.0f), ((k >> 8) & 15) * (1.0f / 16.0f), 0.2f);
2615 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2616 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
2620 static void RSurf_DrawBatch_Lightmap(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, int lightmode, qboolean applycolor, qboolean applyfog)
2622 int texturesurfaceindex;
2630 vec3_t ambientcolor;
2631 vec3_t diffusecolor;
2633 VectorCopy(rsurface_entity->modellight_lightdir, lightdir);
2634 ambientcolor[0] = rsurface_entity->modellight_ambient[0] * r * 0.5f;
2635 ambientcolor[1] = rsurface_entity->modellight_ambient[1] * g * 0.5f;
2636 ambientcolor[2] = rsurface_entity->modellight_ambient[2] * b * 0.5f;
2637 diffusecolor[0] = rsurface_entity->modellight_diffuse[0] * r * 0.5f;
2638 diffusecolor[1] = rsurface_entity->modellight_diffuse[1] * g * 0.5f;
2639 diffusecolor[2] = rsurface_entity->modellight_diffuse[2] * b * 0.5f;
2640 if (VectorLength2(diffusecolor) > 0)
2642 // generate color arrays for the surfaces in this list
2643 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2645 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2646 int numverts = surface->num_vertices;
2647 v = rsurface_vertex3f + 3 * surface->num_firstvertex;
2648 c2 = rsurface_normal3f + 3 * surface->num_firstvertex;
2649 c = rsurface_array_color4f + 4 * surface->num_firstvertex;
2650 // q3-style directional shading
2651 for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
2653 if ((f = DotProduct(c2, lightdir)) > 0)
2654 VectorMA(ambientcolor, f, diffusecolor, c);
2656 VectorCopy(ambientcolor, c);
2665 rsurface_lightmapcolor4f = rsurface_array_color4f;
2669 r = ambientcolor[0];
2670 g = ambientcolor[1];
2671 b = ambientcolor[2];
2672 rsurface_lightmapcolor4f = NULL;
2675 else if (lightmode >= 1 || !rsurface_lightmaptexture)
2677 if (texturesurfacelist[0]->lightmapinfo && texturesurfacelist[0]->lightmapinfo->stainsamples)
2679 // generate color arrays for the surfaces in this list
2680 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2682 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2683 for (i = 0, c = rsurface_array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
2685 if (surface->lightmapinfo->samples)
2687 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface_model->surfmesh.data_lightmapoffsets + surface->num_firstvertex)[i];
2688 float scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
2689 VectorScale(lm, scale, c);
2690 if (surface->lightmapinfo->styles[1] != 255)
2692 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
2694 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
2695 VectorMA(c, scale, lm, c);
2696 if (surface->lightmapinfo->styles[2] != 255)
2699 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
2700 VectorMA(c, scale, lm, c);
2701 if (surface->lightmapinfo->styles[3] != 255)
2704 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
2705 VectorMA(c, scale, lm, c);
2715 rsurface_lightmapcolor4f = rsurface_array_color4f;
2718 rsurface_lightmapcolor4f = rsurface_model->surfmesh.data_lightmapcolor4f;
2723 rsurface_lightmapcolor4f = NULL;
2727 if (rsurface_lightmapcolor4f)
2729 // generate color arrays for the surfaces in this list
2730 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2732 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2733 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)
2735 f = 1 - VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
2745 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2747 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2748 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)
2750 f = 1 - VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
2758 rsurface_lightmapcolor4f = rsurface_array_color4f;
2760 if (applycolor && rsurface_lightmapcolor4f)
2762 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2764 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2765 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)
2773 rsurface_lightmapcolor4f = rsurface_array_color4f;
2775 R_Mesh_ColorPointer(rsurface_lightmapcolor4f);
2776 GL_Color(r, g, b, a);
2777 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
2780 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
2782 if (rsurface_mode != RSURFMODE_SHOWSURFACES)
2784 rsurface_mode = RSURFMODE_SHOWSURFACES;
2786 GL_BlendFunc(GL_ONE, GL_ZERO);
2787 R_Mesh_ColorPointer(NULL);
2788 R_Mesh_ResetTextureState();
2790 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
2791 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
2794 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, msurface_t **texturesurfacelist)
2796 // transparent sky would be ridiculous
2797 if ((rsurface_texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
2799 if (rsurface_mode != RSURFMODE_SKY)
2801 if (rsurface_mode == RSURFMODE_GLSL)
2803 qglUseProgramObjectARB(0);CHECKGLERROR
2805 rsurface_mode = RSURFMODE_SKY;
2809 skyrendernow = false;
2811 // restore entity matrix
2812 R_Mesh_Matrix(&rsurface_entity->matrix);
2815 // LordHavoc: HalfLife maps have freaky skypolys so don't use
2816 // skymasking on them, and Quake3 never did sky masking (unlike
2817 // software Quake and software Quake2), so disable the sky masking
2818 // in Quake3 maps as it causes problems with q3map2 sky tricks,
2819 // and skymasking also looks very bad when noclipping outside the
2820 // level, so don't use it then either.
2821 if (rsurface_model->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_viewcache.world_novis)
2823 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
2824 R_Mesh_ColorPointer(NULL);
2825 R_Mesh_ResetTextureState();
2826 if (skyrendermasked)
2828 // depth-only (masking)
2829 GL_ColorMask(0,0,0,0);
2830 // just to make sure that braindead drivers don't draw
2831 // anything despite that colormask...
2832 GL_BlendFunc(GL_ZERO, GL_ONE);
2837 GL_BlendFunc(GL_ONE, GL_ZERO);
2839 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
2840 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
2841 if (skyrendermasked)
2842 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
2846 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, msurface_t **texturesurfacelist)
2849 // FIXME: identify models using a better check than rsurface_model->brush.shadowmesh
2850 lightmode = ((rsurface_entity->effects & EF_FULLBRIGHT) || rsurface_model->brush.shadowmesh) ? 0 : 2;
2851 if (rsurface_mode != RSURFMODE_GLSL)
2853 rsurface_mode = RSURFMODE_GLSL;
2854 rsurface_glsl_texture = NULL;
2855 rsurface_glsl_uselightmap = false;
2856 R_Mesh_ResetTextureState();
2858 if (rsurface_glsl_texture != rsurface_texture || rsurface_glsl_uselightmap != (rsurface_lightmaptexture != NULL))
2860 rsurface_glsl_texture = rsurface_texture;
2861 rsurface_glsl_uselightmap = rsurface_lightmaptexture != NULL;
2862 GL_BlendFunc(rsurface_texture->currentlayers[0].blendfunc1, rsurface_texture->currentlayers[0].blendfunc2);
2863 GL_DepthMask(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_BLENDED));
2864 GL_Color(rsurface_entity->colormod[0], rsurface_entity->colormod[1], rsurface_entity->colormod[2], rsurface_texture->currentalpha);
2865 R_SetupSurfaceShader(vec3_origin, lightmode == 2);
2866 //permutation_deluxemapping = permutation_lightmapping = R_SetupSurfaceShader(vec3_origin, lightmode == 2, false);
2867 //if (r_glsl_deluxemapping.integer)
2868 // permutation_deluxemapping = R_SetupSurfaceShader(vec3_origin, lightmode == 2, true);
2869 R_Mesh_TexCoordPointer(0, 2, rsurface_model->surfmesh.data_texcoordtexture2f);
2870 R_Mesh_TexCoordPointer(4, 2, rsurface_model->surfmesh.data_texcoordlightmap2f);
2871 GL_AlphaTest((rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2873 if (!r_glsl_permutation)
2875 RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
2876 R_Mesh_TexCoordPointer(1, 3, rsurface_svector3f);
2877 R_Mesh_TexCoordPointer(2, 3, rsurface_tvector3f);
2878 R_Mesh_TexCoordPointer(3, 3, rsurface_normal3f);
2879 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2881 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
2882 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
2883 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
2884 R_Mesh_ColorPointer(NULL);
2886 else if (rsurface_lightmaptexture)
2888 R_Mesh_TexBind(7, R_GetTexture(rsurface_lightmaptexture));
2889 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
2890 R_Mesh_TexBind(8, R_GetTexture(texturesurfacelist[0]->deluxemaptexture));
2891 R_Mesh_ColorPointer(NULL);
2895 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
2896 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
2897 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
2898 R_Mesh_ColorPointer(rsurface_model->surfmesh.data_lightmapcolor4f);
2900 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
2903 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, msurface_t **texturesurfacelist)
2905 // OpenGL 1.3 path - anything not completely ancient
2906 int texturesurfaceindex;
2908 qboolean applycolor;
2912 const texturelayer_t *layer;
2914 // FIXME: identify models using a better check than rsurface_model->brush.shadowmesh
2915 lightmode = ((rsurface_entity->effects & EF_FULLBRIGHT) || rsurface_model->brush.shadowmesh) ? 0 : 2;
2916 if (rsurface_mode != RSURFMODE_MULTIPASS)
2917 rsurface_mode = RSURFMODE_MULTIPASS;
2918 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
2919 for (layerindex = 0, layer = rsurface_texture->currentlayers;layerindex < rsurface_texture->currentnumlayers;layerindex++, layer++)
2922 int layertexrgbscale;
2923 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2925 if (layerindex == 0)
2929 GL_AlphaTest(false);
2930 qglDepthFunc(GL_EQUAL);CHECKGLERROR
2933 GL_DepthMask(layer->depthmask);
2934 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
2935 if ((layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2) && (gl_combine.integer || layer->depthmask))
2937 layertexrgbscale = 4;
2938 VectorScale(layer->color, 0.25f, layercolor);
2940 else if ((layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1) && (gl_combine.integer || layer->depthmask))
2942 layertexrgbscale = 2;
2943 VectorScale(layer->color, 0.5f, layercolor);
2947 layertexrgbscale = 1;
2948 VectorScale(layer->color, 1.0f, layercolor);
2950 layercolor[3] = layer->color[3];
2951 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
2952 R_Mesh_ColorPointer(NULL);
2953 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
2954 switch (layer->type)
2956 case TEXTURELAYERTYPE_LITTEXTURE:
2957 memset(&m, 0, sizeof(m));
2958 if (lightmode >= 1 || !rsurface_lightmaptexture)
2959 m.tex[0] = R_GetTexture(r_texture_white);
2961 m.tex[0] = R_GetTexture(rsurface_lightmaptexture);
2962 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordlightmap2f;
2963 m.tex[1] = R_GetTexture(layer->texture);
2964 m.texmatrix[1] = layer->texmatrix;
2965 m.texrgbscale[1] = layertexrgbscale;
2966 m.pointer_texcoord[1] = rsurface_model->surfmesh.data_texcoordtexture2f;
2967 R_Mesh_TextureState(&m);
2968 RSurf_DrawBatch_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], lightmode, applycolor, applyfog);
2970 case TEXTURELAYERTYPE_TEXTURE:
2971 memset(&m, 0, sizeof(m));
2972 m.tex[0] = R_GetTexture(layer->texture);
2973 m.texmatrix[0] = layer->texmatrix;
2974 m.texrgbscale[0] = layertexrgbscale;
2975 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
2976 R_Mesh_TextureState(&m);
2977 RSurf_DrawBatch_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, applyfog);
2979 case TEXTURELAYERTYPE_FOG:
2980 memset(&m, 0, sizeof(m));
2981 m.texrgbscale[0] = layertexrgbscale;
2984 m.tex[0] = R_GetTexture(layer->texture);
2985 m.texmatrix[0] = layer->texmatrix;
2986 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
2988 R_Mesh_TextureState(&m);
2989 // generate a color array for the fog pass
2990 R_Mesh_ColorPointer(rsurface_array_color4f);
2991 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2995 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2996 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)
2998 f = VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
2999 c[0] = layercolor[0];
3000 c[1] = layercolor[1];
3001 c[2] = layercolor[2];
3002 c[3] = f * layercolor[3];
3005 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3008 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
3010 GL_LockArrays(0, 0);
3013 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
3015 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3016 GL_AlphaTest(false);
3020 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, msurface_t **texturesurfacelist)
3022 // OpenGL 1.1 - crusty old voodoo path
3023 int texturesurfaceindex;
3028 const texturelayer_t *layer;
3030 // FIXME: identify models using a better check than rsurface_model->brush.shadowmesh
3031 lightmode = ((rsurface_entity->effects & EF_FULLBRIGHT) || rsurface_model->brush.shadowmesh) ? 0 : 2;
3032 if (rsurface_mode != RSURFMODE_MULTIPASS)
3033 rsurface_mode = RSURFMODE_MULTIPASS;
3034 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
3035 for (layerindex = 0, layer = rsurface_texture->currentlayers;layerindex < rsurface_texture->currentnumlayers;layerindex++, layer++)
3037 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
3039 if (layerindex == 0)
3043 GL_AlphaTest(false);
3044 qglDepthFunc(GL_EQUAL);CHECKGLERROR
3047 GL_DepthMask(layer->depthmask);
3048 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
3049 R_Mesh_ColorPointer(NULL);
3050 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
3051 switch (layer->type)
3053 case TEXTURELAYERTYPE_LITTEXTURE:
3054 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
3056 // two-pass lit texture with 2x rgbscale
3057 // first the lightmap pass
3058 memset(&m, 0, sizeof(m));
3059 if (lightmode >= 1 || !rsurface_lightmaptexture)
3060 m.tex[0] = R_GetTexture(r_texture_white);
3062 m.tex[0] = R_GetTexture(rsurface_lightmaptexture);
3063 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordlightmap2f;
3064 R_Mesh_TextureState(&m);
3065 RSurf_DrawBatch_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, lightmode, false, false);
3066 GL_LockArrays(0, 0);
3067 // then apply the texture to it
3068 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
3069 memset(&m, 0, sizeof(m));
3070 m.tex[0] = R_GetTexture(layer->texture);
3071 m.texmatrix[0] = layer->texmatrix;
3072 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3073 R_Mesh_TextureState(&m);
3074 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);
3078 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
3079 memset(&m, 0, sizeof(m));
3080 m.tex[0] = R_GetTexture(layer->texture);
3081 m.texmatrix[0] = layer->texmatrix;
3082 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3083 R_Mesh_TextureState(&m);
3084 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);
3087 case TEXTURELAYERTYPE_TEXTURE:
3088 // singletexture unlit texture with transparency support
3089 memset(&m, 0, sizeof(m));
3090 m.tex[0] = R_GetTexture(layer->texture);
3091 m.texmatrix[0] = layer->texmatrix;
3092 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3093 R_Mesh_TextureState(&m);
3094 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);
3096 case TEXTURELAYERTYPE_FOG:
3097 // singletexture fogging
3098 R_Mesh_ColorPointer(rsurface_array_color4f);
3101 memset(&m, 0, sizeof(m));
3102 m.tex[0] = R_GetTexture(layer->texture);
3103 m.texmatrix[0] = layer->texmatrix;
3104 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3105 R_Mesh_TextureState(&m);
3108 R_Mesh_ResetTextureState();
3109 // generate a color array for the fog pass
3110 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3114 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3115 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)
3117 f = VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
3118 c[0] = layer->color[0];
3119 c[1] = layer->color[1];
3120 c[2] = layer->color[2];
3121 c[3] = f * layer->color[3];
3124 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3127 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
3129 GL_LockArrays(0, 0);
3132 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
3134 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3135 GL_AlphaTest(false);
3139 static void R_DrawTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist)
3141 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_NODRAW)
3143 r_shadow_rtlight = NULL;
3144 r_refdef.stats.entities_surfaces += texturenumsurfaces;
3146 GL_DepthTest(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
3147 if ((rsurface_texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (rsurface_entity->flags & RENDER_NOCULLFACE))
3149 qglDisable(GL_CULL_FACE);CHECKGLERROR
3151 if (r_showsurfaces.integer)
3152 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
3153 else if (rsurface_texture->currentmaterialflags & MATERIALFLAG_SKY)
3154 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
3155 else if (rsurface_texture->currentnumlayers)
3157 if (r_glsl.integer && gl_support_fragment_shader)
3158 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist);
3159 else if (gl_combine.integer && r_textureunits.integer >= 2)
3160 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist);
3162 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist);
3165 GL_LockArrays(0, 0);
3166 if ((rsurface_texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (rsurface_entity->flags & RENDER_NOCULLFACE))
3168 qglEnable(GL_CULL_FACE);CHECKGLERROR
3172 #define BATCHSIZE 256
3173 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
3175 int surfacelistindex;
3178 msurface_t *texturesurfacelist[BATCHSIZE];
3179 // if the model is static it doesn't matter what value we give for
3180 // wantnormals and wanttangents, so this logic uses only rules applicable
3181 // to a model, knowing that they are meaningless otherwise
3182 if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
3183 RSurf_ActiveEntity(ent, false, false);
3185 RSurf_ActiveEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
3188 for (surfacelistindex = 0;surfacelistindex < numsurfaces;surfacelistindex++)
3190 msurface_t *surface = ent->model->data_surfaces + surfacelist[surfacelistindex];
3192 if (t != surface->texture || rsurface_lightmaptexture != surface->lightmaptexture)
3195 R_DrawTextureSurfaceList(batchcount, texturesurfacelist);
3197 t = surface->texture;
3198 rsurface_lightmaptexture = surface->lightmaptexture;
3199 R_UpdateTextureInfo(ent, t);
3200 rsurface_texture = t->currentframe;
3202 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_SKY)
3203 continue; // transparent sky is too difficult
3205 texturesurfacelist[batchcount++] = surface;
3208 R_DrawTextureSurfaceList(batchcount, texturesurfacelist);
3212 void R_QueueTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist)
3214 int texturesurfaceindex;
3215 vec3_t tempcenter, center;
3216 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_BLENDED)
3218 // drawing sky transparently would be too difficult
3219 if (!(rsurface_texture->currentmaterialflags & MATERIALFLAG_SKY))
3221 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3223 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3224 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
3225 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
3226 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
3227 Matrix4x4_Transform(&rsurface_entity->matrix, tempcenter, center);
3228 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);
3233 R_DrawTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
3236 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
3237 void R_DrawSurfaces(entity_render_t *ent, qboolean skysurfaces)
3239 int i, j, f, flagsmask;
3240 int counttriangles = 0;
3242 model_t *model = ent->model;
3243 const int maxsurfacelist = 1024;
3244 int numsurfacelist = 0;
3245 msurface_t *surfacelist[1024];
3249 // if the model is static it doesn't matter what value we give for
3250 // wantnormals and wanttangents, so this logic uses only rules applicable
3251 // to a model, knowing that they are meaningless otherwise
3252 if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
3253 RSurf_ActiveEntity(ent, false, false);
3255 RSurf_ActiveEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
3257 // update light styles
3258 if (!skysurfaces && model->brushq1.light_styleupdatechains)
3260 msurface_t *surface, **surfacechain;
3261 for (i = 0;i < model->brushq1.light_styles;i++)
3263 if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
3265 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
3266 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
3267 for (;(surface = *surfacechain);surfacechain++)
3268 surface->cached_dlight = true;
3273 R_UpdateAllTextureInfo(ent);
3274 flagsmask = skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL);
3277 rsurface_lightmaptexture = NULL;
3278 rsurface_texture = NULL;
3280 if (ent == r_refdef.worldentity)
3282 msurface_t *surface;
3283 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
3285 if (!r_viewcache.world_surfacevisible[j])
3287 if (t != surface->texture || rsurface_lightmaptexture != surface->lightmaptexture)
3291 R_QueueTextureSurfaceList(numsurfacelist, surfacelist);
3294 t = surface->texture;
3295 rsurface_lightmaptexture = surface->lightmaptexture;
3296 rsurface_texture = t->currentframe;
3297 f = rsurface_texture->currentmaterialflags & flagsmask;
3299 if (f && surface->num_triangles)
3301 // if lightmap parameters changed, rebuild lightmap texture
3302 if (surface->cached_dlight)
3303 R_BuildLightMap(ent, surface);
3304 // add face to draw list
3305 surfacelist[numsurfacelist++] = surface;
3306 counttriangles += surface->num_triangles;
3307 if (numsurfacelist >= maxsurfacelist)
3309 R_QueueTextureSurfaceList(numsurfacelist, surfacelist);
3317 msurface_t *surface;
3318 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
3320 if (t != surface->texture || rsurface_lightmaptexture != surface->lightmaptexture)
3324 R_QueueTextureSurfaceList(numsurfacelist, surfacelist);
3327 t = surface->texture;
3328 rsurface_lightmaptexture = surface->lightmaptexture;
3329 rsurface_texture = t->currentframe;
3330 f = rsurface_texture->currentmaterialflags & flagsmask;
3332 if (f && surface->num_triangles)
3334 // if lightmap parameters changed, rebuild lightmap texture
3335 if (surface->cached_dlight)
3336 R_BuildLightMap(ent, surface);
3337 // add face to draw list
3338 surfacelist[numsurfacelist++] = surface;
3339 counttriangles += surface->num_triangles;
3340 if (numsurfacelist >= maxsurfacelist)
3342 R_QueueTextureSurfaceList(numsurfacelist, surfacelist);
3349 R_QueueTextureSurfaceList(numsurfacelist, surfacelist);
3350 r_refdef.stats.entities_triangles += counttriangles;
3353 if (r_showcollisionbrushes.integer && model->brush.num_brushes && !skysurfaces)
3356 const msurface_t *surface;
3359 R_Mesh_Matrix(&ent->matrix);
3360 R_Mesh_ColorPointer(NULL);
3361 R_Mesh_ResetTextureState();
3362 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
3363 GL_DepthMask(false);
3364 GL_DepthTest(!r_showdisabledepthtest.integer);
3365 qglPolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);CHECKGLERROR
3366 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
3367 if (brush->colbrushf && brush->colbrushf->numtriangles)
3368 R_DrawCollisionBrush(brush->colbrushf);
3369 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
3370 if (surface->num_collisiontriangles)
3371 R_DrawCollisionSurface(ent, surface);
3372 qglPolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR
3375 if (r_showtris.integer || r_shownormals.integer)
3378 msurface_t *surface;
3379 const int *elements;
3384 if (r_showdisabledepthtest.integer)
3386 qglDepthFunc(GL_ALWAYS);CHECKGLERROR
3388 GL_BlendFunc(GL_ONE, GL_ZERO);
3389 R_Mesh_ColorPointer(NULL);
3390 R_Mesh_ResetTextureState();
3391 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
3393 if (ent == r_refdef.worldentity && !r_viewcache.world_surfacevisible[j])
3395 rsurface_texture = surface->texture->currentframe;
3396 if ((rsurface_texture->currentmaterialflags & flagsmask) && surface->num_triangles)
3398 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
3399 if (r_showtris.integer)
3401 if (!rsurface_texture->currentlayers->depthmask)
3402 GL_Color(r_showtris.value, 0, 0, 1);
3403 else if (ent == r_refdef.worldentity)
3404 GL_Color(r_showtris.value, r_showtris.value, r_showtris.value, 1);
3406 GL_Color(0, r_showtris.value, 0, 1);
3407 elements = (ent->model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
3410 for (k = 0;k < surface->num_triangles;k++, elements += 3)
3412 qglArrayElement(elements[0]);qglArrayElement(elements[1]);
3413 qglArrayElement(elements[1]);qglArrayElement(elements[2]);
3414 qglArrayElement(elements[2]);qglArrayElement(elements[0]);
3419 if (r_shownormals.integer)
3421 GL_Color(r_shownormals.value, 0, 0, 1);
3423 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
3425 VectorCopy(rsurface_vertex3f + l * 3, v);
3426 qglVertex3f(v[0], v[1], v[2]);
3427 VectorMA(v, 8, rsurface_svector3f + l * 3, v);
3428 qglVertex3f(v[0], v[1], v[2]);
3432 GL_Color(0, 0, r_shownormals.value, 1);
3434 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
3436 VectorCopy(rsurface_vertex3f + l * 3, v);
3437 qglVertex3f(v[0], v[1], v[2]);
3438 VectorMA(v, 8, rsurface_tvector3f + l * 3, v);
3439 qglVertex3f(v[0], v[1], v[2]);
3443 GL_Color(0, r_shownormals.value, 0, 1);
3445 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
3447 VectorCopy(rsurface_vertex3f + l * 3, v);
3448 qglVertex3f(v[0], v[1], v[2]);
3449 VectorMA(v, 8, rsurface_normal3f + l * 3, v);
3450 qglVertex3f(v[0], v[1], v[2]);
3457 rsurface_texture = NULL;
3458 if (r_showdisabledepthtest.integer)
3460 qglDepthFunc(GL_LEQUAL);CHECKGLERROR