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\n"};
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 VM_AddPolygonsToMeshQueue();
1795 R_MeshQueue_RenderTransparent();
1796 if (r_timereport_active)
1797 R_TimeReport("drawtrans");
1799 if (cl.csqc_vidvars.drawworld)
1802 if (r_timereport_active)
1803 R_TimeReport("coronas");
1805 if(cl.csqc_vidvars.drawcrosshair)
1807 R_DrawWorldCrosshair();
1808 if (r_timereport_active)
1809 R_TimeReport("crosshair");
1812 // don't let sound skip if going slow
1813 if (r_refdef.extraupdate)
1817 if (gl_support_fragment_shader)
1819 qglUseProgramObjectARB(0);CHECKGLERROR
1821 qglPolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR
1822 qglDisable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
1826 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
1829 float *v, *c, f1, f2, diff[3], vertex3f[8*3], color4f[8*4];
1830 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1831 GL_DepthMask(false);
1833 R_Mesh_Matrix(&identitymatrix);
1835 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2];
1836 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
1837 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
1838 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
1839 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
1840 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
1841 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
1842 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
1843 R_FillColors(color, 8, cr, cg, cb, ca);
1844 if (r_refdef.fogenabled)
1846 for (i = 0, v = vertex, c = color;i < 8;i++, v += 4, c += 4)
1848 f2 = VERTEXFOGTABLE(VectorDistance(v, r_view.origin));
1850 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
1851 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
1852 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
1855 R_Mesh_VertexPointer(vertex3f);
1856 R_Mesh_ColorPointer(color);
1857 R_Mesh_ResetTextureState();
1862 int nomodelelements[24] =
1874 float nomodelvertex3f[6*3] =
1884 float nomodelcolor4f[6*4] =
1886 0.0f, 0.0f, 0.5f, 1.0f,
1887 0.0f, 0.0f, 0.5f, 1.0f,
1888 0.0f, 0.5f, 0.0f, 1.0f,
1889 0.0f, 0.5f, 0.0f, 1.0f,
1890 0.5f, 0.0f, 0.0f, 1.0f,
1891 0.5f, 0.0f, 0.0f, 1.0f
1894 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
1899 // this is only called once per entity so numsurfaces is always 1, and
1900 // surfacelist is always {0}, so this code does not handle batches
1901 R_Mesh_Matrix(&ent->matrix);
1903 if (ent->flags & EF_ADDITIVE)
1905 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
1906 GL_DepthMask(false);
1908 else if (ent->alpha < 1)
1910 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1911 GL_DepthMask(false);
1915 GL_BlendFunc(GL_ONE, GL_ZERO);
1918 GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
1919 R_Mesh_VertexPointer(nomodelvertex3f);
1920 if (r_refdef.fogenabled)
1922 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
1923 R_Mesh_ColorPointer(color4f);
1924 f2 = VERTEXFOGTABLE(VectorDistance(ent->origin, r_view.origin));
1926 for (i = 0, c = color4f;i < 6;i++, c += 4)
1928 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
1929 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
1930 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
1934 else if (ent->alpha != 1)
1936 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
1937 R_Mesh_ColorPointer(color4f);
1938 for (i = 0, c = color4f;i < 6;i++, c += 4)
1942 R_Mesh_ColorPointer(nomodelcolor4f);
1943 R_Mesh_ResetTextureState();
1944 R_Mesh_Draw(0, 6, 8, nomodelelements);
1947 void R_DrawNoModel(entity_render_t *ent)
1949 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
1950 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_view.origin : ent->origin, R_DrawNoModel_TransparentCallback, ent, 0, r_shadow_rtlight);
1952 // R_DrawNoModelCallback(ent, 0);
1955 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
1957 vec3_t right1, right2, diff, normal;
1959 VectorSubtract (org2, org1, normal);
1961 // calculate 'right' vector for start
1962 VectorSubtract (r_view.origin, org1, diff);
1963 CrossProduct (normal, diff, right1);
1964 VectorNormalize (right1);
1966 // calculate 'right' vector for end
1967 VectorSubtract (r_view.origin, org2, diff);
1968 CrossProduct (normal, diff, right2);
1969 VectorNormalize (right2);
1971 vert[ 0] = org1[0] + width * right1[0];
1972 vert[ 1] = org1[1] + width * right1[1];
1973 vert[ 2] = org1[2] + width * right1[2];
1974 vert[ 3] = org1[0] - width * right1[0];
1975 vert[ 4] = org1[1] - width * right1[1];
1976 vert[ 5] = org1[2] - width * right1[2];
1977 vert[ 6] = org2[0] - width * right2[0];
1978 vert[ 7] = org2[1] - width * right2[1];
1979 vert[ 8] = org2[2] - width * right2[2];
1980 vert[ 9] = org2[0] + width * right2[0];
1981 vert[10] = org2[1] + width * right2[1];
1982 vert[11] = org2[2] + width * right2[2];
1985 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
1987 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)
1989 float fog = 0.0f, ifog;
1992 if (r_refdef.fogenabled)
1993 fog = VERTEXFOGTABLE(VectorDistance(origin, r_view.origin));
1996 R_Mesh_Matrix(&identitymatrix);
1997 GL_BlendFunc(blendfunc1, blendfunc2);
1998 GL_DepthMask(false);
1999 GL_DepthTest(!depthdisable);
2001 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
2002 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
2003 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
2004 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
2005 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
2006 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
2007 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
2008 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
2009 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
2010 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
2011 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
2012 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
2014 R_Mesh_VertexPointer(vertex3f);
2015 R_Mesh_ColorPointer(NULL);
2016 R_Mesh_ResetTextureState();
2017 R_Mesh_TexBind(0, R_GetTexture(texture));
2018 R_Mesh_TexCoordPointer(0, 2, spritetexcoord2f);
2019 GL_Color(cr * ifog, cg * ifog, cb * ifog, ca);
2020 R_Mesh_Draw(0, 4, 2, polygonelements);
2022 if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
2024 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
2025 GL_BlendFunc(blendfunc1, GL_ONE);
2026 GL_Color(r_refdef.fogcolor[0] * fog, r_refdef.fogcolor[1] * fog, r_refdef.fogcolor[2] * fog, ca);
2027 R_Mesh_Draw(0, 4, 2, polygonelements);
2031 int R_Mesh_AddVertex3f(rmesh_t *mesh, const float *v)
2035 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
2036 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
2038 if (i == mesh->numvertices)
2040 if (mesh->numvertices < mesh->maxvertices)
2042 VectorCopy(v, vertex3f);
2043 mesh->numvertices++;
2045 return mesh->numvertices;
2051 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
2055 element[0] = R_Mesh_AddVertex3f(mesh, vertex3f);vertex3f += 3;
2056 element[1] = R_Mesh_AddVertex3f(mesh, vertex3f);vertex3f += 3;
2057 e = mesh->element3i + mesh->numtriangles * 3;
2058 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
2060 element[2] = R_Mesh_AddVertex3f(mesh, vertex3f);
2061 if (mesh->numtriangles < mesh->maxtriangles)
2066 mesh->numtriangles++;
2068 element[1] = element[2];
2072 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
2074 int planenum, planenum2;
2077 mplane_t *plane, *plane2;
2078 float temppoints[2][256*3];
2079 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
2083 PolygonF_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->normal[3], 1024.0*1024.0*1024.0);
2084 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
2086 if (planenum2 == planenum)
2088 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);
2091 if (tempnumpoints < 3)
2093 // generate elements forming a triangle fan for this polygon
2094 R_Mesh_AddPolygon3f(mesh, tempnumpoints, temppoints[w]);
2098 static void R_DrawCollisionBrush(const colbrushf_t *brush)
2101 R_Mesh_VertexPointer(brush->points->v);
2102 i = (int)(((size_t)brush) / sizeof(colbrushf_t));
2103 GL_Color((i & 31) * (1.0f / 32.0f), ((i >> 5) & 31) * (1.0f / 32.0f), ((i >> 10) & 31) * (1.0f / 32.0f), 0.2f);
2104 GL_LockArrays(0, brush->numpoints);
2105 R_Mesh_Draw(0, brush->numpoints, brush->numtriangles, brush->elements);
2106 GL_LockArrays(0, 0);
2109 static void R_DrawCollisionSurface(const entity_render_t *ent, const msurface_t *surface)
2112 if (!surface->num_collisiontriangles)
2114 R_Mesh_VertexPointer(surface->data_collisionvertex3f);
2115 i = (int)(((size_t)surface) / sizeof(msurface_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, surface->num_collisionvertices);
2118 R_Mesh_Draw(0, surface->num_collisionvertices, surface->num_collisiontriangles, surface->data_collisionelement3i);
2119 GL_LockArrays(0, 0);
2122 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)
2124 texturelayer_t *layer;
2125 layer = t->currentlayers + t->currentnumlayers++;
2127 layer->depthmask = depthmask;
2128 layer->blendfunc1 = blendfunc1;
2129 layer->blendfunc2 = blendfunc2;
2130 layer->texture = texture;
2131 layer->texmatrix = *matrix;
2132 layer->color[0] = r;
2133 layer->color[1] = g;
2134 layer->color[2] = b;
2135 layer->color[3] = a;
2138 void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
2140 // FIXME: identify models using a better check than ent->model->brush.shadowmesh
2141 //int lightmode = ((ent->effects & EF_FULLBRIGHT) || ent->model->brush.shadowmesh) ? 0 : 2;
2144 texture_t *texture = t;
2145 model_t *model = ent->model;
2146 int s = ent->skinnum;
2147 if ((unsigned int)s >= (unsigned int)model->numskins)
2149 if (model->skinscenes)
2151 if (model->skinscenes[s].framecount > 1)
2152 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
2154 s = model->skinscenes[s].firstframe;
2157 t = t + s * model->num_surfaces;
2159 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];
2160 texture->currentframe = t;
2163 t->currentmaterialflags = t->basematerialflags;
2164 t->currentalpha = ent->alpha;
2165 if (t->basematerialflags & MATERIALFLAG_WATERALPHA)
2166 t->currentalpha *= r_wateralpha.value;
2167 if (!(ent->flags & RENDER_LIGHT))
2168 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
2169 if (ent->effects & EF_ADDITIVE)
2170 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_TRANSPARENT;
2171 else if (t->currentalpha < 1)
2172 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_TRANSPARENT;
2173 if (ent->effects & EF_NODEPTHTEST)
2174 t->currentmaterialflags |= MATERIALFLAG_NODEPTHTEST;
2175 if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
2176 t->currenttexmatrix = r_waterscrollmatrix;
2178 t->currenttexmatrix = identitymatrix;
2180 t->colormapping = VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f);
2181 t->basetexture = (!t->colormapping && t->skin.merged) ? t->skin.merged : t->skin.base;
2182 t->glosstexture = r_texture_white;
2183 t->specularpower = 8;
2184 t->specularscale = 0;
2185 if (r_shadow_gloss.integer > 0)
2189 if (r_shadow_glossintensity.value > 0)
2191 t->glosstexture = t->skin.gloss;
2192 t->specularscale = r_shadow_glossintensity.value;
2195 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
2196 t->specularscale = r_shadow_gloss2intensity.value;
2199 t->currentnumlayers = 0;
2200 if (!(t->currentmaterialflags & MATERIALFLAG_NODRAW))
2202 if (gl_lightmaps.integer)
2203 R_Texture_AddLayer(t, true, GL_ONE, GL_ZERO, TEXTURELAYERTYPE_LITTEXTURE, r_texture_white, &identitymatrix, 1, 1, 1, 1);
2204 else if (!(t->currentmaterialflags & MATERIALFLAG_SKY))
2206 int blendfunc1, blendfunc2, depthmask;
2207 if (t->currentmaterialflags & MATERIALFLAG_ADD)
2209 blendfunc1 = GL_SRC_ALPHA;
2210 blendfunc2 = GL_ONE;
2212 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
2214 blendfunc1 = GL_SRC_ALPHA;
2215 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
2217 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
2219 blendfunc1 = t->customblendfunc[0];
2220 blendfunc2 = t->customblendfunc[1];
2224 blendfunc1 = GL_ONE;
2225 blendfunc2 = GL_ZERO;
2227 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
2228 if (t->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL))
2230 rtexture_t *currentbasetexture;
2232 if (r_refdef.fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED))
2233 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
2234 currentbasetexture = (VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) < (1.0f / 1048576.0f) && t->skin.merged) ? t->skin.merged : t->skin.base;
2235 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2237 // fullbright is not affected by r_refdef.lightmapintensity
2238 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
2239 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->skin.pants)
2240 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);
2241 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->skin.shirt)
2242 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);
2248 // q3bsp has no lightmap updates, so the lightstylevalue that
2249 // would normally be baked into the lightmap must be
2250 // applied to the color
2251 if (ent->model->type == mod_brushq3)
2252 colorscale *= r_refdef.lightstylevalue[0] * (1.0f / 256.0f);
2253 colorscale *= r_refdef.lightmapintensity;
2254 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);
2255 if (r_ambient.value >= (1.0f/64.0f))
2256 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);
2257 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->skin.pants)
2259 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);
2260 if (r_ambient.value >= (1.0f/64.0f))
2261 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);
2263 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->skin.shirt)
2265 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);
2266 if (r_ambient.value >= (1.0f/64.0f))
2267 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);
2270 if (t->skin.glow != NULL)
2271 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.glow, &t->currenttexmatrix, 1, 1, 1, t->currentalpha);
2272 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
2274 // if this is opaque use alpha blend which will darken the earlier
2277 // if this is an alpha blended material, all the earlier passes
2278 // were darkened by fog already, so we only need to add the fog
2279 // color ontop through the fog mask texture
2281 // if this is an additive blended material, all the earlier passes
2282 // were darkened by fog already, and we should not add fog color
2283 // (because the background was not darkened, there is no fog color
2284 // that was lost behind it).
2285 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);
2292 void R_UpdateAllTextureInfo(entity_render_t *ent)
2296 for (i = 0;i < ent->model->num_textures;i++)
2297 R_UpdateTextureInfo(ent, ent->model->data_textures + i);
2300 int rsurface_array_size = 0;
2301 float *rsurface_array_modelvertex3f = NULL;
2302 float *rsurface_array_modelsvector3f = NULL;
2303 float *rsurface_array_modeltvector3f = NULL;
2304 float *rsurface_array_modelnormal3f = NULL;
2305 float *rsurface_array_deformedvertex3f = NULL;
2306 float *rsurface_array_deformedsvector3f = NULL;
2307 float *rsurface_array_deformedtvector3f = NULL;
2308 float *rsurface_array_deformednormal3f = NULL;
2309 float *rsurface_array_color4f = NULL;
2310 float *rsurface_array_texcoord3f = NULL;
2312 void R_Mesh_ResizeArrays(int newvertices)
2315 if (rsurface_array_size >= newvertices)
2317 if (rsurface_array_modelvertex3f)
2318 Mem_Free(rsurface_array_modelvertex3f);
2319 rsurface_array_size = (newvertices + 1023) & ~1023;
2320 base = (float *)Mem_Alloc(r_main_mempool, rsurface_array_size * sizeof(float[31]));
2321 rsurface_array_modelvertex3f = base + rsurface_array_size * 0;
2322 rsurface_array_modelsvector3f = base + rsurface_array_size * 3;
2323 rsurface_array_modeltvector3f = base + rsurface_array_size * 6;
2324 rsurface_array_modelnormal3f = base + rsurface_array_size * 9;
2325 rsurface_array_deformedvertex3f = base + rsurface_array_size * 12;
2326 rsurface_array_deformedsvector3f = base + rsurface_array_size * 15;
2327 rsurface_array_deformedtvector3f = base + rsurface_array_size * 18;
2328 rsurface_array_deformednormal3f = base + rsurface_array_size * 21;
2329 rsurface_array_texcoord3f = base + rsurface_array_size * 24;
2330 rsurface_array_color4f = base + rsurface_array_size * 27;
2333 float *rsurface_modelvertex3f;
2334 float *rsurface_modelsvector3f;
2335 float *rsurface_modeltvector3f;
2336 float *rsurface_modelnormal3f;
2337 float *rsurface_vertex3f;
2338 float *rsurface_svector3f;
2339 float *rsurface_tvector3f;
2340 float *rsurface_normal3f;
2341 float *rsurface_lightmapcolor4f;
2342 vec3_t rsurface_modelorg;
2343 qboolean rsurface_generatedvertex;
2344 const entity_render_t *rsurface_entity;
2345 const model_t *rsurface_model;
2346 texture_t *rsurface_texture;
2347 rtexture_t *rsurface_lightmaptexture;
2348 rsurfmode_t rsurface_mode;
2349 texture_t *rsurface_glsl_texture;
2350 qboolean rsurface_glsl_uselightmap;
2352 void RSurf_ActiveEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
2354 Matrix4x4_Transform(&ent->inversematrix, r_view.origin, rsurface_modelorg);
2355 rsurface_entity = ent;
2356 rsurface_model = ent->model;
2357 if (rsurface_array_size < rsurface_model->surfmesh.num_vertices)
2358 R_Mesh_ResizeArrays(rsurface_model->surfmesh.num_vertices);
2359 R_Mesh_Matrix(&ent->matrix);
2360 Matrix4x4_Transform(&ent->inversematrix, r_view.origin, rsurface_modelorg);
2361 if ((rsurface_entity->frameblend[0].lerp != 1 || rsurface_entity->frameblend[0].frame != 0) && (rsurface_model->surfmesh.data_morphvertex3f || rsurface_model->surfmesh.data_vertexweightindex4i))
2365 rsurface_modelvertex3f = rsurface_array_modelvertex3f;
2366 rsurface_modelsvector3f = rsurface_array_modelsvector3f;
2367 rsurface_modeltvector3f = rsurface_array_modeltvector3f;
2368 rsurface_modelnormal3f = rsurface_array_modelnormal3f;
2369 Mod_Alias_GetMesh_Vertices(rsurface_model, rsurface_entity->frameblend, rsurface_array_modelvertex3f, rsurface_array_modelnormal3f, rsurface_array_modelsvector3f, rsurface_array_modeltvector3f);
2371 else if (wantnormals)
2373 rsurface_modelvertex3f = rsurface_array_modelvertex3f;
2374 rsurface_modelsvector3f = NULL;
2375 rsurface_modeltvector3f = NULL;
2376 rsurface_modelnormal3f = rsurface_array_modelnormal3f;
2377 Mod_Alias_GetMesh_Vertices(rsurface_model, rsurface_entity->frameblend, rsurface_array_modelvertex3f, rsurface_array_modelnormal3f, NULL, NULL);
2381 rsurface_modelvertex3f = rsurface_array_modelvertex3f;
2382 rsurface_modelsvector3f = NULL;
2383 rsurface_modeltvector3f = NULL;
2384 rsurface_modelnormal3f = NULL;
2385 Mod_Alias_GetMesh_Vertices(rsurface_model, rsurface_entity->frameblend, rsurface_array_modelvertex3f, NULL, NULL, NULL);
2387 rsurface_generatedvertex = true;
2391 rsurface_modelvertex3f = rsurface_model->surfmesh.data_vertex3f;
2392 rsurface_modelsvector3f = rsurface_model->surfmesh.data_svector3f;
2393 rsurface_modeltvector3f = rsurface_model->surfmesh.data_tvector3f;
2394 rsurface_modelnormal3f = rsurface_model->surfmesh.data_normal3f;
2395 rsurface_generatedvertex = false;
2397 rsurface_vertex3f = rsurface_modelvertex3f;
2398 rsurface_svector3f = rsurface_modelsvector3f;
2399 rsurface_tvector3f = rsurface_modeltvector3f;
2400 rsurface_normal3f = rsurface_modelnormal3f;
2401 rsurface_mode = RSURFMODE_NONE;
2402 rsurface_lightmaptexture = NULL;
2403 rsurface_texture = NULL;
2404 rsurface_glsl_texture = NULL;
2405 rsurface_glsl_uselightmap = false;
2408 void RSurf_CleanUp(void)
2411 if (rsurface_mode == RSURFMODE_GLSL)
2413 qglUseProgramObjectARB(0);CHECKGLERROR
2415 GL_AlphaTest(false);
2416 rsurface_mode = RSURFMODE_NONE;
2417 rsurface_lightmaptexture = NULL;
2418 rsurface_texture = NULL;
2419 rsurface_glsl_texture = NULL;
2420 rsurface_glsl_uselightmap = false;
2423 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, msurface_t **texturesurfacelist)
2425 if (rsurface_generatedvertex)
2427 if (rsurface_texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
2428 generatetangents = true;
2429 if (generatetangents)
2430 generatenormals = true;
2431 if (generatenormals && !rsurface_modelnormal3f)
2433 rsurface_normal3f = rsurface_modelnormal3f = rsurface_array_modelnormal3f;
2434 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);
2436 if (generatetangents && !rsurface_modelsvector3f)
2438 rsurface_svector3f = rsurface_modelsvector3f = rsurface_array_modelsvector3f;
2439 rsurface_tvector3f = rsurface_modeltvector3f = rsurface_array_modeltvector3f;
2440 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);
2443 if (rsurface_texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
2445 int texturesurfaceindex;
2446 float center[3], forward[3], right[3], up[3], v[4][3];
2447 matrix4x4_t matrix1, imatrix1;
2448 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_view.forward, forward);
2449 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_view.right, right);
2450 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_view.up, up);
2451 // make deformed versions of only the vertices used by the specified surfaces
2452 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2455 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2456 // a single autosprite surface can contain multiple sprites...
2457 for (j = 0;j < surface->num_vertices - 3;j += 4)
2459 VectorClear(center);
2460 for (i = 0;i < 4;i++)
2461 VectorAdd(center, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
2462 VectorScale(center, 0.25f, center);
2463 if (rsurface_texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE2)
2465 forward[0] = rsurface_modelorg[0] - center[0];
2466 forward[1] = rsurface_modelorg[1] - center[1];
2468 VectorNormalize(forward);
2469 right[0] = forward[1];
2470 right[1] = -forward[0];
2472 VectorSet(up, 0, 0, 1);
2474 // FIXME: calculate vectors from triangle edges instead of using texture vectors as an easy way out?
2475 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);
2476 Matrix4x4_Invert_Simple(&imatrix1, &matrix1);
2477 for (i = 0;i < 4;i++)
2478 Matrix4x4_Transform(&imatrix1, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, v[i]);
2479 for (i = 0;i < 4;i++)
2480 VectorMAMAMAM(1, center, v[i][0], forward, v[i][1], right, v[i][2], up, rsurface_array_modelvertex3f + (surface->num_firstvertex+i+j) * 3);
2482 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);
2483 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);
2485 rsurface_vertex3f = rsurface_array_deformedvertex3f;
2486 rsurface_svector3f = rsurface_array_deformedsvector3f;
2487 rsurface_tvector3f = rsurface_array_deformedtvector3f;
2488 rsurface_normal3f = rsurface_array_deformednormal3f;
2490 R_Mesh_VertexPointer(rsurface_vertex3f);
2493 void RSurf_DrawBatch_Simple(int texturenumsurfaces, msurface_t **texturesurfacelist)
2495 int texturesurfaceindex;
2496 const msurface_t *surface = texturesurfacelist[0];
2497 int firstvertex = surface->num_firstvertex;
2498 int endvertex = surface->num_firstvertex + surface->num_vertices;
2499 if (texturenumsurfaces == 1)
2501 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2502 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
2504 else if (r_batchmode.integer == 2)
2506 #define MAXBATCHTRIANGLES 4096
2507 int batchtriangles = 0;
2508 int batchelements[MAXBATCHTRIANGLES*3];
2509 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2511 surface = texturesurfacelist[texturesurfaceindex];
2512 if (surface->num_triangles >= 256 || (batchtriangles == 0 && texturesurfaceindex + 1 >= texturenumsurfaces))
2514 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
2517 if (batchtriangles + surface->num_triangles > MAXBATCHTRIANGLES)
2519 R_Mesh_Draw(firstvertex, endvertex - firstvertex, batchtriangles, batchelements);
2521 firstvertex = surface->num_firstvertex;
2522 endvertex = surface->num_firstvertex + surface->num_vertices;
2526 firstvertex = min(firstvertex, surface->num_firstvertex);
2527 endvertex = max(endvertex, surface->num_firstvertex + surface->num_vertices);
2529 memcpy(batchelements + batchtriangles * 3, rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
2530 batchtriangles += surface->num_triangles;
2533 R_Mesh_Draw(firstvertex, endvertex - firstvertex, batchtriangles, batchelements);
2535 else if (r_batchmode.integer == 1)
2537 int firsttriangle = 0;
2538 int endtriangle = -1;
2539 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2541 surface = texturesurfacelist[texturesurfaceindex];
2542 if (surface->num_firsttriangle != endtriangle)
2544 if (endtriangle > firsttriangle)
2546 GL_LockArrays(firstvertex, endvertex - firstvertex);
2547 R_Mesh_Draw(firstvertex, endvertex - firstvertex, endtriangle - firsttriangle, (rsurface_model->surfmesh.data_element3i + 3 * firsttriangle));
2549 firstvertex = surface->num_firstvertex;
2550 endvertex = surface->num_firstvertex + surface->num_vertices;
2551 firsttriangle = surface->num_firsttriangle;
2555 firstvertex = min(firstvertex, surface->num_firstvertex);
2556 endvertex = max(endvertex, surface->num_firstvertex + surface->num_vertices);
2558 endtriangle = surface->num_firsttriangle + surface->num_triangles;
2560 if (endtriangle > firsttriangle)
2562 GL_LockArrays(firstvertex, endvertex - firstvertex);
2563 R_Mesh_Draw(firstvertex, endvertex - firstvertex, endtriangle - firsttriangle, (rsurface_model->surfmesh.data_element3i + 3 * firsttriangle));
2568 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2570 surface = texturesurfacelist[texturesurfaceindex];
2571 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2572 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
2577 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
2579 int texturesurfaceindex;
2580 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2582 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2583 int k = (int)(((size_t)surface) / sizeof(msurface_t));
2584 GL_Color((k & 15) * (1.0f / 16.0f), ((k >> 4) & 15) * (1.0f / 16.0f), ((k >> 8) & 15) * (1.0f / 16.0f), 0.2f);
2585 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2586 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_Lightmap(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, int lightmode, qboolean applycolor, qboolean applyfog)
2592 int texturesurfaceindex;
2600 vec3_t ambientcolor;
2601 vec3_t diffusecolor;
2603 VectorCopy(rsurface_entity->modellight_lightdir, lightdir);
2604 ambientcolor[0] = rsurface_entity->modellight_ambient[0] * r * 0.5f;
2605 ambientcolor[1] = rsurface_entity->modellight_ambient[1] * g * 0.5f;
2606 ambientcolor[2] = rsurface_entity->modellight_ambient[2] * b * 0.5f;
2607 diffusecolor[0] = rsurface_entity->modellight_diffuse[0] * r * 0.5f;
2608 diffusecolor[1] = rsurface_entity->modellight_diffuse[1] * g * 0.5f;
2609 diffusecolor[2] = rsurface_entity->modellight_diffuse[2] * b * 0.5f;
2610 if (VectorLength2(diffusecolor) > 0)
2612 // generate color arrays for the surfaces in this list
2613 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2615 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2616 int numverts = surface->num_vertices;
2617 v = rsurface_vertex3f + 3 * surface->num_firstvertex;
2618 c2 = rsurface_normal3f + 3 * surface->num_firstvertex;
2619 c = rsurface_array_color4f + 4 * surface->num_firstvertex;
2620 // q3-style directional shading
2621 for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
2623 if ((f = DotProduct(c2, lightdir)) > 0)
2624 VectorMA(ambientcolor, f, diffusecolor, c);
2626 VectorCopy(ambientcolor, c);
2635 rsurface_lightmapcolor4f = rsurface_array_color4f;
2639 r = ambientcolor[0];
2640 g = ambientcolor[1];
2641 b = ambientcolor[2];
2642 rsurface_lightmapcolor4f = NULL;
2645 else if (lightmode >= 1 || !rsurface_lightmaptexture)
2647 if (texturesurfacelist[0]->lightmapinfo && texturesurfacelist[0]->lightmapinfo->stainsamples)
2649 // generate color arrays for the surfaces in this list
2650 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2652 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2653 for (i = 0, c = rsurface_array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
2655 if (surface->lightmapinfo->samples)
2657 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface_model->surfmesh.data_lightmapoffsets + surface->num_firstvertex)[i];
2658 float scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
2659 VectorScale(lm, scale, c);
2660 if (surface->lightmapinfo->styles[1] != 255)
2662 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
2664 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
2665 VectorMA(c, scale, lm, c);
2666 if (surface->lightmapinfo->styles[2] != 255)
2669 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
2670 VectorMA(c, scale, lm, c);
2671 if (surface->lightmapinfo->styles[3] != 255)
2674 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
2675 VectorMA(c, scale, lm, c);
2685 rsurface_lightmapcolor4f = rsurface_array_color4f;
2688 rsurface_lightmapcolor4f = rsurface_model->surfmesh.data_lightmapcolor4f;
2693 rsurface_lightmapcolor4f = NULL;
2697 if (rsurface_lightmapcolor4f)
2699 // generate color arrays for the surfaces in this list
2700 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2702 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2703 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)
2705 f = 1 - VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
2715 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2717 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2718 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)
2720 f = 1 - VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
2728 rsurface_lightmapcolor4f = rsurface_array_color4f;
2730 if (applycolor && rsurface_lightmapcolor4f)
2732 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2734 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2735 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)
2743 rsurface_lightmapcolor4f = rsurface_array_color4f;
2745 R_Mesh_ColorPointer(rsurface_lightmapcolor4f);
2746 GL_Color(r, g, b, a);
2747 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
2750 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
2752 if (rsurface_mode != RSURFMODE_SHOWSURFACES)
2754 rsurface_mode = RSURFMODE_SHOWSURFACES;
2756 GL_BlendFunc(GL_ONE, GL_ZERO);
2757 R_Mesh_ColorPointer(NULL);
2758 R_Mesh_ResetTextureState();
2760 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
2761 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
2764 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, msurface_t **texturesurfacelist)
2766 // transparent sky would be ridiculous
2767 if ((rsurface_texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
2769 if (rsurface_mode != RSURFMODE_SKY)
2771 if (rsurface_mode == RSURFMODE_GLSL)
2773 qglUseProgramObjectARB(0);CHECKGLERROR
2775 rsurface_mode = RSURFMODE_SKY;
2779 skyrendernow = false;
2781 // restore entity matrix
2782 R_Mesh_Matrix(&rsurface_entity->matrix);
2785 // LordHavoc: HalfLife maps have freaky skypolys so don't use
2786 // skymasking on them, and Quake3 never did sky masking (unlike
2787 // software Quake and software Quake2), so disable the sky masking
2788 // in Quake3 maps as it causes problems with q3map2 sky tricks,
2789 // and skymasking also looks very bad when noclipping outside the
2790 // level, so don't use it then either.
2791 if (rsurface_model->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_viewcache.world_novis)
2793 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
2794 R_Mesh_ColorPointer(NULL);
2795 R_Mesh_ResetTextureState();
2796 if (skyrendermasked)
2798 // depth-only (masking)
2799 GL_ColorMask(0,0,0,0);
2800 // just to make sure that braindead drivers don't draw
2801 // anything despite that colormask...
2802 GL_BlendFunc(GL_ZERO, GL_ONE);
2807 GL_BlendFunc(GL_ONE, GL_ZERO);
2809 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
2810 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
2811 if (skyrendermasked)
2812 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
2816 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, msurface_t **texturesurfacelist)
2819 // FIXME: identify models using a better check than rsurface_model->brush.shadowmesh
2820 lightmode = ((rsurface_entity->effects & EF_FULLBRIGHT) || rsurface_model->brush.shadowmesh) ? 0 : 2;
2821 if (rsurface_mode != RSURFMODE_GLSL)
2823 rsurface_mode = RSURFMODE_GLSL;
2824 rsurface_glsl_texture = NULL;
2825 rsurface_glsl_uselightmap = false;
2826 R_Mesh_ResetTextureState();
2828 if (rsurface_glsl_texture != rsurface_texture || rsurface_glsl_uselightmap != (rsurface_lightmaptexture != NULL))
2830 rsurface_glsl_texture = rsurface_texture;
2831 rsurface_glsl_uselightmap = rsurface_lightmaptexture != NULL;
2832 GL_BlendFunc(rsurface_texture->currentlayers[0].blendfunc1, rsurface_texture->currentlayers[0].blendfunc2);
2833 GL_DepthMask(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_BLENDED));
2834 GL_Color(rsurface_entity->colormod[0], rsurface_entity->colormod[1], rsurface_entity->colormod[2], rsurface_texture->currentalpha);
2835 R_SetupSurfaceShader(vec3_origin, lightmode == 2);
2836 //permutation_deluxemapping = permutation_lightmapping = R_SetupSurfaceShader(vec3_origin, lightmode == 2, false);
2837 //if (r_glsl_deluxemapping.integer)
2838 // permutation_deluxemapping = R_SetupSurfaceShader(vec3_origin, lightmode == 2, true);
2839 R_Mesh_TexCoordPointer(0, 2, rsurface_model->surfmesh.data_texcoordtexture2f);
2840 R_Mesh_TexCoordPointer(4, 2, rsurface_model->surfmesh.data_texcoordlightmap2f);
2841 GL_AlphaTest((rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2843 if (!r_glsl_permutation)
2845 RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
2846 R_Mesh_TexCoordPointer(1, 3, rsurface_svector3f);
2847 R_Mesh_TexCoordPointer(2, 3, rsurface_tvector3f);
2848 R_Mesh_TexCoordPointer(3, 3, rsurface_normal3f);
2849 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2851 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
2852 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
2853 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
2854 R_Mesh_ColorPointer(NULL);
2856 else if (rsurface_lightmaptexture)
2858 R_Mesh_TexBind(7, R_GetTexture(rsurface_lightmaptexture));
2859 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
2860 R_Mesh_TexBind(8, R_GetTexture(texturesurfacelist[0]->deluxemaptexture));
2861 R_Mesh_ColorPointer(NULL);
2865 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
2866 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
2867 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
2868 R_Mesh_ColorPointer(rsurface_model->surfmesh.data_lightmapcolor4f);
2870 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
2873 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, msurface_t **texturesurfacelist)
2875 // OpenGL 1.3 path - anything not completely ancient
2876 int texturesurfaceindex;
2878 qboolean applycolor;
2882 const texturelayer_t *layer;
2884 // FIXME: identify models using a better check than rsurface_model->brush.shadowmesh
2885 lightmode = ((rsurface_entity->effects & EF_FULLBRIGHT) || rsurface_model->brush.shadowmesh) ? 0 : 2;
2886 if (rsurface_mode != RSURFMODE_MULTIPASS)
2887 rsurface_mode = RSURFMODE_MULTIPASS;
2888 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
2889 for (layerindex = 0, layer = rsurface_texture->currentlayers;layerindex < rsurface_texture->currentnumlayers;layerindex++, layer++)
2892 int layertexrgbscale;
2893 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2895 if (layerindex == 0)
2899 GL_AlphaTest(false);
2900 qglDepthFunc(GL_EQUAL);CHECKGLERROR
2903 GL_DepthMask(layer->depthmask);
2904 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
2905 if ((layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2) && (gl_combine.integer || layer->depthmask))
2907 layertexrgbscale = 4;
2908 VectorScale(layer->color, 0.25f, layercolor);
2910 else if ((layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1) && (gl_combine.integer || layer->depthmask))
2912 layertexrgbscale = 2;
2913 VectorScale(layer->color, 0.5f, layercolor);
2917 layertexrgbscale = 1;
2918 VectorScale(layer->color, 1.0f, layercolor);
2920 layercolor[3] = layer->color[3];
2921 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
2922 R_Mesh_ColorPointer(NULL);
2923 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
2924 switch (layer->type)
2926 case TEXTURELAYERTYPE_LITTEXTURE:
2927 memset(&m, 0, sizeof(m));
2928 if (lightmode >= 1 || !rsurface_lightmaptexture)
2929 m.tex[0] = R_GetTexture(r_texture_white);
2931 m.tex[0] = R_GetTexture(rsurface_lightmaptexture);
2932 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordlightmap2f;
2933 m.tex[1] = R_GetTexture(layer->texture);
2934 m.texmatrix[1] = layer->texmatrix;
2935 m.texrgbscale[1] = layertexrgbscale;
2936 m.pointer_texcoord[1] = rsurface_model->surfmesh.data_texcoordtexture2f;
2937 R_Mesh_TextureState(&m);
2938 RSurf_DrawBatch_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], lightmode, applycolor, applyfog);
2940 case TEXTURELAYERTYPE_TEXTURE:
2941 memset(&m, 0, sizeof(m));
2942 m.tex[0] = R_GetTexture(layer->texture);
2943 m.texmatrix[0] = layer->texmatrix;
2944 m.texrgbscale[0] = layertexrgbscale;
2945 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
2946 R_Mesh_TextureState(&m);
2947 RSurf_DrawBatch_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, applyfog);
2949 case TEXTURELAYERTYPE_FOG:
2950 memset(&m, 0, sizeof(m));
2951 m.texrgbscale[0] = layertexrgbscale;
2954 m.tex[0] = R_GetTexture(layer->texture);
2955 m.texmatrix[0] = layer->texmatrix;
2956 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
2958 R_Mesh_TextureState(&m);
2959 // generate a color array for the fog pass
2960 R_Mesh_ColorPointer(rsurface_array_color4f);
2961 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2965 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2966 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)
2968 f = VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
2969 c[0] = layercolor[0];
2970 c[1] = layercolor[1];
2971 c[2] = layercolor[2];
2972 c[3] = f * layercolor[3];
2975 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
2978 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
2980 GL_LockArrays(0, 0);
2983 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2985 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
2986 GL_AlphaTest(false);
2990 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, msurface_t **texturesurfacelist)
2992 // OpenGL 1.1 - crusty old voodoo path
2993 int texturesurfaceindex;
2998 const texturelayer_t *layer;
3000 // FIXME: identify models using a better check than rsurface_model->brush.shadowmesh
3001 lightmode = ((rsurface_entity->effects & EF_FULLBRIGHT) || rsurface_model->brush.shadowmesh) ? 0 : 2;
3002 if (rsurface_mode != RSURFMODE_MULTIPASS)
3003 rsurface_mode = RSURFMODE_MULTIPASS;
3004 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
3005 for (layerindex = 0, layer = rsurface_texture->currentlayers;layerindex < rsurface_texture->currentnumlayers;layerindex++, layer++)
3007 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
3009 if (layerindex == 0)
3013 GL_AlphaTest(false);
3014 qglDepthFunc(GL_EQUAL);CHECKGLERROR
3017 GL_DepthMask(layer->depthmask);
3018 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
3019 R_Mesh_ColorPointer(NULL);
3020 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
3021 switch (layer->type)
3023 case TEXTURELAYERTYPE_LITTEXTURE:
3024 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
3026 // two-pass lit texture with 2x rgbscale
3027 // first the lightmap pass
3028 memset(&m, 0, sizeof(m));
3029 if (lightmode >= 1 || !rsurface_lightmaptexture)
3030 m.tex[0] = R_GetTexture(r_texture_white);
3032 m.tex[0] = R_GetTexture(rsurface_lightmaptexture);
3033 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordlightmap2f;
3034 R_Mesh_TextureState(&m);
3035 RSurf_DrawBatch_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, lightmode, false, false);
3036 GL_LockArrays(0, 0);
3037 // then apply the texture to it
3038 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
3039 memset(&m, 0, sizeof(m));
3040 m.tex[0] = R_GetTexture(layer->texture);
3041 m.texmatrix[0] = layer->texmatrix;
3042 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3043 R_Mesh_TextureState(&m);
3044 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);
3048 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
3049 memset(&m, 0, sizeof(m));
3050 m.tex[0] = R_GetTexture(layer->texture);
3051 m.texmatrix[0] = layer->texmatrix;
3052 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3053 R_Mesh_TextureState(&m);
3054 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);
3057 case TEXTURELAYERTYPE_TEXTURE:
3058 // singletexture unlit texture with transparency support
3059 memset(&m, 0, sizeof(m));
3060 m.tex[0] = R_GetTexture(layer->texture);
3061 m.texmatrix[0] = layer->texmatrix;
3062 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3063 R_Mesh_TextureState(&m);
3064 RSurf_DrawBatch_Lightmap(texturenumsurfaces, texturesurfacelist, layer->color[0], 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);
3066 case TEXTURELAYERTYPE_FOG:
3067 // singletexture fogging
3068 R_Mesh_ColorPointer(rsurface_array_color4f);
3071 memset(&m, 0, sizeof(m));
3072 m.tex[0] = R_GetTexture(layer->texture);
3073 m.texmatrix[0] = layer->texmatrix;
3074 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3075 R_Mesh_TextureState(&m);
3078 R_Mesh_ResetTextureState();
3079 // generate a color array for the fog pass
3080 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3084 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3085 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)
3087 f = VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
3088 c[0] = layer->color[0];
3089 c[1] = layer->color[1];
3090 c[2] = layer->color[2];
3091 c[3] = f * layer->color[3];
3094 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3097 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
3099 GL_LockArrays(0, 0);
3102 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
3104 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3105 GL_AlphaTest(false);
3109 static void R_DrawTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist)
3111 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_NODRAW)
3113 r_shadow_rtlight = NULL;
3114 r_refdef.stats.entities_surfaces += texturenumsurfaces;
3116 GL_DepthTest(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
3117 if ((rsurface_texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (rsurface_entity->flags & RENDER_NOCULLFACE))
3119 qglDisable(GL_CULL_FACE);CHECKGLERROR
3121 if (r_showsurfaces.integer)
3122 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
3123 else if (rsurface_texture->currentmaterialflags & MATERIALFLAG_SKY)
3124 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
3125 else if (rsurface_texture->currentnumlayers)
3127 if (r_glsl.integer && gl_support_fragment_shader)
3128 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist);
3129 else if (gl_combine.integer && r_textureunits.integer >= 2)
3130 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist);
3132 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist);
3135 GL_LockArrays(0, 0);
3136 if ((rsurface_texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (rsurface_entity->flags & RENDER_NOCULLFACE))
3138 qglEnable(GL_CULL_FACE);CHECKGLERROR
3142 #define BATCHSIZE 256
3143 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
3145 int surfacelistindex;
3148 msurface_t *texturesurfacelist[BATCHSIZE];
3149 // if the model is static it doesn't matter what value we give for
3150 // wantnormals and wanttangents, so this logic uses only rules applicable
3151 // to a model, knowing that they are meaningless otherwise
3152 if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
3153 RSurf_ActiveEntity(ent, false, false);
3155 RSurf_ActiveEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
3158 for (surfacelistindex = 0;surfacelistindex < numsurfaces;surfacelistindex++)
3160 msurface_t *surface = ent->model->data_surfaces + surfacelist[surfacelistindex];
3162 if (t != surface->texture || rsurface_lightmaptexture != surface->lightmaptexture)
3165 R_DrawTextureSurfaceList(batchcount, texturesurfacelist);
3167 t = surface->texture;
3168 rsurface_lightmaptexture = surface->lightmaptexture;
3169 R_UpdateTextureInfo(ent, t);
3170 rsurface_texture = t->currentframe;
3172 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_SKY)
3173 continue; // transparent sky is too difficult
3175 texturesurfacelist[batchcount++] = surface;
3178 R_DrawTextureSurfaceList(batchcount, texturesurfacelist);
3182 void R_QueueTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist)
3184 int texturesurfaceindex;
3185 vec3_t tempcenter, center;
3186 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_BLENDED)
3188 // drawing sky transparently would be too difficult
3189 if (!(rsurface_texture->currentmaterialflags & MATERIALFLAG_SKY))
3191 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3193 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3194 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
3195 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
3196 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
3197 Matrix4x4_Transform(&rsurface_entity->matrix, tempcenter, center);
3198 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);
3203 R_DrawTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
3206 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
3207 void R_DrawSurfaces(entity_render_t *ent, qboolean skysurfaces)
3209 int i, j, f, flagsmask;
3210 int counttriangles = 0;
3212 model_t *model = ent->model;
3213 const int maxsurfacelist = 1024;
3214 int numsurfacelist = 0;
3215 msurface_t *surfacelist[1024];
3219 // if the model is static it doesn't matter what value we give for
3220 // wantnormals and wanttangents, so this logic uses only rules applicable
3221 // to a model, knowing that they are meaningless otherwise
3222 if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
3223 RSurf_ActiveEntity(ent, false, false);
3225 RSurf_ActiveEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
3227 // update light styles
3228 if (!skysurfaces && model->brushq1.light_styleupdatechains)
3230 msurface_t *surface, **surfacechain;
3231 for (i = 0;i < model->brushq1.light_styles;i++)
3233 if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
3235 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
3236 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
3237 for (;(surface = *surfacechain);surfacechain++)
3238 surface->cached_dlight = true;
3243 R_UpdateAllTextureInfo(ent);
3244 flagsmask = skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL);
3247 rsurface_lightmaptexture = NULL;
3248 rsurface_texture = NULL;
3250 if (ent == r_refdef.worldentity)
3252 msurface_t *surface;
3253 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
3255 if (!r_viewcache.world_surfacevisible[j])
3257 if (t != surface->texture || rsurface_lightmaptexture != surface->lightmaptexture)
3261 R_QueueTextureSurfaceList(numsurfacelist, surfacelist);
3264 t = surface->texture;
3265 rsurface_lightmaptexture = surface->lightmaptexture;
3266 rsurface_texture = t->currentframe;
3267 f = rsurface_texture->currentmaterialflags & flagsmask;
3269 if (f && surface->num_triangles)
3271 // if lightmap parameters changed, rebuild lightmap texture
3272 if (surface->cached_dlight)
3273 R_BuildLightMap(ent, surface);
3274 // add face to draw list
3275 surfacelist[numsurfacelist++] = surface;
3276 counttriangles += surface->num_triangles;
3277 if (numsurfacelist >= maxsurfacelist)
3279 R_QueueTextureSurfaceList(numsurfacelist, surfacelist);
3287 msurface_t *surface;
3288 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
3290 if (t != surface->texture || rsurface_lightmaptexture != surface->lightmaptexture)
3294 R_QueueTextureSurfaceList(numsurfacelist, surfacelist);
3297 t = surface->texture;
3298 rsurface_lightmaptexture = surface->lightmaptexture;
3299 rsurface_texture = t->currentframe;
3300 f = rsurface_texture->currentmaterialflags & flagsmask;
3302 if (f && surface->num_triangles)
3304 // if lightmap parameters changed, rebuild lightmap texture
3305 if (surface->cached_dlight)
3306 R_BuildLightMap(ent, surface);
3307 // add face to draw list
3308 surfacelist[numsurfacelist++] = surface;
3309 counttriangles += surface->num_triangles;
3310 if (numsurfacelist >= maxsurfacelist)
3312 R_QueueTextureSurfaceList(numsurfacelist, surfacelist);
3319 R_QueueTextureSurfaceList(numsurfacelist, surfacelist);
3320 r_refdef.stats.entities_triangles += counttriangles;
3323 if (r_showcollisionbrushes.integer && model->brush.num_brushes && !skysurfaces)
3326 const msurface_t *surface;
3329 R_Mesh_Matrix(&ent->matrix);
3330 R_Mesh_ColorPointer(NULL);
3331 R_Mesh_ResetTextureState();
3332 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
3333 GL_DepthMask(false);
3334 GL_DepthTest(!r_showdisabledepthtest.integer);
3335 qglPolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);CHECKGLERROR
3336 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
3337 if (brush->colbrushf && brush->colbrushf->numtriangles)
3338 R_DrawCollisionBrush(brush->colbrushf);
3339 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
3340 if (surface->num_collisiontriangles)
3341 R_DrawCollisionSurface(ent, surface);
3342 qglPolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR
3345 if (r_showtris.integer || r_shownormals.integer)
3348 msurface_t *surface;
3349 const int *elements;
3354 if (r_showdisabledepthtest.integer)
3356 qglDepthFunc(GL_ALWAYS);CHECKGLERROR
3358 GL_BlendFunc(GL_ONE, GL_ZERO);
3359 R_Mesh_ColorPointer(NULL);
3360 R_Mesh_ResetTextureState();
3361 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
3363 if (ent == r_refdef.worldentity && !r_viewcache.world_surfacevisible[j])
3365 rsurface_texture = surface->texture->currentframe;
3366 if ((rsurface_texture->currentmaterialflags & flagsmask) && surface->num_triangles)
3368 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
3369 if (r_showtris.integer)
3371 if (!rsurface_texture->currentlayers->depthmask)
3372 GL_Color(r_showtris.value, 0, 0, 1);
3373 else if (ent == r_refdef.worldentity)
3374 GL_Color(r_showtris.value, r_showtris.value, r_showtris.value, 1);
3376 GL_Color(0, r_showtris.value, 0, 1);
3377 elements = (ent->model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
3380 for (k = 0;k < surface->num_triangles;k++, elements += 3)
3382 qglArrayElement(elements[0]);qglArrayElement(elements[1]);
3383 qglArrayElement(elements[1]);qglArrayElement(elements[2]);
3384 qglArrayElement(elements[2]);qglArrayElement(elements[0]);
3389 if (r_shownormals.integer)
3391 GL_Color(r_shownormals.value, 0, 0, 1);
3393 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
3395 VectorCopy(rsurface_vertex3f + l * 3, v);
3396 qglVertex3f(v[0], v[1], v[2]);
3397 VectorMA(v, 8, rsurface_svector3f + l * 3, v);
3398 qglVertex3f(v[0], v[1], v[2]);
3402 GL_Color(0, 0, r_shownormals.value, 1);
3404 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
3406 VectorCopy(rsurface_vertex3f + l * 3, v);
3407 qglVertex3f(v[0], v[1], v[2]);
3408 VectorMA(v, 8, rsurface_tvector3f + l * 3, v);
3409 qglVertex3f(v[0], v[1], v[2]);
3413 GL_Color(0, r_shownormals.value, 0, 1);
3415 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
3417 VectorCopy(rsurface_vertex3f + l * 3, v);
3418 qglVertex3f(v[0], v[1], v[2]);
3419 VectorMA(v, 8, rsurface_normal3f + l * 3, v);
3420 qglVertex3f(v[0], v[1], v[2]);
3427 rsurface_texture = NULL;
3428 if (r_showdisabledepthtest.integer)
3430 qglDepthFunc(GL_LEQUAL);CHECKGLERROR