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_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
47 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
48 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
49 cvar_t r_fullbright = {0, "r_fullbright","0", "make everything bright cheat (not allowed in multiplayer)"};
50 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
51 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
52 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
53 cvar_t r_q1bsp_skymasking = {0, "r_qb1sp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
55 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
56 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
57 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
58 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
59 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
60 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
61 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
63 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)"};
65 cvar_t r_glsl = {0, "r_glsl", "1", "enables use of OpenGL 2.0 pixel shaders for lighting"};
66 cvar_t r_glsl_offsetmapping = {0, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
67 cvar_t r_glsl_offsetmapping_reliefmapping = {0, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
68 cvar_t r_glsl_offsetmapping_scale = {0, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
69 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)"};
71 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1", "enables animation smoothing on sprites (requires r_lerpmodels 1)"};
72 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
73 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
75 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
76 cvar_t r_bloom_intensity = {CVAR_SAVE, "r_bloom_intensity", "1.5", "how bright the glow is"};
77 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
78 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
79 cvar_t r_bloom_power = {CVAR_SAVE, "r_bloom_power", "2", "how much to darken the image before blurring to make the bloom effect"};
81 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"};
83 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"};
85 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
87 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
88 cvar_t r_batchmode = {0, "r_batchmode", "1", "selects method of rendering multiple surfaces with one driver call (values are 0, 1, 2, etc...)"};
90 rtexture_t *r_bloom_texture_screen;
91 rtexture_t *r_bloom_texture_bloom;
92 rtexture_t *r_texture_blanknormalmap;
93 rtexture_t *r_texture_white;
94 rtexture_t *r_texture_black;
95 rtexture_t *r_texture_notexture;
96 rtexture_t *r_texture_whitecube;
97 rtexture_t *r_texture_normalizationcube;
98 rtexture_t *r_texture_fogattenuation;
99 //rtexture_t *r_texture_fogintensity;
101 // information about each possible shader permutation
102 r_glsl_permutation_t r_glsl_permutations[SHADERPERMUTATION_COUNT];
103 // currently selected permutation
104 r_glsl_permutation_t *r_glsl_permutation;
106 // temporary variable used by a macro
109 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
112 for (i = 0;i < verts;i++)
123 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
126 for (i = 0;i < verts;i++)
136 // FIXME: move this to client?
139 if (gamemode == GAME_NEHAHRA)
141 Cvar_Set("gl_fogenable", "0");
142 Cvar_Set("gl_fogdensity", "0.2");
143 Cvar_Set("gl_fogred", "0.3");
144 Cvar_Set("gl_foggreen", "0.3");
145 Cvar_Set("gl_fogblue", "0.3");
147 r_refdef.fog_density = r_refdef.fog_red = r_refdef.fog_green = r_refdef.fog_blue = 0.0f;
150 // FIXME: move this to client?
151 void FOG_registercvars(void)
156 if (gamemode == GAME_NEHAHRA)
158 Cvar_RegisterVariable (&gl_fogenable);
159 Cvar_RegisterVariable (&gl_fogdensity);
160 Cvar_RegisterVariable (&gl_fogred);
161 Cvar_RegisterVariable (&gl_foggreen);
162 Cvar_RegisterVariable (&gl_fogblue);
163 Cvar_RegisterVariable (&gl_fogstart);
164 Cvar_RegisterVariable (&gl_fogend);
167 r = (-1.0/256.0) * (FOGTABLEWIDTH * FOGTABLEWIDTH);
168 for (x = 0;x < FOGTABLEWIDTH;x++)
170 alpha = exp(r / ((double)x*(double)x));
171 if (x == FOGTABLEWIDTH - 1)
173 r_refdef.fogtable[x] = bound(0, alpha, 1);
177 static void R_BuildBlankTextures(void)
179 unsigned char data[4];
180 data[0] = 128; // normal X
181 data[1] = 128; // normal Y
182 data[2] = 255; // normal Z
183 data[3] = 128; // height
184 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
189 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
194 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
197 static void R_BuildNoTexture(void)
200 unsigned char pix[16][16][4];
201 // this makes a light grey/dark grey checkerboard texture
202 for (y = 0;y < 16;y++)
204 for (x = 0;x < 16;x++)
206 if ((y < 8) ^ (x < 8))
222 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_RGBA, TEXF_MIPMAP, NULL);
225 static void R_BuildWhiteCube(void)
227 unsigned char data[6*1*1*4];
228 data[ 0] = 255;data[ 1] = 255;data[ 2] = 255;data[ 3] = 255;
229 data[ 4] = 255;data[ 5] = 255;data[ 6] = 255;data[ 7] = 255;
230 data[ 8] = 255;data[ 9] = 255;data[10] = 255;data[11] = 255;
231 data[12] = 255;data[13] = 255;data[14] = 255;data[15] = 255;
232 data[16] = 255;data[17] = 255;data[18] = 255;data[19] = 255;
233 data[20] = 255;data[21] = 255;data[22] = 255;data[23] = 255;
234 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
237 static void R_BuildNormalizationCube(void)
241 vec_t s, t, intensity;
243 unsigned char data[6][NORMSIZE][NORMSIZE][4];
244 for (side = 0;side < 6;side++)
246 for (y = 0;y < NORMSIZE;y++)
248 for (x = 0;x < NORMSIZE;x++)
250 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
251 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
286 intensity = 127.0f / sqrt(DotProduct(v, v));
287 data[side][y][x][0] = (unsigned char)(128.0f + intensity * v[0]);
288 data[side][y][x][1] = (unsigned char)(128.0f + intensity * v[1]);
289 data[side][y][x][2] = (unsigned char)(128.0f + intensity * v[2]);
290 data[side][y][x][3] = 255;
294 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, &data[0][0][0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
297 static void R_BuildFogTexture(void)
302 unsigned char data1[FOGWIDTH][4];
303 //unsigned char data2[FOGWIDTH][4];
304 r = (-1.0/256.0) * (FOGWIDTH * FOGWIDTH);
305 for (x = 0;x < FOGWIDTH;x++)
307 alpha = exp(r / ((double)x*(double)x));
308 if (x == FOGWIDTH - 1)
310 b = (int)(256.0 * alpha);
311 b = bound(0, b, 255);
312 data1[x][0] = 255 - b;
313 data1[x][1] = 255 - b;
314 data1[x][2] = 255 - b;
321 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
322 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
325 static const char *builtinshaderstring =
326 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
327 "// written by Forest 'LordHavoc' Hale\n"
329 "// common definitions between vertex shader and fragment shader:\n"
331 "varying vec2 TexCoord;\n"
332 "varying vec2 TexCoordLightmap;\n"
334 "varying vec3 CubeVector;\n"
335 "varying vec3 LightVector;\n"
336 "varying vec3 EyeVector;\n"
338 "varying vec3 EyeVectorModelSpace;\n"
341 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
342 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
343 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
348 "// vertex shader specific:\n"
349 "#ifdef VERTEX_SHADER\n"
351 "uniform vec3 LightPosition;\n"
352 "uniform vec3 EyePosition;\n"
353 "uniform vec3 LightDir;\n"
355 "// TODO: get rid of tangentt (texcoord2) and use a crossproduct to regenerate it from tangents (texcoord1) and normal (texcoord3)\n"
359 " gl_FrontColor = gl_Color;\n"
360 " // copy the surface texcoord\n"
361 " TexCoord = vec2(gl_TextureMatrix[0] * gl_MultiTexCoord0);\n"
362 "#if !defined(MODE_LIGHTSOURCE) && !defined(MODE_LIGHTDIRECTION)\n"
363 " TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
366 "#ifdef MODE_LIGHTSOURCE\n"
367 " // transform vertex position into light attenuation/cubemap space\n"
368 " // (-1 to +1 across the light box)\n"
369 " CubeVector = vec3(gl_TextureMatrix[3] * gl_Vertex);\n"
371 " // transform unnormalized light direction into tangent space\n"
372 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
373 " // normalize it per pixel)\n"
374 " vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
375 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
376 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
377 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
380 "#ifdef MODE_LIGHTDIRECTION\n"
381 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
382 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
383 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
386 " // transform unnormalized eye direction into tangent space\n"
388 " vec3 EyeVectorModelSpace;\n"
390 " EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
391 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
392 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
393 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
395 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
396 " VectorS = gl_MultiTexCoord1.xyz;\n"
397 " VectorT = gl_MultiTexCoord2.xyz;\n"
398 " VectorR = gl_MultiTexCoord3.xyz;\n"
401 " // transform vertex to camera space, using ftransform to match non-VS\n"
403 " gl_Position = ftransform();\n"
406 "#endif // VERTEX_SHADER\n"
411 "// fragment shader specific:\n"
412 "#ifdef FRAGMENT_SHADER\n"
414 "uniform sampler2D Texture_Normal;\n"
415 "uniform sampler2D Texture_Color;\n"
416 "uniform sampler2D Texture_Gloss;\n"
417 "uniform samplerCube Texture_Cube;\n"
418 "uniform sampler2D Texture_FogMask;\n"
419 "uniform sampler2D Texture_Pants;\n"
420 "uniform sampler2D Texture_Shirt;\n"
421 "uniform sampler2D Texture_Lightmap;\n"
422 "uniform sampler2D Texture_Deluxemap;\n"
423 "uniform sampler2D Texture_Glow;\n"
425 "uniform vec3 LightColor;\n"
426 "uniform vec3 AmbientColor;\n"
427 "uniform vec3 DiffuseColor;\n"
428 "uniform vec3 SpecularColor;\n"
429 "uniform vec3 Color_Pants;\n"
430 "uniform vec3 Color_Shirt;\n"
431 "uniform vec3 FogColor;\n"
433 "uniform float OffsetMapping_Scale;\n"
434 "uniform float OffsetMapping_Bias;\n"
435 "uniform float FogRangeRecip;\n"
437 "uniform float AmbientScale;\n"
438 "uniform float DiffuseScale;\n"
439 "uniform float SpecularScale;\n"
440 "uniform float SpecularPower;\n"
444 " // apply offsetmapping\n"
445 "#ifdef USEOFFSETMAPPING\n"
446 " vec2 TexCoordOffset = TexCoord;\n"
447 "#define TexCoord TexCoordOffset\n"
449 " vec3 eyedir = vec3(normalize(EyeVector));\n"
450 " float depthbias = 1.0 - eyedir.z; // should this be a -?\n"
451 " depthbias = 1.0 - depthbias * depthbias;\n"
453 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
454 " // 14 sample relief mapping: linear search and then binary search\n"
455 " vec3 OffsetVector = vec3(EyeVector.xy * (1.0 / EyeVector.z) * depthbias * OffsetMapping_Scale * vec2(-0.1, 0.1), -0.1);\n"
456 " vec3 RT = vec3(TexCoord - OffsetVector.xy * 10.0, 1.0) + OffsetVector;\n"
457 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += 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;OffsetVector *= 0.5;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 " TexCoord = RT.xy;\n"
473 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
474 " vec2 OffsetVector = vec2((EyeVector.xy * (1.0 / EyeVector.z) * depthbias) * OffsetMapping_Scale * vec2(-0.333, 0.333));\n"
475 " //TexCoord += OffsetVector * 3.0;\n"
476 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
477 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
478 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
482 " // combine the diffuse textures (base, pants, shirt)\n"
483 " vec4 color = vec4(texture2D(Texture_Color, TexCoord));\n"
484 "#ifdef USECOLORMAPPING\n"
485 " color.rgb += vec3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + vec3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
491 "#ifdef MODE_LIGHTSOURCE\n"
494 " // get the surface normal and light normal\n"
495 " vec3 surfacenormal = normalize(vec3(texture2D(Texture_Normal, TexCoord)) - 0.5);\n"
496 " vec3 diffusenormal = vec3(normalize(LightVector));\n"
498 " // calculate directional shading\n"
499 " color.rgb *= (AmbientScale + DiffuseScale * max(dot(surfacenormal, diffusenormal), 0.0));\n"
500 "#ifdef USESPECULAR\n"
501 " vec3 specularnormal = vec3(normalize(diffusenormal + vec3(normalize(EyeVector))));\n"
502 " color.rgb += vec3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(max(dot(surfacenormal, specularnormal), 0.0), SpecularPower);\n"
505 "#ifdef USECUBEFILTER\n"
506 " // apply light cubemap filter\n"
507 " //color.rgb *= normalize(CubeVector) * 0.5 + 0.5;//vec3(textureCube(Texture_Cube, CubeVector));\n"
508 " color.rgb *= vec3(textureCube(Texture_Cube, CubeVector));\n"
511 " // apply light color\n"
512 " color.rgb *= LightColor;\n"
514 " // apply attenuation\n"
516 " // the attenuation is (1-(x*x+y*y+z*z)) which gives a large bright\n"
517 " // center and sharp falloff at the edge, this is about the most efficient\n"
518 " // we can get away with as far as providing illumination.\n"
520 " // pow(1-(x*x+y*y+z*z), 4) is far more realistic but needs large lights to\n"
521 " // provide significant illumination, large = slow = pain.\n"
522 " color.rgb *= max(1.0 - dot(CubeVector, CubeVector), 0.0);\n"
527 "#elif defined(MODE_LIGHTDIRECTION)\n"
528 " // directional model lighting\n"
530 " // get the surface normal and light normal\n"
531 " vec3 surfacenormal = normalize(vec3(texture2D(Texture_Normal, TexCoord)) - 0.5);\n"
532 " vec3 diffusenormal = vec3(normalize(LightVector));\n"
534 " // calculate directional shading\n"
535 " color.rgb *= AmbientColor + DiffuseColor * max(dot(surfacenormal, diffusenormal), 0.0);\n"
536 "#ifdef USESPECULAR\n"
537 " vec3 specularnormal = vec3(normalize(diffusenormal + vec3(normalize(EyeVector))));\n"
538 " color.rgb += vec3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(max(dot(surfacenormal, specularnormal), 0.0), SpecularPower);\n"
544 "#elif defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE)\n"
545 " // deluxemap lightmapping using light vectors in modelspace (evil q3map2)\n"
547 " // get the surface normal and light normal\n"
548 " vec3 surfacenormal = normalize(vec3(texture2D(Texture_Normal, TexCoord)) - 0.5);\n"
549 " vec3 diffusenormal_modelspace = vec3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - 0.5;\n"
550 " vec3 diffusenormal = normalize(vec3(dot(diffusenormal_modelspace, VectorS), dot(diffusenormal_modelspace, VectorT), dot(diffusenormal_modelspace, VectorR)));\n"
552 " // calculate directional shading\n"
553 " vec3 tempcolor = color.rgb * (DiffuseScale * max(dot(surfacenormal, diffusenormal), 0.0));\n"
554 "#ifdef USESPECULAR\n"
555 " vec3 specularnormal = vec3(normalize(diffusenormal + vec3(normalize(EyeVector))));\n"
556 " tempcolor += vec3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(max(dot(surfacenormal, specularnormal), 0.0), SpecularPower);\n"
559 " // apply lightmap color\n"
560 " color.rgb = tempcolor * vec3(texture2D(Texture_Lightmap, TexCoordLightmap)) + color.rgb * vec3(AmbientScale);\n"
565 "#elif defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
566 " // deluxemap lightmapping using light vectors in tangentspace\n"
568 " // get the surface normal and light normal\n"
569 " vec3 surfacenormal = normalize(vec3(texture2D(Texture_Normal, TexCoord)) - 0.5);\n"
570 " vec3 diffusenormal = normalize(vec3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - 0.5);\n"
572 " // calculate directional shading\n"
573 " vec3 tempcolor = color.rgb * (DiffuseScale * max(dot(surfacenormal, diffusenormal), 0.0));\n"
574 "#ifdef USESPECULAR\n"
575 " vec3 specularnormal = vec3(normalize(diffusenormal + vec3(normalize(EyeVector))));\n"
576 " tempcolor += vec3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(max(dot(surfacenormal, specularnormal), 0.0), SpecularPower);\n"
579 " // apply lightmap color\n"
580 " color.rgb = tempcolor * vec3(texture2D(Texture_Lightmap, TexCoordLightmap)) + color.rgb * vec3(AmbientScale);\n"
585 "#else // MODE none (lightmap)\n"
586 " // apply lightmap color\n"
587 " color.rgb *= vec3(texture2D(Texture_Lightmap, TexCoordLightmap)) * DiffuseScale + vec3(AmbientScale);\n"
590 " color *= gl_Color;\n"
593 " color.rgb += vec3(texture2D(Texture_Glow, TexCoord));\n"
598 " float fog = texture2D(Texture_FogMask, vec2(length(EyeVectorModelSpace)*FogRangeRecip, 0.0)).x;\n"
599 " color.rgb = color.rgb * fog + FogColor * (1.0 - fog);\n"
602 " gl_FragColor = color;\n"
605 "#endif // FRAGMENT_SHADER\n"
608 void R_GLSL_CompilePermutation(int permutation)
610 r_glsl_permutation_t *p = r_glsl_permutations + permutation;
611 int vertstrings_count;
612 int fragstrings_count;
614 const char *vertstrings_list[SHADERPERMUTATION_COUNT+1];
615 const char *fragstrings_list[SHADERPERMUTATION_COUNT+1];
616 char permutationname[256];
620 vertstrings_list[0] = "#define VERTEX_SHADER\n";
621 fragstrings_list[0] = "#define FRAGMENT_SHADER\n";
622 vertstrings_count = 1;
623 fragstrings_count = 1;
624 permutationname[0] = 0;
625 if (permutation & SHADERPERMUTATION_MODE_LIGHTSOURCE)
627 vertstrings_list[vertstrings_count++] = "#define MODE_LIGHTSOURCE\n";
628 fragstrings_list[fragstrings_count++] = "#define MODE_LIGHTSOURCE\n";
629 strlcat(permutationname, " lightsource", sizeof(permutationname));
631 if (permutation & SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_MODELSPACE)
633 vertstrings_list[vertstrings_count++] = "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n";
634 fragstrings_list[fragstrings_count++] = "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n";
635 strlcat(permutationname, " lightdirectionmap_modelspace", sizeof(permutationname));
637 if (permutation & SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)
639 vertstrings_list[vertstrings_count++] = "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n";
640 fragstrings_list[fragstrings_count++] = "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n";
641 strlcat(permutationname, " lightdirectionmap_tangentspace", sizeof(permutationname));
643 if (permutation & SHADERPERMUTATION_MODE_LIGHTDIRECTION)
645 vertstrings_list[vertstrings_count++] = "#define MODE_LIGHTDIRECTION\n";
646 fragstrings_list[fragstrings_count++] = "#define MODE_LIGHTDIRECTION\n";
647 strlcat(permutationname, " lightdirection", sizeof(permutationname));
649 if (permutation & SHADERPERMUTATION_GLOW)
651 vertstrings_list[vertstrings_count++] = "#define USEGLOW\n";
652 fragstrings_list[fragstrings_count++] = "#define USEGLOW\n";
653 strlcat(permutationname, " glow", sizeof(permutationname));
655 if (permutation & SHADERPERMUTATION_COLORMAPPING)
657 vertstrings_list[vertstrings_count++] = "#define USECOLORMAPPING\n";
658 fragstrings_list[fragstrings_count++] = "#define USECOLORMAPPING\n";
659 strlcat(permutationname, " colormapping", sizeof(permutationname));
661 if (permutation & SHADERPERMUTATION_SPECULAR)
663 vertstrings_list[vertstrings_count++] = "#define USESPECULAR\n";
664 fragstrings_list[fragstrings_count++] = "#define USESPECULAR\n";
665 strlcat(permutationname, " specular", sizeof(permutationname));
667 if (permutation & SHADERPERMUTATION_FOG)
669 vertstrings_list[vertstrings_count++] = "#define USEFOG\n";
670 fragstrings_list[fragstrings_count++] = "#define USEFOG\n";
671 strlcat(permutationname, " fog", sizeof(permutationname));
673 if (permutation & SHADERPERMUTATION_CUBEFILTER)
675 vertstrings_list[vertstrings_count++] = "#define USECUBEFILTER\n";
676 fragstrings_list[fragstrings_count++] = "#define USECUBEFILTER\n";
677 strlcat(permutationname, " cubefilter", sizeof(permutationname));
679 if (permutation & SHADERPERMUTATION_OFFSETMAPPING)
681 vertstrings_list[vertstrings_count++] = "#define USEOFFSETMAPPING\n";
682 fragstrings_list[fragstrings_count++] = "#define USEOFFSETMAPPING\n";
683 strlcat(permutationname, " offsetmapping", sizeof(permutationname));
685 if (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING)
687 vertstrings_list[vertstrings_count++] = "#define USEOFFSETMAPPING_RELIEFMAPPING\n";
688 fragstrings_list[fragstrings_count++] = "#define USEOFFSETMAPPING_RELIEFMAPPING\n";
689 strlcat(permutationname, " OFFSETMAPPING_RELIEFMAPPING", sizeof(permutationname));
691 shaderstring = (char *)FS_LoadFile("glsl/default.glsl", r_main_mempool, false, NULL);
694 Con_DPrintf("GLSL shader text loaded from disk\n");
695 vertstrings_list[vertstrings_count++] = shaderstring;
696 fragstrings_list[fragstrings_count++] = shaderstring;
700 vertstrings_list[vertstrings_count++] = builtinshaderstring;
701 fragstrings_list[fragstrings_count++] = builtinshaderstring;
703 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, fragstrings_count, fragstrings_list);
707 qglUseProgramObjectARB(p->program);CHECKGLERROR
708 p->loc_Texture_Normal = qglGetUniformLocationARB(p->program, "Texture_Normal");
709 p->loc_Texture_Color = qglGetUniformLocationARB(p->program, "Texture_Color");
710 p->loc_Texture_Gloss = qglGetUniformLocationARB(p->program, "Texture_Gloss");
711 p->loc_Texture_Cube = qglGetUniformLocationARB(p->program, "Texture_Cube");
712 p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
713 p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
714 p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
715 p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
716 p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
717 p->loc_Texture_Glow = qglGetUniformLocationARB(p->program, "Texture_Glow");
718 p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
719 p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
720 p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
721 p->loc_LightColor = qglGetUniformLocationARB(p->program, "LightColor");
722 p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants");
723 p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt");
724 p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip");
725 p->loc_AmbientScale = qglGetUniformLocationARB(p->program, "AmbientScale");
726 p->loc_DiffuseScale = qglGetUniformLocationARB(p->program, "DiffuseScale");
727 p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
728 p->loc_SpecularScale = qglGetUniformLocationARB(p->program, "SpecularScale");
729 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
730 p->loc_AmbientColor = qglGetUniformLocationARB(p->program, "AmbientColor");
731 p->loc_DiffuseColor = qglGetUniformLocationARB(p->program, "DiffuseColor");
732 p->loc_SpecularColor = qglGetUniformLocationARB(p->program, "SpecularColor");
733 p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
734 if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal, 0);
735 if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color, 1);
736 if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss, 2);
737 if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube, 3);
738 if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask, 4);
739 if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants, 5);
740 if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt, 6);
741 if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap, 7);
742 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap, 8);
743 if (p->loc_Texture_Glow >= 0) qglUniform1iARB(p->loc_Texture_Glow, 9);
745 qglUseProgramObjectARB(0);CHECKGLERROR
748 Con_Printf("permutation%s failed for shader %s, some features may not work properly!\n", permutationname, "glsl/default.glsl");
750 Mem_Free(shaderstring);
753 void R_GLSL_Restart_f(void)
756 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
757 if (r_glsl_permutations[i].program)
758 GL_Backend_FreeProgram(r_glsl_permutations[i].program);
759 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
762 int R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting)
764 // select a permutation of the lighting shader appropriate to this
765 // combination of texture, entity, light source, and fogging, only use the
766 // minimum features necessary to avoid wasting rendering time in the
767 // fragment shader on features that are not being used
769 float specularscale = rsurface_texture->specularscale;
770 r_glsl_permutation = NULL;
771 if (r_shadow_rtlight)
773 permutation |= SHADERPERMUTATION_MODE_LIGHTSOURCE;
774 specularscale *= r_shadow_rtlight->specularscale;
775 if (r_shadow_rtlight->currentcubemap != r_texture_whitecube)
776 permutation |= SHADERPERMUTATION_CUBEFILTER;
780 if (!(rsurface_texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
783 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTION;
786 if (r_glsl_deluxemapping.integer >= 1 && r_refdef.worldmodel && r_refdef.worldmodel->brushq3.deluxemapping && rsurface_lightmaptexture)
788 if (r_refdef.worldmodel->brushq3.deluxemapping_modelspace)
789 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_MODELSPACE;
791 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
793 else if (r_glsl_deluxemapping.integer >= 2) // fake mode
794 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
797 if (rsurface_texture->skin.glow)
798 permutation |= SHADERPERMUTATION_GLOW;
800 if (specularscale > 0)
801 permutation |= SHADERPERMUTATION_SPECULAR;
802 if (r_refdef.fogenabled)
803 permutation |= SHADERPERMUTATION_FOG;
804 if (rsurface_texture->colormapping)
805 permutation |= SHADERPERMUTATION_COLORMAPPING;
806 if (r_glsl_offsetmapping.integer)
808 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
809 if (r_glsl_offsetmapping_reliefmapping.integer)
810 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
812 if (!r_glsl_permutations[permutation].program)
814 if (!r_glsl_permutations[permutation].compiled)
815 R_GLSL_CompilePermutation(permutation);
816 if (!r_glsl_permutations[permutation].program)
818 // remove features until we find a valid permutation
820 for (i = SHADERPERMUTATION_COUNT-1;;i>>=1)
822 // reduce i more quickly whenever it would not remove any bits
826 if (!r_glsl_permutations[permutation].compiled)
827 R_GLSL_CompilePermutation(permutation);
828 if (r_glsl_permutations[permutation].program)
831 return 0; // utterly failed
835 r_glsl_permutation = r_glsl_permutations + permutation;
837 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
838 R_Mesh_TexMatrix(0, &rsurface_texture->currenttexmatrix);
839 if (permutation & SHADERPERMUTATION_MODE_LIGHTSOURCE)
841 if (r_glsl_permutation->loc_Texture_Cube >= 0 && r_shadow_rtlight) R_Mesh_TexBindCubeMap(3, R_GetTexture(r_shadow_rtlight->currentcubemap));
842 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]);
843 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
844 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_shadow_rtlight->ambientscale);
845 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_shadow_rtlight->diffusescale);
846 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, specularscale);
848 else if (permutation & SHADERPERMUTATION_MODE_LIGHTDIRECTION)
850 if (r_glsl_permutation->loc_AmbientColor >= 0)
851 qglUniform3fARB(r_glsl_permutation->loc_AmbientColor, rsurface_entity->modellight_ambient[0], rsurface_entity->modellight_ambient[1], rsurface_entity->modellight_ambient[2]);
852 if (r_glsl_permutation->loc_DiffuseColor >= 0)
853 qglUniform3fARB(r_glsl_permutation->loc_DiffuseColor, rsurface_entity->modellight_diffuse[0], rsurface_entity->modellight_diffuse[1], rsurface_entity->modellight_diffuse[2]);
854 if (r_glsl_permutation->loc_SpecularColor >= 0)
855 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);
856 if (r_glsl_permutation->loc_LightDir >= 0)
857 qglUniform3fARB(r_glsl_permutation->loc_LightDir, rsurface_entity->modellight_lightdir[0], rsurface_entity->modellight_lightdir[1], rsurface_entity->modellight_lightdir[2]);
861 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_ambient.value * 2.0f / 128.0f);
862 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_refdef.lightmapintensity * 2.0f);
863 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, r_refdef.lightmapintensity * specularscale * 2.0f);
865 if (r_glsl_permutation->loc_Texture_Normal >= 0) R_Mesh_TexBind(0, R_GetTexture(rsurface_texture->skin.nmap));
866 if (r_glsl_permutation->loc_Texture_Color >= 0) R_Mesh_TexBind(1, R_GetTexture(rsurface_texture->basetexture));
867 if (r_glsl_permutation->loc_Texture_Gloss >= 0) R_Mesh_TexBind(2, R_GetTexture(rsurface_texture->glosstexture));
868 //if (r_glsl_permutation->loc_Texture_Cube >= 0 && permutation & SHADERPERMUTATION_MODE_LIGHTSOURCE) R_Mesh_TexBindCubeMap(3, R_GetTexture(r_shadow_rtlight->currentcubemap));
869 if (r_glsl_permutation->loc_Texture_FogMask >= 0) R_Mesh_TexBind(4, R_GetTexture(r_texture_fogattenuation));
870 if (r_glsl_permutation->loc_Texture_Pants >= 0) R_Mesh_TexBind(5, R_GetTexture(rsurface_texture->skin.pants));
871 if (r_glsl_permutation->loc_Texture_Shirt >= 0) R_Mesh_TexBind(6, R_GetTexture(rsurface_texture->skin.shirt));
872 //if (r_glsl_permutation->loc_Texture_Lightmap >= 0) R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
873 //if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
874 if (r_glsl_permutation->loc_Texture_Glow >= 0) R_Mesh_TexBind(9, R_GetTexture(rsurface_texture->skin.glow));
875 if (r_glsl_permutation->loc_FogColor >= 0)
877 // additive passes are only darkened by fog, not tinted
878 if (r_shadow_rtlight || (rsurface_texture->currentmaterialflags & MATERIALFLAG_ADD))
879 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
881 qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
883 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface_modelorg[0], rsurface_modelorg[1], rsurface_modelorg[2]);
884 if (r_glsl_permutation->loc_Color_Pants >= 0)
886 if (rsurface_texture->skin.pants)
887 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface_entity->colormap_pantscolor[0], rsurface_entity->colormap_pantscolor[1], rsurface_entity->colormap_pantscolor[2]);
889 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
891 if (r_glsl_permutation->loc_Color_Shirt >= 0)
893 if (rsurface_texture->skin.shirt)
894 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface_entity->colormap_shirtcolor[0], rsurface_entity->colormap_shirtcolor[1], rsurface_entity->colormap_shirtcolor[2]);
896 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
898 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, r_refdef.fograngerecip);
899 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface_texture->specularpower);
900 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
905 void R_SwitchSurfaceShader(int permutation)
907 if (r_glsl_permutation != r_glsl_permutations + permutation)
909 r_glsl_permutation = r_glsl_permutations + permutation;
911 qglUseProgramObjectARB(r_glsl_permutation->program);
916 void gl_main_start(void)
918 r_main_texturepool = R_AllocTexturePool();
919 r_bloom_texture_screen = NULL;
920 r_bloom_texture_bloom = NULL;
921 R_BuildBlankTextures();
923 if (gl_texturecubemap)
926 R_BuildNormalizationCube();
929 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
932 void gl_main_shutdown(void)
934 R_FreeTexturePool(&r_main_texturepool);
935 r_bloom_texture_screen = NULL;
936 r_bloom_texture_bloom = NULL;
937 r_texture_blanknormalmap = NULL;
938 r_texture_white = NULL;
939 r_texture_black = NULL;
940 r_texture_whitecube = NULL;
941 r_texture_normalizationcube = NULL;
945 extern void CL_ParseEntityLump(char *entitystring);
946 void gl_main_newmap(void)
948 // FIXME: move this code to client
950 char *entities, entname[MAX_QPATH];
953 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
954 l = (int)strlen(entname) - 4;
955 if (l >= 0 && !strcmp(entname + l, ".bsp"))
957 strcpy(entname + l, ".ent");
958 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
960 CL_ParseEntityLump(entities);
965 if (cl.worldmodel->brush.entities)
966 CL_ParseEntityLump(cl.worldmodel->brush.entities);
970 void GL_Main_Init(void)
972 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
974 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed\n");
975 FOG_registercvars(); // FIXME: move this fog stuff to client?
976 Cvar_RegisterVariable(&r_nearclip);
977 Cvar_RegisterVariable(&r_showsurfaces);
978 Cvar_RegisterVariable(&r_showtris);
979 Cvar_RegisterVariable(&r_shownormals);
980 Cvar_RegisterVariable(&r_showlighting);
981 Cvar_RegisterVariable(&r_showshadowvolumes);
982 Cvar_RegisterVariable(&r_showcollisionbrushes);
983 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
984 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
985 Cvar_RegisterVariable(&r_showdisabledepthtest);
986 Cvar_RegisterVariable(&r_drawentities);
987 Cvar_RegisterVariable(&r_drawviewmodel);
988 Cvar_RegisterVariable(&r_speeds);
989 Cvar_RegisterVariable(&r_fullbrights);
990 Cvar_RegisterVariable(&r_wateralpha);
991 Cvar_RegisterVariable(&r_dynamic);
992 Cvar_RegisterVariable(&r_fullbright);
993 Cvar_RegisterVariable(&r_q1bsp_skymasking);
994 Cvar_RegisterVariable(&r_textureunits);
995 Cvar_RegisterVariable(&r_glsl);
996 Cvar_RegisterVariable(&r_glsl_offsetmapping);
997 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
998 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
999 Cvar_RegisterVariable(&r_glsl_deluxemapping);
1000 Cvar_RegisterVariable(&r_lerpsprites);
1001 Cvar_RegisterVariable(&r_lerpmodels);
1002 Cvar_RegisterVariable(&r_waterscroll);
1003 Cvar_RegisterVariable(&r_bloom);
1004 Cvar_RegisterVariable(&r_bloom_intensity);
1005 Cvar_RegisterVariable(&r_bloom_blur);
1006 Cvar_RegisterVariable(&r_bloom_resolution);
1007 Cvar_RegisterVariable(&r_bloom_power);
1008 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
1009 Cvar_RegisterVariable(&developer_texturelogging);
1010 Cvar_RegisterVariable(&gl_lightmaps);
1011 Cvar_RegisterVariable(&r_test);
1012 Cvar_RegisterVariable(&r_batchmode);
1013 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
1014 Cvar_SetValue("r_fullbrights", 0);
1015 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
1018 extern void R_Textures_Init(void);
1019 extern void GL_Draw_Init(void);
1020 extern void GL_Main_Init(void);
1021 extern void R_Shadow_Init(void);
1022 extern void R_Sky_Init(void);
1023 extern void GL_Surf_Init(void);
1024 extern void R_Crosshairs_Init(void);
1025 extern void R_Light_Init(void);
1026 extern void R_Particles_Init(void);
1027 extern void R_Explosion_Init(void);
1028 extern void gl_backend_init(void);
1029 extern void Sbar_Init(void);
1030 extern void R_LightningBeams_Init(void);
1031 extern void Mod_RenderInit(void);
1033 void Render_Init(void)
1042 R_Crosshairs_Init();
1047 R_LightningBeams_Init();
1056 extern char *ENGINE_EXTENSIONS;
1059 VID_CheckExtensions();
1061 // LordHavoc: report supported extensions
1062 Con_DPrintf("\nengine extensions: %s\n", vm_sv_extensions );
1064 // clear to black (loading plaque will be seen over this)
1066 qglClearColor(0,0,0,1);CHECKGLERROR
1067 qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
1070 int R_CullBox(const vec3_t mins, const vec3_t maxs)
1074 for (i = 0;i < 4;i++)
1076 p = r_view.frustum + i;
1081 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1085 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1089 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1093 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1097 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1101 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1105 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1109 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1117 //==================================================================================
1119 static void R_UpdateEntityLighting(entity_render_t *ent)
1121 vec3_t tempdiffusenormal;
1122 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));
1123 VectorClear(ent->modellight_diffuse);
1124 VectorClear(ent->modellight_lightdir);
1125 if ((ent->flags & RENDER_LIGHT) && r_refdef.worldmodel && r_refdef.worldmodel->brush.LightPoint)
1126 r_refdef.worldmodel->brush.LightPoint(r_refdef.worldmodel, ent->origin, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
1128 VectorSet(ent->modellight_ambient, 1, 1, 1);
1129 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
1130 VectorNormalize(ent->modellight_lightdir);
1131 ent->modellight_ambient[0] *= ent->colormod[0] * r_refdef.lightmapintensity;
1132 ent->modellight_ambient[1] *= ent->colormod[1] * r_refdef.lightmapintensity;
1133 ent->modellight_ambient[2] *= ent->colormod[2] * r_refdef.lightmapintensity;
1134 ent->modellight_diffuse[0] *= ent->colormod[0] * r_refdef.lightmapintensity;
1135 ent->modellight_diffuse[1] *= ent->colormod[1] * r_refdef.lightmapintensity;
1136 ent->modellight_diffuse[2] *= ent->colormod[2] * r_refdef.lightmapintensity;
1139 static void R_View_UpdateEntityVisible (void)
1142 entity_render_t *ent;
1144 if (!r_drawentities.integer)
1147 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : (chase_active.integer ? 0 : RENDER_EXTERIORMODEL);
1148 if (r_refdef.worldmodel && r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs)
1150 // worldmodel can check visibility
1151 for (i = 0;i < r_refdef.numentities;i++)
1153 ent = r_refdef.entities[i];
1154 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));
1159 // no worldmodel or it can't check visibility
1160 for (i = 0;i < r_refdef.numentities;i++)
1162 ent = r_refdef.entities[i];
1163 r_viewcache.entityvisible[i] = !(ent->flags & renderimask) && !R_CullBox(ent->mins, ent->maxs) && (ent->effects & EF_NODEPTHTEST);
1168 // only used if skyrendermasked, and normally returns false
1169 int R_DrawBrushModelsSky (void)
1172 entity_render_t *ent;
1174 if (!r_drawentities.integer)
1178 for (i = 0;i < r_refdef.numentities;i++)
1180 if (!r_viewcache.entityvisible[i])
1182 ent = r_refdef.entities[i];
1183 if (!ent->model || !ent->model->DrawSky)
1185 ent->model->DrawSky(ent);
1191 void R_DrawNoModel(entity_render_t *ent);
1192 void R_DrawModels(void)
1195 entity_render_t *ent;
1197 if (!r_drawentities.integer)
1200 for (i = 0;i < r_refdef.numentities;i++)
1202 if (!r_viewcache.entityvisible[i])
1204 ent = r_refdef.entities[i];
1205 r_refdef.stats.entities++;
1206 if (ent->model && ent->model->Draw != NULL)
1207 ent->model->Draw(ent);
1213 static void R_View_SetFrustum(void)
1215 // break apart the view matrix into vectors for various purposes
1216 Matrix4x4_ToVectors(&r_view.matrix, r_view.forward, r_view.left, r_view.up, r_view.origin);
1217 VectorNegate(r_view.left, r_view.right);
1220 r_view.frustum[0].normal[0] = 0 - 1.0 / r_view.frustum_x;
1221 r_view.frustum[0].normal[1] = 0 - 0;
1222 r_view.frustum[0].normal[2] = -1 - 0;
1223 r_view.frustum[1].normal[0] = 0 + 1.0 / r_view.frustum_x;
1224 r_view.frustum[1].normal[1] = 0 + 0;
1225 r_view.frustum[1].normal[2] = -1 + 0;
1226 r_view.frustum[2].normal[0] = 0 - 0;
1227 r_view.frustum[2].normal[1] = 0 - 1.0 / r_view.frustum_y;
1228 r_view.frustum[2].normal[2] = -1 - 0;
1229 r_view.frustum[3].normal[0] = 0 + 0;
1230 r_view.frustum[3].normal[1] = 0 + 1.0 / r_view.frustum_y;
1231 r_view.frustum[3].normal[2] = -1 + 0;
1235 zNear = r_refdef.nearclip;
1236 nudge = 1.0 - 1.0 / (1<<23);
1237 r_view.frustum[4].normal[0] = 0 - 0;
1238 r_view.frustum[4].normal[1] = 0 - 0;
1239 r_view.frustum[4].normal[2] = -1 - -nudge;
1240 r_view.frustum[4].dist = 0 - -2 * zNear * nudge;
1241 r_view.frustum[5].normal[0] = 0 + 0;
1242 r_view.frustum[5].normal[1] = 0 + 0;
1243 r_view.frustum[5].normal[2] = -1 + -nudge;
1244 r_view.frustum[5].dist = 0 + -2 * zNear * nudge;
1250 r_view.frustum[0].normal[0] = m[3] - m[0];
1251 r_view.frustum[0].normal[1] = m[7] - m[4];
1252 r_view.frustum[0].normal[2] = m[11] - m[8];
1253 r_view.frustum[0].dist = m[15] - m[12];
1255 r_view.frustum[1].normal[0] = m[3] + m[0];
1256 r_view.frustum[1].normal[1] = m[7] + m[4];
1257 r_view.frustum[1].normal[2] = m[11] + m[8];
1258 r_view.frustum[1].dist = m[15] + m[12];
1260 r_view.frustum[2].normal[0] = m[3] - m[1];
1261 r_view.frustum[2].normal[1] = m[7] - m[5];
1262 r_view.frustum[2].normal[2] = m[11] - m[9];
1263 r_view.frustum[2].dist = m[15] - m[13];
1265 r_view.frustum[3].normal[0] = m[3] + m[1];
1266 r_view.frustum[3].normal[1] = m[7] + m[5];
1267 r_view.frustum[3].normal[2] = m[11] + m[9];
1268 r_view.frustum[3].dist = m[15] + m[13];
1270 r_view.frustum[4].normal[0] = m[3] - m[2];
1271 r_view.frustum[4].normal[1] = m[7] - m[6];
1272 r_view.frustum[4].normal[2] = m[11] - m[10];
1273 r_view.frustum[4].dist = m[15] - m[14];
1275 r_view.frustum[5].normal[0] = m[3] + m[2];
1276 r_view.frustum[5].normal[1] = m[7] + m[6];
1277 r_view.frustum[5].normal[2] = m[11] + m[10];
1278 r_view.frustum[5].dist = m[15] + m[14];
1283 VectorMAM(1, r_view.forward, 1.0 / -r_view.frustum_x, r_view.left, r_view.frustum[0].normal);
1284 VectorMAM(1, r_view.forward, 1.0 / r_view.frustum_x, r_view.left, r_view.frustum[1].normal);
1285 VectorMAM(1, r_view.forward, 1.0 / -r_view.frustum_y, r_view.up, r_view.frustum[2].normal);
1286 VectorMAM(1, r_view.forward, 1.0 / r_view.frustum_y, r_view.up, r_view.frustum[3].normal);
1287 VectorCopy(r_view.forward, r_view.frustum[4].normal);
1288 VectorNormalize(r_view.frustum[0].normal);
1289 VectorNormalize(r_view.frustum[1].normal);
1290 VectorNormalize(r_view.frustum[2].normal);
1291 VectorNormalize(r_view.frustum[3].normal);
1292 r_view.frustum[0].dist = DotProduct (r_view.origin, r_view.frustum[0].normal);
1293 r_view.frustum[1].dist = DotProduct (r_view.origin, r_view.frustum[1].normal);
1294 r_view.frustum[2].dist = DotProduct (r_view.origin, r_view.frustum[2].normal);
1295 r_view.frustum[3].dist = DotProduct (r_view.origin, r_view.frustum[3].normal);
1296 r_view.frustum[4].dist = DotProduct (r_view.origin, r_view.frustum[4].normal) + r_refdef.nearclip;
1297 PlaneClassify(&r_view.frustum[0]);
1298 PlaneClassify(&r_view.frustum[1]);
1299 PlaneClassify(&r_view.frustum[2]);
1300 PlaneClassify(&r_view.frustum[3]);
1301 PlaneClassify(&r_view.frustum[4]);
1303 // LordHavoc: note to all quake engine coders, Quake had a special case
1304 // for 90 degrees which assumed a square view (wrong), so I removed it,
1305 // Quake2 has it disabled as well.
1307 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
1308 //RotatePointAroundVector( r_view.frustum[0].normal, r_view.up, r_view.forward, -(90 - r_refdef.fov_x / 2));
1309 //r_view.frustum[0].dist = DotProduct (r_view.origin, frustum[0].normal);
1310 //PlaneClassify(&frustum[0]);
1312 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
1313 //RotatePointAroundVector( r_view.frustum[1].normal, r_view.up, r_view.forward, (90 - r_refdef.fov_x / 2));
1314 //r_view.frustum[1].dist = DotProduct (r_view.origin, frustum[1].normal);
1315 //PlaneClassify(&frustum[1]);
1317 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
1318 //RotatePointAroundVector( r_view.frustum[2].normal, r_view.left, r_view.forward, -(90 - r_refdef.fov_y / 2));
1319 //r_view.frustum[2].dist = DotProduct (r_view.origin, frustum[2].normal);
1320 //PlaneClassify(&frustum[2]);
1322 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
1323 //RotatePointAroundVector( r_view.frustum[3].normal, r_view.left, r_view.forward, (90 - r_refdef.fov_y / 2));
1324 //r_view.frustum[3].dist = DotProduct (r_view.origin, frustum[3].normal);
1325 //PlaneClassify(&frustum[3]);
1328 //VectorCopy(r_view.forward, r_view.frustum[4].normal);
1329 //r_view.frustum[4].dist = DotProduct (r_view.origin, frustum[4].normal) + r_nearclip.value;
1330 //PlaneClassify(&frustum[4]);
1333 void R_View_Update(void)
1335 // GL is weird because it's bottom to top, r_view.y is top to bottom
1336 qglViewport(r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
1337 GL_Scissor(r_view.x, r_view.y, r_view.width, r_view.height);
1338 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
1339 R_View_SetFrustum();
1340 R_View_WorldVisibility();
1341 R_View_UpdateEntityVisible();
1344 static void R_BlendView(void)
1346 int screenwidth, screenheight;
1350 float texcoord2f[3][8];
1352 // set the (poorly named) screenwidth and screenheight variables to
1353 // a power of 2 at least as large as the screen, these will define the
1354 // size of the texture to allocate
1355 for (screenwidth = 1;screenwidth < vid.width;screenwidth *= 2);
1356 for (screenheight = 1;screenheight < vid.height;screenheight *= 2);
1358 doblend = r_refdef.viewblend[3] >= 0.01f;
1359 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;
1361 if (!dobloom && !doblend)
1364 GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
1366 GL_DepthTest(false);
1367 R_Mesh_Matrix(&identitymatrix);
1368 // vertex coordinates for a quad that covers the screen exactly
1369 vertex3f[0] = 0;vertex3f[1] = 0;vertex3f[2] = 0;
1370 vertex3f[3] = 1;vertex3f[4] = 0;vertex3f[5] = 0;
1371 vertex3f[6] = 1;vertex3f[7] = 1;vertex3f[8] = 0;
1372 vertex3f[9] = 0;vertex3f[10] = 1;vertex3f[11] = 0;
1373 R_Mesh_VertexPointer(vertex3f);
1374 R_Mesh_ColorPointer(NULL);
1375 R_Mesh_ResetTextureState();
1378 int bloomwidth, bloomheight, x, range;
1379 float xoffset, yoffset, r;
1380 r_refdef.stats.bloom++;
1381 // allocate textures as needed
1382 if (!r_bloom_texture_screen)
1383 r_bloom_texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", screenwidth, screenheight, NULL, TEXTYPE_RGBA, TEXF_FORCENEAREST | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
1384 if (!r_bloom_texture_bloom)
1385 r_bloom_texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", screenwidth, screenheight, NULL, TEXTYPE_RGBA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
1386 // set bloomwidth and bloomheight to the bloom resolution that will be
1387 // used (often less than the screen resolution for faster rendering)
1388 bloomwidth = min(r_view.width, r_bloom_resolution.integer);
1389 bloomheight = min(r_view.height, bloomwidth * r_view.height / r_view.width);
1390 // set up a texcoord array for the full resolution screen image
1391 // (we have to keep this around to copy back during final render)
1392 texcoord2f[0][0] = 0;
1393 texcoord2f[0][1] = (float)r_view.height / (float)screenheight;
1394 texcoord2f[0][2] = (float)r_view.width / (float)screenwidth;
1395 texcoord2f[0][3] = (float)r_view.height / (float)screenheight;
1396 texcoord2f[0][4] = (float)r_view.width / (float)screenwidth;
1397 texcoord2f[0][5] = 0;
1398 texcoord2f[0][6] = 0;
1399 texcoord2f[0][7] = 0;
1400 // set up a texcoord array for the reduced resolution bloom image
1401 // (which will be additive blended over the screen image)
1402 texcoord2f[1][0] = 0;
1403 texcoord2f[1][1] = (float)bloomheight / (float)screenheight;
1404 texcoord2f[1][2] = (float)bloomwidth / (float)screenwidth;
1405 texcoord2f[1][3] = (float)bloomheight / (float)screenheight;
1406 texcoord2f[1][4] = (float)bloomwidth / (float)screenwidth;
1407 texcoord2f[1][5] = 0;
1408 texcoord2f[1][6] = 0;
1409 texcoord2f[1][7] = 0;
1410 R_Mesh_TexCoordPointer(0, 2, texcoord2f[0]);
1411 R_Mesh_TexBind(0, R_GetTexture(r_bloom_texture_screen));
1412 // copy view into the full resolution screen image texture
1413 GL_ActiveTexture(0);
1415 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
1416 r_refdef.stats.bloom_copypixels += r_view.width * r_view.height;
1417 // now scale it down to the bloom size and raise to a power of itself
1418 // to darken it (this leaves the really bright stuff bright, and
1419 // everything else becomes very dark)
1420 // TODO: optimize with multitexture or GLSL
1422 qglViewport(r_view.x, vid.height - (r_view.y + bloomheight), bloomwidth, bloomheight);CHECKGLERROR
1423 GL_BlendFunc(GL_ONE, GL_ZERO);
1424 GL_Color(1, 1, 1, 1);
1425 R_Mesh_Draw(0, 4, 2, polygonelements);
1426 r_refdef.stats.bloom_drawpixels += bloomwidth * bloomheight;
1427 // render multiple times with a multiply blendfunc to raise to a power
1428 GL_BlendFunc(GL_DST_COLOR, GL_ZERO);
1429 for (x = 1;x < r_bloom_power.integer;x++)
1431 R_Mesh_Draw(0, 4, 2, polygonelements);
1432 r_refdef.stats.bloom_drawpixels += bloomwidth * bloomheight;
1434 // we now have a darkened bloom image in the framebuffer, copy it into
1435 // the bloom image texture for more processing
1436 R_Mesh_TexBind(0, R_GetTexture(r_bloom_texture_bloom));
1437 R_Mesh_TexCoordPointer(0, 2, texcoord2f[2]);
1438 GL_ActiveTexture(0);
1440 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view.x, vid.height - (r_view.y + bloomheight), bloomwidth, bloomheight);CHECKGLERROR
1441 r_refdef.stats.bloom_copypixels += bloomwidth * bloomheight;
1442 // blend on at multiple vertical offsets to achieve a vertical blur
1443 // TODO: do offset blends using GLSL
1444 range = r_bloom_blur.integer * bloomwidth / 320;
1445 GL_BlendFunc(GL_ONE, GL_ZERO);
1446 for (x = -range;x <= range;x++)
1448 xoffset = 0 / (float)bloomwidth * (float)bloomwidth / (float)screenwidth;
1449 yoffset = x / (float)bloomheight * (float)bloomheight / (float)screenheight;
1450 // compute a texcoord array with the specified x and y offset
1451 texcoord2f[2][0] = xoffset+0;
1452 texcoord2f[2][1] = yoffset+(float)bloomheight / (float)screenheight;
1453 texcoord2f[2][2] = xoffset+(float)bloomwidth / (float)screenwidth;
1454 texcoord2f[2][3] = yoffset+(float)bloomheight / (float)screenheight;
1455 texcoord2f[2][4] = xoffset+(float)bloomwidth / (float)screenwidth;
1456 texcoord2f[2][5] = yoffset+0;
1457 texcoord2f[2][6] = xoffset+0;
1458 texcoord2f[2][7] = yoffset+0;
1459 // this r value looks like a 'dot' particle, fading sharply to
1460 // black at the edges
1461 // (probably not realistic but looks good enough)
1462 r = r_bloom_intensity.value/(range*2+1)*(1 - x*x/(float)(range*range));
1465 GL_Color(r, r, r, 1);
1466 R_Mesh_Draw(0, 4, 2, polygonelements);
1467 r_refdef.stats.bloom_drawpixels += bloomwidth * bloomheight;
1468 GL_BlendFunc(GL_ONE, GL_ONE);
1470 // copy the vertically blurred bloom view to a texture
1471 GL_ActiveTexture(0);
1473 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view.x, vid.height - (r_view.y + bloomheight), bloomwidth, bloomheight);CHECKGLERROR
1474 r_refdef.stats.bloom_copypixels += bloomwidth * bloomheight;
1475 // blend the vertically blurred image at multiple offsets horizontally
1476 // to finish the blur effect
1477 // TODO: do offset blends using GLSL
1478 range = r_bloom_blur.integer * bloomwidth / 320;
1479 GL_BlendFunc(GL_ONE, GL_ZERO);
1480 for (x = -range;x <= range;x++)
1482 xoffset = x / (float)bloomwidth * (float)bloomwidth / (float)screenwidth;
1483 yoffset = 0 / (float)bloomheight * (float)bloomheight / (float)screenheight;
1484 // compute a texcoord array with the specified x and y offset
1485 texcoord2f[2][0] = xoffset+0;
1486 texcoord2f[2][1] = yoffset+(float)bloomheight / (float)screenheight;
1487 texcoord2f[2][2] = xoffset+(float)bloomwidth / (float)screenwidth;
1488 texcoord2f[2][3] = yoffset+(float)bloomheight / (float)screenheight;
1489 texcoord2f[2][4] = xoffset+(float)bloomwidth / (float)screenwidth;
1490 texcoord2f[2][5] = yoffset+0;
1491 texcoord2f[2][6] = xoffset+0;
1492 texcoord2f[2][7] = yoffset+0;
1493 // this r value looks like a 'dot' particle, fading sharply to
1494 // black at the edges
1495 // (probably not realistic but looks good enough)
1496 r = r_bloom_intensity.value/(range*2+1)*(1 - x*x/(float)(range*range));
1499 GL_Color(r, r, r, 1);
1500 R_Mesh_Draw(0, 4, 2, polygonelements);
1501 r_refdef.stats.bloom_drawpixels += bloomwidth * bloomheight;
1502 GL_BlendFunc(GL_ONE, GL_ONE);
1504 // copy the blurred bloom view to a texture
1505 GL_ActiveTexture(0);
1507 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view.x, vid.height - (r_view.y + bloomheight), bloomwidth, bloomheight);CHECKGLERROR
1508 r_refdef.stats.bloom_copypixels += bloomwidth * bloomheight;
1509 // go back to full view area
1510 qglViewport(r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
1511 // put the original screen image back in place and blend the bloom
1514 GL_BlendFunc(GL_ONE, GL_ZERO);
1515 // do both in one pass if possible
1516 R_Mesh_TexBind(0, R_GetTexture(r_bloom_texture_screen));
1517 R_Mesh_TexCoordPointer(0, 2, texcoord2f[0]);
1518 if (r_textureunits.integer >= 2 && gl_combine.integer)
1520 R_Mesh_TexCombine(1, GL_ADD, GL_ADD, 1, 1);
1521 R_Mesh_TexBind(1, R_GetTexture(r_bloom_texture_bloom));
1522 R_Mesh_TexCoordPointer(1, 2, texcoord2f[1]);
1526 R_Mesh_Draw(0, 4, 2, polygonelements);
1527 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
1528 // now blend on the bloom texture
1529 GL_BlendFunc(GL_ONE, GL_ONE);
1530 R_Mesh_TexBind(0, R_GetTexture(r_bloom_texture_bloom));
1531 R_Mesh_TexCoordPointer(0, 2, texcoord2f[1]);
1533 R_Mesh_Draw(0, 4, 2, polygonelements);
1534 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
1538 // apply a color tint to the whole view
1539 R_Mesh_ResetTextureState();
1540 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1541 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
1542 R_Mesh_Draw(0, 4, 2, polygonelements);
1546 void R_RenderScene(void);
1548 matrix4x4_t r_waterscrollmatrix;
1550 void R_UpdateVariables(void)
1556 r_refdef.farclip = 4096;
1557 if (r_refdef.worldmodel)
1558 r_refdef.farclip += VectorDistance(r_refdef.worldmodel->normalmins, r_refdef.worldmodel->normalmaxs);
1559 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
1561 r_refdef.polygonfactor = 0;
1562 r_refdef.polygonoffset = 0;
1563 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_shadow_polygonfactor.value;
1564 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_shadow_polygonoffset.value;
1566 r_refdef.rtworld = r_shadow_realtime_world.integer;
1567 r_refdef.rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
1568 r_refdef.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer;
1569 r_refdef.rtdlightshadows = r_refdef.rtdlight && (r_refdef.rtworld ? r_shadow_realtime_world_dlightshadows.integer : r_shadow_realtime_dlight_shadows.integer) && gl_stencil;
1570 r_refdef.lightmapintensity = r_refdef.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
1571 if (r_showsurfaces.integer)
1573 r_refdef.rtworld = false;
1574 r_refdef.rtworldshadows = false;
1575 r_refdef.rtdlight = false;
1576 r_refdef.rtdlightshadows = false;
1577 r_refdef.lightmapintensity = 0;
1580 if (gamemode == GAME_NEHAHRA)
1582 if (gl_fogenable.integer)
1584 r_refdef.oldgl_fogenable = true;
1585 r_refdef.fog_density = gl_fogdensity.value;
1586 r_refdef.fog_red = gl_fogred.value;
1587 r_refdef.fog_green = gl_foggreen.value;
1588 r_refdef.fog_blue = gl_fogblue.value;
1590 else if (r_refdef.oldgl_fogenable)
1592 r_refdef.oldgl_fogenable = false;
1593 r_refdef.fog_density = 0;
1594 r_refdef.fog_red = 0;
1595 r_refdef.fog_green = 0;
1596 r_refdef.fog_blue = 0;
1599 if (r_refdef.fog_density)
1601 r_refdef.fogcolor[0] = bound(0.0f, r_refdef.fog_red , 1.0f);
1602 r_refdef.fogcolor[1] = bound(0.0f, r_refdef.fog_green, 1.0f);
1603 r_refdef.fogcolor[2] = bound(0.0f, r_refdef.fog_blue , 1.0f);
1605 if (r_refdef.fog_density)
1607 r_refdef.fogenabled = true;
1608 // this is the point where the fog reaches 0.9986 alpha, which we
1609 // consider a good enough cutoff point for the texture
1610 // (0.9986 * 256 == 255.6)
1611 r_refdef.fogrange = 400 / r_refdef.fog_density;
1612 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
1613 r_refdef.fogtabledistmultiplier = FOGTABLEWIDTH * r_refdef.fograngerecip;
1614 // fog color was already set
1617 r_refdef.fogenabled = false;
1619 // update some cached entity properties...
1620 for (i = 0;i < r_refdef.numentities;i++)
1622 entity_render_t *ent = r_refdef.entities[i];
1623 // some of the renderer still relies on origin...
1624 Matrix4x4_OriginFromMatrix(&ent->matrix, ent->origin);
1625 // some of the renderer still relies on scale...
1626 ent->scale = Matrix4x4_ScaleFromMatrix(&ent->matrix);
1627 R_UpdateEntityLighting(ent);
1636 void R_RenderView(void)
1638 if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
1639 return; //Host_Error ("R_RenderView: NULL worldmodel");
1642 GL_ScissorTest(true);
1644 if (r_timereport_active)
1645 R_TimeReport("setup");
1648 if (r_timereport_active)
1649 R_TimeReport("visibility");
1652 if (r_timereport_active)
1653 R_TimeReport("clear");
1658 if (r_timereport_active)
1659 R_TimeReport("blendview");
1661 GL_Scissor(0, 0, vid.width, vid.height);
1662 GL_ScissorTest(false);
1667 void CSQC_R_ClearScreen (void)
1669 if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
1670 return; //Host_Error ("R_RenderView: NULL worldmodel");
1673 GL_ScissorTest(true);
1675 if (r_timereport_active)
1676 R_TimeReport("setup");
1679 if (r_timereport_active)
1680 R_TimeReport("visibility");
1683 if (r_timereport_active)
1684 R_TimeReport("clear");
1689 void CSQC_R_RenderScene (void)
1694 if (r_timereport_active)
1695 R_TimeReport("blendview");
1697 GL_Scissor(0, 0, vid.width, vid.height);
1698 GL_ScissorTest(false);
1702 extern void R_DrawLightningBeams (void);
1703 extern void VM_AddPolygonsToMeshQueue (void);
1704 void R_RenderScene(void)
1706 // don't let sound skip if going slow
1707 if (r_refdef.extraupdate)
1711 if (gl_support_fragment_shader)
1713 qglUseProgramObjectARB(0);CHECKGLERROR
1715 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
1716 qglPolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR
1717 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
1719 R_MeshQueue_BeginScene();
1721 if (r_refdef.rtworldshadows || r_refdef.rtdlightshadows)
1722 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_view.frustum_x, r_view.frustum_y, r_refdef.nearclip);
1724 GL_SetupView_Mode_Perspective(r_view.frustum_x, r_view.frustum_y, r_refdef.nearclip, r_refdef.farclip);
1726 GL_SetupView_Orientation_FromEntity(&r_view.matrix);
1728 R_Shadow_UpdateWorldLightSelection();
1732 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);
1734 if (cl.csqc_vidvars.drawworld)
1736 // don't let sound skip if going slow
1737 if (r_refdef.extraupdate)
1740 if (r_refdef.worldmodel && r_refdef.worldmodel->DrawSky)
1742 r_refdef.worldmodel->DrawSky(r_refdef.worldentity);
1743 if (r_timereport_active)
1744 R_TimeReport("worldsky");
1747 if (R_DrawBrushModelsSky() && r_timereport_active)
1748 R_TimeReport("bmodelsky");
1750 if (r_refdef.worldmodel && r_refdef.worldmodel->Draw)
1752 r_refdef.worldmodel->Draw(r_refdef.worldentity);
1753 if (r_timereport_active)
1754 R_TimeReport("world");
1758 // don't let sound skip if going slow
1759 if (r_refdef.extraupdate)
1763 if (r_timereport_active)
1764 R_TimeReport("models");
1766 // don't let sound skip if going slow
1767 if (r_refdef.extraupdate)
1770 R_ShadowVolumeLighting(false);
1771 if (r_timereport_active)
1772 R_TimeReport("rtlights");
1774 // don't let sound skip if going slow
1775 if (r_refdef.extraupdate)
1778 if (cl.csqc_vidvars.drawworld)
1780 R_DrawLightningBeams();
1781 if (r_timereport_active)
1782 R_TimeReport("lightning");
1785 if (r_timereport_active)
1786 R_TimeReport("particles");
1789 if (r_timereport_active)
1790 R_TimeReport("explosions");
1793 if (gl_support_fragment_shader)
1795 qglUseProgramObjectARB(0);CHECKGLERROR
1797 VM_AddPolygonsToMeshQueue();
1799 if (gl_support_fragment_shader)
1801 qglUseProgramObjectARB(0);CHECKGLERROR
1803 R_MeshQueue_RenderTransparent();
1804 if (r_timereport_active)
1805 R_TimeReport("drawtrans");
1807 if (gl_support_fragment_shader)
1809 qglUseProgramObjectARB(0);CHECKGLERROR
1812 if (cl.csqc_vidvars.drawworld)
1815 if (r_timereport_active)
1816 R_TimeReport("coronas");
1818 if(cl.csqc_vidvars.drawcrosshair)
1820 R_DrawWorldCrosshair();
1821 if (r_timereport_active)
1822 R_TimeReport("crosshair");
1825 // don't let sound skip if going slow
1826 if (r_refdef.extraupdate)
1830 if (gl_support_fragment_shader)
1832 qglUseProgramObjectARB(0);CHECKGLERROR
1834 qglPolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR
1835 qglDisable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
1839 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
1842 float *v, *c, f1, f2, diff[3], vertex3f[8*3], color4f[8*4];
1843 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1844 GL_DepthMask(false);
1846 R_Mesh_Matrix(&identitymatrix);
1848 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2];
1849 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
1850 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
1851 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
1852 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
1853 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
1854 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
1855 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
1856 R_FillColors(color, 8, cr, cg, cb, ca);
1857 if (r_refdef.fogenabled)
1859 for (i = 0, v = vertex, c = color;i < 8;i++, v += 4, c += 4)
1861 f2 = VERTEXFOGTABLE(VectorDistance(v, r_view.origin));
1863 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
1864 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
1865 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
1868 R_Mesh_VertexPointer(vertex3f);
1869 R_Mesh_ColorPointer(color);
1870 R_Mesh_ResetTextureState();
1875 int nomodelelements[24] =
1887 float nomodelvertex3f[6*3] =
1897 float nomodelcolor4f[6*4] =
1899 0.0f, 0.0f, 0.5f, 1.0f,
1900 0.0f, 0.0f, 0.5f, 1.0f,
1901 0.0f, 0.5f, 0.0f, 1.0f,
1902 0.0f, 0.5f, 0.0f, 1.0f,
1903 0.5f, 0.0f, 0.0f, 1.0f,
1904 0.5f, 0.0f, 0.0f, 1.0f
1907 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
1912 // this is only called once per entity so numsurfaces is always 1, and
1913 // surfacelist is always {0}, so this code does not handle batches
1914 R_Mesh_Matrix(&ent->matrix);
1916 if (ent->flags & EF_ADDITIVE)
1918 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
1919 GL_DepthMask(false);
1921 else if (ent->alpha < 1)
1923 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1924 GL_DepthMask(false);
1928 GL_BlendFunc(GL_ONE, GL_ZERO);
1931 GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
1932 R_Mesh_VertexPointer(nomodelvertex3f);
1933 if (r_refdef.fogenabled)
1935 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
1936 R_Mesh_ColorPointer(color4f);
1937 f2 = VERTEXFOGTABLE(VectorDistance(ent->origin, r_view.origin));
1939 for (i = 0, c = color4f;i < 6;i++, c += 4)
1941 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
1942 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
1943 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
1947 else if (ent->alpha != 1)
1949 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
1950 R_Mesh_ColorPointer(color4f);
1951 for (i = 0, c = color4f;i < 6;i++, c += 4)
1955 R_Mesh_ColorPointer(nomodelcolor4f);
1956 R_Mesh_ResetTextureState();
1957 R_Mesh_Draw(0, 6, 8, nomodelelements);
1960 void R_DrawNoModel(entity_render_t *ent)
1962 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
1963 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_view.origin : ent->origin, R_DrawNoModel_TransparentCallback, ent, 0, r_shadow_rtlight);
1965 // R_DrawNoModelCallback(ent, 0);
1968 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
1970 vec3_t right1, right2, diff, normal;
1972 VectorSubtract (org2, org1, normal);
1974 // calculate 'right' vector for start
1975 VectorSubtract (r_view.origin, org1, diff);
1976 CrossProduct (normal, diff, right1);
1977 VectorNormalize (right1);
1979 // calculate 'right' vector for end
1980 VectorSubtract (r_view.origin, org2, diff);
1981 CrossProduct (normal, diff, right2);
1982 VectorNormalize (right2);
1984 vert[ 0] = org1[0] + width * right1[0];
1985 vert[ 1] = org1[1] + width * right1[1];
1986 vert[ 2] = org1[2] + width * right1[2];
1987 vert[ 3] = org1[0] - width * right1[0];
1988 vert[ 4] = org1[1] - width * right1[1];
1989 vert[ 5] = org1[2] - width * right1[2];
1990 vert[ 6] = org2[0] - width * right2[0];
1991 vert[ 7] = org2[1] - width * right2[1];
1992 vert[ 8] = org2[2] - width * right2[2];
1993 vert[ 9] = org2[0] + width * right2[0];
1994 vert[10] = org2[1] + width * right2[1];
1995 vert[11] = org2[2] + width * right2[2];
1998 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
2000 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)
2002 float fog = 0.0f, ifog;
2005 if (r_refdef.fogenabled)
2006 fog = VERTEXFOGTABLE(VectorDistance(origin, r_view.origin));
2009 R_Mesh_Matrix(&identitymatrix);
2010 GL_BlendFunc(blendfunc1, blendfunc2);
2011 GL_DepthMask(false);
2012 GL_DepthTest(!depthdisable);
2014 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
2015 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
2016 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
2017 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
2018 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
2019 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
2020 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
2021 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
2022 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
2023 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
2024 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
2025 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
2027 R_Mesh_VertexPointer(vertex3f);
2028 R_Mesh_ColorPointer(NULL);
2029 R_Mesh_ResetTextureState();
2030 R_Mesh_TexBind(0, R_GetTexture(texture));
2031 R_Mesh_TexCoordPointer(0, 2, spritetexcoord2f);
2032 GL_Color(cr * ifog, cg * ifog, cb * ifog, ca);
2033 R_Mesh_Draw(0, 4, 2, polygonelements);
2035 if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
2037 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
2038 GL_BlendFunc(blendfunc1, GL_ONE);
2039 GL_Color(r_refdef.fogcolor[0] * fog, r_refdef.fogcolor[1] * fog, r_refdef.fogcolor[2] * fog, ca);
2040 R_Mesh_Draw(0, 4, 2, polygonelements);
2044 int R_Mesh_AddVertex3f(rmesh_t *mesh, const float *v)
2048 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
2049 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
2051 if (i == mesh->numvertices)
2053 if (mesh->numvertices < mesh->maxvertices)
2055 VectorCopy(v, vertex3f);
2056 mesh->numvertices++;
2058 return mesh->numvertices;
2064 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
2068 element[0] = R_Mesh_AddVertex3f(mesh, vertex3f);vertex3f += 3;
2069 element[1] = R_Mesh_AddVertex3f(mesh, vertex3f);vertex3f += 3;
2070 e = mesh->element3i + mesh->numtriangles * 3;
2071 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
2073 element[2] = R_Mesh_AddVertex3f(mesh, vertex3f);
2074 if (mesh->numtriangles < mesh->maxtriangles)
2079 mesh->numtriangles++;
2081 element[1] = element[2];
2085 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
2087 int planenum, planenum2;
2090 mplane_t *plane, *plane2;
2091 float temppoints[2][256*3];
2092 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
2096 PolygonF_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->normal[3], 1024.0*1024.0*1024.0);
2097 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
2099 if (planenum2 == planenum)
2101 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);
2104 if (tempnumpoints < 3)
2106 // generate elements forming a triangle fan for this polygon
2107 R_Mesh_AddPolygon3f(mesh, tempnumpoints, temppoints[w]);
2111 static void R_DrawCollisionBrush(const colbrushf_t *brush)
2114 R_Mesh_VertexPointer(brush->points->v);
2115 i = (int)(((size_t)brush) / sizeof(colbrushf_t));
2116 GL_Color((i & 31) * (1.0f / 32.0f), ((i >> 5) & 31) * (1.0f / 32.0f), ((i >> 10) & 31) * (1.0f / 32.0f), 0.2f);
2117 GL_LockArrays(0, brush->numpoints);
2118 R_Mesh_Draw(0, brush->numpoints, brush->numtriangles, brush->elements);
2119 GL_LockArrays(0, 0);
2122 static void R_DrawCollisionSurface(const entity_render_t *ent, const msurface_t *surface)
2125 if (!surface->num_collisiontriangles)
2127 R_Mesh_VertexPointer(surface->data_collisionvertex3f);
2128 i = (int)(((size_t)surface) / sizeof(msurface_t));
2129 GL_Color((i & 31) * (1.0f / 32.0f), ((i >> 5) & 31) * (1.0f / 32.0f), ((i >> 10) & 31) * (1.0f / 32.0f), 0.2f);
2130 GL_LockArrays(0, surface->num_collisionvertices);
2131 R_Mesh_Draw(0, surface->num_collisionvertices, surface->num_collisiontriangles, surface->data_collisionelement3i);
2132 GL_LockArrays(0, 0);
2135 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)
2137 texturelayer_t *layer;
2138 layer = t->currentlayers + t->currentnumlayers++;
2140 layer->depthmask = depthmask;
2141 layer->blendfunc1 = blendfunc1;
2142 layer->blendfunc2 = blendfunc2;
2143 layer->texture = texture;
2144 layer->texmatrix = *matrix;
2145 layer->color[0] = r;
2146 layer->color[1] = g;
2147 layer->color[2] = b;
2148 layer->color[3] = a;
2151 void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
2153 // FIXME: identify models using a better check than ent->model->brush.shadowmesh
2154 //int lightmode = ((ent->effects & EF_FULLBRIGHT) || ent->model->brush.shadowmesh) ? 0 : 2;
2157 texture_t *texture = t;
2158 model_t *model = ent->model;
2159 int s = ent->skinnum;
2160 if ((unsigned int)s >= (unsigned int)model->numskins)
2162 if (model->skinscenes)
2164 if (model->skinscenes[s].framecount > 1)
2165 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
2167 s = model->skinscenes[s].firstframe;
2170 t = t + s * model->num_surfaces;
2173 // use an alternate animation if the entity's frame is not 0,
2174 // and only if the texture has an alternate animation
2175 if (ent->frame != 0 && t->anim_total[1])
2176 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.time * 5.0f) % t->anim_total[1]) : 0];
2178 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.time * 5.0f) % t->anim_total[0]) : 0];
2180 texture->currentframe = t;
2183 t->currentmaterialflags = t->basematerialflags;
2184 t->currentalpha = ent->alpha;
2185 if (t->basematerialflags & MATERIALFLAG_WATERALPHA)
2186 t->currentalpha *= r_wateralpha.value;
2187 if (!(ent->flags & RENDER_LIGHT))
2188 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
2189 if (ent->effects & EF_ADDITIVE)
2190 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_TRANSPARENT;
2191 else if (t->currentalpha < 1)
2192 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_TRANSPARENT;
2193 if (ent->effects & EF_NODEPTHTEST)
2194 t->currentmaterialflags |= MATERIALFLAG_NODEPTHTEST;
2195 if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
2196 t->currenttexmatrix = r_waterscrollmatrix;
2198 t->currenttexmatrix = identitymatrix;
2200 t->colormapping = VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f);
2201 t->basetexture = (!t->colormapping && t->skin.merged) ? t->skin.merged : t->skin.base;
2202 t->glosstexture = r_texture_white;
2203 t->specularpower = 8;
2204 t->specularscale = 0;
2205 if (r_shadow_gloss.integer > 0)
2209 if (r_shadow_glossintensity.value > 0)
2211 t->glosstexture = t->skin.gloss;
2212 t->specularscale = r_shadow_glossintensity.value;
2215 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
2216 t->specularscale = r_shadow_gloss2intensity.value;
2219 t->currentnumlayers = 0;
2220 if (!(t->currentmaterialflags & MATERIALFLAG_NODRAW))
2222 if (gl_lightmaps.integer)
2223 R_Texture_AddLayer(t, true, GL_ONE, GL_ZERO, TEXTURELAYERTYPE_LITTEXTURE, r_texture_white, &identitymatrix, 1, 1, 1, 1);
2224 else if (!(t->currentmaterialflags & MATERIALFLAG_SKY))
2226 int blendfunc1, blendfunc2, depthmask;
2227 if (t->currentmaterialflags & MATERIALFLAG_ADD)
2229 blendfunc1 = GL_SRC_ALPHA;
2230 blendfunc2 = GL_ONE;
2232 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
2234 blendfunc1 = GL_SRC_ALPHA;
2235 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
2237 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
2239 blendfunc1 = t->customblendfunc[0];
2240 blendfunc2 = t->customblendfunc[1];
2244 blendfunc1 = GL_ONE;
2245 blendfunc2 = GL_ZERO;
2247 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
2248 if (t->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL))
2250 rtexture_t *currentbasetexture;
2252 if (r_refdef.fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED))
2253 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
2254 currentbasetexture = (VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) < (1.0f / 1048576.0f) && t->skin.merged) ? t->skin.merged : t->skin.base;
2255 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2257 // fullbright is not affected by r_refdef.lightmapintensity
2258 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
2259 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->skin.pants)
2260 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);
2261 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->skin.shirt)
2262 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);
2268 // q3bsp has no lightmap updates, so the lightstylevalue that
2269 // would normally be baked into the lightmap must be
2270 // applied to the color
2271 if (ent->model->type == mod_brushq3)
2272 colorscale *= r_refdef.lightstylevalue[0] * (1.0f / 256.0f);
2273 colorscale *= r_refdef.lightmapintensity;
2274 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);
2275 if (r_ambient.value >= (1.0f/64.0f))
2276 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);
2277 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->skin.pants)
2279 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);
2280 if (r_ambient.value >= (1.0f/64.0f))
2281 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);
2283 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->skin.shirt)
2285 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);
2286 if (r_ambient.value >= (1.0f/64.0f))
2287 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);
2290 if (t->skin.glow != NULL)
2291 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.glow, &t->currenttexmatrix, 1, 1, 1, t->currentalpha);
2292 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
2294 // if this is opaque use alpha blend which will darken the earlier
2297 // if this is an alpha blended material, all the earlier passes
2298 // were darkened by fog already, so we only need to add the fog
2299 // color ontop through the fog mask texture
2301 // if this is an additive blended material, all the earlier passes
2302 // were darkened by fog already, and we should not add fog color
2303 // (because the background was not darkened, there is no fog color
2304 // that was lost behind it).
2305 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);
2312 void R_UpdateAllTextureInfo(entity_render_t *ent)
2316 for (i = 0;i < ent->model->num_textures;i++)
2317 R_UpdateTextureInfo(ent, ent->model->data_textures + i);
2320 int rsurface_array_size = 0;
2321 float *rsurface_array_modelvertex3f = NULL;
2322 float *rsurface_array_modelsvector3f = NULL;
2323 float *rsurface_array_modeltvector3f = NULL;
2324 float *rsurface_array_modelnormal3f = NULL;
2325 float *rsurface_array_deformedvertex3f = NULL;
2326 float *rsurface_array_deformedsvector3f = NULL;
2327 float *rsurface_array_deformedtvector3f = NULL;
2328 float *rsurface_array_deformednormal3f = NULL;
2329 float *rsurface_array_color4f = NULL;
2330 float *rsurface_array_texcoord3f = NULL;
2332 void R_Mesh_ResizeArrays(int newvertices)
2335 if (rsurface_array_size >= newvertices)
2337 if (rsurface_array_modelvertex3f)
2338 Mem_Free(rsurface_array_modelvertex3f);
2339 rsurface_array_size = (newvertices + 1023) & ~1023;
2340 base = (float *)Mem_Alloc(r_main_mempool, rsurface_array_size * sizeof(float[31]));
2341 rsurface_array_modelvertex3f = base + rsurface_array_size * 0;
2342 rsurface_array_modelsvector3f = base + rsurface_array_size * 3;
2343 rsurface_array_modeltvector3f = base + rsurface_array_size * 6;
2344 rsurface_array_modelnormal3f = base + rsurface_array_size * 9;
2345 rsurface_array_deformedvertex3f = base + rsurface_array_size * 12;
2346 rsurface_array_deformedsvector3f = base + rsurface_array_size * 15;
2347 rsurface_array_deformedtvector3f = base + rsurface_array_size * 18;
2348 rsurface_array_deformednormal3f = base + rsurface_array_size * 21;
2349 rsurface_array_texcoord3f = base + rsurface_array_size * 24;
2350 rsurface_array_color4f = base + rsurface_array_size * 27;
2353 float *rsurface_modelvertex3f;
2354 float *rsurface_modelsvector3f;
2355 float *rsurface_modeltvector3f;
2356 float *rsurface_modelnormal3f;
2357 float *rsurface_vertex3f;
2358 float *rsurface_svector3f;
2359 float *rsurface_tvector3f;
2360 float *rsurface_normal3f;
2361 float *rsurface_lightmapcolor4f;
2362 vec3_t rsurface_modelorg;
2363 qboolean rsurface_generatedvertex;
2364 const entity_render_t *rsurface_entity;
2365 const model_t *rsurface_model;
2366 texture_t *rsurface_texture;
2367 rtexture_t *rsurface_lightmaptexture;
2368 rsurfmode_t rsurface_mode;
2369 texture_t *rsurface_glsl_texture;
2370 qboolean rsurface_glsl_uselightmap;
2372 void RSurf_ActiveEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
2374 Matrix4x4_Transform(&ent->inversematrix, r_view.origin, rsurface_modelorg);
2375 rsurface_entity = ent;
2376 rsurface_model = ent->model;
2377 if (rsurface_array_size < rsurface_model->surfmesh.num_vertices)
2378 R_Mesh_ResizeArrays(rsurface_model->surfmesh.num_vertices);
2379 R_Mesh_Matrix(&ent->matrix);
2380 Matrix4x4_Transform(&ent->inversematrix, r_view.origin, rsurface_modelorg);
2381 if ((rsurface_entity->frameblend[0].lerp != 1 || rsurface_entity->frameblend[0].frame != 0) && (rsurface_model->surfmesh.data_morphvertex3f || rsurface_model->surfmesh.data_vertexweightindex4i))
2385 rsurface_modelvertex3f = rsurface_array_modelvertex3f;
2386 rsurface_modelsvector3f = rsurface_array_modelsvector3f;
2387 rsurface_modeltvector3f = rsurface_array_modeltvector3f;
2388 rsurface_modelnormal3f = rsurface_array_modelnormal3f;
2389 Mod_Alias_GetMesh_Vertices(rsurface_model, rsurface_entity->frameblend, rsurface_array_modelvertex3f, rsurface_array_modelnormal3f, rsurface_array_modelsvector3f, rsurface_array_modeltvector3f);
2391 else if (wantnormals)
2393 rsurface_modelvertex3f = rsurface_array_modelvertex3f;
2394 rsurface_modelsvector3f = NULL;
2395 rsurface_modeltvector3f = NULL;
2396 rsurface_modelnormal3f = rsurface_array_modelnormal3f;
2397 Mod_Alias_GetMesh_Vertices(rsurface_model, rsurface_entity->frameblend, rsurface_array_modelvertex3f, rsurface_array_modelnormal3f, NULL, NULL);
2401 rsurface_modelvertex3f = rsurface_array_modelvertex3f;
2402 rsurface_modelsvector3f = NULL;
2403 rsurface_modeltvector3f = NULL;
2404 rsurface_modelnormal3f = NULL;
2405 Mod_Alias_GetMesh_Vertices(rsurface_model, rsurface_entity->frameblend, rsurface_array_modelvertex3f, NULL, NULL, NULL);
2407 rsurface_generatedvertex = true;
2411 rsurface_modelvertex3f = rsurface_model->surfmesh.data_vertex3f;
2412 rsurface_modelsvector3f = rsurface_model->surfmesh.data_svector3f;
2413 rsurface_modeltvector3f = rsurface_model->surfmesh.data_tvector3f;
2414 rsurface_modelnormal3f = rsurface_model->surfmesh.data_normal3f;
2415 rsurface_generatedvertex = false;
2417 rsurface_vertex3f = rsurface_modelvertex3f;
2418 rsurface_svector3f = rsurface_modelsvector3f;
2419 rsurface_tvector3f = rsurface_modeltvector3f;
2420 rsurface_normal3f = rsurface_modelnormal3f;
2421 rsurface_mode = RSURFMODE_NONE;
2422 rsurface_lightmaptexture = NULL;
2423 rsurface_texture = NULL;
2424 rsurface_glsl_texture = NULL;
2425 rsurface_glsl_uselightmap = false;
2428 void RSurf_CleanUp(void)
2431 if (rsurface_mode == RSURFMODE_GLSL)
2433 qglUseProgramObjectARB(0);CHECKGLERROR
2435 GL_AlphaTest(false);
2436 rsurface_mode = RSURFMODE_NONE;
2437 rsurface_lightmaptexture = NULL;
2438 rsurface_texture = NULL;
2439 rsurface_glsl_texture = NULL;
2440 rsurface_glsl_uselightmap = false;
2443 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, msurface_t **texturesurfacelist)
2445 if (rsurface_generatedvertex)
2447 if (rsurface_texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
2448 generatetangents = true;
2449 if (generatetangents)
2450 generatenormals = true;
2451 if (generatenormals && !rsurface_modelnormal3f)
2453 rsurface_normal3f = rsurface_modelnormal3f = rsurface_array_modelnormal3f;
2454 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);
2456 if (generatetangents && !rsurface_modelsvector3f)
2458 rsurface_svector3f = rsurface_modelsvector3f = rsurface_array_modelsvector3f;
2459 rsurface_tvector3f = rsurface_modeltvector3f = rsurface_array_modeltvector3f;
2460 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);
2463 if (rsurface_texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
2465 int texturesurfaceindex;
2466 float center[3], forward[3], right[3], up[3], v[4][3];
2467 matrix4x4_t matrix1, imatrix1;
2468 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_view.forward, forward);
2469 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_view.right, right);
2470 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_view.up, up);
2471 // make deformed versions of only the vertices used by the specified surfaces
2472 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2475 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2476 // a single autosprite surface can contain multiple sprites...
2477 for (j = 0;j < surface->num_vertices - 3;j += 4)
2479 VectorClear(center);
2480 for (i = 0;i < 4;i++)
2481 VectorAdd(center, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
2482 VectorScale(center, 0.25f, center);
2483 if (rsurface_texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE2)
2485 forward[0] = rsurface_modelorg[0] - center[0];
2486 forward[1] = rsurface_modelorg[1] - center[1];
2488 VectorNormalize(forward);
2489 right[0] = forward[1];
2490 right[1] = -forward[0];
2492 VectorSet(up, 0, 0, 1);
2494 // FIXME: calculate vectors from triangle edges instead of using texture vectors as an easy way out?
2495 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);
2496 Matrix4x4_Invert_Simple(&imatrix1, &matrix1);
2497 for (i = 0;i < 4;i++)
2498 Matrix4x4_Transform(&imatrix1, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, v[i]);
2499 for (i = 0;i < 4;i++)
2500 VectorMAMAMAM(1, center, v[i][0], forward, v[i][1], right, v[i][2], up, rsurface_array_modelvertex3f + (surface->num_firstvertex+i+j) * 3);
2502 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);
2503 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);
2505 rsurface_vertex3f = rsurface_array_deformedvertex3f;
2506 rsurface_svector3f = rsurface_array_deformedsvector3f;
2507 rsurface_tvector3f = rsurface_array_deformedtvector3f;
2508 rsurface_normal3f = rsurface_array_deformednormal3f;
2510 R_Mesh_VertexPointer(rsurface_vertex3f);
2513 void RSurf_DrawBatch_Simple(int texturenumsurfaces, msurface_t **texturesurfacelist)
2515 int texturesurfaceindex;
2516 const msurface_t *surface = texturesurfacelist[0];
2517 int firstvertex = surface->num_firstvertex;
2518 int endvertex = surface->num_firstvertex + surface->num_vertices;
2519 if (texturenumsurfaces == 1)
2521 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2522 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
2524 else if (r_batchmode.integer == 2)
2526 #define MAXBATCHTRIANGLES 4096
2527 int batchtriangles = 0;
2528 int batchelements[MAXBATCHTRIANGLES*3];
2529 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2531 surface = texturesurfacelist[texturesurfaceindex];
2532 if (surface->num_triangles >= 256 || (batchtriangles == 0 && texturesurfaceindex + 1 >= texturenumsurfaces))
2534 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
2537 if (batchtriangles + surface->num_triangles > MAXBATCHTRIANGLES)
2539 R_Mesh_Draw(firstvertex, endvertex - firstvertex, batchtriangles, batchelements);
2541 firstvertex = surface->num_firstvertex;
2542 endvertex = surface->num_firstvertex + surface->num_vertices;
2546 firstvertex = min(firstvertex, surface->num_firstvertex);
2547 endvertex = max(endvertex, surface->num_firstvertex + surface->num_vertices);
2549 memcpy(batchelements + batchtriangles * 3, rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
2550 batchtriangles += surface->num_triangles;
2553 R_Mesh_Draw(firstvertex, endvertex - firstvertex, batchtriangles, batchelements);
2555 else if (r_batchmode.integer == 1)
2557 int firsttriangle = 0;
2558 int endtriangle = -1;
2559 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2561 surface = texturesurfacelist[texturesurfaceindex];
2562 if (surface->num_firsttriangle != endtriangle)
2564 if (endtriangle > firsttriangle)
2566 GL_LockArrays(firstvertex, endvertex - firstvertex);
2567 R_Mesh_Draw(firstvertex, endvertex - firstvertex, endtriangle - firsttriangle, (rsurface_model->surfmesh.data_element3i + 3 * firsttriangle));
2569 firstvertex = surface->num_firstvertex;
2570 endvertex = surface->num_firstvertex + surface->num_vertices;
2571 firsttriangle = surface->num_firsttriangle;
2575 firstvertex = min(firstvertex, surface->num_firstvertex);
2576 endvertex = max(endvertex, surface->num_firstvertex + surface->num_vertices);
2578 endtriangle = surface->num_firsttriangle + surface->num_triangles;
2580 if (endtriangle > firsttriangle)
2582 GL_LockArrays(firstvertex, endvertex - firstvertex);
2583 R_Mesh_Draw(firstvertex, endvertex - firstvertex, endtriangle - firsttriangle, (rsurface_model->surfmesh.data_element3i + 3 * firsttriangle));
2588 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2590 surface = texturesurfacelist[texturesurfaceindex];
2591 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2592 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
2597 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
2599 int texturesurfaceindex;
2600 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2602 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2603 int k = (int)(((size_t)surface) / sizeof(msurface_t));
2604 GL_Color((k & 15) * (1.0f / 16.0f), ((k >> 4) & 15) * (1.0f / 16.0f), ((k >> 8) & 15) * (1.0f / 16.0f), 0.2f);
2605 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2606 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
2610 static void RSurf_DrawBatch_Lightmap(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, int lightmode, qboolean applycolor, qboolean applyfog)
2612 int texturesurfaceindex;
2620 vec3_t ambientcolor;
2621 vec3_t diffusecolor;
2623 VectorCopy(rsurface_entity->modellight_lightdir, lightdir);
2624 ambientcolor[0] = rsurface_entity->modellight_ambient[0] * r * 0.5f;
2625 ambientcolor[1] = rsurface_entity->modellight_ambient[1] * g * 0.5f;
2626 ambientcolor[2] = rsurface_entity->modellight_ambient[2] * b * 0.5f;
2627 diffusecolor[0] = rsurface_entity->modellight_diffuse[0] * r * 0.5f;
2628 diffusecolor[1] = rsurface_entity->modellight_diffuse[1] * g * 0.5f;
2629 diffusecolor[2] = rsurface_entity->modellight_diffuse[2] * b * 0.5f;
2630 if (VectorLength2(diffusecolor) > 0)
2632 // generate color arrays for the surfaces in this list
2633 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2635 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2636 int numverts = surface->num_vertices;
2637 v = rsurface_vertex3f + 3 * surface->num_firstvertex;
2638 c2 = rsurface_normal3f + 3 * surface->num_firstvertex;
2639 c = rsurface_array_color4f + 4 * surface->num_firstvertex;
2640 // q3-style directional shading
2641 for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
2643 if ((f = DotProduct(c2, lightdir)) > 0)
2644 VectorMA(ambientcolor, f, diffusecolor, c);
2646 VectorCopy(ambientcolor, c);
2655 rsurface_lightmapcolor4f = rsurface_array_color4f;
2659 r = ambientcolor[0];
2660 g = ambientcolor[1];
2661 b = ambientcolor[2];
2662 rsurface_lightmapcolor4f = NULL;
2665 else if (lightmode >= 1 || !rsurface_lightmaptexture)
2667 if (texturesurfacelist[0]->lightmapinfo && texturesurfacelist[0]->lightmapinfo->stainsamples)
2669 // generate color arrays for the surfaces in this list
2670 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2672 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2673 for (i = 0, c = rsurface_array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
2675 if (surface->lightmapinfo->samples)
2677 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface_model->surfmesh.data_lightmapoffsets + surface->num_firstvertex)[i];
2678 float scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
2679 VectorScale(lm, scale, c);
2680 if (surface->lightmapinfo->styles[1] != 255)
2682 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
2684 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
2685 VectorMA(c, scale, lm, c);
2686 if (surface->lightmapinfo->styles[2] != 255)
2689 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
2690 VectorMA(c, scale, lm, c);
2691 if (surface->lightmapinfo->styles[3] != 255)
2694 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
2695 VectorMA(c, scale, lm, c);
2705 rsurface_lightmapcolor4f = rsurface_array_color4f;
2708 rsurface_lightmapcolor4f = rsurface_model->surfmesh.data_lightmapcolor4f;
2713 rsurface_lightmapcolor4f = NULL;
2717 if (rsurface_lightmapcolor4f)
2719 // generate color arrays for the surfaces in this list
2720 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2722 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2723 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)
2725 f = 1 - VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
2735 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2737 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2738 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)
2740 f = 1 - VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
2748 rsurface_lightmapcolor4f = rsurface_array_color4f;
2750 if (applycolor && rsurface_lightmapcolor4f)
2752 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2754 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2755 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)
2763 rsurface_lightmapcolor4f = rsurface_array_color4f;
2765 R_Mesh_ColorPointer(rsurface_lightmapcolor4f);
2766 GL_Color(r, g, b, a);
2767 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
2770 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
2772 if (rsurface_mode != RSURFMODE_SHOWSURFACES)
2774 rsurface_mode = RSURFMODE_SHOWSURFACES;
2776 GL_BlendFunc(GL_ONE, GL_ZERO);
2777 R_Mesh_ColorPointer(NULL);
2778 R_Mesh_ResetTextureState();
2780 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
2781 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
2784 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, msurface_t **texturesurfacelist)
2786 // transparent sky would be ridiculous
2787 if ((rsurface_texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
2789 if (rsurface_mode != RSURFMODE_SKY)
2791 if (rsurface_mode == RSURFMODE_GLSL)
2793 qglUseProgramObjectARB(0);CHECKGLERROR
2795 rsurface_mode = RSURFMODE_SKY;
2799 skyrendernow = false;
2801 // restore entity matrix
2802 R_Mesh_Matrix(&rsurface_entity->matrix);
2805 // LordHavoc: HalfLife maps have freaky skypolys so don't use
2806 // skymasking on them, and Quake3 never did sky masking (unlike
2807 // software Quake and software Quake2), so disable the sky masking
2808 // in Quake3 maps as it causes problems with q3map2 sky tricks,
2809 // and skymasking also looks very bad when noclipping outside the
2810 // level, so don't use it then either.
2811 if (rsurface_model->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_viewcache.world_novis)
2813 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
2814 R_Mesh_ColorPointer(NULL);
2815 R_Mesh_ResetTextureState();
2816 if (skyrendermasked)
2818 // depth-only (masking)
2819 GL_ColorMask(0,0,0,0);
2820 // just to make sure that braindead drivers don't draw
2821 // anything despite that colormask...
2822 GL_BlendFunc(GL_ZERO, GL_ONE);
2827 GL_BlendFunc(GL_ONE, GL_ZERO);
2829 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
2830 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
2831 if (skyrendermasked)
2832 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
2836 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, msurface_t **texturesurfacelist)
2839 // FIXME: identify models using a better check than rsurface_model->brush.shadowmesh
2840 lightmode = ((rsurface_entity->effects & EF_FULLBRIGHT) || rsurface_model->brush.shadowmesh) ? 0 : 2;
2841 if (rsurface_mode != RSURFMODE_GLSL)
2843 rsurface_mode = RSURFMODE_GLSL;
2844 rsurface_glsl_texture = NULL;
2845 rsurface_glsl_uselightmap = false;
2846 R_Mesh_ResetTextureState();
2848 if (rsurface_glsl_texture != rsurface_texture || rsurface_glsl_uselightmap != (rsurface_lightmaptexture != NULL))
2850 rsurface_glsl_texture = rsurface_texture;
2851 rsurface_glsl_uselightmap = rsurface_lightmaptexture != NULL;
2852 GL_BlendFunc(rsurface_texture->currentlayers[0].blendfunc1, rsurface_texture->currentlayers[0].blendfunc2);
2853 GL_DepthMask(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_BLENDED));
2854 GL_Color(rsurface_entity->colormod[0], rsurface_entity->colormod[1], rsurface_entity->colormod[2], rsurface_texture->currentalpha);
2855 R_SetupSurfaceShader(vec3_origin, lightmode == 2);
2856 //permutation_deluxemapping = permutation_lightmapping = R_SetupSurfaceShader(vec3_origin, lightmode == 2, false);
2857 //if (r_glsl_deluxemapping.integer)
2858 // permutation_deluxemapping = R_SetupSurfaceShader(vec3_origin, lightmode == 2, true);
2859 R_Mesh_TexCoordPointer(0, 2, rsurface_model->surfmesh.data_texcoordtexture2f);
2860 R_Mesh_TexCoordPointer(4, 2, rsurface_model->surfmesh.data_texcoordlightmap2f);
2861 GL_AlphaTest((rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2863 if (!r_glsl_permutation)
2865 RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
2866 R_Mesh_TexCoordPointer(1, 3, rsurface_svector3f);
2867 R_Mesh_TexCoordPointer(2, 3, rsurface_tvector3f);
2868 R_Mesh_TexCoordPointer(3, 3, rsurface_normal3f);
2869 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2871 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
2872 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
2873 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
2874 R_Mesh_ColorPointer(NULL);
2876 else if (rsurface_lightmaptexture)
2878 R_Mesh_TexBind(7, R_GetTexture(rsurface_lightmaptexture));
2879 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
2880 R_Mesh_TexBind(8, R_GetTexture(texturesurfacelist[0]->deluxemaptexture));
2881 R_Mesh_ColorPointer(NULL);
2885 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
2886 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
2887 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
2888 R_Mesh_ColorPointer(rsurface_model->surfmesh.data_lightmapcolor4f);
2890 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
2893 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, msurface_t **texturesurfacelist)
2895 // OpenGL 1.3 path - anything not completely ancient
2896 int texturesurfaceindex;
2898 qboolean applycolor;
2902 const texturelayer_t *layer;
2904 // FIXME: identify models using a better check than rsurface_model->brush.shadowmesh
2905 lightmode = ((rsurface_entity->effects & EF_FULLBRIGHT) || rsurface_model->brush.shadowmesh) ? 0 : 2;
2906 if (rsurface_mode != RSURFMODE_MULTIPASS)
2907 rsurface_mode = RSURFMODE_MULTIPASS;
2908 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
2909 for (layerindex = 0, layer = rsurface_texture->currentlayers;layerindex < rsurface_texture->currentnumlayers;layerindex++, layer++)
2912 int layertexrgbscale;
2913 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2915 if (layerindex == 0)
2919 GL_AlphaTest(false);
2920 qglDepthFunc(GL_EQUAL);CHECKGLERROR
2923 GL_DepthMask(layer->depthmask);
2924 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
2925 if ((layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2) && (gl_combine.integer || layer->depthmask))
2927 layertexrgbscale = 4;
2928 VectorScale(layer->color, 0.25f, layercolor);
2930 else if ((layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1) && (gl_combine.integer || layer->depthmask))
2932 layertexrgbscale = 2;
2933 VectorScale(layer->color, 0.5f, layercolor);
2937 layertexrgbscale = 1;
2938 VectorScale(layer->color, 1.0f, layercolor);
2940 layercolor[3] = layer->color[3];
2941 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
2942 R_Mesh_ColorPointer(NULL);
2943 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
2944 switch (layer->type)
2946 case TEXTURELAYERTYPE_LITTEXTURE:
2947 memset(&m, 0, sizeof(m));
2948 if (lightmode >= 1 || !rsurface_lightmaptexture)
2949 m.tex[0] = R_GetTexture(r_texture_white);
2951 m.tex[0] = R_GetTexture(rsurface_lightmaptexture);
2952 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordlightmap2f;
2953 m.tex[1] = R_GetTexture(layer->texture);
2954 m.texmatrix[1] = layer->texmatrix;
2955 m.texrgbscale[1] = layertexrgbscale;
2956 m.pointer_texcoord[1] = rsurface_model->surfmesh.data_texcoordtexture2f;
2957 R_Mesh_TextureState(&m);
2958 RSurf_DrawBatch_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], lightmode, applycolor, applyfog);
2960 case TEXTURELAYERTYPE_TEXTURE:
2961 memset(&m, 0, sizeof(m));
2962 m.tex[0] = R_GetTexture(layer->texture);
2963 m.texmatrix[0] = layer->texmatrix;
2964 m.texrgbscale[0] = layertexrgbscale;
2965 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
2966 R_Mesh_TextureState(&m);
2967 RSurf_DrawBatch_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, applyfog);
2969 case TEXTURELAYERTYPE_FOG:
2970 memset(&m, 0, sizeof(m));
2971 m.texrgbscale[0] = layertexrgbscale;
2974 m.tex[0] = R_GetTexture(layer->texture);
2975 m.texmatrix[0] = layer->texmatrix;
2976 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
2978 R_Mesh_TextureState(&m);
2979 // generate a color array for the fog pass
2980 R_Mesh_ColorPointer(rsurface_array_color4f);
2981 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2985 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2986 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)
2988 f = VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
2989 c[0] = layercolor[0];
2990 c[1] = layercolor[1];
2991 c[2] = layercolor[2];
2992 c[3] = f * layercolor[3];
2995 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
2998 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
3000 GL_LockArrays(0, 0);
3003 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
3005 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3006 GL_AlphaTest(false);
3010 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, msurface_t **texturesurfacelist)
3012 // OpenGL 1.1 - crusty old voodoo path
3013 int texturesurfaceindex;
3018 const texturelayer_t *layer;
3020 // FIXME: identify models using a better check than rsurface_model->brush.shadowmesh
3021 lightmode = ((rsurface_entity->effects & EF_FULLBRIGHT) || rsurface_model->brush.shadowmesh) ? 0 : 2;
3022 if (rsurface_mode != RSURFMODE_MULTIPASS)
3023 rsurface_mode = RSURFMODE_MULTIPASS;
3024 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
3025 for (layerindex = 0, layer = rsurface_texture->currentlayers;layerindex < rsurface_texture->currentnumlayers;layerindex++, layer++)
3027 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
3029 if (layerindex == 0)
3033 GL_AlphaTest(false);
3034 qglDepthFunc(GL_EQUAL);CHECKGLERROR
3037 GL_DepthMask(layer->depthmask);
3038 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
3039 R_Mesh_ColorPointer(NULL);
3040 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
3041 switch (layer->type)
3043 case TEXTURELAYERTYPE_LITTEXTURE:
3044 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
3046 // two-pass lit texture with 2x rgbscale
3047 // first the lightmap pass
3048 memset(&m, 0, sizeof(m));
3049 if (lightmode >= 1 || !rsurface_lightmaptexture)
3050 m.tex[0] = R_GetTexture(r_texture_white);
3052 m.tex[0] = R_GetTexture(rsurface_lightmaptexture);
3053 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordlightmap2f;
3054 R_Mesh_TextureState(&m);
3055 RSurf_DrawBatch_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, lightmode, false, false);
3056 GL_LockArrays(0, 0);
3057 // then apply the texture to it
3058 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
3059 memset(&m, 0, sizeof(m));
3060 m.tex[0] = R_GetTexture(layer->texture);
3061 m.texmatrix[0] = layer->texmatrix;
3062 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3063 R_Mesh_TextureState(&m);
3064 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);
3068 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
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], 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);
3077 case TEXTURELAYERTYPE_TEXTURE:
3078 // singletexture unlit texture with 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], 0, layer->color[0] != 1 || layer->color[1] != 1 || layer->color[2] != 1 || layer->color[3] != 1, applyfog);
3086 case TEXTURELAYERTYPE_FOG:
3087 // singletexture fogging
3088 R_Mesh_ColorPointer(rsurface_array_color4f);
3091 memset(&m, 0, sizeof(m));
3092 m.tex[0] = R_GetTexture(layer->texture);
3093 m.texmatrix[0] = layer->texmatrix;
3094 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3095 R_Mesh_TextureState(&m);
3098 R_Mesh_ResetTextureState();
3099 // generate a color array for the fog pass
3100 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3104 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3105 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)
3107 f = VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
3108 c[0] = layer->color[0];
3109 c[1] = layer->color[1];
3110 c[2] = layer->color[2];
3111 c[3] = f * layer->color[3];
3114 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3117 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
3119 GL_LockArrays(0, 0);
3122 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
3124 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3125 GL_AlphaTest(false);
3129 static void R_DrawTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist)
3131 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_NODRAW)
3133 r_shadow_rtlight = NULL;
3134 r_refdef.stats.entities_surfaces += texturenumsurfaces;
3136 GL_DepthTest(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
3137 if ((rsurface_texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (rsurface_entity->flags & RENDER_NOCULLFACE))
3139 qglDisable(GL_CULL_FACE);CHECKGLERROR
3141 if (r_showsurfaces.integer)
3142 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
3143 else if (rsurface_texture->currentmaterialflags & MATERIALFLAG_SKY)
3144 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
3145 else if (rsurface_texture->currentnumlayers)
3147 if (r_glsl.integer && gl_support_fragment_shader)
3148 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist);
3149 else if (gl_combine.integer && r_textureunits.integer >= 2)
3150 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist);
3152 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist);
3155 GL_LockArrays(0, 0);
3156 if ((rsurface_texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (rsurface_entity->flags & RENDER_NOCULLFACE))
3158 qglEnable(GL_CULL_FACE);CHECKGLERROR
3162 #define BATCHSIZE 256
3163 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
3165 int surfacelistindex;
3168 msurface_t *texturesurfacelist[BATCHSIZE];
3169 // if the model is static it doesn't matter what value we give for
3170 // wantnormals and wanttangents, so this logic uses only rules applicable
3171 // to a model, knowing that they are meaningless otherwise
3172 if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
3173 RSurf_ActiveEntity(ent, false, false);
3175 RSurf_ActiveEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
3178 for (surfacelistindex = 0;surfacelistindex < numsurfaces;surfacelistindex++)
3180 msurface_t *surface = ent->model->data_surfaces + surfacelist[surfacelistindex];
3182 if (t != surface->texture || rsurface_lightmaptexture != surface->lightmaptexture)
3185 R_DrawTextureSurfaceList(batchcount, texturesurfacelist);
3187 t = surface->texture;
3188 rsurface_lightmaptexture = surface->lightmaptexture;
3189 R_UpdateTextureInfo(ent, t);
3190 rsurface_texture = t->currentframe;
3192 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_SKY)
3193 continue; // transparent sky is too difficult
3195 texturesurfacelist[batchcount++] = surface;
3198 R_DrawTextureSurfaceList(batchcount, texturesurfacelist);
3202 void R_QueueTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist)
3204 int texturesurfaceindex;
3205 vec3_t tempcenter, center;
3206 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_BLENDED)
3208 // drawing sky transparently would be too difficult
3209 if (!(rsurface_texture->currentmaterialflags & MATERIALFLAG_SKY))
3211 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3213 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3214 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
3215 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
3216 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
3217 Matrix4x4_Transform(&rsurface_entity->matrix, tempcenter, center);
3218 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);
3223 R_DrawTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
3226 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
3227 void R_DrawSurfaces(entity_render_t *ent, qboolean skysurfaces)
3229 int i, j, f, flagsmask;
3230 int counttriangles = 0;
3232 model_t *model = ent->model;
3233 const int maxsurfacelist = 1024;
3234 int numsurfacelist = 0;
3235 msurface_t *surfacelist[1024];
3239 // if the model is static it doesn't matter what value we give for
3240 // wantnormals and wanttangents, so this logic uses only rules applicable
3241 // to a model, knowing that they are meaningless otherwise
3242 if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
3243 RSurf_ActiveEntity(ent, false, false);
3245 RSurf_ActiveEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
3247 // update light styles
3248 if (!skysurfaces && model->brushq1.light_styleupdatechains)
3250 msurface_t *surface, **surfacechain;
3251 for (i = 0;i < model->brushq1.light_styles;i++)
3253 if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
3255 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
3256 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
3257 for (;(surface = *surfacechain);surfacechain++)
3258 surface->cached_dlight = true;
3263 R_UpdateAllTextureInfo(ent);
3264 flagsmask = skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL);
3267 rsurface_lightmaptexture = NULL;
3268 rsurface_texture = NULL;
3270 if (ent == r_refdef.worldentity)
3272 msurface_t *surface;
3273 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
3275 if (!r_viewcache.world_surfacevisible[j])
3277 if (t != surface->texture || rsurface_lightmaptexture != surface->lightmaptexture)
3281 R_QueueTextureSurfaceList(numsurfacelist, surfacelist);
3284 t = surface->texture;
3285 rsurface_lightmaptexture = surface->lightmaptexture;
3286 rsurface_texture = t->currentframe;
3287 f = rsurface_texture->currentmaterialflags & flagsmask;
3289 if (f && surface->num_triangles)
3291 // if lightmap parameters changed, rebuild lightmap texture
3292 if (surface->cached_dlight)
3293 R_BuildLightMap(ent, surface);
3294 // add face to draw list
3295 surfacelist[numsurfacelist++] = surface;
3296 counttriangles += surface->num_triangles;
3297 if (numsurfacelist >= maxsurfacelist)
3299 R_QueueTextureSurfaceList(numsurfacelist, surfacelist);
3307 msurface_t *surface;
3308 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
3310 if (t != surface->texture || rsurface_lightmaptexture != surface->lightmaptexture)
3314 R_QueueTextureSurfaceList(numsurfacelist, surfacelist);
3317 t = surface->texture;
3318 rsurface_lightmaptexture = surface->lightmaptexture;
3319 rsurface_texture = t->currentframe;
3320 f = rsurface_texture->currentmaterialflags & flagsmask;
3322 if (f && surface->num_triangles)
3324 // if lightmap parameters changed, rebuild lightmap texture
3325 if (surface->cached_dlight)
3326 R_BuildLightMap(ent, surface);
3327 // add face to draw list
3328 surfacelist[numsurfacelist++] = surface;
3329 counttriangles += surface->num_triangles;
3330 if (numsurfacelist >= maxsurfacelist)
3332 R_QueueTextureSurfaceList(numsurfacelist, surfacelist);
3339 R_QueueTextureSurfaceList(numsurfacelist, surfacelist);
3340 r_refdef.stats.entities_triangles += counttriangles;
3343 if (r_showcollisionbrushes.integer && model->brush.num_brushes && !skysurfaces)
3346 const msurface_t *surface;
3349 R_Mesh_Matrix(&ent->matrix);
3350 R_Mesh_ColorPointer(NULL);
3351 R_Mesh_ResetTextureState();
3352 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
3353 GL_DepthMask(false);
3354 GL_DepthTest(!r_showdisabledepthtest.integer);
3355 qglPolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);CHECKGLERROR
3356 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
3357 if (brush->colbrushf && brush->colbrushf->numtriangles)
3358 R_DrawCollisionBrush(brush->colbrushf);
3359 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
3360 if (surface->num_collisiontriangles)
3361 R_DrawCollisionSurface(ent, surface);
3362 qglPolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR
3365 if (r_showtris.integer || r_shownormals.integer)
3368 msurface_t *surface;
3369 const int *elements;
3374 if (r_showdisabledepthtest.integer)
3376 qglDepthFunc(GL_ALWAYS);CHECKGLERROR
3378 GL_BlendFunc(GL_ONE, GL_ZERO);
3379 R_Mesh_ColorPointer(NULL);
3380 R_Mesh_ResetTextureState();
3381 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
3383 if (ent == r_refdef.worldentity && !r_viewcache.world_surfacevisible[j])
3385 rsurface_texture = surface->texture->currentframe;
3386 if ((rsurface_texture->currentmaterialflags & flagsmask) && surface->num_triangles)
3388 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
3389 if (r_showtris.integer)
3391 if (!rsurface_texture->currentlayers->depthmask)
3392 GL_Color(r_showtris.value, 0, 0, 1);
3393 else if (ent == r_refdef.worldentity)
3394 GL_Color(r_showtris.value, r_showtris.value, r_showtris.value, 1);
3396 GL_Color(0, r_showtris.value, 0, 1);
3397 elements = (ent->model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
3400 for (k = 0;k < surface->num_triangles;k++, elements += 3)
3402 qglArrayElement(elements[0]);qglArrayElement(elements[1]);
3403 qglArrayElement(elements[1]);qglArrayElement(elements[2]);
3404 qglArrayElement(elements[2]);qglArrayElement(elements[0]);
3409 if (r_shownormals.integer)
3411 GL_Color(r_shownormals.value, 0, 0, 1);
3413 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
3415 VectorCopy(rsurface_vertex3f + l * 3, v);
3416 qglVertex3f(v[0], v[1], v[2]);
3417 VectorMA(v, 8, rsurface_svector3f + l * 3, v);
3418 qglVertex3f(v[0], v[1], v[2]);
3422 GL_Color(0, 0, r_shownormals.value, 1);
3424 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
3426 VectorCopy(rsurface_vertex3f + l * 3, v);
3427 qglVertex3f(v[0], v[1], v[2]);
3428 VectorMA(v, 8, rsurface_tvector3f + l * 3, v);
3429 qglVertex3f(v[0], v[1], v[2]);
3433 GL_Color(0, r_shownormals.value, 0, 1);
3435 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
3437 VectorCopy(rsurface_vertex3f + l * 3, v);
3438 qglVertex3f(v[0], v[1], v[2]);
3439 VectorMA(v, 8, rsurface_normal3f + l * 3, v);
3440 qglVertex3f(v[0], v[1], v[2]);
3447 rsurface_texture = NULL;
3448 if (r_showdisabledepthtest.integer)
3450 qglDepthFunc(GL_LEQUAL);CHECKGLERROR