2 Copyright (C) 1996-1997 Id Software, Inc.
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26 mempool_t *r_main_mempool;
27 rtexturepool_t *r_main_texturepool;
34 r_viewcache_t r_viewcache;
36 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
37 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "shows surfaces as different colors"};
38 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
39 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
40 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
41 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
42 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
43 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
44 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
45 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
46 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
47 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
48 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
49 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
50 cvar_t r_fullbright = {0, "r_fullbright","0", "make everything bright cheat (not allowed in multiplayer)"};
51 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
52 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
53 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
54 cvar_t r_q1bsp_skymasking = {0, "r_qb1sp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
56 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
57 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
58 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
59 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
60 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
61 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
62 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
64 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of hardware texture units reported by driver (note: setting this to 1 turns off gl_combine)"};
66 cvar_t r_glsl = {0, "r_glsl", "1", "enables use of OpenGL 2.0 pixel shaders for lighting"};
67 cvar_t r_glsl_offsetmapping = {0, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
68 cvar_t r_glsl_offsetmapping_reliefmapping = {0, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
69 cvar_t r_glsl_offsetmapping_scale = {0, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
70 cvar_t r_glsl_deluxemapping = {0, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"};
72 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1", "enables animation smoothing on sprites (requires r_lerpmodels 1)"};
73 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
74 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
76 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
77 cvar_t r_bloom_intensity = {CVAR_SAVE, "r_bloom_intensity", "1.5", "how bright the glow is"};
78 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
79 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
80 cvar_t r_bloom_power = {CVAR_SAVE, "r_bloom_power", "2", "how much to darken the image before blurring to make the bloom effect"};
82 cvar_t r_smoothnormals_areaweighting = {0, "r_smoothnormals_areaweighting", "1", "uses significantly faster (and supposedly higher quality) area-weighted vertex normals and tangent vectors rather than summing normalized triangle normals and tangents"};
84 cvar_t developer_texturelogging = {0, "developer_texturelogging", "0", "produces a textures.log file containing names of skins and map textures the engine tried to load"};
86 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
88 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"}; // used for testing renderer code changes, otherwise does nothing
89 cvar_t r_batchmode = {0, "r_batchmode", "1", "selects method of rendering multiple surfaces with one driver call (values are 0, 1, 2, etc...)"};
91 rtexture_t *r_bloom_texture_screen;
92 rtexture_t *r_bloom_texture_bloom;
93 rtexture_t *r_texture_blanknormalmap;
94 rtexture_t *r_texture_white;
95 rtexture_t *r_texture_black;
96 rtexture_t *r_texture_notexture;
97 rtexture_t *r_texture_whitecube;
98 rtexture_t *r_texture_normalizationcube;
99 rtexture_t *r_texture_fogattenuation;
100 //rtexture_t *r_texture_fogintensity;
102 // information about each possible shader permutation
103 r_glsl_permutation_t r_glsl_permutations[SHADERPERMUTATION_COUNT];
104 // currently selected permutation
105 r_glsl_permutation_t *r_glsl_permutation;
107 // temporary variable used by a macro
110 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
113 for (i = 0;i < verts;i++)
124 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
127 for (i = 0;i < verts;i++)
137 // FIXME: move this to client?
140 if (gamemode == GAME_NEHAHRA)
142 Cvar_Set("gl_fogenable", "0");
143 Cvar_Set("gl_fogdensity", "0.2");
144 Cvar_Set("gl_fogred", "0.3");
145 Cvar_Set("gl_foggreen", "0.3");
146 Cvar_Set("gl_fogblue", "0.3");
148 r_refdef.fog_density = r_refdef.fog_red = r_refdef.fog_green = r_refdef.fog_blue = 0.0f;
151 // FIXME: move this to client?
152 void FOG_registercvars(void)
157 if (gamemode == GAME_NEHAHRA)
159 Cvar_RegisterVariable (&gl_fogenable);
160 Cvar_RegisterVariable (&gl_fogdensity);
161 Cvar_RegisterVariable (&gl_fogred);
162 Cvar_RegisterVariable (&gl_foggreen);
163 Cvar_RegisterVariable (&gl_fogblue);
164 Cvar_RegisterVariable (&gl_fogstart);
165 Cvar_RegisterVariable (&gl_fogend);
168 r = (-1.0/256.0) * (FOGTABLEWIDTH * FOGTABLEWIDTH);
169 for (x = 0;x < FOGTABLEWIDTH;x++)
171 alpha = exp(r / ((double)x*(double)x));
172 if (x == FOGTABLEWIDTH - 1)
174 r_refdef.fogtable[x] = bound(0, alpha, 1);
178 static void R_BuildBlankTextures(void)
180 unsigned char data[4];
181 data[0] = 128; // normal X
182 data[1] = 128; // normal Y
183 data[2] = 255; // normal Z
184 data[3] = 128; // height
185 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
190 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
195 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
198 static void R_BuildNoTexture(void)
201 unsigned char pix[16][16][4];
202 // this makes a light grey/dark grey checkerboard texture
203 for (y = 0;y < 16;y++)
205 for (x = 0;x < 16;x++)
207 if ((y < 8) ^ (x < 8))
223 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_RGBA, TEXF_MIPMAP, NULL);
226 static void R_BuildWhiteCube(void)
228 unsigned char data[6*1*1*4];
229 data[ 0] = 255;data[ 1] = 255;data[ 2] = 255;data[ 3] = 255;
230 data[ 4] = 255;data[ 5] = 255;data[ 6] = 255;data[ 7] = 255;
231 data[ 8] = 255;data[ 9] = 255;data[10] = 255;data[11] = 255;
232 data[12] = 255;data[13] = 255;data[14] = 255;data[15] = 255;
233 data[16] = 255;data[17] = 255;data[18] = 255;data[19] = 255;
234 data[20] = 255;data[21] = 255;data[22] = 255;data[23] = 255;
235 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
238 static void R_BuildNormalizationCube(void)
242 vec_t s, t, intensity;
244 unsigned char data[6][NORMSIZE][NORMSIZE][4];
245 for (side = 0;side < 6;side++)
247 for (y = 0;y < NORMSIZE;y++)
249 for (x = 0;x < NORMSIZE;x++)
251 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
252 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
287 intensity = 127.0f / sqrt(DotProduct(v, v));
288 data[side][y][x][0] = (unsigned char)(128.0f + intensity * v[0]);
289 data[side][y][x][1] = (unsigned char)(128.0f + intensity * v[1]);
290 data[side][y][x][2] = (unsigned char)(128.0f + intensity * v[2]);
291 data[side][y][x][3] = 255;
295 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, &data[0][0][0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
298 static void R_BuildFogTexture(void)
303 unsigned char data1[FOGWIDTH][4];
304 //unsigned char data2[FOGWIDTH][4];
305 r = (-1.0/256.0) * (FOGWIDTH * FOGWIDTH);
306 for (x = 0;x < FOGWIDTH;x++)
308 alpha = exp(r / ((double)x*(double)x));
309 if (x == FOGWIDTH - 1)
311 b = (int)(256.0 * alpha);
312 b = bound(0, b, 255);
313 data1[x][0] = 255 - b;
314 data1[x][1] = 255 - b;
315 data1[x][2] = 255 - b;
322 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
323 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
326 static const char *builtinshaderstring =
327 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
328 "// written by Forest 'LordHavoc' Hale\n"
330 "// common definitions between vertex shader and fragment shader:\n"
332 "varying vec2 TexCoord;\n"
333 "varying vec2 TexCoordLightmap;\n"
335 "varying vec3 CubeVector;\n"
336 "varying vec3 LightVector;\n"
337 "varying vec3 EyeVector;\n"
339 "varying vec3 EyeVectorModelSpace;\n"
342 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
343 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
344 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
349 "// vertex shader specific:\n"
350 "#ifdef VERTEX_SHADER\n"
352 "uniform vec3 LightPosition;\n"
353 "uniform vec3 EyePosition;\n"
354 "uniform vec3 LightDir;\n"
356 "// TODO: get rid of tangentt (texcoord2) and use a crossproduct to regenerate it from tangents (texcoord1) and normal (texcoord3)\n"
360 " gl_FrontColor = gl_Color;\n"
361 " // copy the surface texcoord\n"
362 " TexCoord = vec2(gl_TextureMatrix[0] * gl_MultiTexCoord0);\n"
363 "#if !defined(MODE_LIGHTSOURCE) && !defined(MODE_LIGHTDIRECTION)\n"
364 " TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
367 "#ifdef MODE_LIGHTSOURCE\n"
368 " // transform vertex position into light attenuation/cubemap space\n"
369 " // (-1 to +1 across the light box)\n"
370 " CubeVector = vec3(gl_TextureMatrix[3] * gl_Vertex);\n"
372 " // transform unnormalized light direction into tangent space\n"
373 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
374 " // normalize it per pixel)\n"
375 " vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
376 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
377 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
378 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
381 "#ifdef MODE_LIGHTDIRECTION\n"
382 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
383 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
384 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
387 " // transform unnormalized eye direction into tangent space\n"
389 " vec3 EyeVectorModelSpace;\n"
391 " EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
392 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
393 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
394 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
396 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
397 " VectorS = gl_MultiTexCoord1.xyz;\n"
398 " VectorT = gl_MultiTexCoord2.xyz;\n"
399 " VectorR = gl_MultiTexCoord3.xyz;\n"
402 " // transform vertex to camera space, using ftransform to match non-VS\n"
404 " gl_Position = ftransform();\n"
407 "#endif // VERTEX_SHADER\n"
412 "// fragment shader specific:\n"
413 "#ifdef FRAGMENT_SHADER\n"
415 "uniform sampler2D Texture_Normal;\n"
416 "uniform sampler2D Texture_Color;\n"
417 "uniform sampler2D Texture_Gloss;\n"
418 "uniform samplerCube Texture_Cube;\n"
419 "uniform sampler2D Texture_FogMask;\n"
420 "uniform sampler2D Texture_Pants;\n"
421 "uniform sampler2D Texture_Shirt;\n"
422 "uniform sampler2D Texture_Lightmap;\n"
423 "uniform sampler2D Texture_Deluxemap;\n"
424 "uniform sampler2D Texture_Glow;\n"
426 "uniform vec3 LightColor;\n"
427 "uniform vec3 AmbientColor;\n"
428 "uniform vec3 DiffuseColor;\n"
429 "uniform vec3 SpecularColor;\n"
430 "uniform vec3 Color_Pants;\n"
431 "uniform vec3 Color_Shirt;\n"
432 "uniform vec3 FogColor;\n"
434 "uniform float OffsetMapping_Scale;\n"
435 "uniform float OffsetMapping_Bias;\n"
436 "uniform float FogRangeRecip;\n"
438 "uniform float AmbientScale;\n"
439 "uniform float DiffuseScale;\n"
440 "uniform float SpecularScale;\n"
441 "uniform float SpecularPower;\n"
445 " // apply offsetmapping\n"
446 "#ifdef USEOFFSETMAPPING\n"
447 " vec2 TexCoordOffset = TexCoord;\n"
448 "#define TexCoord TexCoordOffset\n"
450 " vec3 eyedir = vec3(normalize(EyeVector));\n"
451 " float depthbias = 1.0 - eyedir.z; // should this be a -?\n"
452 " depthbias = 1.0 - depthbias * depthbias;\n"
454 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
455 " // 14 sample relief mapping: linear search and then binary search\n"
456 " vec3 OffsetVector = vec3(EyeVector.xy * (1.0 / EyeVector.z) * depthbias * OffsetMapping_Scale * vec2(-0.1, 0.1), -0.1);\n"
457 " vec3 RT = vec3(TexCoord - OffsetVector.xy * 10.0, 1.0) + OffsetVector;\n"
458 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
459 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
460 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
461 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
462 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
463 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
464 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
465 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
466 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;OffsetVector *= 0.5;RT -= OffsetVector;\n"
467 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;OffsetVector *= 0.5;RT -= OffsetVector;\n"
468 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;OffsetVector *= 0.5;RT -= OffsetVector;\n"
469 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;OffsetVector *= 0.5;RT -= OffsetVector;\n"
470 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;OffsetVector *= 0.5;RT -= OffsetVector;\n"
471 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;OffsetVector *= 0.5;RT -= OffsetVector;\n"
472 " TexCoord = RT.xy;\n"
474 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
475 " vec2 OffsetVector = vec2((EyeVector.xy * (1.0 / EyeVector.z) * depthbias) * OffsetMapping_Scale * vec2(-0.333, 0.333));\n"
476 " //TexCoord += OffsetVector * 3.0;\n"
477 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
478 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
479 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
483 " // combine the diffuse textures (base, pants, shirt)\n"
484 " vec4 color = vec4(texture2D(Texture_Color, TexCoord));\n"
485 "#ifdef USECOLORMAPPING\n"
486 " color.rgb += vec3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + vec3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
492 "#ifdef MODE_LIGHTSOURCE\n"
495 " // get the surface normal and light normal\n"
496 " vec3 surfacenormal = normalize(vec3(texture2D(Texture_Normal, TexCoord)) - 0.5);\n"
497 " vec3 diffusenormal = vec3(normalize(LightVector));\n"
499 " // calculate directional shading\n"
500 " color.rgb *= (AmbientScale + DiffuseScale * max(dot(surfacenormal, diffusenormal), 0.0));\n"
501 "#ifdef USESPECULAR\n"
502 " vec3 specularnormal = vec3(normalize(diffusenormal + vec3(normalize(EyeVector))));\n"
503 " color.rgb += vec3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(max(dot(surfacenormal, specularnormal), 0.0), SpecularPower);\n"
506 "#ifdef USECUBEFILTER\n"
507 " // apply light cubemap filter\n"
508 " //color.rgb *= normalize(CubeVector) * 0.5 + 0.5;//vec3(textureCube(Texture_Cube, CubeVector));\n"
509 " color.rgb *= vec3(textureCube(Texture_Cube, CubeVector));\n"
512 " // apply light color\n"
513 " color.rgb *= LightColor;\n"
515 " // apply attenuation\n"
517 " // the attenuation is (1-(x*x+y*y+z*z)) which gives a large bright\n"
518 " // center and sharp falloff at the edge, this is about the most efficient\n"
519 " // we can get away with as far as providing illumination.\n"
521 " // pow(1-(x*x+y*y+z*z), 4) is far more realistic but needs large lights to\n"
522 " // provide significant illumination, large = slow = pain.\n"
523 " color.rgb *= max(1.0 - dot(CubeVector, CubeVector), 0.0);\n"
528 "#elif defined(MODE_LIGHTDIRECTION)\n"
529 " // directional model lighting\n"
531 " // get the surface normal and light normal\n"
532 " vec3 surfacenormal = normalize(vec3(texture2D(Texture_Normal, TexCoord)) - 0.5);\n"
533 " vec3 diffusenormal = vec3(normalize(LightVector));\n"
535 " // calculate directional shading\n"
536 " color.rgb *= AmbientColor + DiffuseColor * max(dot(surfacenormal, diffusenormal), 0.0);\n"
537 "#ifdef USESPECULAR\n"
538 " vec3 specularnormal = vec3(normalize(diffusenormal + vec3(normalize(EyeVector))));\n"
539 " color.rgb += vec3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(max(dot(surfacenormal, specularnormal), 0.0), SpecularPower);\n"
545 "#elif defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE)\n"
546 " // deluxemap lightmapping using light vectors in modelspace (evil q3map2)\n"
548 " // get the surface normal and light normal\n"
549 " vec3 surfacenormal = normalize(vec3(texture2D(Texture_Normal, TexCoord)) - 0.5);\n"
550 " vec3 diffusenormal_modelspace = vec3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - 0.5;\n"
551 " vec3 diffusenormal = normalize(vec3(dot(diffusenormal_modelspace, VectorS), dot(diffusenormal_modelspace, VectorT), dot(diffusenormal_modelspace, VectorR)));\n"
553 " // calculate directional shading\n"
554 " vec3 tempcolor = color.rgb * (DiffuseScale * max(dot(surfacenormal, diffusenormal), 0.0));\n"
555 "#ifdef USESPECULAR\n"
556 " vec3 specularnormal = vec3(normalize(diffusenormal + vec3(normalize(EyeVector))));\n"
557 " tempcolor += vec3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(max(dot(surfacenormal, specularnormal), 0.0), SpecularPower);\n"
560 " // apply lightmap color\n"
561 " color.rgb = tempcolor * vec3(texture2D(Texture_Lightmap, TexCoordLightmap)) + color.rgb * vec3(AmbientScale);\n"
566 "#elif defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
567 " // deluxemap lightmapping using light vectors in tangentspace\n"
569 " // get the surface normal and light normal\n"
570 " vec3 surfacenormal = normalize(vec3(texture2D(Texture_Normal, TexCoord)) - 0.5);\n"
571 " vec3 diffusenormal = normalize(vec3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - 0.5);\n"
573 " // calculate directional shading\n"
574 " vec3 tempcolor = color.rgb * (DiffuseScale * max(dot(surfacenormal, diffusenormal), 0.0));\n"
575 "#ifdef USESPECULAR\n"
576 " vec3 specularnormal = vec3(normalize(diffusenormal + vec3(normalize(EyeVector))));\n"
577 " tempcolor += vec3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(max(dot(surfacenormal, specularnormal), 0.0), SpecularPower);\n"
580 " // apply lightmap color\n"
581 " color.rgb = tempcolor * vec3(texture2D(Texture_Lightmap, TexCoordLightmap)) + color.rgb * vec3(AmbientScale);\n"
586 "#else // MODE none (lightmap)\n"
587 " // apply lightmap color\n"
588 " color.rgb *= vec3(texture2D(Texture_Lightmap, TexCoordLightmap)) * DiffuseScale + vec3(AmbientScale);\n"
591 " color *= gl_Color;\n"
594 " color.rgb += vec3(texture2D(Texture_Glow, TexCoord));\n"
599 " float fog = texture2D(Texture_FogMask, vec2(length(EyeVectorModelSpace)*FogRangeRecip, 0.0)).x;\n"
600 " color.rgb = color.rgb * fog + FogColor * (1.0 - fog);\n"
603 " gl_FragColor = color;\n"
606 "#endif // FRAGMENT_SHADER\n"
609 void R_GLSL_CompilePermutation(int permutation)
611 r_glsl_permutation_t *p = r_glsl_permutations + permutation;
612 int vertstrings_count;
613 int fragstrings_count;
615 const char *vertstrings_list[SHADERPERMUTATION_COUNT+1];
616 const char *fragstrings_list[SHADERPERMUTATION_COUNT+1];
617 char permutationname[256];
621 vertstrings_list[0] = "#define VERTEX_SHADER\n";
622 fragstrings_list[0] = "#define FRAGMENT_SHADER\n";
623 vertstrings_count = 1;
624 fragstrings_count = 1;
625 permutationname[0] = 0;
626 if (permutation & SHADERPERMUTATION_MODE_LIGHTSOURCE)
628 vertstrings_list[vertstrings_count++] = "#define MODE_LIGHTSOURCE\n";
629 fragstrings_list[fragstrings_count++] = "#define MODE_LIGHTSOURCE\n";
630 strlcat(permutationname, " lightsource", sizeof(permutationname));
632 if (permutation & SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_MODELSPACE)
634 vertstrings_list[vertstrings_count++] = "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n";
635 fragstrings_list[fragstrings_count++] = "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n";
636 strlcat(permutationname, " lightdirectionmap_modelspace", sizeof(permutationname));
638 if (permutation & SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)
640 vertstrings_list[vertstrings_count++] = "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n";
641 fragstrings_list[fragstrings_count++] = "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n";
642 strlcat(permutationname, " lightdirectionmap_tangentspace", sizeof(permutationname));
644 if (permutation & SHADERPERMUTATION_MODE_LIGHTDIRECTION)
646 vertstrings_list[vertstrings_count++] = "#define MODE_LIGHTDIRECTION\n";
647 fragstrings_list[fragstrings_count++] = "#define MODE_LIGHTDIRECTION\n";
648 strlcat(permutationname, " lightdirection", sizeof(permutationname));
650 if (permutation & SHADERPERMUTATION_GLOW)
652 vertstrings_list[vertstrings_count++] = "#define USEGLOW\n";
653 fragstrings_list[fragstrings_count++] = "#define USEGLOW\n";
654 strlcat(permutationname, " glow", sizeof(permutationname));
656 if (permutation & SHADERPERMUTATION_COLORMAPPING)
658 vertstrings_list[vertstrings_count++] = "#define USECOLORMAPPING\n";
659 fragstrings_list[fragstrings_count++] = "#define USECOLORMAPPING\n";
660 strlcat(permutationname, " colormapping", sizeof(permutationname));
662 if (permutation & SHADERPERMUTATION_SPECULAR)
664 vertstrings_list[vertstrings_count++] = "#define USESPECULAR\n";
665 fragstrings_list[fragstrings_count++] = "#define USESPECULAR\n";
666 strlcat(permutationname, " specular", sizeof(permutationname));
668 if (permutation & SHADERPERMUTATION_FOG)
670 vertstrings_list[vertstrings_count++] = "#define USEFOG\n";
671 fragstrings_list[fragstrings_count++] = "#define USEFOG\n";
672 strlcat(permutationname, " fog", sizeof(permutationname));
674 if (permutation & SHADERPERMUTATION_CUBEFILTER)
676 vertstrings_list[vertstrings_count++] = "#define USECUBEFILTER\n";
677 fragstrings_list[fragstrings_count++] = "#define USECUBEFILTER\n";
678 strlcat(permutationname, " cubefilter", sizeof(permutationname));
680 if (permutation & SHADERPERMUTATION_OFFSETMAPPING)
682 vertstrings_list[vertstrings_count++] = "#define USEOFFSETMAPPING\n";
683 fragstrings_list[fragstrings_count++] = "#define USEOFFSETMAPPING\n";
684 strlcat(permutationname, " offsetmapping", sizeof(permutationname));
686 if (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING)
688 vertstrings_list[vertstrings_count++] = "#define USEOFFSETMAPPING_RELIEFMAPPING\n";
689 fragstrings_list[fragstrings_count++] = "#define USEOFFSETMAPPING_RELIEFMAPPING\n";
690 strlcat(permutationname, " OFFSETMAPPING_RELIEFMAPPING", sizeof(permutationname));
692 shaderstring = (char *)FS_LoadFile("glsl/default.glsl", r_main_mempool, false, NULL);
695 Con_DPrintf("GLSL shader text loaded from disk\n");
696 vertstrings_list[vertstrings_count++] = shaderstring;
697 fragstrings_list[fragstrings_count++] = shaderstring;
701 vertstrings_list[vertstrings_count++] = builtinshaderstring;
702 fragstrings_list[fragstrings_count++] = builtinshaderstring;
704 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, fragstrings_count, fragstrings_list);
708 qglUseProgramObjectARB(p->program);CHECKGLERROR
709 p->loc_Texture_Normal = qglGetUniformLocationARB(p->program, "Texture_Normal");
710 p->loc_Texture_Color = qglGetUniformLocationARB(p->program, "Texture_Color");
711 p->loc_Texture_Gloss = qglGetUniformLocationARB(p->program, "Texture_Gloss");
712 p->loc_Texture_Cube = qglGetUniformLocationARB(p->program, "Texture_Cube");
713 p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
714 p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
715 p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
716 p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
717 p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
718 p->loc_Texture_Glow = qglGetUniformLocationARB(p->program, "Texture_Glow");
719 p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
720 p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
721 p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
722 p->loc_LightColor = qglGetUniformLocationARB(p->program, "LightColor");
723 p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants");
724 p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt");
725 p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip");
726 p->loc_AmbientScale = qglGetUniformLocationARB(p->program, "AmbientScale");
727 p->loc_DiffuseScale = qglGetUniformLocationARB(p->program, "DiffuseScale");
728 p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
729 p->loc_SpecularScale = qglGetUniformLocationARB(p->program, "SpecularScale");
730 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
731 p->loc_AmbientColor = qglGetUniformLocationARB(p->program, "AmbientColor");
732 p->loc_DiffuseColor = qglGetUniformLocationARB(p->program, "DiffuseColor");
733 p->loc_SpecularColor = qglGetUniformLocationARB(p->program, "SpecularColor");
734 p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
735 if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal, 0);
736 if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color, 1);
737 if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss, 2);
738 if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube, 3);
739 if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask, 4);
740 if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants, 5);
741 if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt, 6);
742 if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap, 7);
743 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap, 8);
744 if (p->loc_Texture_Glow >= 0) qglUniform1iARB(p->loc_Texture_Glow, 9);
746 qglUseProgramObjectARB(0);CHECKGLERROR
749 Con_Printf("permutation%s failed for shader %s, some features may not work properly!\n", permutationname, "glsl/default.glsl");
751 Mem_Free(shaderstring);
754 void R_GLSL_Restart_f(void)
757 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
758 if (r_glsl_permutations[i].program)
759 GL_Backend_FreeProgram(r_glsl_permutations[i].program);
760 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
763 int R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting)
765 // select a permutation of the lighting shader appropriate to this
766 // combination of texture, entity, light source, and fogging, only use the
767 // minimum features necessary to avoid wasting rendering time in the
768 // fragment shader on features that are not being used
770 float specularscale = rsurface_texture->specularscale;
771 r_glsl_permutation = NULL;
772 if (r_shadow_rtlight)
774 permutation |= SHADERPERMUTATION_MODE_LIGHTSOURCE;
775 specularscale *= r_shadow_rtlight->specularscale;
776 if (r_shadow_rtlight->currentcubemap != r_texture_whitecube)
777 permutation |= SHADERPERMUTATION_CUBEFILTER;
781 if (!(rsurface_texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
784 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTION;
787 if (r_glsl_deluxemapping.integer >= 1 && r_refdef.worldmodel && r_refdef.worldmodel->brushq3.deluxemapping && rsurface_lightmaptexture)
789 if (r_refdef.worldmodel->brushq3.deluxemapping_modelspace)
790 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_MODELSPACE;
792 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
794 else if (r_glsl_deluxemapping.integer >= 2) // fake mode
795 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
798 if (rsurface_texture->skin.glow)
799 permutation |= SHADERPERMUTATION_GLOW;
801 if (specularscale > 0)
802 permutation |= SHADERPERMUTATION_SPECULAR;
803 if (r_refdef.fogenabled)
804 permutation |= SHADERPERMUTATION_FOG;
805 if (rsurface_texture->colormapping)
806 permutation |= SHADERPERMUTATION_COLORMAPPING;
807 if (r_glsl_offsetmapping.integer)
809 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
810 if (r_glsl_offsetmapping_reliefmapping.integer)
811 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
813 if (!r_glsl_permutations[permutation].program)
815 if (!r_glsl_permutations[permutation].compiled)
816 R_GLSL_CompilePermutation(permutation);
817 if (!r_glsl_permutations[permutation].program)
819 // remove features until we find a valid permutation
821 for (i = SHADERPERMUTATION_COUNT-1;;i>>=1)
823 // reduce i more quickly whenever it would not remove any bits
827 if (!r_glsl_permutations[permutation].compiled)
828 R_GLSL_CompilePermutation(permutation);
829 if (r_glsl_permutations[permutation].program)
832 return 0; // utterly failed
836 r_glsl_permutation = r_glsl_permutations + permutation;
838 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
839 R_Mesh_TexMatrix(0, &rsurface_texture->currenttexmatrix);
840 if (permutation & SHADERPERMUTATION_MODE_LIGHTSOURCE)
842 if (r_glsl_permutation->loc_Texture_Cube >= 0 && r_shadow_rtlight) R_Mesh_TexBindCubeMap(3, R_GetTexture(r_shadow_rtlight->currentcubemap));
843 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, r_shadow_entitylightorigin[0], r_shadow_entitylightorigin[1], r_shadow_entitylightorigin[2]);
844 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
845 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_shadow_rtlight->ambientscale);
846 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_shadow_rtlight->diffusescale);
847 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, specularscale);
849 else if (permutation & SHADERPERMUTATION_MODE_LIGHTDIRECTION)
851 if (r_glsl_permutation->loc_AmbientColor >= 0)
852 qglUniform3fARB(r_glsl_permutation->loc_AmbientColor, rsurface_entity->modellight_ambient[0], rsurface_entity->modellight_ambient[1], rsurface_entity->modellight_ambient[2]);
853 if (r_glsl_permutation->loc_DiffuseColor >= 0)
854 qglUniform3fARB(r_glsl_permutation->loc_DiffuseColor, rsurface_entity->modellight_diffuse[0], rsurface_entity->modellight_diffuse[1], rsurface_entity->modellight_diffuse[2]);
855 if (r_glsl_permutation->loc_SpecularColor >= 0)
856 qglUniform3fARB(r_glsl_permutation->loc_SpecularColor, rsurface_entity->modellight_diffuse[0] * rsurface_texture->specularscale, rsurface_entity->modellight_diffuse[1] * rsurface_texture->specularscale, rsurface_entity->modellight_diffuse[2] * rsurface_texture->specularscale);
857 if (r_glsl_permutation->loc_LightDir >= 0)
858 qglUniform3fARB(r_glsl_permutation->loc_LightDir, rsurface_entity->modellight_lightdir[0], rsurface_entity->modellight_lightdir[1], rsurface_entity->modellight_lightdir[2]);
862 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_ambient.value * 2.0f / 128.0f);
863 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_refdef.lightmapintensity * 2.0f);
864 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, r_refdef.lightmapintensity * specularscale * 2.0f);
866 if (r_glsl_permutation->loc_Texture_Normal >= 0) R_Mesh_TexBind(0, R_GetTexture(rsurface_texture->skin.nmap));
867 if (r_glsl_permutation->loc_Texture_Color >= 0) R_Mesh_TexBind(1, R_GetTexture(rsurface_texture->basetexture));
868 if (r_glsl_permutation->loc_Texture_Gloss >= 0) R_Mesh_TexBind(2, R_GetTexture(rsurface_texture->glosstexture));
869 //if (r_glsl_permutation->loc_Texture_Cube >= 0 && permutation & SHADERPERMUTATION_MODE_LIGHTSOURCE) R_Mesh_TexBindCubeMap(3, R_GetTexture(r_shadow_rtlight->currentcubemap));
870 if (r_glsl_permutation->loc_Texture_FogMask >= 0) R_Mesh_TexBind(4, R_GetTexture(r_texture_fogattenuation));
871 if (r_glsl_permutation->loc_Texture_Pants >= 0) R_Mesh_TexBind(5, R_GetTexture(rsurface_texture->skin.pants));
872 if (r_glsl_permutation->loc_Texture_Shirt >= 0) R_Mesh_TexBind(6, R_GetTexture(rsurface_texture->skin.shirt));
873 //if (r_glsl_permutation->loc_Texture_Lightmap >= 0) R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
874 //if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
875 if (r_glsl_permutation->loc_Texture_Glow >= 0) R_Mesh_TexBind(9, R_GetTexture(rsurface_texture->skin.glow));
876 if (r_glsl_permutation->loc_FogColor >= 0)
878 // additive passes are only darkened by fog, not tinted
879 if (r_shadow_rtlight || (rsurface_texture->currentmaterialflags & MATERIALFLAG_ADD))
880 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
882 qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
884 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface_modelorg[0], rsurface_modelorg[1], rsurface_modelorg[2]);
885 if (r_glsl_permutation->loc_Color_Pants >= 0)
887 if (rsurface_texture->skin.pants)
888 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface_entity->colormap_pantscolor[0], rsurface_entity->colormap_pantscolor[1], rsurface_entity->colormap_pantscolor[2]);
890 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
892 if (r_glsl_permutation->loc_Color_Shirt >= 0)
894 if (rsurface_texture->skin.shirt)
895 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface_entity->colormap_shirtcolor[0], rsurface_entity->colormap_shirtcolor[1], rsurface_entity->colormap_shirtcolor[2]);
897 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
899 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, r_refdef.fograngerecip);
900 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface_texture->specularpower);
901 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
906 void R_SwitchSurfaceShader(int permutation)
908 if (r_glsl_permutation != r_glsl_permutations + permutation)
910 r_glsl_permutation = r_glsl_permutations + permutation;
912 qglUseProgramObjectARB(r_glsl_permutation->program);
917 void gl_main_start(void)
919 r_main_texturepool = R_AllocTexturePool();
920 r_bloom_texture_screen = NULL;
921 r_bloom_texture_bloom = NULL;
922 R_BuildBlankTextures();
924 if (gl_texturecubemap)
927 R_BuildNormalizationCube();
930 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
933 void gl_main_shutdown(void)
935 R_FreeTexturePool(&r_main_texturepool);
936 r_bloom_texture_screen = NULL;
937 r_bloom_texture_bloom = NULL;
938 r_texture_blanknormalmap = NULL;
939 r_texture_white = NULL;
940 r_texture_black = NULL;
941 r_texture_whitecube = NULL;
942 r_texture_normalizationcube = NULL;
946 extern void CL_ParseEntityLump(char *entitystring);
947 void gl_main_newmap(void)
949 // FIXME: move this code to client
951 char *entities, entname[MAX_QPATH];
954 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
955 l = (int)strlen(entname) - 4;
956 if (l >= 0 && !strcmp(entname + l, ".bsp"))
958 strcpy(entname + l, ".ent");
959 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
961 CL_ParseEntityLump(entities);
966 if (cl.worldmodel->brush.entities)
967 CL_ParseEntityLump(cl.worldmodel->brush.entities);
971 void GL_Main_Init(void)
973 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
975 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed\n");
976 FOG_registercvars(); // FIXME: move this fog stuff to client?
977 Cvar_RegisterVariable(&r_nearclip);
978 Cvar_RegisterVariable(&r_showsurfaces);
979 Cvar_RegisterVariable(&r_showtris);
980 Cvar_RegisterVariable(&r_shownormals);
981 Cvar_RegisterVariable(&r_showlighting);
982 Cvar_RegisterVariable(&r_showshadowvolumes);
983 Cvar_RegisterVariable(&r_showcollisionbrushes);
984 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
985 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
986 Cvar_RegisterVariable(&r_showdisabledepthtest);
987 Cvar_RegisterVariable(&r_drawportals);
988 Cvar_RegisterVariable(&r_drawentities);
989 Cvar_RegisterVariable(&r_drawviewmodel);
990 Cvar_RegisterVariable(&r_speeds);
991 Cvar_RegisterVariable(&r_fullbrights);
992 Cvar_RegisterVariable(&r_wateralpha);
993 Cvar_RegisterVariable(&r_dynamic);
994 Cvar_RegisterVariable(&r_fullbright);
995 Cvar_RegisterVariable(&r_q1bsp_skymasking);
996 Cvar_RegisterVariable(&r_textureunits);
997 Cvar_RegisterVariable(&r_glsl);
998 Cvar_RegisterVariable(&r_glsl_offsetmapping);
999 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
1000 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
1001 Cvar_RegisterVariable(&r_glsl_deluxemapping);
1002 Cvar_RegisterVariable(&r_lerpsprites);
1003 Cvar_RegisterVariable(&r_lerpmodels);
1004 Cvar_RegisterVariable(&r_waterscroll);
1005 Cvar_RegisterVariable(&r_bloom);
1006 Cvar_RegisterVariable(&r_bloom_intensity);
1007 Cvar_RegisterVariable(&r_bloom_blur);
1008 Cvar_RegisterVariable(&r_bloom_resolution);
1009 Cvar_RegisterVariable(&r_bloom_power);
1010 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
1011 Cvar_RegisterVariable(&developer_texturelogging);
1012 Cvar_RegisterVariable(&gl_lightmaps);
1013 Cvar_RegisterVariable(&r_test);
1014 Cvar_RegisterVariable(&r_batchmode);
1015 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
1016 Cvar_SetValue("r_fullbrights", 0);
1017 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
1020 extern void R_Textures_Init(void);
1021 extern void GL_Draw_Init(void);
1022 extern void GL_Main_Init(void);
1023 extern void R_Shadow_Init(void);
1024 extern void R_Sky_Init(void);
1025 extern void GL_Surf_Init(void);
1026 extern void R_Light_Init(void);
1027 extern void R_Particles_Init(void);
1028 extern void R_Explosion_Init(void);
1029 extern void gl_backend_init(void);
1030 extern void Sbar_Init(void);
1031 extern void R_LightningBeams_Init(void);
1032 extern void Mod_RenderInit(void);
1034 void Render_Init(void)
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 extern void R_DrawPortals (void);
1705 void R_RenderScene(void)
1707 // don't let sound skip if going slow
1708 if (r_refdef.extraupdate)
1712 if (gl_support_fragment_shader)
1714 qglUseProgramObjectARB(0);CHECKGLERROR
1716 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
1717 qglPolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR
1718 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
1720 R_MeshQueue_BeginScene();
1722 if (r_refdef.rtworldshadows || r_refdef.rtdlightshadows)
1723 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_view.frustum_x, r_view.frustum_y, r_refdef.nearclip);
1725 GL_SetupView_Mode_Perspective(r_view.frustum_x, r_view.frustum_y, r_refdef.nearclip, r_refdef.farclip);
1727 GL_SetupView_Orientation_FromEntity(&r_view.matrix);
1729 R_Shadow_UpdateWorldLightSelection();
1733 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);
1735 if (cl.csqc_vidvars.drawworld)
1737 // don't let sound skip if going slow
1738 if (r_refdef.extraupdate)
1741 if (r_refdef.worldmodel && r_refdef.worldmodel->DrawSky)
1743 r_refdef.worldmodel->DrawSky(r_refdef.worldentity);
1744 if (r_timereport_active)
1745 R_TimeReport("worldsky");
1748 if (R_DrawBrushModelsSky() && r_timereport_active)
1749 R_TimeReport("bmodelsky");
1751 if (r_refdef.worldmodel && r_refdef.worldmodel->Draw)
1753 r_refdef.worldmodel->Draw(r_refdef.worldentity);
1754 if (r_timereport_active)
1755 R_TimeReport("world");
1759 // don't let sound skip if going slow
1760 if (r_refdef.extraupdate)
1764 if (r_timereport_active)
1765 R_TimeReport("models");
1767 // don't let sound skip if going slow
1768 if (r_refdef.extraupdate)
1771 R_ShadowVolumeLighting(false);
1772 if (r_timereport_active)
1773 R_TimeReport("rtlights");
1775 // don't let sound skip if going slow
1776 if (r_refdef.extraupdate)
1779 if (cl.csqc_vidvars.drawworld)
1781 R_DrawLightningBeams();
1782 if (r_timereport_active)
1783 R_TimeReport("lightning");
1786 if (r_timereport_active)
1787 R_TimeReport("particles");
1790 if (r_timereport_active)
1791 R_TimeReport("explosions");
1794 if (gl_support_fragment_shader)
1796 qglUseProgramObjectARB(0);CHECKGLERROR
1798 VM_AddPolygonsToMeshQueue();
1800 if (r_drawportals.integer)
1803 if (r_timereport_active)
1804 R_TimeReport("portals");
1807 if (gl_support_fragment_shader)
1809 qglUseProgramObjectARB(0);CHECKGLERROR
1811 R_MeshQueue_RenderTransparent();
1812 if (r_timereport_active)
1813 R_TimeReport("drawtrans");
1815 if (gl_support_fragment_shader)
1817 qglUseProgramObjectARB(0);CHECKGLERROR
1820 if (cl.csqc_vidvars.drawworld)
1823 if (r_timereport_active)
1824 R_TimeReport("coronas");
1827 // don't let sound skip if going slow
1828 if (r_refdef.extraupdate)
1832 if (gl_support_fragment_shader)
1834 qglUseProgramObjectARB(0);CHECKGLERROR
1836 qglPolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR
1837 qglDisable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
1841 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
1844 float *v, *c, f1, f2, diff[3], vertex3f[8*3], color4f[8*4];
1845 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1846 GL_DepthMask(false);
1848 R_Mesh_Matrix(&identitymatrix);
1850 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2];
1851 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
1852 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
1853 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
1854 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
1855 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
1856 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
1857 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
1858 R_FillColors(color, 8, cr, cg, cb, ca);
1859 if (r_refdef.fogenabled)
1861 for (i = 0, v = vertex, c = color;i < 8;i++, v += 4, c += 4)
1863 f2 = VERTEXFOGTABLE(VectorDistance(v, r_view.origin));
1865 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
1866 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
1867 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
1870 R_Mesh_VertexPointer(vertex3f);
1871 R_Mesh_ColorPointer(color);
1872 R_Mesh_ResetTextureState();
1877 int nomodelelements[24] =
1889 float nomodelvertex3f[6*3] =
1899 float nomodelcolor4f[6*4] =
1901 0.0f, 0.0f, 0.5f, 1.0f,
1902 0.0f, 0.0f, 0.5f, 1.0f,
1903 0.0f, 0.5f, 0.0f, 1.0f,
1904 0.0f, 0.5f, 0.0f, 1.0f,
1905 0.5f, 0.0f, 0.0f, 1.0f,
1906 0.5f, 0.0f, 0.0f, 1.0f
1909 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
1914 // this is only called once per entity so numsurfaces is always 1, and
1915 // surfacelist is always {0}, so this code does not handle batches
1916 R_Mesh_Matrix(&ent->matrix);
1918 if (ent->flags & EF_ADDITIVE)
1920 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
1921 GL_DepthMask(false);
1923 else if (ent->alpha < 1)
1925 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1926 GL_DepthMask(false);
1930 GL_BlendFunc(GL_ONE, GL_ZERO);
1933 GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
1934 R_Mesh_VertexPointer(nomodelvertex3f);
1935 if (r_refdef.fogenabled)
1937 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
1938 R_Mesh_ColorPointer(color4f);
1939 f2 = VERTEXFOGTABLE(VectorDistance(ent->origin, r_view.origin));
1941 for (i = 0, c = color4f;i < 6;i++, c += 4)
1943 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
1944 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
1945 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
1949 else if (ent->alpha != 1)
1951 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
1952 R_Mesh_ColorPointer(color4f);
1953 for (i = 0, c = color4f;i < 6;i++, c += 4)
1957 R_Mesh_ColorPointer(nomodelcolor4f);
1958 R_Mesh_ResetTextureState();
1959 R_Mesh_Draw(0, 6, 8, nomodelelements);
1962 void R_DrawNoModel(entity_render_t *ent)
1964 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
1965 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_view.origin : ent->origin, R_DrawNoModel_TransparentCallback, ent, 0, r_shadow_rtlight);
1967 // R_DrawNoModelCallback(ent, 0);
1970 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
1972 vec3_t right1, right2, diff, normal;
1974 VectorSubtract (org2, org1, normal);
1976 // calculate 'right' vector for start
1977 VectorSubtract (r_view.origin, org1, diff);
1978 CrossProduct (normal, diff, right1);
1979 VectorNormalize (right1);
1981 // calculate 'right' vector for end
1982 VectorSubtract (r_view.origin, org2, diff);
1983 CrossProduct (normal, diff, right2);
1984 VectorNormalize (right2);
1986 vert[ 0] = org1[0] + width * right1[0];
1987 vert[ 1] = org1[1] + width * right1[1];
1988 vert[ 2] = org1[2] + width * right1[2];
1989 vert[ 3] = org1[0] - width * right1[0];
1990 vert[ 4] = org1[1] - width * right1[1];
1991 vert[ 5] = org1[2] - width * right1[2];
1992 vert[ 6] = org2[0] - width * right2[0];
1993 vert[ 7] = org2[1] - width * right2[1];
1994 vert[ 8] = org2[2] - width * right2[2];
1995 vert[ 9] = org2[0] + width * right2[0];
1996 vert[10] = org2[1] + width * right2[1];
1997 vert[11] = org2[2] + width * right2[2];
2000 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
2002 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)
2004 float fog = 0.0f, ifog;
2007 if (r_refdef.fogenabled)
2008 fog = VERTEXFOGTABLE(VectorDistance(origin, r_view.origin));
2011 R_Mesh_Matrix(&identitymatrix);
2012 GL_BlendFunc(blendfunc1, blendfunc2);
2013 GL_DepthMask(false);
2014 GL_DepthTest(!depthdisable);
2016 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
2017 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
2018 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
2019 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
2020 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
2021 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
2022 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
2023 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
2024 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
2025 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
2026 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
2027 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
2029 R_Mesh_VertexPointer(vertex3f);
2030 R_Mesh_ColorPointer(NULL);
2031 R_Mesh_ResetTextureState();
2032 R_Mesh_TexBind(0, R_GetTexture(texture));
2033 R_Mesh_TexCoordPointer(0, 2, spritetexcoord2f);
2034 GL_Color(cr * ifog, cg * ifog, cb * ifog, ca);
2035 R_Mesh_Draw(0, 4, 2, polygonelements);
2037 if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
2039 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
2040 GL_BlendFunc(blendfunc1, GL_ONE);
2041 GL_Color(r_refdef.fogcolor[0] * fog, r_refdef.fogcolor[1] * fog, r_refdef.fogcolor[2] * fog, ca);
2042 R_Mesh_Draw(0, 4, 2, polygonelements);
2046 int R_Mesh_AddVertex3f(rmesh_t *mesh, const float *v)
2050 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
2051 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
2053 if (i == mesh->numvertices)
2055 if (mesh->numvertices < mesh->maxvertices)
2057 VectorCopy(v, vertex3f);
2058 mesh->numvertices++;
2060 return mesh->numvertices;
2066 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
2070 element[0] = R_Mesh_AddVertex3f(mesh, vertex3f);vertex3f += 3;
2071 element[1] = R_Mesh_AddVertex3f(mesh, vertex3f);vertex3f += 3;
2072 e = mesh->element3i + mesh->numtriangles * 3;
2073 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
2075 element[2] = R_Mesh_AddVertex3f(mesh, vertex3f);
2076 if (mesh->numtriangles < mesh->maxtriangles)
2081 mesh->numtriangles++;
2083 element[1] = element[2];
2087 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
2089 int planenum, planenum2;
2092 mplane_t *plane, *plane2;
2093 float temppoints[2][256*3];
2094 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
2098 PolygonF_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->normal[3], 1024.0*1024.0*1024.0);
2099 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
2101 if (planenum2 == planenum)
2103 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);
2106 if (tempnumpoints < 3)
2108 // generate elements forming a triangle fan for this polygon
2109 R_Mesh_AddPolygon3f(mesh, tempnumpoints, temppoints[w]);
2113 static void R_DrawCollisionBrush(const colbrushf_t *brush)
2116 R_Mesh_VertexPointer(brush->points->v);
2117 i = (int)(((size_t)brush) / sizeof(colbrushf_t));
2118 GL_Color((i & 31) * (1.0f / 32.0f), ((i >> 5) & 31) * (1.0f / 32.0f), ((i >> 10) & 31) * (1.0f / 32.0f), 0.2f);
2119 GL_LockArrays(0, brush->numpoints);
2120 R_Mesh_Draw(0, brush->numpoints, brush->numtriangles, brush->elements);
2121 GL_LockArrays(0, 0);
2124 static void R_DrawCollisionSurface(const entity_render_t *ent, const msurface_t *surface)
2127 if (!surface->num_collisiontriangles)
2129 R_Mesh_VertexPointer(surface->data_collisionvertex3f);
2130 i = (int)(((size_t)surface) / sizeof(msurface_t));
2131 GL_Color((i & 31) * (1.0f / 32.0f), ((i >> 5) & 31) * (1.0f / 32.0f), ((i >> 10) & 31) * (1.0f / 32.0f), 0.2f);
2132 GL_LockArrays(0, surface->num_collisionvertices);
2133 R_Mesh_Draw(0, surface->num_collisionvertices, surface->num_collisiontriangles, surface->data_collisionelement3i);
2134 GL_LockArrays(0, 0);
2137 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)
2139 texturelayer_t *layer;
2140 layer = t->currentlayers + t->currentnumlayers++;
2142 layer->depthmask = depthmask;
2143 layer->blendfunc1 = blendfunc1;
2144 layer->blendfunc2 = blendfunc2;
2145 layer->texture = texture;
2146 layer->texmatrix = *matrix;
2147 layer->color[0] = r;
2148 layer->color[1] = g;
2149 layer->color[2] = b;
2150 layer->color[3] = a;
2153 void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
2155 // FIXME: identify models using a better check than ent->model->brush.shadowmesh
2156 //int lightmode = ((ent->effects & EF_FULLBRIGHT) || ent->model->brush.shadowmesh) ? 0 : 2;
2159 texture_t *texture = t;
2160 model_t *model = ent->model;
2161 int s = ent->skinnum;
2162 if ((unsigned int)s >= (unsigned int)model->numskins)
2164 if (model->skinscenes)
2166 if (model->skinscenes[s].framecount > 1)
2167 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
2169 s = model->skinscenes[s].firstframe;
2172 t = t + s * model->num_surfaces;
2175 // use an alternate animation if the entity's frame is not 0,
2176 // and only if the texture has an alternate animation
2177 if (ent->frame != 0 && t->anim_total[1])
2178 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.time * 5.0f) % t->anim_total[1]) : 0];
2180 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.time * 5.0f) % t->anim_total[0]) : 0];
2182 texture->currentframe = t;
2185 t->currentmaterialflags = t->basematerialflags;
2186 t->currentalpha = ent->alpha;
2187 if (t->basematerialflags & MATERIALFLAG_WATERALPHA)
2188 t->currentalpha *= r_wateralpha.value;
2189 if (!(ent->flags & RENDER_LIGHT))
2190 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
2191 if (ent->effects & EF_ADDITIVE)
2192 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_TRANSPARENT;
2193 else if (t->currentalpha < 1)
2194 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_TRANSPARENT;
2195 if (ent->effects & EF_NODEPTHTEST)
2196 t->currentmaterialflags |= MATERIALFLAG_NODEPTHTEST;
2197 if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
2198 t->currenttexmatrix = r_waterscrollmatrix;
2200 t->currenttexmatrix = identitymatrix;
2202 t->colormapping = VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f);
2203 t->basetexture = (!t->colormapping && t->skin.merged) ? t->skin.merged : t->skin.base;
2204 t->glosstexture = r_texture_white;
2205 t->specularpower = 8;
2206 t->specularscale = 0;
2207 if (r_shadow_gloss.integer > 0)
2211 if (r_shadow_glossintensity.value > 0)
2213 t->glosstexture = t->skin.gloss;
2214 t->specularscale = r_shadow_glossintensity.value;
2217 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
2218 t->specularscale = r_shadow_gloss2intensity.value;
2221 t->currentnumlayers = 0;
2222 if (!(t->currentmaterialflags & MATERIALFLAG_NODRAW))
2224 if (gl_lightmaps.integer)
2225 R_Texture_AddLayer(t, true, GL_ONE, GL_ZERO, TEXTURELAYERTYPE_LITTEXTURE, r_texture_white, &identitymatrix, 1, 1, 1, 1);
2226 else if (!(t->currentmaterialflags & MATERIALFLAG_SKY))
2228 int blendfunc1, blendfunc2, depthmask;
2229 if (t->currentmaterialflags & MATERIALFLAG_ADD)
2231 blendfunc1 = GL_SRC_ALPHA;
2232 blendfunc2 = GL_ONE;
2234 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
2236 blendfunc1 = GL_SRC_ALPHA;
2237 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
2239 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
2241 blendfunc1 = t->customblendfunc[0];
2242 blendfunc2 = t->customblendfunc[1];
2246 blendfunc1 = GL_ONE;
2247 blendfunc2 = GL_ZERO;
2249 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
2250 if (t->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL))
2252 rtexture_t *currentbasetexture;
2254 if (r_refdef.fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED))
2255 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
2256 currentbasetexture = (VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) < (1.0f / 1048576.0f) && t->skin.merged) ? t->skin.merged : t->skin.base;
2257 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2259 // fullbright is not affected by r_refdef.lightmapintensity
2260 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
2261 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->skin.pants)
2262 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);
2263 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->skin.shirt)
2264 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);
2270 // q3bsp has no lightmap updates, so the lightstylevalue that
2271 // would normally be baked into the lightmap must be
2272 // applied to the color
2273 if (ent->model->type == mod_brushq3)
2274 colorscale *= r_refdef.lightstylevalue[0] * (1.0f / 256.0f);
2275 colorscale *= r_refdef.lightmapintensity;
2276 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);
2277 if (r_ambient.value >= (1.0f/64.0f))
2278 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);
2279 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->skin.pants)
2281 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);
2282 if (r_ambient.value >= (1.0f/64.0f))
2283 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);
2285 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->skin.shirt)
2287 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);
2288 if (r_ambient.value >= (1.0f/64.0f))
2289 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);
2292 if (t->skin.glow != NULL)
2293 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.glow, &t->currenttexmatrix, 1, 1, 1, t->currentalpha);
2294 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
2296 // if this is opaque use alpha blend which will darken the earlier
2299 // if this is an alpha blended material, all the earlier passes
2300 // were darkened by fog already, so we only need to add the fog
2301 // color ontop through the fog mask texture
2303 // if this is an additive blended material, all the earlier passes
2304 // were darkened by fog already, and we should not add fog color
2305 // (because the background was not darkened, there is no fog color
2306 // that was lost behind it).
2307 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);
2314 void R_UpdateAllTextureInfo(entity_render_t *ent)
2318 for (i = 0;i < ent->model->num_textures;i++)
2319 R_UpdateTextureInfo(ent, ent->model->data_textures + i);
2322 int rsurface_array_size = 0;
2323 float *rsurface_array_modelvertex3f = NULL;
2324 float *rsurface_array_modelsvector3f = NULL;
2325 float *rsurface_array_modeltvector3f = NULL;
2326 float *rsurface_array_modelnormal3f = NULL;
2327 float *rsurface_array_deformedvertex3f = NULL;
2328 float *rsurface_array_deformedsvector3f = NULL;
2329 float *rsurface_array_deformedtvector3f = NULL;
2330 float *rsurface_array_deformednormal3f = NULL;
2331 float *rsurface_array_color4f = NULL;
2332 float *rsurface_array_texcoord3f = NULL;
2334 void R_Mesh_ResizeArrays(int newvertices)
2337 if (rsurface_array_size >= newvertices)
2339 if (rsurface_array_modelvertex3f)
2340 Mem_Free(rsurface_array_modelvertex3f);
2341 rsurface_array_size = (newvertices + 1023) & ~1023;
2342 base = (float *)Mem_Alloc(r_main_mempool, rsurface_array_size * sizeof(float[31]));
2343 rsurface_array_modelvertex3f = base + rsurface_array_size * 0;
2344 rsurface_array_modelsvector3f = base + rsurface_array_size * 3;
2345 rsurface_array_modeltvector3f = base + rsurface_array_size * 6;
2346 rsurface_array_modelnormal3f = base + rsurface_array_size * 9;
2347 rsurface_array_deformedvertex3f = base + rsurface_array_size * 12;
2348 rsurface_array_deformedsvector3f = base + rsurface_array_size * 15;
2349 rsurface_array_deformedtvector3f = base + rsurface_array_size * 18;
2350 rsurface_array_deformednormal3f = base + rsurface_array_size * 21;
2351 rsurface_array_texcoord3f = base + rsurface_array_size * 24;
2352 rsurface_array_color4f = base + rsurface_array_size * 27;
2355 float *rsurface_modelvertex3f;
2356 float *rsurface_modelsvector3f;
2357 float *rsurface_modeltvector3f;
2358 float *rsurface_modelnormal3f;
2359 float *rsurface_vertex3f;
2360 float *rsurface_svector3f;
2361 float *rsurface_tvector3f;
2362 float *rsurface_normal3f;
2363 float *rsurface_lightmapcolor4f;
2364 vec3_t rsurface_modelorg;
2365 qboolean rsurface_generatedvertex;
2366 const entity_render_t *rsurface_entity;
2367 const model_t *rsurface_model;
2368 texture_t *rsurface_texture;
2369 rtexture_t *rsurface_lightmaptexture;
2370 rsurfmode_t rsurface_mode;
2371 texture_t *rsurface_glsl_texture;
2372 qboolean rsurface_glsl_uselightmap;
2374 void RSurf_ActiveEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
2376 Matrix4x4_Transform(&ent->inversematrix, r_view.origin, rsurface_modelorg);
2377 rsurface_entity = ent;
2378 rsurface_model = ent->model;
2379 if (rsurface_array_size < rsurface_model->surfmesh.num_vertices)
2380 R_Mesh_ResizeArrays(rsurface_model->surfmesh.num_vertices);
2381 R_Mesh_Matrix(&ent->matrix);
2382 Matrix4x4_Transform(&ent->inversematrix, r_view.origin, rsurface_modelorg);
2383 if ((rsurface_entity->frameblend[0].lerp != 1 || rsurface_entity->frameblend[0].frame != 0) && rsurface_model->surfmesh.isanimated)
2387 rsurface_modelvertex3f = rsurface_array_modelvertex3f;
2388 rsurface_modelsvector3f = rsurface_array_modelsvector3f;
2389 rsurface_modeltvector3f = rsurface_array_modeltvector3f;
2390 rsurface_modelnormal3f = rsurface_array_modelnormal3f;
2391 Mod_Alias_GetMesh_Vertices(rsurface_model, rsurface_entity->frameblend, rsurface_array_modelvertex3f, rsurface_array_modelnormal3f, rsurface_array_modelsvector3f, rsurface_array_modeltvector3f);
2393 else if (wantnormals)
2395 rsurface_modelvertex3f = rsurface_array_modelvertex3f;
2396 rsurface_modelsvector3f = NULL;
2397 rsurface_modeltvector3f = NULL;
2398 rsurface_modelnormal3f = rsurface_array_modelnormal3f;
2399 Mod_Alias_GetMesh_Vertices(rsurface_model, rsurface_entity->frameblend, rsurface_array_modelvertex3f, rsurface_array_modelnormal3f, NULL, NULL);
2403 rsurface_modelvertex3f = rsurface_array_modelvertex3f;
2404 rsurface_modelsvector3f = NULL;
2405 rsurface_modeltvector3f = NULL;
2406 rsurface_modelnormal3f = NULL;
2407 Mod_Alias_GetMesh_Vertices(rsurface_model, rsurface_entity->frameblend, rsurface_array_modelvertex3f, NULL, NULL, NULL);
2409 rsurface_generatedvertex = true;
2413 rsurface_modelvertex3f = rsurface_model->surfmesh.data_vertex3f;
2414 rsurface_modelsvector3f = rsurface_model->surfmesh.data_svector3f;
2415 rsurface_modeltvector3f = rsurface_model->surfmesh.data_tvector3f;
2416 rsurface_modelnormal3f = rsurface_model->surfmesh.data_normal3f;
2417 rsurface_generatedvertex = false;
2419 rsurface_vertex3f = rsurface_modelvertex3f;
2420 rsurface_svector3f = rsurface_modelsvector3f;
2421 rsurface_tvector3f = rsurface_modeltvector3f;
2422 rsurface_normal3f = rsurface_modelnormal3f;
2423 rsurface_mode = RSURFMODE_NONE;
2424 rsurface_lightmaptexture = NULL;
2425 rsurface_texture = NULL;
2426 rsurface_glsl_texture = NULL;
2427 rsurface_glsl_uselightmap = false;
2430 void RSurf_CleanUp(void)
2433 if (rsurface_mode == RSURFMODE_GLSL)
2435 qglUseProgramObjectARB(0);CHECKGLERROR
2437 GL_AlphaTest(false);
2438 rsurface_mode = RSURFMODE_NONE;
2439 rsurface_lightmaptexture = NULL;
2440 rsurface_texture = NULL;
2441 rsurface_glsl_texture = NULL;
2442 rsurface_glsl_uselightmap = false;
2445 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, msurface_t **texturesurfacelist)
2447 if (rsurface_generatedvertex)
2449 if (rsurface_texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
2450 generatetangents = true;
2451 if (generatetangents)
2452 generatenormals = true;
2453 if (generatenormals && !rsurface_modelnormal3f)
2455 rsurface_normal3f = rsurface_modelnormal3f = rsurface_array_modelnormal3f;
2456 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);
2458 if (generatetangents && !rsurface_modelsvector3f)
2460 rsurface_svector3f = rsurface_modelsvector3f = rsurface_array_modelsvector3f;
2461 rsurface_tvector3f = rsurface_modeltvector3f = rsurface_array_modeltvector3f;
2462 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);
2465 if (rsurface_texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
2467 int texturesurfaceindex;
2468 float center[3], forward[3], right[3], up[3], v[4][3];
2469 matrix4x4_t matrix1, imatrix1;
2470 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_view.forward, forward);
2471 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_view.right, right);
2472 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_view.up, up);
2473 // make deformed versions of only the vertices used by the specified surfaces
2474 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2477 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2478 // a single autosprite surface can contain multiple sprites...
2479 for (j = 0;j < surface->num_vertices - 3;j += 4)
2481 VectorClear(center);
2482 for (i = 0;i < 4;i++)
2483 VectorAdd(center, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
2484 VectorScale(center, 0.25f, center);
2485 if (rsurface_texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE2)
2487 forward[0] = rsurface_modelorg[0] - center[0];
2488 forward[1] = rsurface_modelorg[1] - center[1];
2490 VectorNormalize(forward);
2491 right[0] = forward[1];
2492 right[1] = -forward[0];
2494 VectorSet(up, 0, 0, 1);
2496 // FIXME: calculate vectors from triangle edges instead of using texture vectors as an easy way out?
2497 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);
2498 Matrix4x4_Invert_Simple(&imatrix1, &matrix1);
2499 for (i = 0;i < 4;i++)
2500 Matrix4x4_Transform(&imatrix1, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, v[i]);
2501 for (i = 0;i < 4;i++)
2502 VectorMAMAMAM(1, center, v[i][0], forward, v[i][1], right, v[i][2], up, rsurface_array_modelvertex3f + (surface->num_firstvertex+i+j) * 3);
2504 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);
2505 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);
2507 rsurface_vertex3f = rsurface_array_deformedvertex3f;
2508 rsurface_svector3f = rsurface_array_deformedsvector3f;
2509 rsurface_tvector3f = rsurface_array_deformedtvector3f;
2510 rsurface_normal3f = rsurface_array_deformednormal3f;
2512 R_Mesh_VertexPointer(rsurface_vertex3f);
2515 void RSurf_DrawBatch_Simple(int texturenumsurfaces, msurface_t **texturesurfacelist)
2517 int texturesurfaceindex;
2518 const msurface_t *surface = texturesurfacelist[0];
2519 int firstvertex = surface->num_firstvertex;
2520 int endvertex = surface->num_firstvertex + surface->num_vertices;
2521 if (texturenumsurfaces == 1)
2523 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2524 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
2526 else if (r_batchmode.integer == 2)
2528 #define MAXBATCHTRIANGLES 4096
2529 int batchtriangles = 0;
2530 int batchelements[MAXBATCHTRIANGLES*3];
2531 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2533 surface = texturesurfacelist[texturesurfaceindex];
2534 if (surface->num_triangles >= 256 || (batchtriangles == 0 && texturesurfaceindex + 1 >= texturenumsurfaces))
2536 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
2539 if (batchtriangles + surface->num_triangles > MAXBATCHTRIANGLES)
2541 R_Mesh_Draw(firstvertex, endvertex - firstvertex, batchtriangles, batchelements);
2543 firstvertex = surface->num_firstvertex;
2544 endvertex = surface->num_firstvertex + surface->num_vertices;
2548 firstvertex = min(firstvertex, surface->num_firstvertex);
2549 endvertex = max(endvertex, surface->num_firstvertex + surface->num_vertices);
2551 memcpy(batchelements + batchtriangles * 3, rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
2552 batchtriangles += surface->num_triangles;
2555 R_Mesh_Draw(firstvertex, endvertex - firstvertex, batchtriangles, batchelements);
2557 else if (r_batchmode.integer == 1)
2559 int firsttriangle = 0;
2560 int endtriangle = -1;
2561 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2563 surface = texturesurfacelist[texturesurfaceindex];
2564 if (surface->num_firsttriangle != endtriangle)
2566 if (endtriangle > firsttriangle)
2568 GL_LockArrays(firstvertex, endvertex - firstvertex);
2569 R_Mesh_Draw(firstvertex, endvertex - firstvertex, endtriangle - firsttriangle, (rsurface_model->surfmesh.data_element3i + 3 * firsttriangle));
2571 firstvertex = surface->num_firstvertex;
2572 endvertex = surface->num_firstvertex + surface->num_vertices;
2573 firsttriangle = surface->num_firsttriangle;
2577 firstvertex = min(firstvertex, surface->num_firstvertex);
2578 endvertex = max(endvertex, surface->num_firstvertex + surface->num_vertices);
2580 endtriangle = surface->num_firsttriangle + surface->num_triangles;
2582 if (endtriangle > firsttriangle)
2584 GL_LockArrays(firstvertex, endvertex - firstvertex);
2585 R_Mesh_Draw(firstvertex, endvertex - firstvertex, endtriangle - firsttriangle, (rsurface_model->surfmesh.data_element3i + 3 * firsttriangle));
2590 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2592 surface = texturesurfacelist[texturesurfaceindex];
2593 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2594 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
2599 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
2601 int texturesurfaceindex;
2602 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2604 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2605 int k = (int)(((size_t)surface) / sizeof(msurface_t));
2606 GL_Color((k & 15) * (1.0f / 16.0f), ((k >> 4) & 15) * (1.0f / 16.0f), ((k >> 8) & 15) * (1.0f / 16.0f), 0.2f);
2607 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2608 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
2612 static void RSurf_DrawBatch_Lightmap(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, int lightmode, qboolean applycolor, qboolean applyfog)
2614 int texturesurfaceindex;
2622 vec3_t ambientcolor;
2623 vec3_t diffusecolor;
2625 VectorCopy(rsurface_entity->modellight_lightdir, lightdir);
2626 ambientcolor[0] = rsurface_entity->modellight_ambient[0] * r * 0.5f;
2627 ambientcolor[1] = rsurface_entity->modellight_ambient[1] * g * 0.5f;
2628 ambientcolor[2] = rsurface_entity->modellight_ambient[2] * b * 0.5f;
2629 diffusecolor[0] = rsurface_entity->modellight_diffuse[0] * r * 0.5f;
2630 diffusecolor[1] = rsurface_entity->modellight_diffuse[1] * g * 0.5f;
2631 diffusecolor[2] = rsurface_entity->modellight_diffuse[2] * b * 0.5f;
2632 if (VectorLength2(diffusecolor) > 0)
2634 // generate color arrays for the surfaces in this list
2635 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2637 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2638 int numverts = surface->num_vertices;
2639 v = rsurface_vertex3f + 3 * surface->num_firstvertex;
2640 c2 = rsurface_normal3f + 3 * surface->num_firstvertex;
2641 c = rsurface_array_color4f + 4 * surface->num_firstvertex;
2642 // q3-style directional shading
2643 for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
2645 if ((f = DotProduct(c2, lightdir)) > 0)
2646 VectorMA(ambientcolor, f, diffusecolor, c);
2648 VectorCopy(ambientcolor, c);
2657 rsurface_lightmapcolor4f = rsurface_array_color4f;
2661 r = ambientcolor[0];
2662 g = ambientcolor[1];
2663 b = ambientcolor[2];
2664 rsurface_lightmapcolor4f = NULL;
2667 else if (lightmode >= 1 || !rsurface_lightmaptexture)
2669 if (texturesurfacelist[0]->lightmapinfo && texturesurfacelist[0]->lightmapinfo->stainsamples)
2671 // generate color arrays for the surfaces in this list
2672 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2674 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2675 for (i = 0, c = rsurface_array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
2677 if (surface->lightmapinfo->samples)
2679 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface_model->surfmesh.data_lightmapoffsets + surface->num_firstvertex)[i];
2680 float scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
2681 VectorScale(lm, scale, c);
2682 if (surface->lightmapinfo->styles[1] != 255)
2684 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
2686 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
2687 VectorMA(c, scale, lm, c);
2688 if (surface->lightmapinfo->styles[2] != 255)
2691 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
2692 VectorMA(c, scale, lm, c);
2693 if (surface->lightmapinfo->styles[3] != 255)
2696 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
2697 VectorMA(c, scale, lm, c);
2707 rsurface_lightmapcolor4f = rsurface_array_color4f;
2710 rsurface_lightmapcolor4f = rsurface_model->surfmesh.data_lightmapcolor4f;
2715 rsurface_lightmapcolor4f = NULL;
2719 if (rsurface_lightmapcolor4f)
2721 // generate color arrays for the surfaces in this list
2722 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2724 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2725 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)
2727 f = 1 - VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
2737 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2739 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2740 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)
2742 f = 1 - VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
2750 rsurface_lightmapcolor4f = rsurface_array_color4f;
2752 if (applycolor && rsurface_lightmapcolor4f)
2754 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2756 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2757 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)
2765 rsurface_lightmapcolor4f = rsurface_array_color4f;
2767 R_Mesh_ColorPointer(rsurface_lightmapcolor4f);
2768 GL_Color(r, g, b, a);
2769 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
2772 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
2774 if (rsurface_mode != RSURFMODE_SHOWSURFACES)
2776 rsurface_mode = RSURFMODE_SHOWSURFACES;
2778 GL_BlendFunc(GL_ONE, GL_ZERO);
2779 R_Mesh_ColorPointer(NULL);
2780 R_Mesh_ResetTextureState();
2782 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
2783 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
2786 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, msurface_t **texturesurfacelist)
2788 // transparent sky would be ridiculous
2789 if ((rsurface_texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
2791 if (rsurface_mode != RSURFMODE_SKY)
2793 if (rsurface_mode == RSURFMODE_GLSL)
2795 qglUseProgramObjectARB(0);CHECKGLERROR
2797 rsurface_mode = RSURFMODE_SKY;
2801 skyrendernow = false;
2803 // restore entity matrix
2804 R_Mesh_Matrix(&rsurface_entity->matrix);
2807 // LordHavoc: HalfLife maps have freaky skypolys so don't use
2808 // skymasking on them, and Quake3 never did sky masking (unlike
2809 // software Quake and software Quake2), so disable the sky masking
2810 // in Quake3 maps as it causes problems with q3map2 sky tricks,
2811 // and skymasking also looks very bad when noclipping outside the
2812 // level, so don't use it then either.
2813 if (rsurface_model->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_viewcache.world_novis)
2815 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
2816 R_Mesh_ColorPointer(NULL);
2817 R_Mesh_ResetTextureState();
2818 if (skyrendermasked)
2820 // depth-only (masking)
2821 GL_ColorMask(0,0,0,0);
2822 // just to make sure that braindead drivers don't draw
2823 // anything despite that colormask...
2824 GL_BlendFunc(GL_ZERO, GL_ONE);
2829 GL_BlendFunc(GL_ONE, GL_ZERO);
2831 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
2832 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
2833 if (skyrendermasked)
2834 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
2838 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, msurface_t **texturesurfacelist)
2841 // FIXME: identify models using a better check than rsurface_model->brush.shadowmesh
2842 lightmode = ((rsurface_entity->effects & EF_FULLBRIGHT) || rsurface_model->brush.shadowmesh) ? 0 : 2;
2843 if (rsurface_mode != RSURFMODE_GLSL)
2845 rsurface_mode = RSURFMODE_GLSL;
2846 rsurface_glsl_texture = NULL;
2847 rsurface_glsl_uselightmap = false;
2848 R_Mesh_ResetTextureState();
2850 if (rsurface_glsl_texture != rsurface_texture || rsurface_glsl_uselightmap != (rsurface_lightmaptexture != NULL))
2852 rsurface_glsl_texture = rsurface_texture;
2853 rsurface_glsl_uselightmap = rsurface_lightmaptexture != NULL;
2854 GL_BlendFunc(rsurface_texture->currentlayers[0].blendfunc1, rsurface_texture->currentlayers[0].blendfunc2);
2855 GL_DepthMask(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_BLENDED));
2856 GL_Color(rsurface_entity->colormod[0], rsurface_entity->colormod[1], rsurface_entity->colormod[2], rsurface_texture->currentalpha);
2857 R_SetupSurfaceShader(vec3_origin, lightmode == 2);
2858 //permutation_deluxemapping = permutation_lightmapping = R_SetupSurfaceShader(vec3_origin, lightmode == 2, false);
2859 //if (r_glsl_deluxemapping.integer)
2860 // permutation_deluxemapping = R_SetupSurfaceShader(vec3_origin, lightmode == 2, true);
2861 R_Mesh_TexCoordPointer(0, 2, rsurface_model->surfmesh.data_texcoordtexture2f);
2862 R_Mesh_TexCoordPointer(4, 2, rsurface_model->surfmesh.data_texcoordlightmap2f);
2863 GL_AlphaTest((rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2865 if (!r_glsl_permutation)
2867 RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
2868 R_Mesh_TexCoordPointer(1, 3, rsurface_svector3f);
2869 R_Mesh_TexCoordPointer(2, 3, rsurface_tvector3f);
2870 R_Mesh_TexCoordPointer(3, 3, rsurface_normal3f);
2871 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2873 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
2874 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
2875 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
2876 R_Mesh_ColorPointer(NULL);
2878 else if (rsurface_lightmaptexture)
2880 R_Mesh_TexBind(7, R_GetTexture(rsurface_lightmaptexture));
2881 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
2882 R_Mesh_TexBind(8, R_GetTexture(texturesurfacelist[0]->deluxemaptexture));
2883 R_Mesh_ColorPointer(NULL);
2887 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
2888 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
2889 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
2890 R_Mesh_ColorPointer(rsurface_model->surfmesh.data_lightmapcolor4f);
2892 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
2895 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, msurface_t **texturesurfacelist)
2897 // OpenGL 1.3 path - anything not completely ancient
2898 int texturesurfaceindex;
2900 qboolean applycolor;
2904 const texturelayer_t *layer;
2906 // FIXME: identify models using a better check than rsurface_model->brush.shadowmesh
2907 lightmode = ((rsurface_entity->effects & EF_FULLBRIGHT) || rsurface_model->brush.shadowmesh) ? 0 : 2;
2908 if (rsurface_mode != RSURFMODE_MULTIPASS)
2909 rsurface_mode = RSURFMODE_MULTIPASS;
2910 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
2911 for (layerindex = 0, layer = rsurface_texture->currentlayers;layerindex < rsurface_texture->currentnumlayers;layerindex++, layer++)
2914 int layertexrgbscale;
2915 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2917 if (layerindex == 0)
2921 GL_AlphaTest(false);
2922 qglDepthFunc(GL_EQUAL);CHECKGLERROR
2925 GL_DepthMask(layer->depthmask);
2926 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
2927 if ((layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2) && (gl_combine.integer || layer->depthmask))
2929 layertexrgbscale = 4;
2930 VectorScale(layer->color, 0.25f, layercolor);
2932 else if ((layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1) && (gl_combine.integer || layer->depthmask))
2934 layertexrgbscale = 2;
2935 VectorScale(layer->color, 0.5f, layercolor);
2939 layertexrgbscale = 1;
2940 VectorScale(layer->color, 1.0f, layercolor);
2942 layercolor[3] = layer->color[3];
2943 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
2944 R_Mesh_ColorPointer(NULL);
2945 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
2946 switch (layer->type)
2948 case TEXTURELAYERTYPE_LITTEXTURE:
2949 memset(&m, 0, sizeof(m));
2950 if (lightmode >= 1 || !rsurface_lightmaptexture)
2951 m.tex[0] = R_GetTexture(r_texture_white);
2953 m.tex[0] = R_GetTexture(rsurface_lightmaptexture);
2954 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordlightmap2f;
2955 m.tex[1] = R_GetTexture(layer->texture);
2956 m.texmatrix[1] = layer->texmatrix;
2957 m.texrgbscale[1] = layertexrgbscale;
2958 m.pointer_texcoord[1] = rsurface_model->surfmesh.data_texcoordtexture2f;
2959 R_Mesh_TextureState(&m);
2960 RSurf_DrawBatch_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], lightmode, applycolor, applyfog);
2962 case TEXTURELAYERTYPE_TEXTURE:
2963 memset(&m, 0, sizeof(m));
2964 m.tex[0] = R_GetTexture(layer->texture);
2965 m.texmatrix[0] = layer->texmatrix;
2966 m.texrgbscale[0] = layertexrgbscale;
2967 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
2968 R_Mesh_TextureState(&m);
2969 RSurf_DrawBatch_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, applyfog);
2971 case TEXTURELAYERTYPE_FOG:
2972 memset(&m, 0, sizeof(m));
2973 m.texrgbscale[0] = layertexrgbscale;
2976 m.tex[0] = R_GetTexture(layer->texture);
2977 m.texmatrix[0] = layer->texmatrix;
2978 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
2980 R_Mesh_TextureState(&m);
2981 // generate a color array for the fog pass
2982 R_Mesh_ColorPointer(rsurface_array_color4f);
2983 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2987 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2988 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)
2990 f = VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
2991 c[0] = layercolor[0];
2992 c[1] = layercolor[1];
2993 c[2] = layercolor[2];
2994 c[3] = f * layercolor[3];
2997 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3000 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
3002 GL_LockArrays(0, 0);
3005 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
3007 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3008 GL_AlphaTest(false);
3012 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, msurface_t **texturesurfacelist)
3014 // OpenGL 1.1 - crusty old voodoo path
3015 int texturesurfaceindex;
3020 const texturelayer_t *layer;
3022 // FIXME: identify models using a better check than rsurface_model->brush.shadowmesh
3023 lightmode = ((rsurface_entity->effects & EF_FULLBRIGHT) || rsurface_model->brush.shadowmesh) ? 0 : 2;
3024 if (rsurface_mode != RSURFMODE_MULTIPASS)
3025 rsurface_mode = RSURFMODE_MULTIPASS;
3026 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
3027 for (layerindex = 0, layer = rsurface_texture->currentlayers;layerindex < rsurface_texture->currentnumlayers;layerindex++, layer++)
3029 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
3031 if (layerindex == 0)
3035 GL_AlphaTest(false);
3036 qglDepthFunc(GL_EQUAL);CHECKGLERROR
3039 GL_DepthMask(layer->depthmask);
3040 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
3041 R_Mesh_ColorPointer(NULL);
3042 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
3043 switch (layer->type)
3045 case TEXTURELAYERTYPE_LITTEXTURE:
3046 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
3048 // two-pass lit texture with 2x rgbscale
3049 // first the lightmap pass
3050 memset(&m, 0, sizeof(m));
3051 if (lightmode >= 1 || !rsurface_lightmaptexture)
3052 m.tex[0] = R_GetTexture(r_texture_white);
3054 m.tex[0] = R_GetTexture(rsurface_lightmaptexture);
3055 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordlightmap2f;
3056 R_Mesh_TextureState(&m);
3057 RSurf_DrawBatch_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, lightmode, false, false);
3058 GL_LockArrays(0, 0);
3059 // then apply the texture to it
3060 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
3061 memset(&m, 0, sizeof(m));
3062 m.tex[0] = R_GetTexture(layer->texture);
3063 m.texmatrix[0] = layer->texmatrix;
3064 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3065 R_Mesh_TextureState(&m);
3066 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);
3070 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
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);
3076 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);
3079 case TEXTURELAYERTYPE_TEXTURE:
3080 // singletexture unlit texture with transparency support
3081 memset(&m, 0, sizeof(m));
3082 m.tex[0] = R_GetTexture(layer->texture);
3083 m.texmatrix[0] = layer->texmatrix;
3084 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3085 R_Mesh_TextureState(&m);
3086 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);
3088 case TEXTURELAYERTYPE_FOG:
3089 // singletexture fogging
3090 R_Mesh_ColorPointer(rsurface_array_color4f);
3093 memset(&m, 0, sizeof(m));
3094 m.tex[0] = R_GetTexture(layer->texture);
3095 m.texmatrix[0] = layer->texmatrix;
3096 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3097 R_Mesh_TextureState(&m);
3100 R_Mesh_ResetTextureState();
3101 // generate a color array for the fog pass
3102 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3106 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3107 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)
3109 f = VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
3110 c[0] = layer->color[0];
3111 c[1] = layer->color[1];
3112 c[2] = layer->color[2];
3113 c[3] = f * layer->color[3];
3116 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3119 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
3121 GL_LockArrays(0, 0);
3124 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
3126 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3127 GL_AlphaTest(false);
3131 static void R_DrawTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist)
3133 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_NODRAW)
3135 r_shadow_rtlight = NULL;
3136 r_refdef.stats.entities_surfaces += texturenumsurfaces;
3138 GL_DepthTest(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
3139 if ((rsurface_texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (rsurface_entity->flags & RENDER_NOCULLFACE))
3141 qglDisable(GL_CULL_FACE);CHECKGLERROR
3143 if (r_showsurfaces.integer)
3144 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
3145 else if (rsurface_texture->currentmaterialflags & MATERIALFLAG_SKY)
3146 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
3147 else if (rsurface_texture->currentnumlayers)
3149 if (r_glsl.integer && gl_support_fragment_shader)
3150 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist);
3151 else if (gl_combine.integer && r_textureunits.integer >= 2)
3152 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist);
3154 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist);
3157 GL_LockArrays(0, 0);
3158 if ((rsurface_texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (rsurface_entity->flags & RENDER_NOCULLFACE))
3160 qglEnable(GL_CULL_FACE);CHECKGLERROR
3164 #define BATCHSIZE 256
3165 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
3167 int surfacelistindex;
3170 msurface_t *texturesurfacelist[BATCHSIZE];
3171 // if the model is static it doesn't matter what value we give for
3172 // wantnormals and wanttangents, so this logic uses only rules applicable
3173 // to a model, knowing that they are meaningless otherwise
3174 if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
3175 RSurf_ActiveEntity(ent, false, false);
3177 RSurf_ActiveEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
3180 for (surfacelistindex = 0;surfacelistindex < numsurfaces;surfacelistindex++)
3182 msurface_t *surface = ent->model->data_surfaces + surfacelist[surfacelistindex];
3184 if (t != surface->texture || rsurface_lightmaptexture != surface->lightmaptexture)
3187 R_DrawTextureSurfaceList(batchcount, texturesurfacelist);
3189 t = surface->texture;
3190 rsurface_lightmaptexture = surface->lightmaptexture;
3191 R_UpdateTextureInfo(ent, t);
3192 rsurface_texture = t->currentframe;
3194 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_SKY)
3195 continue; // transparent sky is too difficult
3197 texturesurfacelist[batchcount++] = surface;
3200 R_DrawTextureSurfaceList(batchcount, texturesurfacelist);
3204 void R_QueueTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist)
3206 int texturesurfaceindex;
3207 vec3_t tempcenter, center;
3208 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_BLENDED)
3210 // drawing sky transparently would be too difficult
3211 if (!(rsurface_texture->currentmaterialflags & MATERIALFLAG_SKY))
3213 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3215 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3216 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
3217 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
3218 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
3219 Matrix4x4_Transform(&rsurface_entity->matrix, tempcenter, center);
3220 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);
3225 R_DrawTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
3228 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
3229 void R_DrawSurfaces(entity_render_t *ent, qboolean skysurfaces)
3231 int i, j, f, flagsmask;
3232 int counttriangles = 0;
3234 model_t *model = ent->model;
3235 const int maxsurfacelist = 1024;
3236 int numsurfacelist = 0;
3237 msurface_t *surfacelist[1024];
3241 // if the model is static it doesn't matter what value we give for
3242 // wantnormals and wanttangents, so this logic uses only rules applicable
3243 // to a model, knowing that they are meaningless otherwise
3244 if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
3245 RSurf_ActiveEntity(ent, false, false);
3247 RSurf_ActiveEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
3249 // update light styles
3250 if (!skysurfaces && model->brushq1.light_styleupdatechains)
3252 msurface_t *surface, **surfacechain;
3253 for (i = 0;i < model->brushq1.light_styles;i++)
3255 if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
3257 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
3258 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
3259 for (;(surface = *surfacechain);surfacechain++)
3260 surface->cached_dlight = true;
3265 R_UpdateAllTextureInfo(ent);
3266 flagsmask = skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL);
3269 rsurface_lightmaptexture = NULL;
3270 rsurface_texture = NULL;
3272 if (ent == r_refdef.worldentity)
3274 msurface_t *surface;
3275 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
3277 if (!r_viewcache.world_surfacevisible[j])
3279 if (t != surface->texture || rsurface_lightmaptexture != surface->lightmaptexture)
3283 R_QueueTextureSurfaceList(numsurfacelist, surfacelist);
3286 t = surface->texture;
3287 rsurface_lightmaptexture = surface->lightmaptexture;
3288 rsurface_texture = t->currentframe;
3289 f = rsurface_texture->currentmaterialflags & flagsmask;
3291 if (f && surface->num_triangles)
3293 // if lightmap parameters changed, rebuild lightmap texture
3294 if (surface->cached_dlight)
3295 R_BuildLightMap(ent, surface);
3296 // add face to draw list
3297 surfacelist[numsurfacelist++] = surface;
3298 counttriangles += surface->num_triangles;
3299 if (numsurfacelist >= maxsurfacelist)
3301 R_QueueTextureSurfaceList(numsurfacelist, surfacelist);
3309 msurface_t *surface;
3310 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
3312 if (t != surface->texture || rsurface_lightmaptexture != surface->lightmaptexture)
3316 R_QueueTextureSurfaceList(numsurfacelist, surfacelist);
3319 t = surface->texture;
3320 rsurface_lightmaptexture = surface->lightmaptexture;
3321 rsurface_texture = t->currentframe;
3322 f = rsurface_texture->currentmaterialflags & flagsmask;
3324 if (f && surface->num_triangles)
3326 // if lightmap parameters changed, rebuild lightmap texture
3327 if (surface->cached_dlight)
3328 R_BuildLightMap(ent, surface);
3329 // add face to draw list
3330 surfacelist[numsurfacelist++] = surface;
3331 counttriangles += surface->num_triangles;
3332 if (numsurfacelist >= maxsurfacelist)
3334 R_QueueTextureSurfaceList(numsurfacelist, surfacelist);
3341 R_QueueTextureSurfaceList(numsurfacelist, surfacelist);
3342 r_refdef.stats.entities_triangles += counttriangles;
3345 if (r_showcollisionbrushes.integer && model->brush.num_brushes && !skysurfaces)
3348 const msurface_t *surface;
3351 R_Mesh_Matrix(&ent->matrix);
3352 R_Mesh_ColorPointer(NULL);
3353 R_Mesh_ResetTextureState();
3354 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
3355 GL_DepthMask(false);
3356 GL_DepthTest(!r_showdisabledepthtest.integer);
3357 qglPolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);CHECKGLERROR
3358 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
3359 if (brush->colbrushf && brush->colbrushf->numtriangles)
3360 R_DrawCollisionBrush(brush->colbrushf);
3361 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
3362 if (surface->num_collisiontriangles)
3363 R_DrawCollisionSurface(ent, surface);
3364 qglPolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR
3367 if (r_showtris.integer || r_shownormals.integer)
3370 msurface_t *surface;
3371 const int *elements;
3376 if (r_showdisabledepthtest.integer)
3378 qglDepthFunc(GL_ALWAYS);CHECKGLERROR
3380 GL_BlendFunc(GL_ONE, GL_ZERO);
3381 R_Mesh_ColorPointer(NULL);
3382 R_Mesh_ResetTextureState();
3383 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
3385 if (ent == r_refdef.worldentity && !r_viewcache.world_surfacevisible[j])
3387 rsurface_texture = surface->texture->currentframe;
3388 if ((rsurface_texture->currentmaterialflags & flagsmask) && surface->num_triangles)
3390 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
3391 if (r_showtris.integer)
3393 if (!rsurface_texture->currentlayers->depthmask)
3394 GL_Color(r_showtris.value, 0, 0, 1);
3395 else if (ent == r_refdef.worldentity)
3396 GL_Color(r_showtris.value, r_showtris.value, r_showtris.value, 1);
3398 GL_Color(0, r_showtris.value, 0, 1);
3399 elements = (ent->model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
3402 for (k = 0;k < surface->num_triangles;k++, elements += 3)
3404 qglArrayElement(elements[0]);qglArrayElement(elements[1]);
3405 qglArrayElement(elements[1]);qglArrayElement(elements[2]);
3406 qglArrayElement(elements[2]);qglArrayElement(elements[0]);
3411 if (r_shownormals.integer)
3413 GL_Color(r_shownormals.value, 0, 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_svector3f + l * 3, v);
3420 qglVertex3f(v[0], v[1], v[2]);
3424 GL_Color(0, 0, r_shownormals.value, 1);
3426 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
3428 VectorCopy(rsurface_vertex3f + l * 3, v);
3429 qglVertex3f(v[0], v[1], v[2]);
3430 VectorMA(v, 8, rsurface_tvector3f + l * 3, v);
3431 qglVertex3f(v[0], v[1], v[2]);
3435 GL_Color(0, r_shownormals.value, 0, 1);
3437 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
3439 VectorCopy(rsurface_vertex3f + l * 3, v);
3440 qglVertex3f(v[0], v[1], v[2]);
3441 VectorMA(v, 8, rsurface_normal3f + l * 3, v);
3442 qglVertex3f(v[0], v[1], v[2]);
3449 rsurface_texture = NULL;
3450 if (r_showdisabledepthtest.integer)
3452 qglDepthFunc(GL_LEQUAL);CHECKGLERROR