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;
29 // used for dlight push checking and other things
34 renderstats_t renderstats;
36 // true during envmap command capture
39 // maximum visible distance (recalculated from world box each frame)
41 // brightness of world lightmaps and related lighting
42 // (often reduced when world rtlights are enabled)
43 float r_lightmapintensity;
44 // whether to draw world lights realtime, dlights realtime, and their shadows
46 qboolean r_rtworldshadows;
48 qboolean r_rtdlightshadows;
63 matrix4x4_t r_view_matrix;
64 float r_polygonfactor;
65 float r_polygonoffset;
66 float r_shadowpolygonfactor;
67 float r_shadowpolygonoffset;
73 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
74 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "shows surfaces as different colors"};
75 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
76 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
77 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"};
78 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"};
79 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
80 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"};
81 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"};
82 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing\n"};
83 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
84 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
85 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
86 cvar_t r_fullbright = {0, "r_fullbright","0", "make everything bright cheat (not allowed in multiplayer)"};
87 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
88 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
89 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
90 cvar_t r_q1bsp_skymasking = {0, "r_qb1sp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
92 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
93 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
94 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
95 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
96 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
97 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
98 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
100 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)"};
102 cvar_t r_glsl = {0, "r_glsl", "1", "enables use of OpenGL 2.0 pixel shaders for lighting"};
103 cvar_t r_glsl_offsetmapping = {0, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
104 cvar_t r_glsl_offsetmapping_reliefmapping = {0, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
105 cvar_t r_glsl_offsetmapping_scale = {0, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
106 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)"};
108 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1", "enables animation smoothing on sprites (requires r_lerpmodels 1)"};
109 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
110 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
112 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
113 cvar_t r_bloom_intensity = {CVAR_SAVE, "r_bloom_intensity", "1.5", "how bright the glow is"};
114 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
115 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
116 cvar_t r_bloom_power = {CVAR_SAVE, "r_bloom_power", "2", "how much to darken the image before blurring to make the bloom effect"};
118 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"};
120 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"};
122 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
124 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
126 rtexture_t *r_bloom_texture_screen;
127 rtexture_t *r_bloom_texture_bloom;
128 rtexture_t *r_texture_blanknormalmap;
129 rtexture_t *r_texture_white;
130 rtexture_t *r_texture_black;
131 rtexture_t *r_texture_notexture;
132 rtexture_t *r_texture_whitecube;
133 rtexture_t *r_texture_normalizationcube;
134 rtexture_t *r_texture_fogattenuation;
135 //rtexture_t *r_texture_fogintensity;
137 // information about each possible shader permutation
138 r_glsl_permutation_t r_glsl_permutations[SHADERPERMUTATION_COUNT];
139 // currently selected permutation
140 r_glsl_permutation_t *r_glsl_permutation;
142 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
145 for (i = 0;i < verts;i++)
156 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
159 for (i = 0;i < verts;i++)
174 vec_t fogtabledistmultiplier;
175 float fogtable[FOGTABLEWIDTH];
176 float fog_density, fog_red, fog_green, fog_blue;
178 qboolean oldgl_fogenable;
179 void R_UpdateFog(void)
181 if (gamemode == GAME_NEHAHRA)
183 if (gl_fogenable.integer)
185 oldgl_fogenable = true;
186 fog_density = gl_fogdensity.value;
187 fog_red = gl_fogred.value;
188 fog_green = gl_foggreen.value;
189 fog_blue = gl_fogblue.value;
191 else if (oldgl_fogenable)
193 oldgl_fogenable = false;
202 fogcolor[0] = fog_red = bound(0.0f, fog_red , 1.0f);
203 fogcolor[1] = fog_green = bound(0.0f, fog_green, 1.0f);
204 fogcolor[2] = fog_blue = bound(0.0f, fog_blue , 1.0f);
209 fogdensity = -4000.0f / (fog_density * fog_density);
210 // this is the point where the fog reaches 0.9986 alpha, which we
211 // consider a good enough cutoff point for the texture
212 // (0.9986 * 256 == 255.6)
213 fogrange = 400 / fog_density;
214 fograngerecip = 1.0f / fogrange;
215 fogtabledistmultiplier = FOGTABLEWIDTH * fograngerecip;
216 // fog color was already set
222 // FIXME: move this to client?
225 if (gamemode == GAME_NEHAHRA)
227 Cvar_Set("gl_fogenable", "0");
228 Cvar_Set("gl_fogdensity", "0.2");
229 Cvar_Set("gl_fogred", "0.3");
230 Cvar_Set("gl_foggreen", "0.3");
231 Cvar_Set("gl_fogblue", "0.3");
233 fog_density = fog_red = fog_green = fog_blue = 0.0f;
236 // FIXME: move this to client?
237 void FOG_registercvars(void)
242 if (gamemode == GAME_NEHAHRA)
244 Cvar_RegisterVariable (&gl_fogenable);
245 Cvar_RegisterVariable (&gl_fogdensity);
246 Cvar_RegisterVariable (&gl_fogred);
247 Cvar_RegisterVariable (&gl_foggreen);
248 Cvar_RegisterVariable (&gl_fogblue);
249 Cvar_RegisterVariable (&gl_fogstart);
250 Cvar_RegisterVariable (&gl_fogend);
253 r = (-1.0/256.0) * (FOGTABLEWIDTH * FOGTABLEWIDTH);
254 for (x = 0;x < FOGTABLEWIDTH;x++)
256 alpha = exp(r / ((double)x*(double)x));
257 if (x == FOGTABLEWIDTH - 1)
259 fogtable[x] = bound(0, alpha, 1);
263 static void R_BuildBlankTextures(void)
265 unsigned char data[4];
266 data[0] = 128; // normal X
267 data[1] = 128; // normal Y
268 data[2] = 255; // normal Z
269 data[3] = 128; // height
270 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
275 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
280 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
283 static void R_BuildNoTexture(void)
286 unsigned char pix[16][16][4];
287 // this makes a light grey/dark grey checkerboard texture
288 for (y = 0;y < 16;y++)
290 for (x = 0;x < 16;x++)
292 if ((y < 8) ^ (x < 8))
308 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_RGBA, TEXF_MIPMAP, NULL);
311 static void R_BuildWhiteCube(void)
313 unsigned char data[6*1*1*4];
314 data[ 0] = 255;data[ 1] = 255;data[ 2] = 255;data[ 3] = 255;
315 data[ 4] = 255;data[ 5] = 255;data[ 6] = 255;data[ 7] = 255;
316 data[ 8] = 255;data[ 9] = 255;data[10] = 255;data[11] = 255;
317 data[12] = 255;data[13] = 255;data[14] = 255;data[15] = 255;
318 data[16] = 255;data[17] = 255;data[18] = 255;data[19] = 255;
319 data[20] = 255;data[21] = 255;data[22] = 255;data[23] = 255;
320 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
323 static void R_BuildNormalizationCube(void)
327 vec_t s, t, intensity;
329 unsigned char data[6][NORMSIZE][NORMSIZE][4];
330 for (side = 0;side < 6;side++)
332 for (y = 0;y < NORMSIZE;y++)
334 for (x = 0;x < NORMSIZE;x++)
336 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
337 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
372 intensity = 127.0f / sqrt(DotProduct(v, v));
373 data[side][y][x][0] = (unsigned char)(128.0f + intensity * v[0]);
374 data[side][y][x][1] = (unsigned char)(128.0f + intensity * v[1]);
375 data[side][y][x][2] = (unsigned char)(128.0f + intensity * v[2]);
376 data[side][y][x][3] = 255;
380 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, &data[0][0][0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
383 static void R_BuildFogTexture(void)
388 unsigned char data1[FOGWIDTH][4];
389 //unsigned char data2[FOGWIDTH][4];
390 r = (-1.0/256.0) * (FOGWIDTH * FOGWIDTH);
391 for (x = 0;x < FOGWIDTH;x++)
393 alpha = exp(r / ((double)x*(double)x));
394 if (x == FOGWIDTH - 1)
396 b = (int)(256.0 * alpha);
397 b = bound(0, b, 255);
398 data1[x][0] = 255 - b;
399 data1[x][1] = 255 - b;
400 data1[x][2] = 255 - b;
407 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
408 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
411 static const char *builtinshaderstring =
412 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
413 "// written by Forest 'LordHavoc' Hale\n"
415 "// common definitions between vertex shader and fragment shader:\n"
417 "varying vec2 TexCoord;\n"
418 "varying vec2 TexCoordLightmap;\n"
420 "varying vec3 CubeVector;\n"
421 "varying vec3 LightVector;\n"
422 "varying vec3 EyeVector;\n"
424 "varying vec3 EyeVectorModelSpace;\n"
427 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
428 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
429 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
434 "// vertex shader specific:\n"
435 "#ifdef VERTEX_SHADER\n"
437 "uniform vec3 LightPosition;\n"
438 "uniform vec3 EyePosition;\n"
439 "uniform vec3 LightDir;\n"
441 "// TODO: get rid of tangentt (texcoord2) and use a crossproduct to regenerate it from tangents (texcoord1) and normal (texcoord3)\n"
445 " gl_FrontColor = gl_Color;\n"
446 " // copy the surface texcoord\n"
447 " TexCoord = vec2(gl_TextureMatrix[0] * gl_MultiTexCoord0);\n"
448 "#if !defined(MODE_LIGHTSOURCE) && !defined(MODE_LIGHTDIRECTION)\n"
449 " TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
452 "#ifdef MODE_LIGHTSOURCE\n"
453 " // transform vertex position into light attenuation/cubemap space\n"
454 " // (-1 to +1 across the light box)\n"
455 " CubeVector = vec3(gl_TextureMatrix[3] * gl_Vertex);\n"
457 " // transform unnormalized light direction into tangent space\n"
458 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
459 " // normalize it per pixel)\n"
460 " vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
461 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
462 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
463 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
466 "#ifdef MODE_LIGHTDIRECTION\n"
467 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
468 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
469 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
472 " // transform unnormalized eye direction into tangent space\n"
474 " vec3 EyeVectorModelSpace;\n"
476 " EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
477 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
478 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
479 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
481 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
482 " VectorS = gl_MultiTexCoord1.xyz;\n"
483 " VectorT = gl_MultiTexCoord2.xyz;\n"
484 " VectorR = gl_MultiTexCoord3.xyz;\n"
487 " // transform vertex to camera space, using ftransform to match non-VS\n"
489 " gl_Position = ftransform();\n"
492 "#endif // VERTEX_SHADER\n"
497 "// fragment shader specific:\n"
498 "#ifdef FRAGMENT_SHADER\n"
500 "uniform sampler2D Texture_Normal;\n"
501 "uniform sampler2D Texture_Color;\n"
502 "uniform sampler2D Texture_Gloss;\n"
503 "uniform samplerCube Texture_Cube;\n"
504 "uniform sampler2D Texture_FogMask;\n"
505 "uniform sampler2D Texture_Pants;\n"
506 "uniform sampler2D Texture_Shirt;\n"
507 "uniform sampler2D Texture_Lightmap;\n"
508 "uniform sampler2D Texture_Deluxemap;\n"
509 "uniform sampler2D Texture_Glow;\n"
511 "uniform vec3 LightColor;\n"
512 "uniform vec3 AmbientColor;\n"
513 "uniform vec3 DiffuseColor;\n"
514 "uniform vec3 SpecularColor;\n"
515 "uniform vec3 Color_Pants;\n"
516 "uniform vec3 Color_Shirt;\n"
517 "uniform vec3 FogColor;\n"
519 "uniform float OffsetMapping_Scale;\n"
520 "uniform float OffsetMapping_Bias;\n"
521 "uniform float FogRangeRecip;\n"
523 "uniform float AmbientScale;\n"
524 "uniform float DiffuseScale;\n"
525 "uniform float SpecularScale;\n"
526 "uniform float SpecularPower;\n"
530 " // apply offsetmapping\n"
531 "#ifdef USEOFFSETMAPPING\n"
532 " vec2 TexCoordOffset = TexCoord;\n"
533 "#define TexCoord TexCoordOffset\n"
535 " vec3 eyedir = vec3(normalize(EyeVector));\n"
536 " float depthbias = 1.0 - eyedir.z; // should this be a -?\n"
537 " depthbias = 1.0 - depthbias * depthbias;\n"
539 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
540 " // 14 sample relief mapping: linear search and then binary search\n"
541 " vec3 OffsetVector = vec3(EyeVector.xy * (1.0 / EyeVector.z) * depthbias * OffsetMapping_Scale * vec2(-0.1, 0.1), -0.1);\n"
542 " vec3 RT = vec3(TexCoord - OffsetVector.xy * 10.0, 1.0) + OffsetVector;\n"
543 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
544 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
545 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
546 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
547 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
548 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
549 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
550 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
551 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;OffsetVector *= 0.5;RT -= OffsetVector;\n"
552 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;OffsetVector *= 0.5;RT -= OffsetVector;\n"
553 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;OffsetVector *= 0.5;RT -= OffsetVector;\n"
554 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;OffsetVector *= 0.5;RT -= OffsetVector;\n"
555 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;OffsetVector *= 0.5;RT -= OffsetVector;\n"
556 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;OffsetVector *= 0.5;RT -= OffsetVector;\n"
557 " TexCoord = RT.xy;\n"
559 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
560 " vec2 OffsetVector = vec2((EyeVector.xy * (1.0 / EyeVector.z) * depthbias) * OffsetMapping_Scale * vec2(-0.333, 0.333));\n"
561 " //TexCoord += OffsetVector * 3.0;\n"
562 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
563 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
564 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
568 " // combine the diffuse textures (base, pants, shirt)\n"
569 " vec4 color = vec4(texture2D(Texture_Color, TexCoord));\n"
570 "#ifdef USECOLORMAPPING\n"
571 " color.rgb += vec3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + vec3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
577 "#ifdef MODE_LIGHTSOURCE\n"
580 " // get the surface normal and light normal\n"
581 " vec3 surfacenormal = normalize(vec3(texture2D(Texture_Normal, TexCoord)) - 0.5);\n"
582 " vec3 diffusenormal = vec3(normalize(LightVector));\n"
584 " // calculate directional shading\n"
585 " color.rgb *= (AmbientScale + DiffuseScale * max(dot(surfacenormal, diffusenormal), 0.0));\n"
586 "#ifdef USESPECULAR\n"
587 " vec3 specularnormal = vec3(normalize(diffusenormal + vec3(normalize(EyeVector))));\n"
588 " color.rgb += vec3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(max(dot(surfacenormal, specularnormal), 0.0), SpecularPower);\n"
591 "#ifdef USECUBEFILTER\n"
592 " // apply light cubemap filter\n"
593 " //color.rgb *= normalize(CubeVector) * 0.5 + 0.5;//vec3(textureCube(Texture_Cube, CubeVector));\n"
594 " color.rgb *= vec3(textureCube(Texture_Cube, CubeVector));\n"
597 " // apply light color\n"
598 " color.rgb *= LightColor;\n"
600 " // apply attenuation\n"
602 " // the attenuation is (1-(x*x+y*y+z*z)) which gives a large bright\n"
603 " // center and sharp falloff at the edge, this is about the most efficient\n"
604 " // we can get away with as far as providing illumination.\n"
606 " // pow(1-(x*x+y*y+z*z), 4) is far more realistic but needs large lights to\n"
607 " // provide significant illumination, large = slow = pain.\n"
608 " color.rgb *= max(1.0 - dot(CubeVector, CubeVector), 0.0);\n"
613 "#elif defined(MODE_LIGHTDIRECTION)\n"
614 " // directional model lighting\n"
616 " // get the surface normal and light normal\n"
617 " vec3 surfacenormal = normalize(vec3(texture2D(Texture_Normal, TexCoord)) - 0.5);\n"
618 " vec3 diffusenormal = vec3(normalize(LightVector));\n"
620 " // calculate directional shading\n"
621 " color.rgb *= AmbientColor + DiffuseColor * max(dot(surfacenormal, diffusenormal), 0.0);\n"
622 "#ifdef USESPECULAR\n"
623 " vec3 specularnormal = vec3(normalize(diffusenormal + vec3(normalize(EyeVector))));\n"
624 " color.rgb += vec3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(max(dot(surfacenormal, specularnormal), 0.0), SpecularPower);\n"
630 "#elif defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE)\n"
631 " // deluxemap lightmapping using light vectors in modelspace (evil q3map2)\n"
633 " // get the surface normal and light normal\n"
634 " vec3 surfacenormal = normalize(vec3(texture2D(Texture_Normal, TexCoord)) - 0.5);\n"
635 " vec3 diffusenormal_modelspace = vec3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - 0.5;\n"
636 " vec3 diffusenormal = normalize(vec3(dot(diffusenormal_modelspace, VectorS), dot(diffusenormal_modelspace, VectorT), dot(diffusenormal_modelspace, VectorR)));\n"
638 " // calculate directional shading\n"
639 " vec3 tempcolor = color.rgb * (DiffuseScale * max(dot(surfacenormal, diffusenormal), 0.0));\n"
640 "#ifdef USESPECULAR\n"
641 " vec3 specularnormal = vec3(normalize(diffusenormal + vec3(normalize(EyeVector))));\n"
642 " tempcolor += vec3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(max(dot(surfacenormal, specularnormal), 0.0), SpecularPower);\n"
645 " // apply lightmap color\n"
646 " color.rgb = tempcolor * vec3(texture2D(Texture_Lightmap, TexCoordLightmap)) + color.rgb * vec3(AmbientScale);\n"
651 "#elif defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
652 " // deluxemap lightmapping using light vectors in tangentspace\n"
654 " // get the surface normal and light normal\n"
655 " vec3 surfacenormal = normalize(vec3(texture2D(Texture_Normal, TexCoord)) - 0.5);\n"
656 " vec3 diffusenormal = normalize(vec3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - 0.5);\n"
658 " // calculate directional shading\n"
659 " vec3 tempcolor = color.rgb * (DiffuseScale * max(dot(surfacenormal, diffusenormal), 0.0));\n"
660 "#ifdef USESPECULAR\n"
661 " vec3 specularnormal = vec3(normalize(diffusenormal + vec3(normalize(EyeVector))));\n"
662 " tempcolor += vec3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(max(dot(surfacenormal, specularnormal), 0.0), SpecularPower);\n"
665 " // apply lightmap color\n"
666 " color.rgb = tempcolor * vec3(texture2D(Texture_Lightmap, TexCoordLightmap)) + color.rgb * vec3(AmbientScale);\n"
671 "#else // MODE none (lightmap)\n"
672 " // apply lightmap color\n"
673 " color.rgb *= vec3(texture2D(Texture_Lightmap, TexCoordLightmap)) * DiffuseScale + vec3(AmbientScale);\n"
676 " color *= gl_Color;\n"
679 " color.rgb += vec3(texture2D(Texture_Glow, TexCoord));\n"
684 " float fog = texture2D(Texture_FogMask, vec2(length(EyeVectorModelSpace)*FogRangeRecip, 0.0)).x;\n"
685 " color.rgb = color.rgb * fog + FogColor * (1.0 - fog);\n"
688 " gl_FragColor = color;\n"
691 "#endif // FRAGMENT_SHADER\n"
694 void R_GLSL_CompilePermutation(int permutation)
696 r_glsl_permutation_t *p = r_glsl_permutations + permutation;
697 int vertstrings_count;
698 int fragstrings_count;
700 const char *vertstrings_list[SHADERPERMUTATION_COUNT+1];
701 const char *fragstrings_list[SHADERPERMUTATION_COUNT+1];
702 char permutationname[256];
706 vertstrings_list[0] = "#define VERTEX_SHADER\n";
707 fragstrings_list[0] = "#define FRAGMENT_SHADER\n";
708 vertstrings_count = 1;
709 fragstrings_count = 1;
710 permutationname[0] = 0;
711 if (permutation & SHADERPERMUTATION_MODE_LIGHTSOURCE)
713 vertstrings_list[vertstrings_count++] = "#define MODE_LIGHTSOURCE\n";
714 fragstrings_list[fragstrings_count++] = "#define MODE_LIGHTSOURCE\n";
715 strlcat(permutationname, " lightsource", sizeof(permutationname));
717 if (permutation & SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_MODELSPACE)
719 vertstrings_list[vertstrings_count++] = "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n";
720 fragstrings_list[fragstrings_count++] = "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n";
721 strlcat(permutationname, " lightdirectionmap_modelspace", sizeof(permutationname));
723 if (permutation & SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)
725 vertstrings_list[vertstrings_count++] = "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n";
726 fragstrings_list[fragstrings_count++] = "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n";
727 strlcat(permutationname, " lightdirectionmap_tangentspace", sizeof(permutationname));
729 if (permutation & SHADERPERMUTATION_MODE_LIGHTDIRECTION)
731 vertstrings_list[vertstrings_count++] = "#define MODE_LIGHTDIRECTION\n";
732 fragstrings_list[fragstrings_count++] = "#define MODE_LIGHTDIRECTION\n";
733 strlcat(permutationname, " lightdirection", sizeof(permutationname));
735 if (permutation & SHADERPERMUTATION_GLOW)
737 vertstrings_list[vertstrings_count++] = "#define USEGLOW\n";
738 fragstrings_list[fragstrings_count++] = "#define USEGLOW\n";
739 strlcat(permutationname, " glow", sizeof(permutationname));
741 if (permutation & SHADERPERMUTATION_COLORMAPPING)
743 vertstrings_list[vertstrings_count++] = "#define USECOLORMAPPING\n";
744 fragstrings_list[fragstrings_count++] = "#define USECOLORMAPPING\n";
745 strlcat(permutationname, " colormapping", sizeof(permutationname));
747 if (permutation & SHADERPERMUTATION_SPECULAR)
749 vertstrings_list[vertstrings_count++] = "#define USESPECULAR\n";
750 fragstrings_list[fragstrings_count++] = "#define USESPECULAR\n";
751 strlcat(permutationname, " specular", sizeof(permutationname));
753 if (permutation & SHADERPERMUTATION_FOG)
755 vertstrings_list[vertstrings_count++] = "#define USEFOG\n";
756 fragstrings_list[fragstrings_count++] = "#define USEFOG\n";
757 strlcat(permutationname, " fog", sizeof(permutationname));
759 if (permutation & SHADERPERMUTATION_CUBEFILTER)
761 vertstrings_list[vertstrings_count++] = "#define USECUBEFILTER\n";
762 fragstrings_list[fragstrings_count++] = "#define USECUBEFILTER\n";
763 strlcat(permutationname, " cubefilter", sizeof(permutationname));
765 if (permutation & SHADERPERMUTATION_OFFSETMAPPING)
767 vertstrings_list[vertstrings_count++] = "#define USEOFFSETMAPPING\n";
768 fragstrings_list[fragstrings_count++] = "#define USEOFFSETMAPPING\n";
769 strlcat(permutationname, " offsetmapping", sizeof(permutationname));
771 if (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING)
773 vertstrings_list[vertstrings_count++] = "#define USEOFFSETMAPPING_RELIEFMAPPING\n";
774 fragstrings_list[fragstrings_count++] = "#define USEOFFSETMAPPING_RELIEFMAPPING\n";
775 strlcat(permutationname, " OFFSETMAPPING_RELIEFMAPPING", sizeof(permutationname));
777 shaderstring = (char *)FS_LoadFile("glsl/default.glsl", r_main_mempool, false, NULL);
780 Con_DPrintf("GLSL shader text loaded from disk\n");
781 vertstrings_list[vertstrings_count++] = shaderstring;
782 fragstrings_list[fragstrings_count++] = shaderstring;
786 vertstrings_list[vertstrings_count++] = builtinshaderstring;
787 fragstrings_list[fragstrings_count++] = builtinshaderstring;
789 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, fragstrings_count, fragstrings_list);
793 qglUseProgramObjectARB(p->program);CHECKGLERROR
794 p->loc_Texture_Normal = qglGetUniformLocationARB(p->program, "Texture_Normal");
795 p->loc_Texture_Color = qglGetUniformLocationARB(p->program, "Texture_Color");
796 p->loc_Texture_Gloss = qglGetUniformLocationARB(p->program, "Texture_Gloss");
797 p->loc_Texture_Cube = qglGetUniformLocationARB(p->program, "Texture_Cube");
798 p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
799 p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
800 p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
801 p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
802 p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
803 p->loc_Texture_Glow = qglGetUniformLocationARB(p->program, "Texture_Glow");
804 p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
805 p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
806 p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
807 p->loc_LightColor = qglGetUniformLocationARB(p->program, "LightColor");
808 p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants");
809 p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt");
810 p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip");
811 p->loc_AmbientScale = qglGetUniformLocationARB(p->program, "AmbientScale");
812 p->loc_DiffuseScale = qglGetUniformLocationARB(p->program, "DiffuseScale");
813 p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
814 p->loc_SpecularScale = qglGetUniformLocationARB(p->program, "SpecularScale");
815 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
816 p->loc_AmbientColor = qglGetUniformLocationARB(p->program, "AmbientColor");
817 p->loc_DiffuseColor = qglGetUniformLocationARB(p->program, "DiffuseColor");
818 p->loc_SpecularColor = qglGetUniformLocationARB(p->program, "SpecularColor");
819 p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
820 if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal, 0);
821 if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color, 1);
822 if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss, 2);
823 if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube, 3);
824 if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask, 4);
825 if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants, 5);
826 if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt, 6);
827 if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap, 7);
828 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap, 8);
829 if (p->loc_Texture_Glow >= 0) qglUniform1iARB(p->loc_Texture_Glow, 9);
831 qglUseProgramObjectARB(0);CHECKGLERROR
834 Con_Printf("permutation%s failed for shader %s, some features may not work properly!\n", permutationname, "glsl/default.glsl");
836 Mem_Free(shaderstring);
839 void R_GLSL_Restart_f(void)
842 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
843 if (r_glsl_permutations[i].program)
844 GL_Backend_FreeProgram(r_glsl_permutations[i].program);
845 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
848 int R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting)
850 // select a permutation of the lighting shader appropriate to this
851 // combination of texture, entity, light source, and fogging, only use the
852 // minimum features necessary to avoid wasting rendering time in the
853 // fragment shader on features that are not being used
855 float specularscale = rsurface_texture->specularscale;
856 r_glsl_permutation = NULL;
857 if (r_shadow_rtlight)
859 permutation |= SHADERPERMUTATION_MODE_LIGHTSOURCE;
860 specularscale *= r_shadow_rtlight->specularscale;
861 if (r_shadow_rtlight->currentcubemap != r_texture_whitecube)
862 permutation |= SHADERPERMUTATION_CUBEFILTER;
866 if (!(rsurface_texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
869 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTION;
872 if (r_glsl_deluxemapping.integer >= 1 && r_refdef.worldmodel && r_refdef.worldmodel->brushq3.deluxemapping && rsurface_lightmaptexture)
874 if (r_refdef.worldmodel->brushq3.deluxemapping_modelspace)
875 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_MODELSPACE;
877 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
879 else if (r_glsl_deluxemapping.integer >= 2) // fake mode
880 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
883 if (rsurface_texture->skin.glow)
884 permutation |= SHADERPERMUTATION_GLOW;
886 if (specularscale > 0)
887 permutation |= SHADERPERMUTATION_SPECULAR;
889 permutation |= SHADERPERMUTATION_FOG;
890 if (rsurface_texture->colormapping)
891 permutation |= SHADERPERMUTATION_COLORMAPPING;
892 if (r_glsl_offsetmapping.integer)
894 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
895 if (r_glsl_offsetmapping_reliefmapping.integer)
896 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
898 if (!r_glsl_permutations[permutation].program)
900 if (!r_glsl_permutations[permutation].compiled)
901 R_GLSL_CompilePermutation(permutation);
902 if (!r_glsl_permutations[permutation].program)
904 // remove features until we find a valid permutation
906 for (i = SHADERPERMUTATION_COUNT-1;;i>>=1)
908 // reduce i more quickly whenever it would not remove any bits
912 if (!r_glsl_permutations[permutation].compiled)
913 R_GLSL_CompilePermutation(permutation);
914 if (r_glsl_permutations[permutation].program)
917 return 0; // utterly failed
921 r_glsl_permutation = r_glsl_permutations + permutation;
923 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
924 R_Mesh_TexMatrix(0, &rsurface_texture->currenttexmatrix);
925 if (permutation & SHADERPERMUTATION_MODE_LIGHTSOURCE)
927 if (r_glsl_permutation->loc_Texture_Cube >= 0 && r_shadow_rtlight) R_Mesh_TexBindCubeMap(3, R_GetTexture(r_shadow_rtlight->currentcubemap));
928 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]);
929 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
930 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_shadow_rtlight->ambientscale);
931 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_shadow_rtlight->diffusescale);
932 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, specularscale);
934 else if (permutation & SHADERPERMUTATION_MODE_LIGHTDIRECTION)
936 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
938 if (r_glsl_permutation->loc_AmbientColor >= 0)
939 qglUniform3fARB(r_glsl_permutation->loc_AmbientColor, 1, 1, 1);
940 if (r_glsl_permutation->loc_DiffuseColor >= 0)
941 qglUniform3fARB(r_glsl_permutation->loc_DiffuseColor, 0, 0, 0);
942 if (r_glsl_permutation->loc_SpecularColor >= 0)
943 qglUniform3fARB(r_glsl_permutation->loc_SpecularColor, 0, 0, 0);
944 if (r_glsl_permutation->loc_LightDir >= 0)
945 qglUniform3fARB(r_glsl_permutation->loc_LightDir, 0, 0, -1);
949 if (r_glsl_permutation->loc_AmbientColor >= 0)
950 qglUniform3fARB(r_glsl_permutation->loc_AmbientColor, rsurface_entity->modellight_ambient[0], rsurface_entity->modellight_ambient[1], rsurface_entity->modellight_ambient[2]);
951 if (r_glsl_permutation->loc_DiffuseColor >= 0)
952 qglUniform3fARB(r_glsl_permutation->loc_DiffuseColor, rsurface_entity->modellight_diffuse[0], rsurface_entity->modellight_diffuse[1], rsurface_entity->modellight_diffuse[2]);
953 if (r_glsl_permutation->loc_SpecularColor >= 0)
954 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);
955 if (r_glsl_permutation->loc_LightDir >= 0)
956 qglUniform3fARB(r_glsl_permutation->loc_LightDir, rsurface_entity->modellight_lightdir[0], rsurface_entity->modellight_lightdir[1], rsurface_entity->modellight_lightdir[2]);
961 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_ambient.value * 2.0f / 128.0f);
962 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_lightmapintensity * 2.0f);
963 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, r_lightmapintensity * specularscale * 2.0f);
965 if (r_glsl_permutation->loc_Texture_Normal >= 0) R_Mesh_TexBind(0, R_GetTexture(rsurface_texture->skin.nmap));
966 if (r_glsl_permutation->loc_Texture_Color >= 0) R_Mesh_TexBind(1, R_GetTexture(rsurface_texture->basetexture));
967 if (r_glsl_permutation->loc_Texture_Gloss >= 0) R_Mesh_TexBind(2, R_GetTexture(rsurface_texture->glosstexture));
968 //if (r_glsl_permutation->loc_Texture_Cube >= 0 && permutation & SHADERPERMUTATION_MODE_LIGHTSOURCE) R_Mesh_TexBindCubeMap(3, R_GetTexture(r_shadow_rtlight->currentcubemap));
969 if (r_glsl_permutation->loc_Texture_FogMask >= 0) R_Mesh_TexBind(4, R_GetTexture(r_texture_fogattenuation));
970 if (r_glsl_permutation->loc_Texture_Pants >= 0) R_Mesh_TexBind(5, R_GetTexture(rsurface_texture->skin.pants));
971 if (r_glsl_permutation->loc_Texture_Shirt >= 0) R_Mesh_TexBind(6, R_GetTexture(rsurface_texture->skin.shirt));
972 //if (r_glsl_permutation->loc_Texture_Lightmap >= 0) R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
973 //if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
974 if (r_glsl_permutation->loc_Texture_Glow >= 0) R_Mesh_TexBind(9, R_GetTexture(rsurface_texture->skin.glow));
975 if (r_glsl_permutation->loc_FogColor >= 0)
977 // additive passes are only darkened by fog, not tinted
978 if (r_shadow_rtlight || (rsurface_texture->currentmaterialflags & MATERIALFLAG_ADD))
979 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
981 qglUniform3fARB(r_glsl_permutation->loc_FogColor, fogcolor[0], fogcolor[1], fogcolor[2]);
983 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface_modelorg[0], rsurface_modelorg[1], rsurface_modelorg[2]);
984 if (r_glsl_permutation->loc_Color_Pants >= 0)
986 if (rsurface_texture->skin.pants)
987 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface_entity->colormap_pantscolor[0], rsurface_entity->colormap_pantscolor[1], rsurface_entity->colormap_pantscolor[2]);
989 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
991 if (r_glsl_permutation->loc_Color_Shirt >= 0)
993 if (rsurface_texture->skin.shirt)
994 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface_entity->colormap_shirtcolor[0], rsurface_entity->colormap_shirtcolor[1], rsurface_entity->colormap_shirtcolor[2]);
996 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
998 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, fograngerecip);
999 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface_texture->specularpower);
1000 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
1005 void R_SwitchSurfaceShader(int permutation)
1007 if (r_glsl_permutation != r_glsl_permutations + permutation)
1009 r_glsl_permutation = r_glsl_permutations + permutation;
1011 qglUseProgramObjectARB(r_glsl_permutation->program);
1016 void gl_main_start(void)
1018 r_main_texturepool = R_AllocTexturePool();
1019 r_bloom_texture_screen = NULL;
1020 r_bloom_texture_bloom = NULL;
1021 R_BuildBlankTextures();
1023 if (gl_texturecubemap)
1026 R_BuildNormalizationCube();
1028 R_BuildFogTexture();
1029 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
1032 void gl_main_shutdown(void)
1034 R_FreeTexturePool(&r_main_texturepool);
1035 r_bloom_texture_screen = NULL;
1036 r_bloom_texture_bloom = NULL;
1037 r_texture_blanknormalmap = NULL;
1038 r_texture_white = NULL;
1039 r_texture_black = NULL;
1040 r_texture_whitecube = NULL;
1041 r_texture_normalizationcube = NULL;
1045 extern void CL_ParseEntityLump(char *entitystring);
1046 void gl_main_newmap(void)
1048 // FIXME: move this code to client
1050 char *entities, entname[MAX_QPATH];
1054 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
1055 l = (int)strlen(entname) - 4;
1056 if (l >= 0 && !strcmp(entname + l, ".bsp"))
1058 strcpy(entname + l, ".ent");
1059 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
1061 CL_ParseEntityLump(entities);
1066 if (cl.worldmodel->brush.entities)
1067 CL_ParseEntityLump(cl.worldmodel->brush.entities);
1071 void GL_Main_Init(void)
1073 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
1075 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed\n");
1076 FOG_registercvars(); // FIXME: move this fog stuff to client?
1077 Cvar_RegisterVariable(&r_nearclip);
1078 Cvar_RegisterVariable(&r_showsurfaces);
1079 Cvar_RegisterVariable(&r_showtris);
1080 Cvar_RegisterVariable(&r_shownormals);
1081 Cvar_RegisterVariable(&r_showlighting);
1082 Cvar_RegisterVariable(&r_showshadowvolumes);
1083 Cvar_RegisterVariable(&r_showcollisionbrushes);
1084 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
1085 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
1086 Cvar_RegisterVariable(&r_showdisabledepthtest);
1087 Cvar_RegisterVariable(&r_drawentities);
1088 Cvar_RegisterVariable(&r_drawviewmodel);
1089 Cvar_RegisterVariable(&r_speeds);
1090 Cvar_RegisterVariable(&r_fullbrights);
1091 Cvar_RegisterVariable(&r_wateralpha);
1092 Cvar_RegisterVariable(&r_dynamic);
1093 Cvar_RegisterVariable(&r_fullbright);
1094 Cvar_RegisterVariable(&r_q1bsp_skymasking);
1095 Cvar_RegisterVariable(&r_textureunits);
1096 Cvar_RegisterVariable(&r_glsl);
1097 Cvar_RegisterVariable(&r_glsl_offsetmapping);
1098 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
1099 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
1100 Cvar_RegisterVariable(&r_glsl_deluxemapping);
1101 Cvar_RegisterVariable(&r_lerpsprites);
1102 Cvar_RegisterVariable(&r_lerpmodels);
1103 Cvar_RegisterVariable(&r_waterscroll);
1104 Cvar_RegisterVariable(&r_bloom);
1105 Cvar_RegisterVariable(&r_bloom_intensity);
1106 Cvar_RegisterVariable(&r_bloom_blur);
1107 Cvar_RegisterVariable(&r_bloom_resolution);
1108 Cvar_RegisterVariable(&r_bloom_power);
1109 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
1110 Cvar_RegisterVariable(&developer_texturelogging);
1111 Cvar_RegisterVariable(&gl_lightmaps);
1112 Cvar_RegisterVariable(&r_test);
1113 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
1114 Cvar_SetValue("r_fullbrights", 0);
1115 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
1118 static vec3_t r_farclip_origin;
1119 static vec3_t r_farclip_direction;
1120 static vec_t r_farclip_directiondist;
1121 static vec_t r_farclip_meshfarclip;
1122 static int r_farclip_directionbit0;
1123 static int r_farclip_directionbit1;
1124 static int r_farclip_directionbit2;
1126 // enlarge farclip to accomodate box
1127 static void R_FarClip_Box(vec3_t mins, vec3_t maxs)
1130 d = (r_farclip_directionbit0 ? mins[0] : maxs[0]) * r_farclip_direction[0]
1131 + (r_farclip_directionbit1 ? mins[1] : maxs[1]) * r_farclip_direction[1]
1132 + (r_farclip_directionbit2 ? mins[2] : maxs[2]) * r_farclip_direction[2];
1133 if (r_farclip_meshfarclip < d)
1134 r_farclip_meshfarclip = d;
1137 // return farclip value
1138 static float R_FarClip(vec3_t origin, vec3_t direction, vec_t startfarclip)
1142 VectorCopy(origin, r_farclip_origin);
1143 VectorCopy(direction, r_farclip_direction);
1144 r_farclip_directiondist = DotProduct(r_farclip_origin, r_farclip_direction);
1145 r_farclip_directionbit0 = r_farclip_direction[0] < 0;
1146 r_farclip_directionbit1 = r_farclip_direction[1] < 0;
1147 r_farclip_directionbit2 = r_farclip_direction[2] < 0;
1148 r_farclip_meshfarclip = r_farclip_directiondist + startfarclip;
1150 if (r_refdef.worldmodel)
1151 R_FarClip_Box(r_refdef.worldmodel->normalmins, r_refdef.worldmodel->normalmaxs);
1152 for (i = 0;i < r_refdef.numentities;i++)
1153 R_FarClip_Box(r_refdef.entities[i]->mins, r_refdef.entities[i]->maxs);
1155 return r_farclip_meshfarclip - r_farclip_directiondist;
1158 extern void R_Textures_Init(void);
1159 extern void GL_Draw_Init(void);
1160 extern void GL_Main_Init(void);
1161 extern void R_Shadow_Init(void);
1162 extern void R_Sky_Init(void);
1163 extern void GL_Surf_Init(void);
1164 extern void R_Crosshairs_Init(void);
1165 extern void R_Light_Init(void);
1166 extern void R_Particles_Init(void);
1167 extern void R_Explosion_Init(void);
1168 extern void gl_backend_init(void);
1169 extern void Sbar_Init(void);
1170 extern void R_LightningBeams_Init(void);
1171 extern void Mod_RenderInit(void);
1173 void Render_Init(void)
1183 R_Crosshairs_Init();
1188 R_LightningBeams_Init();
1197 extern char *ENGINE_EXTENSIONS;
1200 VID_CheckExtensions();
1202 // LordHavoc: report supported extensions
1203 Con_DPrintf("\nengine extensions: %s\n", vm_sv_extensions );
1205 // clear to black (loading plaque will be seen over this)
1207 qglClearColor(0,0,0,1);CHECKGLERROR
1208 qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
1211 int R_CullBox(const vec3_t mins, const vec3_t maxs)
1215 for (i = 0;i < 4;i++)
1222 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1226 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1230 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1234 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1238 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1242 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1246 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1250 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1258 //==================================================================================
1260 static void R_UpdateEntityLighting(entity_render_t *ent)
1262 vec3_t tempdiffusenormal;
1263 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));
1264 VectorClear(ent->modellight_diffuse);
1265 VectorClear(ent->modellight_lightdir);
1266 if ((ent->flags & RENDER_LIGHT) && r_refdef.worldmodel && r_refdef.worldmodel->brush.LightPoint)
1267 r_refdef.worldmodel->brush.LightPoint(r_refdef.worldmodel, ent->origin, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
1269 VectorSet(ent->modellight_ambient, 1, 1, 1);
1270 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
1271 VectorNormalize(ent->modellight_lightdir);
1272 ent->modellight_ambient[0] *= ent->colormod[0] * r_lightmapintensity;
1273 ent->modellight_ambient[1] *= ent->colormod[1] * r_lightmapintensity;
1274 ent->modellight_ambient[2] *= ent->colormod[2] * r_lightmapintensity;
1275 ent->modellight_diffuse[0] *= ent->colormod[0] * r_lightmapintensity;
1276 ent->modellight_diffuse[1] *= ent->colormod[1] * r_lightmapintensity;
1277 ent->modellight_diffuse[2] *= ent->colormod[2] * r_lightmapintensity;
1280 static void R_MarkEntities (void)
1283 entity_render_t *ent;
1285 if (!r_drawentities.integer)
1288 r_refdef.worldentity->visframe = r_framecount;
1289 renderimask = envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : (chase_active.integer ? 0 : RENDER_EXTERIORMODEL);
1290 if (r_refdef.worldmodel && r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs)
1292 // worldmodel can check visibility
1293 for (i = 0;i < r_refdef.numentities;i++)
1295 ent = r_refdef.entities[i];
1296 // some of the renderer still relies on origin...
1297 Matrix4x4_OriginFromMatrix(&ent->matrix, ent->origin);
1298 // some of the renderer still relies on scale...
1299 ent->scale = Matrix4x4_ScaleFromMatrix(&ent->matrix);
1300 if (!(ent->flags & renderimask) && !R_CullBox(ent->mins, ent->maxs) && ((ent->effects & EF_NODEPTHTEST) || r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs(r_refdef.worldmodel, r_worldleafvisible, ent->mins, ent->maxs)))
1302 ent->visframe = r_framecount;
1303 R_UpdateEntityLighting(ent);
1309 // no worldmodel or it can't check visibility
1310 for (i = 0;i < r_refdef.numentities;i++)
1312 ent = r_refdef.entities[i];
1313 // some of the renderer still relies on origin...
1314 Matrix4x4_OriginFromMatrix(&ent->matrix, ent->origin);
1315 // some of the renderer still relies on scale...
1316 ent->scale = Matrix4x4_ScaleFromMatrix(&ent->matrix);
1317 if (!(ent->flags & renderimask) && !R_CullBox(ent->mins, ent->maxs) && (ent->effects & EF_NODEPTHTEST))
1319 ent->visframe = r_framecount;
1320 R_UpdateEntityLighting(ent);
1326 // only used if skyrendermasked, and normally returns false
1327 int R_DrawBrushModelsSky (void)
1330 entity_render_t *ent;
1332 if (!r_drawentities.integer)
1336 for (i = 0;i < r_refdef.numentities;i++)
1338 ent = r_refdef.entities[i];
1339 if (ent->visframe == r_framecount && ent->model && ent->model->DrawSky)
1341 ent->model->DrawSky(ent);
1348 void R_DrawNoModel(entity_render_t *ent);
1349 void R_DrawModels(void)
1352 entity_render_t *ent;
1354 if (!r_drawentities.integer)
1357 for (i = 0;i < r_refdef.numentities;i++)
1359 ent = r_refdef.entities[i];
1360 if (ent->visframe == r_framecount)
1362 renderstats.entities++;
1363 if (ent->model && ent->model->Draw != NULL)
1364 ent->model->Draw(ent);
1371 static void R_SetFrustum(void)
1373 // break apart the view matrix into vectors for various purposes
1374 Matrix4x4_ToVectors(&r_view_matrix, r_viewforward, r_viewleft, r_viewup, r_vieworigin);
1375 VectorNegate(r_viewleft, r_viewright);
1378 frustum[0].normal[0] = 0 - 1.0 / r_refdef.frustum_x;
1379 frustum[0].normal[1] = 0 - 0;
1380 frustum[0].normal[2] = -1 - 0;
1381 frustum[1].normal[0] = 0 + 1.0 / r_refdef.frustum_x;
1382 frustum[1].normal[1] = 0 + 0;
1383 frustum[1].normal[2] = -1 + 0;
1384 frustum[2].normal[0] = 0 - 0;
1385 frustum[2].normal[1] = 0 - 1.0 / r_refdef.frustum_y;
1386 frustum[2].normal[2] = -1 - 0;
1387 frustum[3].normal[0] = 0 + 0;
1388 frustum[3].normal[1] = 0 + 1.0 / r_refdef.frustum_y;
1389 frustum[3].normal[2] = -1 + 0;
1393 zNear = r_nearclip.value;
1394 nudge = 1.0 - 1.0 / (1<<23);
1395 frustum[4].normal[0] = 0 - 0;
1396 frustum[4].normal[1] = 0 - 0;
1397 frustum[4].normal[2] = -1 - -nudge;
1398 frustum[4].dist = 0 - -2 * zNear * nudge;
1399 frustum[5].normal[0] = 0 + 0;
1400 frustum[5].normal[1] = 0 + 0;
1401 frustum[5].normal[2] = -1 + -nudge;
1402 frustum[5].dist = 0 + -2 * zNear * nudge;
1408 frustum[0].normal[0] = m[3] - m[0];
1409 frustum[0].normal[1] = m[7] - m[4];
1410 frustum[0].normal[2] = m[11] - m[8];
1411 frustum[0].dist = m[15] - m[12];
1413 frustum[1].normal[0] = m[3] + m[0];
1414 frustum[1].normal[1] = m[7] + m[4];
1415 frustum[1].normal[2] = m[11] + m[8];
1416 frustum[1].dist = m[15] + m[12];
1418 frustum[2].normal[0] = m[3] - m[1];
1419 frustum[2].normal[1] = m[7] - m[5];
1420 frustum[2].normal[2] = m[11] - m[9];
1421 frustum[2].dist = m[15] - m[13];
1423 frustum[3].normal[0] = m[3] + m[1];
1424 frustum[3].normal[1] = m[7] + m[5];
1425 frustum[3].normal[2] = m[11] + m[9];
1426 frustum[3].dist = m[15] + m[13];
1428 frustum[4].normal[0] = m[3] - m[2];
1429 frustum[4].normal[1] = m[7] - m[6];
1430 frustum[4].normal[2] = m[11] - m[10];
1431 frustum[4].dist = m[15] - m[14];
1433 frustum[5].normal[0] = m[3] + m[2];
1434 frustum[5].normal[1] = m[7] + m[6];
1435 frustum[5].normal[2] = m[11] + m[10];
1436 frustum[5].dist = m[15] + m[14];
1441 VectorMAM(1, r_viewforward, 1.0 / -r_refdef.frustum_x, r_viewleft, frustum[0].normal);
1442 VectorMAM(1, r_viewforward, 1.0 / r_refdef.frustum_x, r_viewleft, frustum[1].normal);
1443 VectorMAM(1, r_viewforward, 1.0 / -r_refdef.frustum_y, r_viewup, frustum[2].normal);
1444 VectorMAM(1, r_viewforward, 1.0 / r_refdef.frustum_y, r_viewup, frustum[3].normal);
1445 VectorCopy(r_viewforward, frustum[4].normal);
1446 VectorNormalize(frustum[0].normal);
1447 VectorNormalize(frustum[1].normal);
1448 VectorNormalize(frustum[2].normal);
1449 VectorNormalize(frustum[3].normal);
1450 frustum[0].dist = DotProduct (r_vieworigin, frustum[0].normal);
1451 frustum[1].dist = DotProduct (r_vieworigin, frustum[1].normal);
1452 frustum[2].dist = DotProduct (r_vieworigin, frustum[2].normal);
1453 frustum[3].dist = DotProduct (r_vieworigin, frustum[3].normal);
1454 frustum[4].dist = DotProduct (r_vieworigin, frustum[4].normal) + r_nearclip.value;
1455 PlaneClassify(&frustum[0]);
1456 PlaneClassify(&frustum[1]);
1457 PlaneClassify(&frustum[2]);
1458 PlaneClassify(&frustum[3]);
1459 PlaneClassify(&frustum[4]);
1461 // LordHavoc: note to all quake engine coders, Quake had a special case
1462 // for 90 degrees which assumed a square view (wrong), so I removed it,
1463 // Quake2 has it disabled as well.
1465 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
1466 //RotatePointAroundVector( frustum[0].normal, r_viewup, r_viewforward, -(90 - r_refdef.fov_x / 2));
1467 //frustum[0].dist = DotProduct (r_vieworigin, frustum[0].normal);
1468 //PlaneClassify(&frustum[0]);
1470 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
1471 //RotatePointAroundVector( frustum[1].normal, r_viewup, r_viewforward, (90 - r_refdef.fov_x / 2));
1472 //frustum[1].dist = DotProduct (r_vieworigin, frustum[1].normal);
1473 //PlaneClassify(&frustum[1]);
1475 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
1476 //RotatePointAroundVector( frustum[2].normal, r_viewleft, r_viewforward, -(90 - r_refdef.fov_y / 2));
1477 //frustum[2].dist = DotProduct (r_vieworigin, frustum[2].normal);
1478 //PlaneClassify(&frustum[2]);
1480 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
1481 //RotatePointAroundVector( frustum[3].normal, r_viewleft, r_viewforward, (90 - r_refdef.fov_y / 2));
1482 //frustum[3].dist = DotProduct (r_vieworigin, frustum[3].normal);
1483 //PlaneClassify(&frustum[3]);
1486 //VectorCopy(r_viewforward, frustum[4].normal);
1487 //frustum[4].dist = DotProduct (r_vieworigin, frustum[4].normal) + r_nearclip.value;
1488 //PlaneClassify(&frustum[4]);
1491 static void R_BlendView(void)
1493 int screenwidth, screenheight;
1497 float texcoord2f[3][8];
1499 // set the (poorly named) screenwidth and screenheight variables to
1500 // a power of 2 at least as large as the screen, these will define the
1501 // size of the texture to allocate
1502 for (screenwidth = 1;screenwidth < vid.width;screenwidth *= 2);
1503 for (screenheight = 1;screenheight < vid.height;screenheight *= 2);
1505 doblend = r_refdef.viewblend[3] >= 0.01f;
1506 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;
1508 if (!dobloom && !doblend)
1511 GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
1513 GL_DepthTest(false);
1514 R_Mesh_Matrix(&identitymatrix);
1515 // vertex coordinates for a quad that covers the screen exactly
1516 vertex3f[0] = 0;vertex3f[1] = 0;vertex3f[2] = 0;
1517 vertex3f[3] = 1;vertex3f[4] = 0;vertex3f[5] = 0;
1518 vertex3f[6] = 1;vertex3f[7] = 1;vertex3f[8] = 0;
1519 vertex3f[9] = 0;vertex3f[10] = 1;vertex3f[11] = 0;
1520 R_Mesh_VertexPointer(vertex3f);
1521 R_Mesh_ColorPointer(NULL);
1522 R_Mesh_ResetTextureState();
1525 int bloomwidth, bloomheight, x, range;
1526 float xoffset, yoffset, r;
1527 renderstats.bloom++;
1528 // allocate textures as needed
1529 if (!r_bloom_texture_screen)
1530 r_bloom_texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", screenwidth, screenheight, NULL, TEXTYPE_RGBA, TEXF_FORCENEAREST | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
1531 if (!r_bloom_texture_bloom)
1532 r_bloom_texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", screenwidth, screenheight, NULL, TEXTYPE_RGBA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
1533 // set bloomwidth and bloomheight to the bloom resolution that will be
1534 // used (often less than the screen resolution for faster rendering)
1535 bloomwidth = min(r_view_width, r_bloom_resolution.integer);
1536 bloomheight = min(r_view_height, bloomwidth * r_view_height / r_view_width);
1537 // set up a texcoord array for the full resolution screen image
1538 // (we have to keep this around to copy back during final render)
1539 texcoord2f[0][0] = 0;
1540 texcoord2f[0][1] = (float)r_view_height / (float)screenheight;
1541 texcoord2f[0][2] = (float)r_view_width / (float)screenwidth;
1542 texcoord2f[0][3] = (float)r_view_height / (float)screenheight;
1543 texcoord2f[0][4] = (float)r_view_width / (float)screenwidth;
1544 texcoord2f[0][5] = 0;
1545 texcoord2f[0][6] = 0;
1546 texcoord2f[0][7] = 0;
1547 // set up a texcoord array for the reduced resolution bloom image
1548 // (which will be additive blended over the screen image)
1549 texcoord2f[1][0] = 0;
1550 texcoord2f[1][1] = (float)bloomheight / (float)screenheight;
1551 texcoord2f[1][2] = (float)bloomwidth / (float)screenwidth;
1552 texcoord2f[1][3] = (float)bloomheight / (float)screenheight;
1553 texcoord2f[1][4] = (float)bloomwidth / (float)screenwidth;
1554 texcoord2f[1][5] = 0;
1555 texcoord2f[1][6] = 0;
1556 texcoord2f[1][7] = 0;
1557 R_Mesh_TexCoordPointer(0, 2, texcoord2f[0]);
1558 R_Mesh_TexBind(0, R_GetTexture(r_bloom_texture_screen));
1559 // copy view into the full resolution screen image texture
1560 GL_ActiveTexture(0);
1562 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
1563 renderstats.bloom_copypixels += r_view_width * r_view_height;
1564 // now scale it down to the bloom size and raise to a power of itself
1565 // to darken it (this leaves the really bright stuff bright, and
1566 // everything else becomes very dark)
1567 // TODO: optimize with multitexture or GLSL
1569 qglViewport(r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);CHECKGLERROR
1570 GL_BlendFunc(GL_ONE, GL_ZERO);
1571 GL_Color(1, 1, 1, 1);
1572 R_Mesh_Draw(0, 4, 2, polygonelements);
1573 renderstats.bloom_drawpixels += bloomwidth * bloomheight;
1574 // render multiple times with a multiply blendfunc to raise to a power
1575 GL_BlendFunc(GL_DST_COLOR, GL_ZERO);
1576 for (x = 1;x < r_bloom_power.integer;x++)
1578 R_Mesh_Draw(0, 4, 2, polygonelements);
1579 renderstats.bloom_drawpixels += bloomwidth * bloomheight;
1581 // we now have a darkened bloom image in the framebuffer, copy it into
1582 // the bloom image texture for more processing
1583 R_Mesh_TexBind(0, R_GetTexture(r_bloom_texture_bloom));
1584 R_Mesh_TexCoordPointer(0, 2, texcoord2f[2]);
1585 GL_ActiveTexture(0);
1587 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);CHECKGLERROR
1588 renderstats.bloom_copypixels += bloomwidth * bloomheight;
1589 // blend on at multiple vertical offsets to achieve a vertical blur
1590 // TODO: do offset blends using GLSL
1591 range = r_bloom_blur.integer * bloomwidth / 320;
1592 GL_BlendFunc(GL_ONE, GL_ZERO);
1593 for (x = -range;x <= range;x++)
1595 xoffset = 0 / (float)bloomwidth * (float)bloomwidth / (float)screenwidth;
1596 yoffset = x / (float)bloomheight * (float)bloomheight / (float)screenheight;
1597 // compute a texcoord array with the specified x and y offset
1598 texcoord2f[2][0] = xoffset+0;
1599 texcoord2f[2][1] = yoffset+(float)bloomheight / (float)screenheight;
1600 texcoord2f[2][2] = xoffset+(float)bloomwidth / (float)screenwidth;
1601 texcoord2f[2][3] = yoffset+(float)bloomheight / (float)screenheight;
1602 texcoord2f[2][4] = xoffset+(float)bloomwidth / (float)screenwidth;
1603 texcoord2f[2][5] = yoffset+0;
1604 texcoord2f[2][6] = xoffset+0;
1605 texcoord2f[2][7] = yoffset+0;
1606 // this r value looks like a 'dot' particle, fading sharply to
1607 // black at the edges
1608 // (probably not realistic but looks good enough)
1609 r = r_bloom_intensity.value/(range*2+1)*(1 - x*x/(float)(range*range));
1612 GL_Color(r, r, r, 1);
1613 R_Mesh_Draw(0, 4, 2, polygonelements);
1614 renderstats.bloom_drawpixels += bloomwidth * bloomheight;
1615 GL_BlendFunc(GL_ONE, GL_ONE);
1617 // copy the vertically blurred bloom view to a texture
1618 GL_ActiveTexture(0);
1620 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);CHECKGLERROR
1621 renderstats.bloom_copypixels += bloomwidth * bloomheight;
1622 // blend the vertically blurred image at multiple offsets horizontally
1623 // to finish the blur effect
1624 // TODO: do offset blends using GLSL
1625 range = r_bloom_blur.integer * bloomwidth / 320;
1626 GL_BlendFunc(GL_ONE, GL_ZERO);
1627 for (x = -range;x <= range;x++)
1629 xoffset = x / (float)bloomwidth * (float)bloomwidth / (float)screenwidth;
1630 yoffset = 0 / (float)bloomheight * (float)bloomheight / (float)screenheight;
1631 // compute a texcoord array with the specified x and y offset
1632 texcoord2f[2][0] = xoffset+0;
1633 texcoord2f[2][1] = yoffset+(float)bloomheight / (float)screenheight;
1634 texcoord2f[2][2] = xoffset+(float)bloomwidth / (float)screenwidth;
1635 texcoord2f[2][3] = yoffset+(float)bloomheight / (float)screenheight;
1636 texcoord2f[2][4] = xoffset+(float)bloomwidth / (float)screenwidth;
1637 texcoord2f[2][5] = yoffset+0;
1638 texcoord2f[2][6] = xoffset+0;
1639 texcoord2f[2][7] = yoffset+0;
1640 // this r value looks like a 'dot' particle, fading sharply to
1641 // black at the edges
1642 // (probably not realistic but looks good enough)
1643 r = r_bloom_intensity.value/(range*2+1)*(1 - x*x/(float)(range*range));
1646 GL_Color(r, r, r, 1);
1647 R_Mesh_Draw(0, 4, 2, polygonelements);
1648 renderstats.bloom_drawpixels += bloomwidth * bloomheight;
1649 GL_BlendFunc(GL_ONE, GL_ONE);
1651 // copy the blurred bloom view to a texture
1652 GL_ActiveTexture(0);
1654 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);CHECKGLERROR
1655 renderstats.bloom_copypixels += bloomwidth * bloomheight;
1656 // go back to full view area
1657 qglViewport(r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);CHECKGLERROR
1658 // put the original screen image back in place and blend the bloom
1661 GL_BlendFunc(GL_ONE, GL_ZERO);
1662 // do both in one pass if possible
1663 R_Mesh_TexBind(0, R_GetTexture(r_bloom_texture_screen));
1664 R_Mesh_TexCoordPointer(0, 2, texcoord2f[0]);
1665 if (r_textureunits.integer >= 2 && gl_combine.integer)
1667 R_Mesh_TexCombine(1, GL_ADD, GL_ADD, 1, 1);
1668 R_Mesh_TexBind(1, R_GetTexture(r_bloom_texture_bloom));
1669 R_Mesh_TexCoordPointer(1, 2, texcoord2f[1]);
1673 R_Mesh_Draw(0, 4, 2, polygonelements);
1674 renderstats.bloom_drawpixels += r_view_width * r_view_height;
1675 // now blend on the bloom texture
1676 GL_BlendFunc(GL_ONE, GL_ONE);
1677 R_Mesh_TexBind(0, R_GetTexture(r_bloom_texture_bloom));
1678 R_Mesh_TexCoordPointer(0, 2, texcoord2f[1]);
1680 R_Mesh_Draw(0, 4, 2, polygonelements);
1681 renderstats.bloom_drawpixels += r_view_width * r_view_height;
1685 // apply a color tint to the whole view
1686 R_Mesh_ResetTextureState();
1687 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1688 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
1689 R_Mesh_Draw(0, 4, 2, polygonelements);
1693 void R_RenderScene(void);
1695 matrix4x4_t r_waterscrollmatrix;
1702 void R_RenderView(void)
1704 if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
1705 return; //Host_Error ("R_RenderView: NULL worldmodel");
1707 r_view_width = bound(0, r_refdef.width, vid.width);
1708 r_view_height = bound(0, r_refdef.height, vid.height);
1710 r_view_x = bound(0, r_refdef.x, vid.width - r_refdef.width);
1711 r_view_y = bound(0, r_refdef.y, vid.height - r_refdef.height);
1713 r_view_matrix = r_refdef.viewentitymatrix;
1714 GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
1715 r_rtworld = r_shadow_realtime_world.integer;
1716 r_rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
1717 r_rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer;
1718 r_rtdlightshadows = r_rtdlight && (r_rtworld ? r_shadow_realtime_world_dlightshadows.integer : r_shadow_realtime_dlight_shadows.integer) && gl_stencil;
1719 r_lightmapintensity = r_rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
1720 r_polygonfactor = 0;
1721 r_polygonoffset = 0;
1722 r_shadowpolygonfactor = r_polygonfactor + r_shadow_shadow_polygonfactor.value;
1723 r_shadowpolygonoffset = r_polygonoffset + r_shadow_shadow_polygonoffset.value;
1724 if (r_showsurfaces.integer)
1727 r_rtworldshadows = false;
1729 r_rtdlightshadows = false;
1730 r_lightmapintensity = 0;
1733 // GL is weird because it's bottom to top, r_view_y is top to bottom
1735 qglViewport(r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);CHECKGLERROR
1736 GL_Scissor(r_view_x, r_view_y, r_view_width, r_view_height);
1737 GL_ScissorTest(true);
1742 if (r_timereport_active)
1743 R_TimeReport("setup");
1746 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
1747 qglPolygonOffset(r_polygonfactor, r_polygonoffset);CHECKGLERROR
1748 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
1753 qglPolygonOffset(r_polygonfactor, r_polygonoffset);CHECKGLERROR
1754 qglDisable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
1757 if (r_timereport_active)
1758 R_TimeReport("blendview");
1760 GL_Scissor(0, 0, vid.width, vid.height);
1761 GL_ScissorTest(false);
1766 void CSQC_R_ClearScreen (void)
1768 if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
1769 return; //Host_Error ("R_RenderView: NULL worldmodel");
1771 r_view_width = bound(0, r_refdef.width, vid.width);
1772 r_view_height = bound(0, r_refdef.height, vid.height);
1774 r_view_x = bound(0, r_refdef.x, vid.width - r_refdef.width);
1775 r_view_y = bound(0, r_refdef.y, vid.height - r_refdef.height);
1777 r_view_matrix = r_refdef.viewentitymatrix;
1778 GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
1779 r_rtworld = r_shadow_realtime_world.integer;
1780 r_rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
1781 r_rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer;
1782 r_rtdlightshadows = r_rtdlight && (r_rtworld ? r_shadow_realtime_world_dlightshadows.integer : r_shadow_realtime_dlight_shadows.integer) && gl_stencil;
1783 r_lightmapintensity = r_rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
1784 r_polygonfactor = 0;
1785 r_polygonoffset = 0;
1786 r_shadowpolygonfactor = r_polygonfactor + r_shadow_shadow_polygonfactor.value;
1787 r_shadowpolygonoffset = r_polygonoffset + r_shadow_shadow_polygonoffset.value;
1788 if (r_showsurfaces.integer)
1791 r_rtworldshadows = false;
1793 r_rtdlightshadows = false;
1794 r_lightmapintensity = 0;
1797 // GL is weird because it's bottom to top, r_view_y is top to bottom
1799 qglViewport(r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);CHECKGLERROR
1800 GL_Scissor(r_view_x, r_view_y, r_view_width, r_view_height);
1801 GL_ScissorTest(true);
1806 if (r_timereport_active)
1807 R_TimeReport("setup");
1812 void CSQC_R_RenderScene (void)
1815 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
1816 qglPolygonOffset(r_polygonfactor, r_polygonoffset);CHECKGLERROR
1817 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
1822 qglPolygonOffset(r_polygonfactor, r_polygonoffset);CHECKGLERROR
1823 qglDisable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
1826 if (r_timereport_active)
1827 R_TimeReport("blendview");
1829 GL_Scissor(0, 0, vid.width, vid.height);
1830 GL_ScissorTest(false);
1834 extern void R_DrawLightningBeams (void);
1835 extern void VM_AddPolygonsToMeshQueue (void);
1836 void R_RenderScene(void)
1840 // don't let sound skip if going slow
1841 if (r_refdef.extraupdate)
1847 if (gl_support_fragment_shader)
1849 qglUseProgramObjectARB(0);CHECKGLERROR
1852 R_MeshQueue_BeginScene();
1856 r_farclip = R_FarClip(r_vieworigin, r_viewforward, 768.0f) + 256.0f;
1857 nearclip = bound (0.001f, r_nearclip.value, r_farclip - 1.0f);
1859 if (r_rtworldshadows || r_rtdlightshadows)
1860 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_refdef.frustum_x, r_refdef.frustum_y, nearclip);
1862 GL_SetupView_Mode_Perspective(r_refdef.frustum_x, r_refdef.frustum_y, nearclip, r_farclip);
1864 GL_SetupView_Orientation_FromEntity(&r_view_matrix);
1866 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);
1870 R_WorldVisibility();
1871 if (r_timereport_active)
1872 R_TimeReport("worldvis");
1875 if (r_timereport_active)
1876 R_TimeReport("markentity");
1878 R_Shadow_UpdateWorldLightSelection();
1880 if (cl.csqc_vidvars.drawworld)
1882 // don't let sound skip if going slow
1883 if (r_refdef.extraupdate)
1886 if (r_refdef.worldmodel && r_refdef.worldmodel->DrawSky)
1888 r_refdef.worldmodel->DrawSky(r_refdef.worldentity);
1889 if (r_timereport_active)
1890 R_TimeReport("worldsky");
1893 if (R_DrawBrushModelsSky() && r_timereport_active)
1894 R_TimeReport("bmodelsky");
1896 if (r_refdef.worldmodel && r_refdef.worldmodel->Draw)
1898 r_refdef.worldmodel->Draw(r_refdef.worldentity);
1899 if (r_timereport_active)
1900 R_TimeReport("world");
1904 // don't let sound skip if going slow
1905 if (r_refdef.extraupdate)
1909 if (r_timereport_active)
1910 R_TimeReport("models");
1912 // don't let sound skip if going slow
1913 if (r_refdef.extraupdate)
1916 R_ShadowVolumeLighting(false);
1917 if (r_timereport_active)
1918 R_TimeReport("rtlights");
1920 // don't let sound skip if going slow
1921 if (r_refdef.extraupdate)
1924 if (cl.csqc_vidvars.drawworld)
1926 R_DrawLightningBeams();
1927 if (r_timereport_active)
1928 R_TimeReport("lightning");
1931 if (r_timereport_active)
1932 R_TimeReport("particles");
1935 if (r_timereport_active)
1936 R_TimeReport("explosions");
1939 R_MeshQueue_RenderTransparent();
1940 if (r_timereport_active)
1941 R_TimeReport("drawtrans");
1943 if (cl.csqc_vidvars.drawworld)
1946 if (r_timereport_active)
1947 R_TimeReport("coronas");
1949 if(cl.csqc_vidvars.drawcrosshair)
1951 R_DrawWorldCrosshair();
1952 if (r_timereport_active)
1953 R_TimeReport("crosshair");
1956 VM_AddPolygonsToMeshQueue();
1958 R_MeshQueue_Render();
1960 R_MeshQueue_EndScene();
1962 // don't let sound skip if going slow
1963 if (r_refdef.extraupdate)
1967 if (gl_support_fragment_shader)
1969 qglUseProgramObjectARB(0);CHECKGLERROR
1974 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
1977 float *v, *c, f1, f2, diff[3], vertex3f[8*3], color4f[8*4];
1978 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1979 GL_DepthMask(false);
1981 R_Mesh_Matrix(&identitymatrix);
1983 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2];
1984 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
1985 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
1986 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
1987 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
1988 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
1989 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
1990 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
1991 R_FillColors(color, 8, cr, cg, cb, ca);
1994 for (i = 0, v = vertex, c = color;i < 8;i++, v += 4, c += 4)
1996 f2 = VERTEXFOGTABLE(VectorDistance(v, r_vieworigin));
1998 c[0] = c[0] * f1 + fogcolor[0] * f2;
1999 c[1] = c[1] * f1 + fogcolor[1] * f2;
2000 c[2] = c[2] * f1 + fogcolor[2] * f2;
2003 R_Mesh_VertexPointer(vertex3f);
2004 R_Mesh_ColorPointer(color);
2005 R_Mesh_ResetTextureState();
2010 int nomodelelements[24] =
2022 float nomodelvertex3f[6*3] =
2032 float nomodelcolor4f[6*4] =
2034 0.0f, 0.0f, 0.5f, 1.0f,
2035 0.0f, 0.0f, 0.5f, 1.0f,
2036 0.0f, 0.5f, 0.0f, 1.0f,
2037 0.0f, 0.5f, 0.0f, 1.0f,
2038 0.5f, 0.0f, 0.0f, 1.0f,
2039 0.5f, 0.0f, 0.0f, 1.0f
2042 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight)
2047 R_Mesh_Matrix(&ent->matrix);
2049 if (ent->flags & EF_ADDITIVE)
2051 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2052 GL_DepthMask(false);
2054 else if (ent->alpha < 1)
2056 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2057 GL_DepthMask(false);
2061 GL_BlendFunc(GL_ONE, GL_ZERO);
2064 GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
2065 R_Mesh_VertexPointer(nomodelvertex3f);
2068 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
2069 R_Mesh_ColorPointer(color4f);
2070 f2 = VERTEXFOGTABLE(VectorDistance(ent->origin, r_vieworigin));
2072 for (i = 0, c = color4f;i < 6;i++, c += 4)
2074 c[0] = (c[0] * f1 + fogcolor[0] * f2);
2075 c[1] = (c[1] * f1 + fogcolor[1] * f2);
2076 c[2] = (c[2] * f1 + fogcolor[2] * f2);
2080 else if (ent->alpha != 1)
2082 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
2083 R_Mesh_ColorPointer(color4f);
2084 for (i = 0, c = color4f;i < 6;i++, c += 4)
2088 R_Mesh_ColorPointer(nomodelcolor4f);
2089 R_Mesh_ResetTextureState();
2090 R_Mesh_Draw(0, 6, 8, nomodelelements);
2093 void R_DrawNoModel(entity_render_t *ent)
2095 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
2096 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_vieworigin : ent->origin, R_DrawNoModel_TransparentCallback, ent, 0, r_shadow_rtlight);
2098 // R_DrawNoModelCallback(ent, 0);
2101 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
2103 vec3_t right1, right2, diff, normal;
2105 VectorSubtract (org2, org1, normal);
2107 // calculate 'right' vector for start
2108 VectorSubtract (r_vieworigin, org1, diff);
2109 CrossProduct (normal, diff, right1);
2110 VectorNormalize (right1);
2112 // calculate 'right' vector for end
2113 VectorSubtract (r_vieworigin, org2, diff);
2114 CrossProduct (normal, diff, right2);
2115 VectorNormalize (right2);
2117 vert[ 0] = org1[0] + width * right1[0];
2118 vert[ 1] = org1[1] + width * right1[1];
2119 vert[ 2] = org1[2] + width * right1[2];
2120 vert[ 3] = org1[0] - width * right1[0];
2121 vert[ 4] = org1[1] - width * right1[1];
2122 vert[ 5] = org1[2] - width * right1[2];
2123 vert[ 6] = org2[0] - width * right2[0];
2124 vert[ 7] = org2[1] - width * right2[1];
2125 vert[ 8] = org2[2] - width * right2[2];
2126 vert[ 9] = org2[0] + width * right2[0];
2127 vert[10] = org2[1] + width * right2[1];
2128 vert[11] = org2[2] + width * right2[2];
2131 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
2133 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)
2135 float fog = 0.0f, ifog;
2139 fog = VERTEXFOGTABLE(VectorDistance(origin, r_vieworigin));
2142 R_Mesh_Matrix(&identitymatrix);
2143 GL_BlendFunc(blendfunc1, blendfunc2);
2144 GL_DepthMask(false);
2145 GL_DepthTest(!depthdisable);
2147 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
2148 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
2149 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
2150 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
2151 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
2152 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
2153 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
2154 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
2155 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
2156 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
2157 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
2158 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
2160 R_Mesh_VertexPointer(vertex3f);
2161 R_Mesh_ColorPointer(NULL);
2162 R_Mesh_ResetTextureState();
2163 R_Mesh_TexBind(0, R_GetTexture(texture));
2164 R_Mesh_TexCoordPointer(0, 2, spritetexcoord2f);
2165 GL_Color(cr * ifog, cg * ifog, cb * ifog, ca);
2166 R_Mesh_Draw(0, 4, 2, polygonelements);
2168 if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
2170 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
2171 GL_BlendFunc(blendfunc1, GL_ONE);
2172 GL_Color(fogcolor[0] * fog, fogcolor[1] * fog, fogcolor[2] * fog, ca);
2173 R_Mesh_Draw(0, 4, 2, polygonelements);
2177 int R_Mesh_AddVertex3f(rmesh_t *mesh, const float *v)
2181 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
2182 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
2184 if (i == mesh->numvertices)
2186 if (mesh->numvertices < mesh->maxvertices)
2188 VectorCopy(v, vertex3f);
2189 mesh->numvertices++;
2191 return mesh->numvertices;
2197 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
2201 element[0] = R_Mesh_AddVertex3f(mesh, vertex3f);vertex3f += 3;
2202 element[1] = R_Mesh_AddVertex3f(mesh, vertex3f);vertex3f += 3;
2203 e = mesh->element3i + mesh->numtriangles * 3;
2204 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
2206 element[2] = R_Mesh_AddVertex3f(mesh, vertex3f);
2207 if (mesh->numtriangles < mesh->maxtriangles)
2212 mesh->numtriangles++;
2214 element[1] = element[2];
2218 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
2220 int planenum, planenum2;
2223 mplane_t *plane, *plane2;
2224 float temppoints[2][256*3];
2225 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
2229 PolygonF_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->normal[3], 1024.0*1024.0*1024.0);
2230 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
2232 if (planenum2 == planenum)
2234 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);
2237 if (tempnumpoints < 3)
2239 // generate elements forming a triangle fan for this polygon
2240 R_Mesh_AddPolygon3f(mesh, tempnumpoints, temppoints[w]);
2244 static void R_DrawCollisionBrush(const colbrushf_t *brush)
2247 R_Mesh_VertexPointer(brush->points->v);
2248 i = (int)(((size_t)brush) / sizeof(colbrushf_t));
2249 GL_Color((i & 31) * (1.0f / 32.0f), ((i >> 5) & 31) * (1.0f / 32.0f), ((i >> 10) & 31) * (1.0f / 32.0f), 0.2f);
2250 GL_LockArrays(0, brush->numpoints);
2251 R_Mesh_Draw(0, brush->numpoints, brush->numtriangles, brush->elements);
2252 GL_LockArrays(0, 0);
2255 static void R_DrawCollisionSurface(const entity_render_t *ent, const msurface_t *surface)
2258 if (!surface->num_collisiontriangles)
2260 R_Mesh_VertexPointer(surface->data_collisionvertex3f);
2261 i = (int)(((size_t)surface) / sizeof(msurface_t));
2262 GL_Color((i & 31) * (1.0f / 32.0f), ((i >> 5) & 31) * (1.0f / 32.0f), ((i >> 10) & 31) * (1.0f / 32.0f), 0.2f);
2263 GL_LockArrays(0, surface->num_collisionvertices);
2264 R_Mesh_Draw(0, surface->num_collisionvertices, surface->num_collisiontriangles, surface->data_collisionelement3i);
2265 GL_LockArrays(0, 0);
2268 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)
2270 texturelayer_t *layer;
2271 layer = t->currentlayers + t->currentnumlayers++;
2273 layer->depthmask = depthmask;
2274 layer->blendfunc1 = blendfunc1;
2275 layer->blendfunc2 = blendfunc2;
2276 layer->texture = texture;
2277 layer->texmatrix = *matrix;
2278 layer->color[0] = r;
2279 layer->color[1] = g;
2280 layer->color[2] = b;
2281 layer->color[3] = a;
2284 void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
2286 // FIXME: identify models using a better check than ent->model->brush.shadowmesh
2287 //int lightmode = ((ent->effects & EF_FULLBRIGHT) || ent->model->brush.shadowmesh) ? 0 : 2;
2290 texture_t *texture = t;
2291 model_t *model = ent->model;
2292 int s = ent->skinnum;
2293 if ((unsigned int)s >= (unsigned int)model->numskins)
2295 if (model->skinscenes)
2297 if (model->skinscenes[s].framecount > 1)
2298 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
2300 s = model->skinscenes[s].firstframe;
2303 t = t + s * model->num_surfaces;
2305 t = t->anim_frames[ent->frame != 0][(t->anim_total[ent->frame != 0] >= 2) ? ((int)(r_refdef.time * 5.0f) % t->anim_total[ent->frame != 0]) : 0];
2306 texture->currentframe = t;
2309 t->currentmaterialflags = t->basematerialflags;
2310 t->currentalpha = ent->alpha;
2311 if (t->basematerialflags & MATERIALFLAG_WATERALPHA)
2312 t->currentalpha *= r_wateralpha.value;
2313 if (!(ent->flags & RENDER_LIGHT))
2314 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
2315 if (ent->effects & EF_ADDITIVE)
2316 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_TRANSPARENT;
2317 else if (t->currentalpha < 1)
2318 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_TRANSPARENT;
2319 if (ent->effects & EF_NODEPTHTEST)
2320 t->currentmaterialflags |= MATERIALFLAG_NODEPTHTEST;
2321 if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
2322 t->currenttexmatrix = r_waterscrollmatrix;
2324 t->currenttexmatrix = identitymatrix;
2326 t->colormapping = VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f);
2327 t->basetexture = (!t->colormapping && t->skin.merged) ? t->skin.merged : t->skin.base;
2328 t->glosstexture = r_texture_white;
2329 t->specularpower = 8;
2330 t->specularscale = 0;
2331 if (r_shadow_gloss.integer > 0)
2335 if (r_shadow_glossintensity.value > 0)
2337 t->glosstexture = t->skin.gloss;
2338 t->specularscale = r_shadow_glossintensity.value;
2341 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
2342 t->specularscale = r_shadow_gloss2intensity.value;
2345 t->currentnumlayers = 0;
2346 if (!(t->currentmaterialflags & MATERIALFLAG_NODRAW))
2348 if (gl_lightmaps.integer)
2349 R_Texture_AddLayer(t, true, GL_ONE, GL_ZERO, TEXTURELAYERTYPE_LITTEXTURE_MULTIPASS, r_texture_white, &identitymatrix, 1, 1, 1, 1);
2350 else if (!(t->currentmaterialflags & MATERIALFLAG_SKY))
2352 int blendfunc1, blendfunc2, depthmask;
2353 if (t->currentmaterialflags & MATERIALFLAG_ADD)
2355 blendfunc1 = GL_SRC_ALPHA;
2356 blendfunc2 = GL_ONE;
2358 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
2360 blendfunc1 = GL_SRC_ALPHA;
2361 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
2363 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
2365 blendfunc1 = t->customblendfunc[0];
2366 blendfunc2 = t->customblendfunc[1];
2370 blendfunc1 = GL_ONE;
2371 blendfunc2 = GL_ZERO;
2373 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
2374 if (t->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL))
2376 rtexture_t *currentbasetexture;
2378 if (fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED))
2379 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
2380 currentbasetexture = (VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) < (1.0f / 1048576.0f) && t->skin.merged) ? t->skin.merged : t->skin.base;
2381 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2383 // fullbright is not affected by r_lightmapintensity
2384 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
2385 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->skin.pants)
2386 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);
2387 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->skin.shirt)
2388 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);
2394 // q3bsp has no lightmap updates, so the lightstylevalue that
2395 // would normally be baked into the lightmap must be
2396 // applied to the color
2397 if (ent->model->type == mod_brushq3)
2398 colorscale *= r_refdef.lightstylevalue[0] * (1.0f / 256.0f);
2399 colorscale *= r_lightmapintensity;
2400 if (r_textureunits.integer >= 2 && gl_combine.integer)
2401 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_LITTEXTURE_COMBINE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0] * colorscale, ent->colormod[1] * colorscale, ent->colormod[2] * colorscale, t->currentalpha);
2402 else if ((t->currentmaterialflags & MATERIALFLAG_BLENDED) == 0)
2403 R_Texture_AddLayer(t, true, GL_ONE, GL_ZERO, TEXTURELAYERTYPE_LITTEXTURE_MULTIPASS, currentbasetexture, &t->currenttexmatrix, ent->colormod[0] * colorscale * 0.5f, ent->colormod[1] * colorscale * 0.5f, ent->colormod[2] * colorscale * 0.5f, t->currentalpha);
2405 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_LITTEXTURE_VERTEX, currentbasetexture, &t->currenttexmatrix, ent->colormod[0] * colorscale, ent->colormod[1] * colorscale, ent->colormod[2] * colorscale, t->currentalpha);
2406 if (r_ambient.value >= (1.0f/64.0f))
2407 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);
2408 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->skin.pants)
2410 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE_VERTEX, 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);
2411 if (r_ambient.value >= (1.0f/64.0f))
2412 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);
2414 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->skin.shirt)
2416 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE_VERTEX, 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);
2417 if (r_ambient.value >= (1.0f/64.0f))
2418 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);
2421 if (t->skin.glow != NULL)
2422 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.glow, &t->currenttexmatrix, 1, 1, 1, t->currentalpha);
2423 if (fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
2425 // if this is opaque use alpha blend which will darken the earlier
2428 // if this is an alpha blended material, all the earlier passes
2429 // were darkened by fog already, so we only need to add the fog
2430 // color ontop through the fog mask texture
2432 // if this is an additive blended material, all the earlier passes
2433 // were darkened by fog already, and we should not add fog color
2434 // (because the background was not darkened, there is no fog color
2435 // that was lost behind it).
2436 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, fogcolor[0], fogcolor[1], fogcolor[2], t->currentalpha);
2443 void R_UpdateAllTextureInfo(entity_render_t *ent)
2447 for (i = 0;i < ent->model->num_textures;i++)
2448 R_UpdateTextureInfo(ent, ent->model->data_textures + i);
2451 int rsurface_array_size = 0;
2452 float *rsurface_array_modelvertex3f = NULL;
2453 float *rsurface_array_modelsvector3f = NULL;
2454 float *rsurface_array_modeltvector3f = NULL;
2455 float *rsurface_array_modelnormal3f = NULL;
2456 float *rsurface_array_deformedvertex3f = NULL;
2457 float *rsurface_array_deformedsvector3f = NULL;
2458 float *rsurface_array_deformedtvector3f = NULL;
2459 float *rsurface_array_deformednormal3f = NULL;
2460 float *rsurface_array_color4f = NULL;
2461 float *rsurface_array_texcoord3f = NULL;
2463 void R_Mesh_ResizeArrays(int newvertices)
2466 if (rsurface_array_size >= newvertices)
2468 if (rsurface_array_modelvertex3f)
2469 Mem_Free(rsurface_array_modelvertex3f);
2470 rsurface_array_size = (newvertices + 1023) & ~1023;
2471 base = (float *)Mem_Alloc(r_main_mempool, rsurface_array_size * sizeof(float[31]));
2472 rsurface_array_modelvertex3f = base + rsurface_array_size * 0;
2473 rsurface_array_modelsvector3f = base + rsurface_array_size * 3;
2474 rsurface_array_modeltvector3f = base + rsurface_array_size * 6;
2475 rsurface_array_modelnormal3f = base + rsurface_array_size * 9;
2476 rsurface_array_deformedvertex3f = base + rsurface_array_size * 12;
2477 rsurface_array_deformedsvector3f = base + rsurface_array_size * 15;
2478 rsurface_array_deformedtvector3f = base + rsurface_array_size * 18;
2479 rsurface_array_deformednormal3f = base + rsurface_array_size * 21;
2480 rsurface_array_texcoord3f = base + rsurface_array_size * 24;
2481 rsurface_array_color4f = base + rsurface_array_size * 27;
2484 float *rsurface_modelvertex3f;
2485 float *rsurface_modelsvector3f;
2486 float *rsurface_modeltvector3f;
2487 float *rsurface_modelnormal3f;
2488 float *rsurface_vertex3f;
2489 float *rsurface_svector3f;
2490 float *rsurface_tvector3f;
2491 float *rsurface_normal3f;
2492 float *rsurface_lightmapcolor4f;
2493 vec3_t rsurface_modelorg;
2494 qboolean rsurface_generatedvertex;
2495 const entity_render_t *rsurface_entity;
2496 const model_t *rsurface_model;
2497 texture_t *rsurface_texture;
2498 rtexture_t *rsurface_lightmaptexture;
2499 rsurfmode_t rsurface_mode;
2500 texture_t *rsurface_glsl_texture;
2501 qboolean rsurface_glsl_uselightmap;
2503 void RSurf_ActiveEntity(const entity_render_t *ent)
2505 Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, rsurface_modelorg);
2506 rsurface_entity = ent;
2507 rsurface_model = ent->model;
2508 if (rsurface_array_size < rsurface_model->surfmesh.num_vertices)
2509 R_Mesh_ResizeArrays(rsurface_model->surfmesh.num_vertices);
2510 R_Mesh_Matrix(&ent->matrix);
2511 Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, rsurface_modelorg);
2512 if ((rsurface_entity->frameblend[0].lerp != 1 || rsurface_entity->frameblend[0].frame != 0) && (rsurface_model->surfmesh.data_morphvertex3f || rsurface_model->surfmesh.data_vertexboneweights))
2514 rsurface_modelvertex3f = rsurface_array_modelvertex3f;
2515 rsurface_modelsvector3f = NULL;
2516 rsurface_modeltvector3f = NULL;
2517 rsurface_modelnormal3f = NULL;
2518 Mod_Alias_GetMesh_Vertex3f(rsurface_model, rsurface_entity->frameblend, rsurface_array_modelvertex3f);
2519 rsurface_generatedvertex = true;
2523 rsurface_modelvertex3f = rsurface_model->surfmesh.data_vertex3f;
2524 rsurface_modelsvector3f = rsurface_model->surfmesh.data_svector3f;
2525 rsurface_modeltvector3f = rsurface_model->surfmesh.data_tvector3f;
2526 rsurface_modelnormal3f = rsurface_model->surfmesh.data_normal3f;
2527 rsurface_generatedvertex = false;
2529 rsurface_vertex3f = rsurface_modelvertex3f;
2530 rsurface_svector3f = rsurface_modelsvector3f;
2531 rsurface_tvector3f = rsurface_modeltvector3f;
2532 rsurface_normal3f = rsurface_modelnormal3f;
2533 rsurface_mode = RSURFMODE_NONE;
2534 rsurface_lightmaptexture = NULL;
2535 rsurface_texture = NULL;
2536 rsurface_glsl_texture = NULL;
2537 rsurface_glsl_uselightmap = false;
2540 void RSurf_CleanUp(void)
2543 if (rsurface_mode == RSURFMODE_GLSL)
2545 qglUseProgramObjectARB(0);CHECKGLERROR
2547 GL_AlphaTest(false);
2548 rsurface_mode = RSURFMODE_NONE;
2549 rsurface_lightmaptexture = NULL;
2550 rsurface_texture = NULL;
2551 rsurface_glsl_texture = NULL;
2552 rsurface_glsl_uselightmap = false;
2555 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, msurface_t **texturesurfacelist)
2557 if (rsurface_generatedvertex)
2559 if (rsurface_texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
2560 generatetangents = true;
2561 if (generatetangents)
2562 generatenormals = true;
2563 if (generatenormals && !rsurface_modelnormal3f)
2565 rsurface_normal3f = rsurface_modelnormal3f = rsurface_array_modelnormal3f;
2566 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);
2568 if (generatetangents && !rsurface_modelsvector3f)
2570 rsurface_svector3f = rsurface_modelsvector3f = rsurface_array_modelsvector3f;
2571 rsurface_tvector3f = rsurface_modeltvector3f = rsurface_array_modeltvector3f;
2572 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);
2575 if (rsurface_texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
2577 int texturesurfaceindex;
2578 float center[3], forward[3], right[3], up[3], v[4][3];
2579 matrix4x4_t matrix1, imatrix1;
2580 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_viewforward, forward);
2581 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_viewright, right);
2582 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_viewup, up);
2583 // make deformed versions of only the vertices used by the specified surfaces
2584 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2587 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2588 // a single autosprite surface can contain multiple sprites...
2589 for (j = 0;j < surface->num_vertices - 3;j += 4)
2591 VectorClear(center);
2592 for (i = 0;i < 4;i++)
2593 VectorAdd(center, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
2594 VectorScale(center, 0.25f, center);
2595 if (rsurface_texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE2)
2597 forward[0] = rsurface_modelorg[0] - center[0];
2598 forward[1] = rsurface_modelorg[1] - center[1];
2600 VectorNormalize(forward);
2601 right[0] = forward[1];
2602 right[1] = -forward[0];
2604 VectorSet(up, 0, 0, 1);
2606 // FIXME: calculate vectors from triangle edges instead of using texture vectors as an easy way out?
2607 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);
2608 Matrix4x4_Invert_Simple(&imatrix1, &matrix1);
2609 for (i = 0;i < 4;i++)
2610 Matrix4x4_Transform(&imatrix1, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, v[i]);
2611 for (i = 0;i < 4;i++)
2612 VectorMAMAMAM(1, center, v[i][0], forward, v[i][1], right, v[i][2], up, rsurface_array_modelvertex3f + (surface->num_firstvertex+i+j) * 3);
2614 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);
2615 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);
2617 rsurface_vertex3f = rsurface_array_deformedvertex3f;
2618 rsurface_svector3f = rsurface_array_deformedsvector3f;
2619 rsurface_tvector3f = rsurface_array_deformedtvector3f;
2620 rsurface_normal3f = rsurface_array_deformednormal3f;
2622 R_Mesh_VertexPointer(rsurface_vertex3f);
2625 static void RSurf_Draw(const msurface_t *surface)
2627 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2628 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
2631 static void RSurf_DrawLightmap(const msurface_t *surface, float r, float g, float b, float a, int lightmode, qboolean applycolor, qboolean applyfog)
2639 vec3_t ambientcolor;
2640 vec3_t diffusecolor;
2642 VectorCopy(rsurface_entity->modellight_lightdir, lightdir);
2643 ambientcolor[0] = rsurface_entity->modellight_ambient[0] * r * 0.5f;
2644 ambientcolor[1] = rsurface_entity->modellight_ambient[1] * g * 0.5f;
2645 ambientcolor[2] = rsurface_entity->modellight_ambient[2] * b * 0.5f;
2646 diffusecolor[0] = rsurface_entity->modellight_diffuse[0] * r * 0.5f;
2647 diffusecolor[1] = rsurface_entity->modellight_diffuse[1] * g * 0.5f;
2648 diffusecolor[2] = rsurface_entity->modellight_diffuse[2] * b * 0.5f;
2649 if (VectorLength2(diffusecolor) > 0)
2651 int numverts = surface->num_vertices;
2652 v = rsurface_vertex3f + 3 * surface->num_firstvertex;
2653 c2 = rsurface_normal3f + 3 * surface->num_firstvertex;
2654 c = rsurface_array_color4f + 4 * surface->num_firstvertex;
2655 // q3-style directional shading
2656 for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
2658 if ((f = DotProduct(c2, lightdir)) > 0)
2659 VectorMA(ambientcolor, f, diffusecolor, c);
2661 VectorCopy(ambientcolor, c);
2669 rsurface_lightmapcolor4f = rsurface_array_color4f;
2673 r = ambientcolor[0];
2674 g = ambientcolor[1];
2675 b = ambientcolor[2];
2676 rsurface_lightmapcolor4f = NULL;
2679 else if (lightmode >= 1)
2681 if (surface->lightmapinfo && surface->lightmapinfo->stainsamples)
2683 for (i = 0, c = rsurface_array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
2685 if (surface->lightmapinfo->samples)
2687 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface_model->surfmesh.data_lightmapoffsets + surface->num_firstvertex)[i];
2688 float scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
2689 VectorScale(lm, scale, c);
2690 if (surface->lightmapinfo->styles[1] != 255)
2692 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
2694 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
2695 VectorMA(c, scale, lm, c);
2696 if (surface->lightmapinfo->styles[2] != 255)
2699 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
2700 VectorMA(c, scale, lm, c);
2701 if (surface->lightmapinfo->styles[3] != 255)
2704 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
2705 VectorMA(c, scale, lm, c);
2713 rsurface_lightmapcolor4f = rsurface_array_color4f;
2716 rsurface_lightmapcolor4f = rsurface_model->surfmesh.data_lightmapcolor4f;
2719 rsurface_lightmapcolor4f = NULL;
2722 if (rsurface_lightmapcolor4f)
2724 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)
2726 f = 1 - VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
2735 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)
2737 f = 1 - VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
2744 rsurface_lightmapcolor4f = rsurface_array_color4f;
2746 if (applycolor && rsurface_lightmapcolor4f)
2748 for (i = 0, c = (rsurface_lightmapcolor4f + 4 * surface->num_firstvertex), c2 = (rsurface_array_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, c += 4, c2 += 4)
2755 rsurface_lightmapcolor4f = rsurface_array_color4f;
2757 R_Mesh_ColorPointer(rsurface_lightmapcolor4f);
2758 GL_Color(r, g, b, a);
2759 RSurf_Draw(surface);
2762 static void R_DrawTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist)
2764 int texturesurfaceindex;
2766 qboolean applycolor;
2769 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_NODRAW)
2771 r_shadow_rtlight = NULL;
2772 renderstats.entities_surfaces += texturenumsurfaces;
2773 // FIXME: identify models using a better check than rsurface_model->brush.shadowmesh
2774 lightmode = ((rsurface_entity->effects & EF_FULLBRIGHT) || rsurface_model->brush.shadowmesh) ? 0 : 2;
2776 GL_DepthTest(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
2777 if ((rsurface_texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (rsurface_entity->flags & RENDER_NOCULLFACE))
2779 qglDisable(GL_CULL_FACE);CHECKGLERROR
2781 if (r_showsurfaces.integer)
2783 if (rsurface_mode != RSURFMODE_SHOWSURFACES)
2785 rsurface_mode = RSURFMODE_SHOWSURFACES;
2787 GL_BlendFunc(GL_ONE, GL_ZERO);
2788 R_Mesh_ColorPointer(NULL);
2789 R_Mesh_ResetTextureState();
2791 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
2792 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2794 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2795 int k = (int)(((size_t)surface) / sizeof(msurface_t));
2796 GL_Color((k & 15) * (1.0f / 16.0f), ((k >> 4) & 15) * (1.0f / 16.0f), ((k >> 8) & 15) * (1.0f / 16.0f), 0.2f);
2797 RSurf_Draw(surface);
2800 else if (rsurface_texture->currentmaterialflags & MATERIALFLAG_SKY)
2802 // transparent sky would be ridiculous
2803 if (!(rsurface_texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
2805 if (rsurface_mode != RSURFMODE_SKY)
2807 if (rsurface_mode == RSURFMODE_GLSL)
2809 qglUseProgramObjectARB(0);CHECKGLERROR
2811 rsurface_mode = RSURFMODE_SKY;
2814 skyrendernow = false;
2816 // restore entity matrix
2817 R_Mesh_Matrix(&rsurface_entity->matrix);
2820 // LordHavoc: HalfLife maps have freaky skypolys so don't use
2821 // skymasking on them, and Quake3 never did sky masking (unlike
2822 // software Quake and software Quake2), so disable the sky masking
2823 // in Quake3 maps as it causes problems with q3map2 sky tricks,
2824 // and skymasking also looks very bad when noclipping outside the
2825 // level, so don't use it then either.
2826 if (rsurface_model->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_worldnovis)
2828 GL_Color(fogcolor[0], fogcolor[1], fogcolor[2], 1);
2829 R_Mesh_ColorPointer(NULL);
2830 R_Mesh_ResetTextureState();
2831 if (skyrendermasked)
2833 // depth-only (masking)
2834 GL_ColorMask(0,0,0,0);
2835 // just to make sure that braindead drivers don't draw
2836 // anything despite that colormask...
2837 GL_BlendFunc(GL_ZERO, GL_ONE);
2842 GL_BlendFunc(GL_ONE, GL_ZERO);
2846 // LordHavoc: HalfLife maps have freaky skypolys so don't use
2847 // skymasking on them, and Quake3 never did sky masking (unlike
2848 // software Quake and software Quake2), so disable the sky masking
2849 // in Quake3 maps as it causes problems with q3map2 sky tricks,
2850 // and skymasking also looks very bad when noclipping outside the
2851 // level, so don't use it then either.
2852 if (rsurface_model->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_worldnovis)
2854 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
2855 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2857 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2858 RSurf_Draw(surface);
2860 if (skyrendermasked)
2861 GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
2865 else if (rsurface_texture->currentnumlayers && r_glsl.integer && gl_support_fragment_shader)
2867 if (rsurface_mode != RSURFMODE_GLSL)
2869 rsurface_mode = RSURFMODE_GLSL;
2870 rsurface_glsl_texture = NULL;
2871 rsurface_glsl_uselightmap = false;
2872 R_Mesh_ResetTextureState();
2874 if (rsurface_glsl_texture != rsurface_texture || rsurface_glsl_uselightmap != (rsurface_lightmaptexture != NULL))
2876 rsurface_glsl_texture = rsurface_texture;
2877 rsurface_glsl_uselightmap = rsurface_lightmaptexture != NULL;
2878 GL_BlendFunc(rsurface_texture->currentlayers[0].blendfunc1, rsurface_texture->currentlayers[0].blendfunc2);
2879 GL_DepthMask(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_BLENDED));
2880 GL_Color(rsurface_entity->colormod[0], rsurface_entity->colormod[1], rsurface_entity->colormod[2], rsurface_texture->currentalpha);
2881 R_SetupSurfaceShader(vec3_origin, lightmode == 2);
2882 //permutation_deluxemapping = permutation_lightmapping = R_SetupSurfaceShader(vec3_origin, lightmode == 2, false);
2883 //if (r_glsl_deluxemapping.integer)
2884 // permutation_deluxemapping = R_SetupSurfaceShader(vec3_origin, lightmode == 2, true);
2885 R_Mesh_TexCoordPointer(0, 2, rsurface_model->surfmesh.data_texcoordtexture2f);
2886 R_Mesh_TexCoordPointer(4, 2, rsurface_model->surfmesh.data_texcoordlightmap2f);
2887 GL_AlphaTest((rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2889 if (!r_glsl_permutation)
2891 RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
2892 R_Mesh_TexCoordPointer(1, 3, rsurface_svector3f);
2893 R_Mesh_TexCoordPointer(2, 3, rsurface_tvector3f);
2894 R_Mesh_TexCoordPointer(3, 3, rsurface_normal3f);
2895 if (rsurface_lightmaptexture)
2897 R_Mesh_TexBind(7, R_GetTexture(rsurface_lightmaptexture));
2898 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
2899 R_Mesh_TexBind(8, R_GetTexture(texturesurfacelist[0]->deluxemaptexture));
2900 R_Mesh_ColorPointer(NULL);
2904 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
2905 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
2906 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
2907 R_Mesh_ColorPointer(rsurface_model->surfmesh.data_lightmapcolor4f);
2909 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2911 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2912 RSurf_Draw(surface);
2915 else if (rsurface_texture->currentnumlayers)
2918 const texturelayer_t *layer;
2920 if (rsurface_mode != RSURFMODE_MULTIPASS)
2922 if (rsurface_mode == RSURFMODE_GLSL)
2924 qglUseProgramObjectARB(0);CHECKGLERROR
2926 rsurface_mode = RSURFMODE_MULTIPASS;
2928 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
2929 for (layerindex = 0, layer = rsurface_texture->currentlayers;layerindex < rsurface_texture->currentnumlayers;layerindex++, layer++)
2932 int layertexrgbscale;
2933 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2935 if (layerindex == 0)
2939 GL_AlphaTest(false);
2940 qglDepthFunc(GL_EQUAL);CHECKGLERROR
2943 GL_DepthMask(layer->depthmask);
2944 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
2945 if ((layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2) && (gl_combine.integer || layer->depthmask))
2947 layertexrgbscale = 4;
2948 VectorScale(layer->color, 0.25f, layercolor);
2950 else if ((layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1) && (gl_combine.integer || layer->depthmask))
2952 layertexrgbscale = 2;
2953 VectorScale(layer->color, 0.5f, layercolor);
2957 layertexrgbscale = 1;
2958 VectorScale(layer->color, 1.0f, layercolor);
2960 layercolor[3] = layer->color[3];
2961 R_Mesh_ColorPointer(NULL);
2962 GL_Color(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
2963 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
2964 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
2965 switch (layer->type)
2967 case TEXTURELAYERTYPE_LITTEXTURE_COMBINE:
2968 memset(&m, 0, sizeof(m));
2969 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordlightmap2f;
2970 m.tex[1] = R_GetTexture(layer->texture);
2971 m.texmatrix[1] = layer->texmatrix;
2972 m.texrgbscale[1] = layertexrgbscale;
2973 m.pointer_texcoord[1] = rsurface_model->surfmesh.data_texcoordtexture2f;
2974 R_Mesh_TextureState(&m);
2977 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2979 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2980 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2981 RSurf_DrawLightmap(surface, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 2, applycolor, applyfog);
2984 else if (rsurface_lightmaptexture)
2986 R_Mesh_TexBind(0, R_GetTexture(rsurface_lightmaptexture));
2987 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2989 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2990 RSurf_DrawLightmap(surface, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, applyfog);
2995 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2996 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2998 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2999 RSurf_DrawLightmap(surface, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 1, applycolor, applyfog);
3003 case TEXTURELAYERTYPE_LITTEXTURE_MULTIPASS:
3004 memset(&m, 0, sizeof(m));
3005 m.tex[0] = R_GetTexture(layer->texture);
3006 m.texmatrix[0] = layer->texmatrix;
3007 m.texrgbscale[0] = layertexrgbscale;
3008 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordlightmap2f;
3009 R_Mesh_TextureState(&m);
3012 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3014 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3015 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
3016 RSurf_DrawLightmap(surface, 1, 1, 1, 1, 2, false, false);
3019 else if (rsurface_lightmaptexture)
3021 R_Mesh_TexBind(0, R_GetTexture(rsurface_lightmaptexture));
3022 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3024 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3025 RSurf_DrawLightmap(surface, 1, 1, 1, 1, 0, false, false);
3030 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
3031 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3033 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3034 RSurf_DrawLightmap(surface, 1, 1, 1, 1, 1, false, false);
3037 GL_LockArrays(0, 0);
3038 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
3039 memset(&m, 0, sizeof(m));
3040 m.tex[0] = R_GetTexture(layer->texture);
3041 m.texmatrix[0] = layer->texmatrix;
3042 m.texrgbscale[0] = layertexrgbscale;
3043 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3044 R_Mesh_TextureState(&m);
3045 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3047 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3048 RSurf_DrawLightmap(surface, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, false);
3051 case TEXTURELAYERTYPE_LITTEXTURE_VERTEX:
3052 memset(&m, 0, sizeof(m));
3053 m.tex[0] = R_GetTexture(layer->texture);
3054 m.texmatrix[0] = layer->texmatrix;
3055 m.texrgbscale[0] = layertexrgbscale;
3056 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3057 R_Mesh_TextureState(&m);
3060 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3062 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3063 RSurf_DrawLightmap(surface, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 2, applycolor, applyfog);
3068 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3070 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3071 RSurf_DrawLightmap(surface, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 1, applycolor, applyfog);
3075 case TEXTURELAYERTYPE_TEXTURE:
3076 memset(&m, 0, sizeof(m));
3077 m.tex[0] = R_GetTexture(layer->texture);
3078 m.texmatrix[0] = layer->texmatrix;
3079 m.texrgbscale[0] = layertexrgbscale;
3080 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3081 R_Mesh_TextureState(&m);
3082 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3084 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3085 RSurf_DrawLightmap(surface, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, applyfog);
3088 case TEXTURELAYERTYPE_FOG:
3089 R_Mesh_ColorPointer(rsurface_array_color4f);
3092 memset(&m, 0, sizeof(m));
3093 m.tex[0] = R_GetTexture(layer->texture);
3094 m.texmatrix[0] = layer->texmatrix;
3095 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3096 R_Mesh_TextureState(&m);
3099 R_Mesh_ResetTextureState();
3100 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3104 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3105 for (i = 0, v = (rsurface_vertex3f + 3 * surface->num_firstvertex), c = (rsurface_array_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4)
3107 f = VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
3108 c[0] = layercolor[0];
3109 c[1] = layercolor[1];
3110 c[2] = layercolor[2];
3111 c[3] = f * layercolor[3];
3113 RSurf_Draw(surface);
3117 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
3119 GL_LockArrays(0, 0);
3120 // if trying to do overbright on first pass of an opaque surface
3121 // when combine is not supported, brighten as a post process
3122 if (layertexrgbscale > 1 && !gl_combine.integer && layer->depthmask)
3125 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
3126 R_Mesh_ColorPointer(NULL);
3127 GL_Color(1, 1, 1, 1);
3128 R_Mesh_ResetTextureState();
3129 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3131 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3132 for (scale = 1;scale < layertexrgbscale;scale <<= 1)
3133 RSurf_Draw(surface);
3135 GL_LockArrays(0, 0);
3139 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
3141 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3142 GL_AlphaTest(false);
3146 GL_LockArrays(0, 0);
3147 if ((rsurface_texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (rsurface_entity->flags & RENDER_NOCULLFACE))
3149 qglEnable(GL_CULL_FACE);CHECKGLERROR
3153 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight)
3155 msurface_t *surface = ent->model->data_surfaces + surfacenumber;
3157 if (surface->texture->basematerialflags & MATERIALFLAG_SKY)
3158 return; // transparent sky is too difficult
3160 RSurf_ActiveEntity(ent);
3161 R_UpdateTextureInfo(ent, surface->texture);
3162 rsurface_texture = surface->texture->currentframe;
3163 R_DrawTextureSurfaceList(1, &surface);
3167 void R_QueueTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist)
3169 int texturesurfaceindex;
3170 vec3_t tempcenter, center;
3171 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_BLENDED)
3173 // drawing sky transparently would be too difficult
3174 if (!(rsurface_texture->currentmaterialflags & MATERIALFLAG_SKY))
3176 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3178 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3179 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
3180 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
3181 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
3182 Matrix4x4_Transform(&rsurface_entity->matrix, tempcenter, center);
3183 R_MeshQueue_AddTransparent(rsurface_texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_vieworigin : center, R_DrawSurface_TransparentCallback, rsurface_entity, surface - rsurface_model->data_surfaces, r_shadow_rtlight);
3188 R_DrawTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
3191 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
3192 void R_DrawSurfaces(entity_render_t *ent, qboolean skysurfaces)
3194 int i, j, f, flagsmask;
3195 int counttriangles = 0;
3197 model_t *model = ent->model;
3198 const int maxsurfacelist = 1024;
3199 int numsurfacelist = 0;
3200 msurface_t *surfacelist[1024];
3204 RSurf_ActiveEntity(ent);
3206 // update light styles
3207 if (!skysurfaces && model->brushq1.light_styleupdatechains)
3209 msurface_t *surface, **surfacechain;
3210 for (i = 0;i < model->brushq1.light_styles;i++)
3212 if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
3214 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
3215 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
3216 for (;(surface = *surfacechain);surfacechain++)
3217 surface->cached_dlight = true;
3222 R_UpdateAllTextureInfo(ent);
3223 flagsmask = skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL);
3226 rsurface_lightmaptexture = NULL;
3227 rsurface_texture = NULL;
3229 if (ent == r_refdef.worldentity)
3231 msurface_t *surface;
3232 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
3234 if (!r_worldsurfacevisible[j])
3236 if (t != surface->texture || rsurface_lightmaptexture != surface->lightmaptexture)
3240 R_QueueTextureSurfaceList(numsurfacelist, surfacelist);
3243 t = surface->texture;
3244 rsurface_lightmaptexture = surface->lightmaptexture;
3245 rsurface_texture = t->currentframe;
3246 f = rsurface_texture->currentmaterialflags & flagsmask;
3248 if (f && surface->num_triangles)
3250 // if lightmap parameters changed, rebuild lightmap texture
3251 if (surface->cached_dlight)
3252 R_BuildLightMap(ent, surface);
3253 // add face to draw list
3254 surfacelist[numsurfacelist++] = surface;
3255 counttriangles += surface->num_triangles;
3256 if (numsurfacelist >= maxsurfacelist)
3258 R_QueueTextureSurfaceList(numsurfacelist, surfacelist);
3266 msurface_t *surface;
3267 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
3269 if (t != surface->texture || rsurface_lightmaptexture != surface->lightmaptexture)
3273 R_QueueTextureSurfaceList(numsurfacelist, surfacelist);
3276 t = surface->texture;
3277 rsurface_lightmaptexture = surface->lightmaptexture;
3278 rsurface_texture = t->currentframe;
3279 f = rsurface_texture->currentmaterialflags & flagsmask;
3281 if (f && surface->num_triangles)
3283 // if lightmap parameters changed, rebuild lightmap texture
3284 if (surface->cached_dlight)
3285 R_BuildLightMap(ent, surface);
3286 // add face to draw list
3287 surfacelist[numsurfacelist++] = surface;
3288 counttriangles += surface->num_triangles;
3289 if (numsurfacelist >= maxsurfacelist)
3291 R_QueueTextureSurfaceList(numsurfacelist, surfacelist);
3298 R_QueueTextureSurfaceList(numsurfacelist, surfacelist);
3299 renderstats.entities_triangles += counttriangles;
3302 if (r_showcollisionbrushes.integer && model->brush.num_brushes && !skysurfaces)
3305 const msurface_t *surface;
3308 R_Mesh_Matrix(&ent->matrix);
3309 R_Mesh_ColorPointer(NULL);
3310 R_Mesh_ResetTextureState();
3311 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
3312 GL_DepthMask(false);
3313 GL_DepthTest(!r_showdisabledepthtest.integer);
3314 qglPolygonOffset(r_polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_polygonoffset + r_showcollisionbrushes_polygonoffset.value);CHECKGLERROR
3315 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
3316 if (brush->colbrushf && brush->colbrushf->numtriangles)
3317 R_DrawCollisionBrush(brush->colbrushf);
3318 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
3319 if (surface->num_collisiontriangles)
3320 R_DrawCollisionSurface(ent, surface);
3321 qglPolygonOffset(r_polygonfactor, r_polygonoffset);CHECKGLERROR
3324 if (r_showtris.integer || r_shownormals.integer)
3327 msurface_t *surface;
3328 const int *elements;
3333 if (r_showdisabledepthtest.integer)
3335 qglDepthFunc(GL_ALWAYS);CHECKGLERROR
3337 GL_BlendFunc(GL_ONE, GL_ZERO);
3338 R_Mesh_ColorPointer(NULL);
3339 R_Mesh_ResetTextureState();
3340 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
3342 if (ent == r_refdef.worldentity && !r_worldsurfacevisible[j])
3344 rsurface_texture = surface->texture->currentframe;
3345 if ((rsurface_texture->currentmaterialflags & flagsmask) && surface->num_triangles)
3347 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
3348 if (r_showtris.integer)
3350 if (!rsurface_texture->currentlayers->depthmask)
3351 GL_Color(r_showtris.value, 0, 0, 1);
3352 else if (ent == r_refdef.worldentity)
3353 GL_Color(r_showtris.value, r_showtris.value, r_showtris.value, 1);
3355 GL_Color(0, r_showtris.value, 0, 1);
3356 elements = (ent->model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
3359 for (k = 0;k < surface->num_triangles;k++, elements += 3)
3361 qglArrayElement(elements[0]);qglArrayElement(elements[1]);
3362 qglArrayElement(elements[1]);qglArrayElement(elements[2]);
3363 qglArrayElement(elements[2]);qglArrayElement(elements[0]);
3368 if (r_shownormals.integer)
3370 GL_Color(r_shownormals.value, 0, 0, 1);
3372 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
3374 VectorCopy(rsurface_vertex3f + l * 3, v);
3375 qglVertex3f(v[0], v[1], v[2]);
3376 VectorMA(v, 8, rsurface_svector3f + l * 3, v);
3377 qglVertex3f(v[0], v[1], v[2]);
3381 GL_Color(0, 0, r_shownormals.value, 1);
3383 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
3385 VectorCopy(rsurface_vertex3f + l * 3, v);
3386 qglVertex3f(v[0], v[1], v[2]);
3387 VectorMA(v, 8, rsurface_tvector3f + l * 3, v);
3388 qglVertex3f(v[0], v[1], v[2]);
3392 GL_Color(0, r_shownormals.value, 0, 1);
3394 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
3396 VectorCopy(rsurface_vertex3f + l * 3, v);
3397 qglVertex3f(v[0], v[1], v[2]);
3398 VectorMA(v, 8, rsurface_normal3f + l * 3, v);
3399 qglVertex3f(v[0], v[1], v[2]);
3406 rsurface_texture = NULL;
3407 if (r_showdisabledepthtest.integer)
3409 qglDepthFunc(GL_LEQUAL);CHECKGLERROR