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;
2172 t = t->anim_frames[ent->frame != 0][(t->anim_total[ent->frame != 0] >= 2) ? ((int)(r_refdef.time * 5.0f) % t->anim_total[ent->frame != 0]) : 0];
2173 texture->currentframe = t;
2176 t->currentmaterialflags = t->basematerialflags;
2177 t->currentalpha = ent->alpha;
2178 if (t->basematerialflags & MATERIALFLAG_WATERALPHA)
2179 t->currentalpha *= r_wateralpha.value;
2180 if (!(ent->flags & RENDER_LIGHT))
2181 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
2182 if (ent->effects & EF_ADDITIVE)
2183 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_TRANSPARENT;
2184 else if (t->currentalpha < 1)
2185 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_TRANSPARENT;
2186 if (ent->effects & EF_NODEPTHTEST)
2187 t->currentmaterialflags |= MATERIALFLAG_NODEPTHTEST;
2188 if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
2189 t->currenttexmatrix = r_waterscrollmatrix;
2191 t->currenttexmatrix = identitymatrix;
2193 t->colormapping = VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f);
2194 t->basetexture = (!t->colormapping && t->skin.merged) ? t->skin.merged : t->skin.base;
2195 t->glosstexture = r_texture_white;
2196 t->specularpower = 8;
2197 t->specularscale = 0;
2198 if (r_shadow_gloss.integer > 0)
2202 if (r_shadow_glossintensity.value > 0)
2204 t->glosstexture = t->skin.gloss;
2205 t->specularscale = r_shadow_glossintensity.value;
2208 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
2209 t->specularscale = r_shadow_gloss2intensity.value;
2212 t->currentnumlayers = 0;
2213 if (!(t->currentmaterialflags & MATERIALFLAG_NODRAW))
2215 if (gl_lightmaps.integer)
2216 R_Texture_AddLayer(t, true, GL_ONE, GL_ZERO, TEXTURELAYERTYPE_LITTEXTURE, r_texture_white, &identitymatrix, 1, 1, 1, 1);
2217 else if (!(t->currentmaterialflags & MATERIALFLAG_SKY))
2219 int blendfunc1, blendfunc2, depthmask;
2220 if (t->currentmaterialflags & MATERIALFLAG_ADD)
2222 blendfunc1 = GL_SRC_ALPHA;
2223 blendfunc2 = GL_ONE;
2225 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
2227 blendfunc1 = GL_SRC_ALPHA;
2228 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
2230 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
2232 blendfunc1 = t->customblendfunc[0];
2233 blendfunc2 = t->customblendfunc[1];
2237 blendfunc1 = GL_ONE;
2238 blendfunc2 = GL_ZERO;
2240 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
2241 if (t->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL))
2243 rtexture_t *currentbasetexture;
2245 if (r_refdef.fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED))
2246 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
2247 currentbasetexture = (VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) < (1.0f / 1048576.0f) && t->skin.merged) ? t->skin.merged : t->skin.base;
2248 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2250 // fullbright is not affected by r_refdef.lightmapintensity
2251 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
2252 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->skin.pants)
2253 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);
2254 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->skin.shirt)
2255 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);
2261 // q3bsp has no lightmap updates, so the lightstylevalue that
2262 // would normally be baked into the lightmap must be
2263 // applied to the color
2264 if (ent->model->type == mod_brushq3)
2265 colorscale *= r_refdef.lightstylevalue[0] * (1.0f / 256.0f);
2266 colorscale *= r_refdef.lightmapintensity;
2267 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);
2268 if (r_ambient.value >= (1.0f/64.0f))
2269 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);
2270 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->skin.pants)
2272 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);
2273 if (r_ambient.value >= (1.0f/64.0f))
2274 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);
2276 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->skin.shirt)
2278 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);
2279 if (r_ambient.value >= (1.0f/64.0f))
2280 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);
2283 if (t->skin.glow != NULL)
2284 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.glow, &t->currenttexmatrix, 1, 1, 1, t->currentalpha);
2285 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
2287 // if this is opaque use alpha blend which will darken the earlier
2290 // if this is an alpha blended material, all the earlier passes
2291 // were darkened by fog already, so we only need to add the fog
2292 // color ontop through the fog mask texture
2294 // if this is an additive blended material, all the earlier passes
2295 // were darkened by fog already, and we should not add fog color
2296 // (because the background was not darkened, there is no fog color
2297 // that was lost behind it).
2298 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);
2305 void R_UpdateAllTextureInfo(entity_render_t *ent)
2309 for (i = 0;i < ent->model->num_textures;i++)
2310 R_UpdateTextureInfo(ent, ent->model->data_textures + i);
2313 int rsurface_array_size = 0;
2314 float *rsurface_array_modelvertex3f = NULL;
2315 float *rsurface_array_modelsvector3f = NULL;
2316 float *rsurface_array_modeltvector3f = NULL;
2317 float *rsurface_array_modelnormal3f = NULL;
2318 float *rsurface_array_deformedvertex3f = NULL;
2319 float *rsurface_array_deformedsvector3f = NULL;
2320 float *rsurface_array_deformedtvector3f = NULL;
2321 float *rsurface_array_deformednormal3f = NULL;
2322 float *rsurface_array_color4f = NULL;
2323 float *rsurface_array_texcoord3f = NULL;
2325 void R_Mesh_ResizeArrays(int newvertices)
2328 if (rsurface_array_size >= newvertices)
2330 if (rsurface_array_modelvertex3f)
2331 Mem_Free(rsurface_array_modelvertex3f);
2332 rsurface_array_size = (newvertices + 1023) & ~1023;
2333 base = (float *)Mem_Alloc(r_main_mempool, rsurface_array_size * sizeof(float[31]));
2334 rsurface_array_modelvertex3f = base + rsurface_array_size * 0;
2335 rsurface_array_modelsvector3f = base + rsurface_array_size * 3;
2336 rsurface_array_modeltvector3f = base + rsurface_array_size * 6;
2337 rsurface_array_modelnormal3f = base + rsurface_array_size * 9;
2338 rsurface_array_deformedvertex3f = base + rsurface_array_size * 12;
2339 rsurface_array_deformedsvector3f = base + rsurface_array_size * 15;
2340 rsurface_array_deformedtvector3f = base + rsurface_array_size * 18;
2341 rsurface_array_deformednormal3f = base + rsurface_array_size * 21;
2342 rsurface_array_texcoord3f = base + rsurface_array_size * 24;
2343 rsurface_array_color4f = base + rsurface_array_size * 27;
2346 float *rsurface_modelvertex3f;
2347 float *rsurface_modelsvector3f;
2348 float *rsurface_modeltvector3f;
2349 float *rsurface_modelnormal3f;
2350 float *rsurface_vertex3f;
2351 float *rsurface_svector3f;
2352 float *rsurface_tvector3f;
2353 float *rsurface_normal3f;
2354 float *rsurface_lightmapcolor4f;
2355 vec3_t rsurface_modelorg;
2356 qboolean rsurface_generatedvertex;
2357 const entity_render_t *rsurface_entity;
2358 const model_t *rsurface_model;
2359 texture_t *rsurface_texture;
2360 rtexture_t *rsurface_lightmaptexture;
2361 rsurfmode_t rsurface_mode;
2362 texture_t *rsurface_glsl_texture;
2363 qboolean rsurface_glsl_uselightmap;
2365 void RSurf_ActiveEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
2367 Matrix4x4_Transform(&ent->inversematrix, r_view.origin, rsurface_modelorg);
2368 rsurface_entity = ent;
2369 rsurface_model = ent->model;
2370 if (rsurface_array_size < rsurface_model->surfmesh.num_vertices)
2371 R_Mesh_ResizeArrays(rsurface_model->surfmesh.num_vertices);
2372 R_Mesh_Matrix(&ent->matrix);
2373 Matrix4x4_Transform(&ent->inversematrix, r_view.origin, rsurface_modelorg);
2374 if ((rsurface_entity->frameblend[0].lerp != 1 || rsurface_entity->frameblend[0].frame != 0) && (rsurface_model->surfmesh.data_morphvertex3f || rsurface_model->surfmesh.data_vertexweightindex4i))
2378 rsurface_modelvertex3f = rsurface_array_modelvertex3f;
2379 rsurface_modelsvector3f = rsurface_array_modelsvector3f;
2380 rsurface_modeltvector3f = rsurface_array_modeltvector3f;
2381 rsurface_modelnormal3f = rsurface_array_modelnormal3f;
2382 Mod_Alias_GetMesh_Vertices(rsurface_model, rsurface_entity->frameblend, rsurface_array_modelvertex3f, rsurface_array_modelnormal3f, rsurface_array_modelsvector3f, rsurface_array_modeltvector3f);
2384 else if (wantnormals)
2386 rsurface_modelvertex3f = rsurface_array_modelvertex3f;
2387 rsurface_modelsvector3f = NULL;
2388 rsurface_modeltvector3f = NULL;
2389 rsurface_modelnormal3f = rsurface_array_modelnormal3f;
2390 Mod_Alias_GetMesh_Vertices(rsurface_model, rsurface_entity->frameblend, rsurface_array_modelvertex3f, rsurface_array_modelnormal3f, NULL, NULL);
2394 rsurface_modelvertex3f = rsurface_array_modelvertex3f;
2395 rsurface_modelsvector3f = NULL;
2396 rsurface_modeltvector3f = NULL;
2397 rsurface_modelnormal3f = NULL;
2398 Mod_Alias_GetMesh_Vertices(rsurface_model, rsurface_entity->frameblend, rsurface_array_modelvertex3f, NULL, NULL, NULL);
2400 rsurface_generatedvertex = true;
2404 rsurface_modelvertex3f = rsurface_model->surfmesh.data_vertex3f;
2405 rsurface_modelsvector3f = rsurface_model->surfmesh.data_svector3f;
2406 rsurface_modeltvector3f = rsurface_model->surfmesh.data_tvector3f;
2407 rsurface_modelnormal3f = rsurface_model->surfmesh.data_normal3f;
2408 rsurface_generatedvertex = false;
2410 rsurface_vertex3f = rsurface_modelvertex3f;
2411 rsurface_svector3f = rsurface_modelsvector3f;
2412 rsurface_tvector3f = rsurface_modeltvector3f;
2413 rsurface_normal3f = rsurface_modelnormal3f;
2414 rsurface_mode = RSURFMODE_NONE;
2415 rsurface_lightmaptexture = NULL;
2416 rsurface_texture = NULL;
2417 rsurface_glsl_texture = NULL;
2418 rsurface_glsl_uselightmap = false;
2421 void RSurf_CleanUp(void)
2424 if (rsurface_mode == RSURFMODE_GLSL)
2426 qglUseProgramObjectARB(0);CHECKGLERROR
2428 GL_AlphaTest(false);
2429 rsurface_mode = RSURFMODE_NONE;
2430 rsurface_lightmaptexture = NULL;
2431 rsurface_texture = NULL;
2432 rsurface_glsl_texture = NULL;
2433 rsurface_glsl_uselightmap = false;
2436 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, msurface_t **texturesurfacelist)
2438 if (rsurface_generatedvertex)
2440 if (rsurface_texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
2441 generatetangents = true;
2442 if (generatetangents)
2443 generatenormals = true;
2444 if (generatenormals && !rsurface_modelnormal3f)
2446 rsurface_normal3f = rsurface_modelnormal3f = rsurface_array_modelnormal3f;
2447 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);
2449 if (generatetangents && !rsurface_modelsvector3f)
2451 rsurface_svector3f = rsurface_modelsvector3f = rsurface_array_modelsvector3f;
2452 rsurface_tvector3f = rsurface_modeltvector3f = rsurface_array_modeltvector3f;
2453 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);
2456 if (rsurface_texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
2458 int texturesurfaceindex;
2459 float center[3], forward[3], right[3], up[3], v[4][3];
2460 matrix4x4_t matrix1, imatrix1;
2461 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_view.forward, forward);
2462 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_view.right, right);
2463 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_view.up, up);
2464 // make deformed versions of only the vertices used by the specified surfaces
2465 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2468 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2469 // a single autosprite surface can contain multiple sprites...
2470 for (j = 0;j < surface->num_vertices - 3;j += 4)
2472 VectorClear(center);
2473 for (i = 0;i < 4;i++)
2474 VectorAdd(center, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
2475 VectorScale(center, 0.25f, center);
2476 if (rsurface_texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE2)
2478 forward[0] = rsurface_modelorg[0] - center[0];
2479 forward[1] = rsurface_modelorg[1] - center[1];
2481 VectorNormalize(forward);
2482 right[0] = forward[1];
2483 right[1] = -forward[0];
2485 VectorSet(up, 0, 0, 1);
2487 // FIXME: calculate vectors from triangle edges instead of using texture vectors as an easy way out?
2488 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);
2489 Matrix4x4_Invert_Simple(&imatrix1, &matrix1);
2490 for (i = 0;i < 4;i++)
2491 Matrix4x4_Transform(&imatrix1, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, v[i]);
2492 for (i = 0;i < 4;i++)
2493 VectorMAMAMAM(1, center, v[i][0], forward, v[i][1], right, v[i][2], up, rsurface_array_modelvertex3f + (surface->num_firstvertex+i+j) * 3);
2495 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);
2496 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);
2498 rsurface_vertex3f = rsurface_array_deformedvertex3f;
2499 rsurface_svector3f = rsurface_array_deformedsvector3f;
2500 rsurface_tvector3f = rsurface_array_deformedtvector3f;
2501 rsurface_normal3f = rsurface_array_deformednormal3f;
2503 R_Mesh_VertexPointer(rsurface_vertex3f);
2506 void RSurf_DrawBatch_Simple(int texturenumsurfaces, msurface_t **texturesurfacelist)
2508 int texturesurfaceindex;
2509 const msurface_t *surface = texturesurfacelist[0];
2510 int firstvertex = surface->num_firstvertex;
2511 int endvertex = surface->num_firstvertex + surface->num_vertices;
2512 if (texturenumsurfaces == 1)
2514 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2515 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
2517 else if (r_batchmode.integer == 2)
2519 #define MAXBATCHTRIANGLES 4096
2520 int batchtriangles = 0;
2521 int batchelements[MAXBATCHTRIANGLES*3];
2522 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2524 surface = texturesurfacelist[texturesurfaceindex];
2525 if (surface->num_triangles >= 256 || (batchtriangles == 0 && texturesurfaceindex + 1 >= texturenumsurfaces))
2527 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
2530 if (batchtriangles + surface->num_triangles > MAXBATCHTRIANGLES)
2532 R_Mesh_Draw(firstvertex, endvertex - firstvertex, batchtriangles, batchelements);
2534 firstvertex = surface->num_firstvertex;
2535 endvertex = surface->num_firstvertex + surface->num_vertices;
2539 firstvertex = min(firstvertex, surface->num_firstvertex);
2540 endvertex = max(endvertex, surface->num_firstvertex + surface->num_vertices);
2542 memcpy(batchelements + batchtriangles * 3, rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
2543 batchtriangles += surface->num_triangles;
2546 R_Mesh_Draw(firstvertex, endvertex - firstvertex, batchtriangles, batchelements);
2548 else if (r_batchmode.integer == 1)
2550 int firsttriangle = 0;
2551 int endtriangle = -1;
2552 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2554 surface = texturesurfacelist[texturesurfaceindex];
2555 if (surface->num_firsttriangle != endtriangle)
2557 if (endtriangle > firsttriangle)
2559 GL_LockArrays(firstvertex, endvertex - firstvertex);
2560 R_Mesh_Draw(firstvertex, endvertex - firstvertex, endtriangle - firsttriangle, (rsurface_model->surfmesh.data_element3i + 3 * firsttriangle));
2562 firstvertex = surface->num_firstvertex;
2563 endvertex = surface->num_firstvertex + surface->num_vertices;
2564 firsttriangle = surface->num_firsttriangle;
2568 firstvertex = min(firstvertex, surface->num_firstvertex);
2569 endvertex = max(endvertex, surface->num_firstvertex + surface->num_vertices);
2571 endtriangle = surface->num_firsttriangle + surface->num_triangles;
2573 if (endtriangle > firsttriangle)
2575 GL_LockArrays(firstvertex, endvertex - firstvertex);
2576 R_Mesh_Draw(firstvertex, endvertex - firstvertex, endtriangle - firsttriangle, (rsurface_model->surfmesh.data_element3i + 3 * firsttriangle));
2581 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2583 surface = texturesurfacelist[texturesurfaceindex];
2584 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2585 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
2590 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
2592 int texturesurfaceindex;
2593 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2595 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2596 int k = (int)(((size_t)surface) / sizeof(msurface_t));
2597 GL_Color((k & 15) * (1.0f / 16.0f), ((k >> 4) & 15) * (1.0f / 16.0f), ((k >> 8) & 15) * (1.0f / 16.0f), 0.2f);
2598 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2599 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
2603 static void RSurf_DrawBatch_Lightmap(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, int lightmode, qboolean applycolor, qboolean applyfog)
2605 int texturesurfaceindex;
2613 vec3_t ambientcolor;
2614 vec3_t diffusecolor;
2616 VectorCopy(rsurface_entity->modellight_lightdir, lightdir);
2617 ambientcolor[0] = rsurface_entity->modellight_ambient[0] * r * 0.5f;
2618 ambientcolor[1] = rsurface_entity->modellight_ambient[1] * g * 0.5f;
2619 ambientcolor[2] = rsurface_entity->modellight_ambient[2] * b * 0.5f;
2620 diffusecolor[0] = rsurface_entity->modellight_diffuse[0] * r * 0.5f;
2621 diffusecolor[1] = rsurface_entity->modellight_diffuse[1] * g * 0.5f;
2622 diffusecolor[2] = rsurface_entity->modellight_diffuse[2] * b * 0.5f;
2623 if (VectorLength2(diffusecolor) > 0)
2625 // generate color arrays for the surfaces in this list
2626 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2628 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2629 int numverts = surface->num_vertices;
2630 v = rsurface_vertex3f + 3 * surface->num_firstvertex;
2631 c2 = rsurface_normal3f + 3 * surface->num_firstvertex;
2632 c = rsurface_array_color4f + 4 * surface->num_firstvertex;
2633 // q3-style directional shading
2634 for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
2636 if ((f = DotProduct(c2, lightdir)) > 0)
2637 VectorMA(ambientcolor, f, diffusecolor, c);
2639 VectorCopy(ambientcolor, c);
2648 rsurface_lightmapcolor4f = rsurface_array_color4f;
2652 r = ambientcolor[0];
2653 g = ambientcolor[1];
2654 b = ambientcolor[2];
2655 rsurface_lightmapcolor4f = NULL;
2658 else if (lightmode >= 1 || !rsurface_lightmaptexture)
2660 if (texturesurfacelist[0]->lightmapinfo && texturesurfacelist[0]->lightmapinfo->stainsamples)
2662 // generate color arrays for the surfaces in this list
2663 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2665 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2666 for (i = 0, c = rsurface_array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
2668 if (surface->lightmapinfo->samples)
2670 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface_model->surfmesh.data_lightmapoffsets + surface->num_firstvertex)[i];
2671 float scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
2672 VectorScale(lm, scale, c);
2673 if (surface->lightmapinfo->styles[1] != 255)
2675 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
2677 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
2678 VectorMA(c, scale, lm, c);
2679 if (surface->lightmapinfo->styles[2] != 255)
2682 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
2683 VectorMA(c, scale, lm, c);
2684 if (surface->lightmapinfo->styles[3] != 255)
2687 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
2688 VectorMA(c, scale, lm, c);
2698 rsurface_lightmapcolor4f = rsurface_array_color4f;
2701 rsurface_lightmapcolor4f = rsurface_model->surfmesh.data_lightmapcolor4f;
2706 rsurface_lightmapcolor4f = NULL;
2710 if (rsurface_lightmapcolor4f)
2712 // generate color arrays for the surfaces in this list
2713 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2715 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2716 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)
2718 f = 1 - VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
2728 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2730 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2731 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)
2733 f = 1 - VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
2741 rsurface_lightmapcolor4f = rsurface_array_color4f;
2743 if (applycolor && rsurface_lightmapcolor4f)
2745 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2747 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2748 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)
2756 rsurface_lightmapcolor4f = rsurface_array_color4f;
2758 R_Mesh_ColorPointer(rsurface_lightmapcolor4f);
2759 GL_Color(r, g, b, a);
2760 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
2763 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
2765 if (rsurface_mode != RSURFMODE_SHOWSURFACES)
2767 rsurface_mode = RSURFMODE_SHOWSURFACES;
2769 GL_BlendFunc(GL_ONE, GL_ZERO);
2770 R_Mesh_ColorPointer(NULL);
2771 R_Mesh_ResetTextureState();
2773 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
2774 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
2777 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, msurface_t **texturesurfacelist)
2779 // transparent sky would be ridiculous
2780 if ((rsurface_texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
2782 if (rsurface_mode != RSURFMODE_SKY)
2784 if (rsurface_mode == RSURFMODE_GLSL)
2786 qglUseProgramObjectARB(0);CHECKGLERROR
2788 rsurface_mode = RSURFMODE_SKY;
2792 skyrendernow = false;
2794 // restore entity matrix
2795 R_Mesh_Matrix(&rsurface_entity->matrix);
2798 // LordHavoc: HalfLife maps have freaky skypolys so don't use
2799 // skymasking on them, and Quake3 never did sky masking (unlike
2800 // software Quake and software Quake2), so disable the sky masking
2801 // in Quake3 maps as it causes problems with q3map2 sky tricks,
2802 // and skymasking also looks very bad when noclipping outside the
2803 // level, so don't use it then either.
2804 if (rsurface_model->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_viewcache.world_novis)
2806 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
2807 R_Mesh_ColorPointer(NULL);
2808 R_Mesh_ResetTextureState();
2809 if (skyrendermasked)
2811 // depth-only (masking)
2812 GL_ColorMask(0,0,0,0);
2813 // just to make sure that braindead drivers don't draw
2814 // anything despite that colormask...
2815 GL_BlendFunc(GL_ZERO, GL_ONE);
2820 GL_BlendFunc(GL_ONE, GL_ZERO);
2822 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
2823 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
2824 if (skyrendermasked)
2825 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
2829 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, msurface_t **texturesurfacelist)
2832 // FIXME: identify models using a better check than rsurface_model->brush.shadowmesh
2833 lightmode = ((rsurface_entity->effects & EF_FULLBRIGHT) || rsurface_model->brush.shadowmesh) ? 0 : 2;
2834 if (rsurface_mode != RSURFMODE_GLSL)
2836 rsurface_mode = RSURFMODE_GLSL;
2837 rsurface_glsl_texture = NULL;
2838 rsurface_glsl_uselightmap = false;
2839 R_Mesh_ResetTextureState();
2841 if (rsurface_glsl_texture != rsurface_texture || rsurface_glsl_uselightmap != (rsurface_lightmaptexture != NULL))
2843 rsurface_glsl_texture = rsurface_texture;
2844 rsurface_glsl_uselightmap = rsurface_lightmaptexture != NULL;
2845 GL_BlendFunc(rsurface_texture->currentlayers[0].blendfunc1, rsurface_texture->currentlayers[0].blendfunc2);
2846 GL_DepthMask(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_BLENDED));
2847 GL_Color(rsurface_entity->colormod[0], rsurface_entity->colormod[1], rsurface_entity->colormod[2], rsurface_texture->currentalpha);
2848 R_SetupSurfaceShader(vec3_origin, lightmode == 2);
2849 //permutation_deluxemapping = permutation_lightmapping = R_SetupSurfaceShader(vec3_origin, lightmode == 2, false);
2850 //if (r_glsl_deluxemapping.integer)
2851 // permutation_deluxemapping = R_SetupSurfaceShader(vec3_origin, lightmode == 2, true);
2852 R_Mesh_TexCoordPointer(0, 2, rsurface_model->surfmesh.data_texcoordtexture2f);
2853 R_Mesh_TexCoordPointer(4, 2, rsurface_model->surfmesh.data_texcoordlightmap2f);
2854 GL_AlphaTest((rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2856 if (!r_glsl_permutation)
2858 RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
2859 R_Mesh_TexCoordPointer(1, 3, rsurface_svector3f);
2860 R_Mesh_TexCoordPointer(2, 3, rsurface_tvector3f);
2861 R_Mesh_TexCoordPointer(3, 3, rsurface_normal3f);
2862 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2864 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
2865 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
2866 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
2867 R_Mesh_ColorPointer(NULL);
2869 else if (rsurface_lightmaptexture)
2871 R_Mesh_TexBind(7, R_GetTexture(rsurface_lightmaptexture));
2872 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
2873 R_Mesh_TexBind(8, R_GetTexture(texturesurfacelist[0]->deluxemaptexture));
2874 R_Mesh_ColorPointer(NULL);
2878 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
2879 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
2880 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
2881 R_Mesh_ColorPointer(rsurface_model->surfmesh.data_lightmapcolor4f);
2883 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
2886 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, msurface_t **texturesurfacelist)
2888 // OpenGL 1.3 path - anything not completely ancient
2889 int texturesurfaceindex;
2891 qboolean applycolor;
2895 const texturelayer_t *layer;
2897 // FIXME: identify models using a better check than rsurface_model->brush.shadowmesh
2898 lightmode = ((rsurface_entity->effects & EF_FULLBRIGHT) || rsurface_model->brush.shadowmesh) ? 0 : 2;
2899 if (rsurface_mode != RSURFMODE_MULTIPASS)
2900 rsurface_mode = RSURFMODE_MULTIPASS;
2901 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
2902 for (layerindex = 0, layer = rsurface_texture->currentlayers;layerindex < rsurface_texture->currentnumlayers;layerindex++, layer++)
2905 int layertexrgbscale;
2906 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2908 if (layerindex == 0)
2912 GL_AlphaTest(false);
2913 qglDepthFunc(GL_EQUAL);CHECKGLERROR
2916 GL_DepthMask(layer->depthmask);
2917 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
2918 if ((layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2) && (gl_combine.integer || layer->depthmask))
2920 layertexrgbscale = 4;
2921 VectorScale(layer->color, 0.25f, layercolor);
2923 else if ((layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1) && (gl_combine.integer || layer->depthmask))
2925 layertexrgbscale = 2;
2926 VectorScale(layer->color, 0.5f, layercolor);
2930 layertexrgbscale = 1;
2931 VectorScale(layer->color, 1.0f, layercolor);
2933 layercolor[3] = layer->color[3];
2934 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
2935 R_Mesh_ColorPointer(NULL);
2936 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
2937 switch (layer->type)
2939 case TEXTURELAYERTYPE_LITTEXTURE:
2940 memset(&m, 0, sizeof(m));
2941 if (lightmode >= 1 || !rsurface_lightmaptexture)
2942 m.tex[0] = R_GetTexture(r_texture_white);
2944 m.tex[0] = R_GetTexture(rsurface_lightmaptexture);
2945 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordlightmap2f;
2946 m.tex[1] = R_GetTexture(layer->texture);
2947 m.texmatrix[1] = layer->texmatrix;
2948 m.texrgbscale[1] = layertexrgbscale;
2949 m.pointer_texcoord[1] = rsurface_model->surfmesh.data_texcoordtexture2f;
2950 R_Mesh_TextureState(&m);
2951 RSurf_DrawBatch_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], lightmode, applycolor, applyfog);
2953 case TEXTURELAYERTYPE_TEXTURE:
2954 memset(&m, 0, sizeof(m));
2955 m.tex[0] = R_GetTexture(layer->texture);
2956 m.texmatrix[0] = layer->texmatrix;
2957 m.texrgbscale[0] = layertexrgbscale;
2958 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
2959 R_Mesh_TextureState(&m);
2960 RSurf_DrawBatch_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, applyfog);
2962 case TEXTURELAYERTYPE_FOG:
2963 memset(&m, 0, sizeof(m));
2964 m.texrgbscale[0] = layertexrgbscale;
2967 m.tex[0] = R_GetTexture(layer->texture);
2968 m.texmatrix[0] = layer->texmatrix;
2969 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
2971 R_Mesh_TextureState(&m);
2972 // generate a color array for the fog pass
2973 R_Mesh_ColorPointer(rsurface_array_color4f);
2974 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2978 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2979 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)
2981 f = VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
2982 c[0] = layercolor[0];
2983 c[1] = layercolor[1];
2984 c[2] = layercolor[2];
2985 c[3] = f * layercolor[3];
2988 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
2991 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
2993 GL_LockArrays(0, 0);
2996 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2998 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
2999 GL_AlphaTest(false);
3003 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, msurface_t **texturesurfacelist)
3005 // OpenGL 1.1 - crusty old voodoo path
3006 int texturesurfaceindex;
3011 const texturelayer_t *layer;
3013 // FIXME: identify models using a better check than rsurface_model->brush.shadowmesh
3014 lightmode = ((rsurface_entity->effects & EF_FULLBRIGHT) || rsurface_model->brush.shadowmesh) ? 0 : 2;
3015 if (rsurface_mode != RSURFMODE_MULTIPASS)
3016 rsurface_mode = RSURFMODE_MULTIPASS;
3017 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
3018 for (layerindex = 0, layer = rsurface_texture->currentlayers;layerindex < rsurface_texture->currentnumlayers;layerindex++, layer++)
3020 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
3022 if (layerindex == 0)
3026 GL_AlphaTest(false);
3027 qglDepthFunc(GL_EQUAL);CHECKGLERROR
3030 GL_DepthMask(layer->depthmask);
3031 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
3032 R_Mesh_ColorPointer(NULL);
3033 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
3034 switch (layer->type)
3036 case TEXTURELAYERTYPE_LITTEXTURE:
3037 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
3039 // two-pass lit texture with 2x rgbscale
3040 // first the lightmap pass
3041 memset(&m, 0, sizeof(m));
3042 if (lightmode >= 1 || !rsurface_lightmaptexture)
3043 m.tex[0] = R_GetTexture(r_texture_white);
3045 m.tex[0] = R_GetTexture(rsurface_lightmaptexture);
3046 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordlightmap2f;
3047 R_Mesh_TextureState(&m);
3048 RSurf_DrawBatch_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, lightmode, false, false);
3049 GL_LockArrays(0, 0);
3050 // then apply the texture to it
3051 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
3052 memset(&m, 0, sizeof(m));
3053 m.tex[0] = R_GetTexture(layer->texture);
3054 m.texmatrix[0] = layer->texmatrix;
3055 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3056 R_Mesh_TextureState(&m);
3057 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);
3061 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
3062 memset(&m, 0, sizeof(m));
3063 m.tex[0] = R_GetTexture(layer->texture);
3064 m.texmatrix[0] = layer->texmatrix;
3065 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3066 R_Mesh_TextureState(&m);
3067 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);
3070 case TEXTURELAYERTYPE_TEXTURE:
3071 // singletexture unlit texture with transparency support
3072 memset(&m, 0, sizeof(m));
3073 m.tex[0] = R_GetTexture(layer->texture);
3074 m.texmatrix[0] = layer->texmatrix;
3075 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3076 R_Mesh_TextureState(&m);
3077 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);
3079 case TEXTURELAYERTYPE_FOG:
3080 // singletexture fogging
3081 R_Mesh_ColorPointer(rsurface_array_color4f);
3084 memset(&m, 0, sizeof(m));
3085 m.tex[0] = R_GetTexture(layer->texture);
3086 m.texmatrix[0] = layer->texmatrix;
3087 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3088 R_Mesh_TextureState(&m);
3091 R_Mesh_ResetTextureState();
3092 // generate a color array for the fog pass
3093 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3097 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3098 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)
3100 f = VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
3101 c[0] = layer->color[0];
3102 c[1] = layer->color[1];
3103 c[2] = layer->color[2];
3104 c[3] = f * layer->color[3];
3107 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3110 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
3112 GL_LockArrays(0, 0);
3115 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
3117 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3118 GL_AlphaTest(false);
3122 static void R_DrawTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist)
3124 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_NODRAW)
3126 r_shadow_rtlight = NULL;
3127 r_refdef.stats.entities_surfaces += texturenumsurfaces;
3129 GL_DepthTest(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
3130 if ((rsurface_texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (rsurface_entity->flags & RENDER_NOCULLFACE))
3132 qglDisable(GL_CULL_FACE);CHECKGLERROR
3134 if (r_showsurfaces.integer)
3135 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
3136 else if (rsurface_texture->currentmaterialflags & MATERIALFLAG_SKY)
3137 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
3138 else if (rsurface_texture->currentnumlayers)
3140 if (r_glsl.integer && gl_support_fragment_shader)
3141 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist);
3142 else if (gl_combine.integer && r_textureunits.integer >= 2)
3143 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist);
3145 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist);
3148 GL_LockArrays(0, 0);
3149 if ((rsurface_texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (rsurface_entity->flags & RENDER_NOCULLFACE))
3151 qglEnable(GL_CULL_FACE);CHECKGLERROR
3155 #define BATCHSIZE 256
3156 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
3158 int surfacelistindex;
3161 msurface_t *texturesurfacelist[BATCHSIZE];
3162 // if the model is static it doesn't matter what value we give for
3163 // wantnormals and wanttangents, so this logic uses only rules applicable
3164 // to a model, knowing that they are meaningless otherwise
3165 if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
3166 RSurf_ActiveEntity(ent, false, false);
3168 RSurf_ActiveEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
3171 for (surfacelistindex = 0;surfacelistindex < numsurfaces;surfacelistindex++)
3173 msurface_t *surface = ent->model->data_surfaces + surfacelist[surfacelistindex];
3175 if (t != surface->texture || rsurface_lightmaptexture != surface->lightmaptexture)
3178 R_DrawTextureSurfaceList(batchcount, texturesurfacelist);
3180 t = surface->texture;
3181 rsurface_lightmaptexture = surface->lightmaptexture;
3182 R_UpdateTextureInfo(ent, t);
3183 rsurface_texture = t->currentframe;
3185 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_SKY)
3186 continue; // transparent sky is too difficult
3188 texturesurfacelist[batchcount++] = surface;
3191 R_DrawTextureSurfaceList(batchcount, texturesurfacelist);
3195 void R_QueueTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist)
3197 int texturesurfaceindex;
3198 vec3_t tempcenter, center;
3199 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_BLENDED)
3201 // drawing sky transparently would be too difficult
3202 if (!(rsurface_texture->currentmaterialflags & MATERIALFLAG_SKY))
3204 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3206 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3207 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
3208 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
3209 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
3210 Matrix4x4_Transform(&rsurface_entity->matrix, tempcenter, center);
3211 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);
3216 R_DrawTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
3219 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
3220 void R_DrawSurfaces(entity_render_t *ent, qboolean skysurfaces)
3222 int i, j, f, flagsmask;
3223 int counttriangles = 0;
3225 model_t *model = ent->model;
3226 const int maxsurfacelist = 1024;
3227 int numsurfacelist = 0;
3228 msurface_t *surfacelist[1024];
3232 // if the model is static it doesn't matter what value we give for
3233 // wantnormals and wanttangents, so this logic uses only rules applicable
3234 // to a model, knowing that they are meaningless otherwise
3235 if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
3236 RSurf_ActiveEntity(ent, false, false);
3238 RSurf_ActiveEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
3240 // update light styles
3241 if (!skysurfaces && model->brushq1.light_styleupdatechains)
3243 msurface_t *surface, **surfacechain;
3244 for (i = 0;i < model->brushq1.light_styles;i++)
3246 if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
3248 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
3249 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
3250 for (;(surface = *surfacechain);surfacechain++)
3251 surface->cached_dlight = true;
3256 R_UpdateAllTextureInfo(ent);
3257 flagsmask = skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL);
3260 rsurface_lightmaptexture = NULL;
3261 rsurface_texture = NULL;
3263 if (ent == r_refdef.worldentity)
3265 msurface_t *surface;
3266 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
3268 if (!r_viewcache.world_surfacevisible[j])
3270 if (t != surface->texture || rsurface_lightmaptexture != surface->lightmaptexture)
3274 R_QueueTextureSurfaceList(numsurfacelist, surfacelist);
3277 t = surface->texture;
3278 rsurface_lightmaptexture = surface->lightmaptexture;
3279 rsurface_texture = t->currentframe;
3280 f = rsurface_texture->currentmaterialflags & flagsmask;
3282 if (f && surface->num_triangles)
3284 // if lightmap parameters changed, rebuild lightmap texture
3285 if (surface->cached_dlight)
3286 R_BuildLightMap(ent, surface);
3287 // add face to draw list
3288 surfacelist[numsurfacelist++] = surface;
3289 counttriangles += surface->num_triangles;
3290 if (numsurfacelist >= maxsurfacelist)
3292 R_QueueTextureSurfaceList(numsurfacelist, surfacelist);
3300 msurface_t *surface;
3301 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
3303 if (t != surface->texture || rsurface_lightmaptexture != surface->lightmaptexture)
3307 R_QueueTextureSurfaceList(numsurfacelist, surfacelist);
3310 t = surface->texture;
3311 rsurface_lightmaptexture = surface->lightmaptexture;
3312 rsurface_texture = t->currentframe;
3313 f = rsurface_texture->currentmaterialflags & flagsmask;
3315 if (f && surface->num_triangles)
3317 // if lightmap parameters changed, rebuild lightmap texture
3318 if (surface->cached_dlight)
3319 R_BuildLightMap(ent, surface);
3320 // add face to draw list
3321 surfacelist[numsurfacelist++] = surface;
3322 counttriangles += surface->num_triangles;
3323 if (numsurfacelist >= maxsurfacelist)
3325 R_QueueTextureSurfaceList(numsurfacelist, surfacelist);
3332 R_QueueTextureSurfaceList(numsurfacelist, surfacelist);
3333 r_refdef.stats.entities_triangles += counttriangles;
3336 if (r_showcollisionbrushes.integer && model->brush.num_brushes && !skysurfaces)
3339 const msurface_t *surface;
3342 R_Mesh_Matrix(&ent->matrix);
3343 R_Mesh_ColorPointer(NULL);
3344 R_Mesh_ResetTextureState();
3345 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
3346 GL_DepthMask(false);
3347 GL_DepthTest(!r_showdisabledepthtest.integer);
3348 qglPolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);CHECKGLERROR
3349 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
3350 if (brush->colbrushf && brush->colbrushf->numtriangles)
3351 R_DrawCollisionBrush(brush->colbrushf);
3352 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
3353 if (surface->num_collisiontriangles)
3354 R_DrawCollisionSurface(ent, surface);
3355 qglPolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR
3358 if (r_showtris.integer || r_shownormals.integer)
3361 msurface_t *surface;
3362 const int *elements;
3367 if (r_showdisabledepthtest.integer)
3369 qglDepthFunc(GL_ALWAYS);CHECKGLERROR
3371 GL_BlendFunc(GL_ONE, GL_ZERO);
3372 R_Mesh_ColorPointer(NULL);
3373 R_Mesh_ResetTextureState();
3374 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
3376 if (ent == r_refdef.worldentity && !r_viewcache.world_surfacevisible[j])
3378 rsurface_texture = surface->texture->currentframe;
3379 if ((rsurface_texture->currentmaterialflags & flagsmask) && surface->num_triangles)
3381 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
3382 if (r_showtris.integer)
3384 if (!rsurface_texture->currentlayers->depthmask)
3385 GL_Color(r_showtris.value, 0, 0, 1);
3386 else if (ent == r_refdef.worldentity)
3387 GL_Color(r_showtris.value, r_showtris.value, r_showtris.value, 1);
3389 GL_Color(0, r_showtris.value, 0, 1);
3390 elements = (ent->model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
3393 for (k = 0;k < surface->num_triangles;k++, elements += 3)
3395 qglArrayElement(elements[0]);qglArrayElement(elements[1]);
3396 qglArrayElement(elements[1]);qglArrayElement(elements[2]);
3397 qglArrayElement(elements[2]);qglArrayElement(elements[0]);
3402 if (r_shownormals.integer)
3404 GL_Color(r_shownormals.value, 0, 0, 1);
3406 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
3408 VectorCopy(rsurface_vertex3f + l * 3, v);
3409 qglVertex3f(v[0], v[1], v[2]);
3410 VectorMA(v, 8, rsurface_svector3f + l * 3, v);
3411 qglVertex3f(v[0], v[1], v[2]);
3415 GL_Color(0, 0, r_shownormals.value, 1);
3417 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
3419 VectorCopy(rsurface_vertex3f + l * 3, v);
3420 qglVertex3f(v[0], v[1], v[2]);
3421 VectorMA(v, 8, rsurface_tvector3f + l * 3, v);
3422 qglVertex3f(v[0], v[1], v[2]);
3426 GL_Color(0, r_shownormals.value, 0, 1);
3428 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
3430 VectorCopy(rsurface_vertex3f + l * 3, v);
3431 qglVertex3f(v[0], v[1], v[2]);
3432 VectorMA(v, 8, rsurface_normal3f + l * 3, v);
3433 qglVertex3f(v[0], v[1], v[2]);
3440 rsurface_texture = NULL;
3441 if (r_showdisabledepthtest.integer)
3443 qglDepthFunc(GL_LEQUAL);CHECKGLERROR