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, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
2047 // this is only called once per entity so numsurfaces is always 1, and
2048 // surfacelist is always {0}, so this code does not handle batches
2049 R_Mesh_Matrix(&ent->matrix);
2051 if (ent->flags & EF_ADDITIVE)
2053 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2054 GL_DepthMask(false);
2056 else if (ent->alpha < 1)
2058 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2059 GL_DepthMask(false);
2063 GL_BlendFunc(GL_ONE, GL_ZERO);
2066 GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
2067 R_Mesh_VertexPointer(nomodelvertex3f);
2070 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
2071 R_Mesh_ColorPointer(color4f);
2072 f2 = VERTEXFOGTABLE(VectorDistance(ent->origin, r_vieworigin));
2074 for (i = 0, c = color4f;i < 6;i++, c += 4)
2076 c[0] = (c[0] * f1 + fogcolor[0] * f2);
2077 c[1] = (c[1] * f1 + fogcolor[1] * f2);
2078 c[2] = (c[2] * f1 + fogcolor[2] * f2);
2082 else if (ent->alpha != 1)
2084 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
2085 R_Mesh_ColorPointer(color4f);
2086 for (i = 0, c = color4f;i < 6;i++, c += 4)
2090 R_Mesh_ColorPointer(nomodelcolor4f);
2091 R_Mesh_ResetTextureState();
2092 R_Mesh_Draw(0, 6, 8, nomodelelements);
2095 void R_DrawNoModel(entity_render_t *ent)
2097 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
2098 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_vieworigin : ent->origin, R_DrawNoModel_TransparentCallback, ent, 0, r_shadow_rtlight);
2100 // R_DrawNoModelCallback(ent, 0);
2103 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
2105 vec3_t right1, right2, diff, normal;
2107 VectorSubtract (org2, org1, normal);
2109 // calculate 'right' vector for start
2110 VectorSubtract (r_vieworigin, org1, diff);
2111 CrossProduct (normal, diff, right1);
2112 VectorNormalize (right1);
2114 // calculate 'right' vector for end
2115 VectorSubtract (r_vieworigin, org2, diff);
2116 CrossProduct (normal, diff, right2);
2117 VectorNormalize (right2);
2119 vert[ 0] = org1[0] + width * right1[0];
2120 vert[ 1] = org1[1] + width * right1[1];
2121 vert[ 2] = org1[2] + width * right1[2];
2122 vert[ 3] = org1[0] - width * right1[0];
2123 vert[ 4] = org1[1] - width * right1[1];
2124 vert[ 5] = org1[2] - width * right1[2];
2125 vert[ 6] = org2[0] - width * right2[0];
2126 vert[ 7] = org2[1] - width * right2[1];
2127 vert[ 8] = org2[2] - width * right2[2];
2128 vert[ 9] = org2[0] + width * right2[0];
2129 vert[10] = org2[1] + width * right2[1];
2130 vert[11] = org2[2] + width * right2[2];
2133 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
2135 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)
2137 float fog = 0.0f, ifog;
2141 fog = VERTEXFOGTABLE(VectorDistance(origin, r_vieworigin));
2144 R_Mesh_Matrix(&identitymatrix);
2145 GL_BlendFunc(blendfunc1, blendfunc2);
2146 GL_DepthMask(false);
2147 GL_DepthTest(!depthdisable);
2149 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
2150 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
2151 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
2152 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
2153 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
2154 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
2155 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
2156 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
2157 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
2158 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
2159 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
2160 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
2162 R_Mesh_VertexPointer(vertex3f);
2163 R_Mesh_ColorPointer(NULL);
2164 R_Mesh_ResetTextureState();
2165 R_Mesh_TexBind(0, R_GetTexture(texture));
2166 R_Mesh_TexCoordPointer(0, 2, spritetexcoord2f);
2167 GL_Color(cr * ifog, cg * ifog, cb * ifog, ca);
2168 R_Mesh_Draw(0, 4, 2, polygonelements);
2170 if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
2172 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
2173 GL_BlendFunc(blendfunc1, GL_ONE);
2174 GL_Color(fogcolor[0] * fog, fogcolor[1] * fog, fogcolor[2] * fog, ca);
2175 R_Mesh_Draw(0, 4, 2, polygonelements);
2179 int R_Mesh_AddVertex3f(rmesh_t *mesh, const float *v)
2183 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
2184 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
2186 if (i == mesh->numvertices)
2188 if (mesh->numvertices < mesh->maxvertices)
2190 VectorCopy(v, vertex3f);
2191 mesh->numvertices++;
2193 return mesh->numvertices;
2199 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
2203 element[0] = R_Mesh_AddVertex3f(mesh, vertex3f);vertex3f += 3;
2204 element[1] = R_Mesh_AddVertex3f(mesh, vertex3f);vertex3f += 3;
2205 e = mesh->element3i + mesh->numtriangles * 3;
2206 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
2208 element[2] = R_Mesh_AddVertex3f(mesh, vertex3f);
2209 if (mesh->numtriangles < mesh->maxtriangles)
2214 mesh->numtriangles++;
2216 element[1] = element[2];
2220 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
2222 int planenum, planenum2;
2225 mplane_t *plane, *plane2;
2226 float temppoints[2][256*3];
2227 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
2231 PolygonF_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->normal[3], 1024.0*1024.0*1024.0);
2232 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
2234 if (planenum2 == planenum)
2236 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);
2239 if (tempnumpoints < 3)
2241 // generate elements forming a triangle fan for this polygon
2242 R_Mesh_AddPolygon3f(mesh, tempnumpoints, temppoints[w]);
2246 static void R_DrawCollisionBrush(const colbrushf_t *brush)
2249 R_Mesh_VertexPointer(brush->points->v);
2250 i = (int)(((size_t)brush) / sizeof(colbrushf_t));
2251 GL_Color((i & 31) * (1.0f / 32.0f), ((i >> 5) & 31) * (1.0f / 32.0f), ((i >> 10) & 31) * (1.0f / 32.0f), 0.2f);
2252 GL_LockArrays(0, brush->numpoints);
2253 R_Mesh_Draw(0, brush->numpoints, brush->numtriangles, brush->elements);
2254 GL_LockArrays(0, 0);
2257 static void R_DrawCollisionSurface(const entity_render_t *ent, const msurface_t *surface)
2260 if (!surface->num_collisiontriangles)
2262 R_Mesh_VertexPointer(surface->data_collisionvertex3f);
2263 i = (int)(((size_t)surface) / sizeof(msurface_t));
2264 GL_Color((i & 31) * (1.0f / 32.0f), ((i >> 5) & 31) * (1.0f / 32.0f), ((i >> 10) & 31) * (1.0f / 32.0f), 0.2f);
2265 GL_LockArrays(0, surface->num_collisionvertices);
2266 R_Mesh_Draw(0, surface->num_collisionvertices, surface->num_collisiontriangles, surface->data_collisionelement3i);
2267 GL_LockArrays(0, 0);
2270 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)
2272 texturelayer_t *layer;
2273 layer = t->currentlayers + t->currentnumlayers++;
2275 layer->depthmask = depthmask;
2276 layer->blendfunc1 = blendfunc1;
2277 layer->blendfunc2 = blendfunc2;
2278 layer->texture = texture;
2279 layer->texmatrix = *matrix;
2280 layer->color[0] = r;
2281 layer->color[1] = g;
2282 layer->color[2] = b;
2283 layer->color[3] = a;
2286 void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
2288 // FIXME: identify models using a better check than ent->model->brush.shadowmesh
2289 //int lightmode = ((ent->effects & EF_FULLBRIGHT) || ent->model->brush.shadowmesh) ? 0 : 2;
2292 texture_t *texture = t;
2293 model_t *model = ent->model;
2294 int s = ent->skinnum;
2295 if ((unsigned int)s >= (unsigned int)model->numskins)
2297 if (model->skinscenes)
2299 if (model->skinscenes[s].framecount > 1)
2300 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
2302 s = model->skinscenes[s].firstframe;
2305 t = t + s * model->num_surfaces;
2307 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];
2308 texture->currentframe = t;
2311 t->currentmaterialflags = t->basematerialflags;
2312 t->currentalpha = ent->alpha;
2313 if (t->basematerialflags & MATERIALFLAG_WATERALPHA)
2314 t->currentalpha *= r_wateralpha.value;
2315 if (!(ent->flags & RENDER_LIGHT))
2316 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
2317 if (ent->effects & EF_ADDITIVE)
2318 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_TRANSPARENT;
2319 else if (t->currentalpha < 1)
2320 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_TRANSPARENT;
2321 if (ent->effects & EF_NODEPTHTEST)
2322 t->currentmaterialflags |= MATERIALFLAG_NODEPTHTEST;
2323 if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
2324 t->currenttexmatrix = r_waterscrollmatrix;
2326 t->currenttexmatrix = identitymatrix;
2328 t->colormapping = VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f);
2329 t->basetexture = (!t->colormapping && t->skin.merged) ? t->skin.merged : t->skin.base;
2330 t->glosstexture = r_texture_white;
2331 t->specularpower = 8;
2332 t->specularscale = 0;
2333 if (r_shadow_gloss.integer > 0)
2337 if (r_shadow_glossintensity.value > 0)
2339 t->glosstexture = t->skin.gloss;
2340 t->specularscale = r_shadow_glossintensity.value;
2343 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
2344 t->specularscale = r_shadow_gloss2intensity.value;
2347 t->currentnumlayers = 0;
2348 if (!(t->currentmaterialflags & MATERIALFLAG_NODRAW))
2350 if (gl_lightmaps.integer)
2351 R_Texture_AddLayer(t, true, GL_ONE, GL_ZERO, TEXTURELAYERTYPE_LITTEXTURE_MULTIPASS, r_texture_white, &identitymatrix, 1, 1, 1, 1);
2352 else if (!(t->currentmaterialflags & MATERIALFLAG_SKY))
2354 int blendfunc1, blendfunc2, depthmask;
2355 if (t->currentmaterialflags & MATERIALFLAG_ADD)
2357 blendfunc1 = GL_SRC_ALPHA;
2358 blendfunc2 = GL_ONE;
2360 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
2362 blendfunc1 = GL_SRC_ALPHA;
2363 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
2365 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
2367 blendfunc1 = t->customblendfunc[0];
2368 blendfunc2 = t->customblendfunc[1];
2372 blendfunc1 = GL_ONE;
2373 blendfunc2 = GL_ZERO;
2375 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
2376 if (t->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL))
2378 rtexture_t *currentbasetexture;
2380 if (fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED))
2381 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
2382 currentbasetexture = (VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) < (1.0f / 1048576.0f) && t->skin.merged) ? t->skin.merged : t->skin.base;
2383 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2385 // fullbright is not affected by r_lightmapintensity
2386 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
2387 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->skin.pants)
2388 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);
2389 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->skin.shirt)
2390 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);
2396 // q3bsp has no lightmap updates, so the lightstylevalue that
2397 // would normally be baked into the lightmap must be
2398 // applied to the color
2399 if (ent->model->type == mod_brushq3)
2400 colorscale *= r_refdef.lightstylevalue[0] * (1.0f / 256.0f);
2401 colorscale *= r_lightmapintensity;
2402 if (r_textureunits.integer >= 2 && gl_combine.integer)
2403 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);
2404 else if ((t->currentmaterialflags & MATERIALFLAG_BLENDED) == 0)
2405 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);
2407 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);
2408 if (r_ambient.value >= (1.0f/64.0f))
2409 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);
2410 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->skin.pants)
2412 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);
2413 if (r_ambient.value >= (1.0f/64.0f))
2414 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);
2416 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->skin.shirt)
2418 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);
2419 if (r_ambient.value >= (1.0f/64.0f))
2420 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);
2423 if (t->skin.glow != NULL)
2424 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.glow, &t->currenttexmatrix, 1, 1, 1, t->currentalpha);
2425 if (fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
2427 // if this is opaque use alpha blend which will darken the earlier
2430 // if this is an alpha blended material, all the earlier passes
2431 // were darkened by fog already, so we only need to add the fog
2432 // color ontop through the fog mask texture
2434 // if this is an additive blended material, all the earlier passes
2435 // were darkened by fog already, and we should not add fog color
2436 // (because the background was not darkened, there is no fog color
2437 // that was lost behind it).
2438 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);
2445 void R_UpdateAllTextureInfo(entity_render_t *ent)
2449 for (i = 0;i < ent->model->num_textures;i++)
2450 R_UpdateTextureInfo(ent, ent->model->data_textures + i);
2453 int rsurface_array_size = 0;
2454 float *rsurface_array_modelvertex3f = NULL;
2455 float *rsurface_array_modelsvector3f = NULL;
2456 float *rsurface_array_modeltvector3f = NULL;
2457 float *rsurface_array_modelnormal3f = NULL;
2458 float *rsurface_array_deformedvertex3f = NULL;
2459 float *rsurface_array_deformedsvector3f = NULL;
2460 float *rsurface_array_deformedtvector3f = NULL;
2461 float *rsurface_array_deformednormal3f = NULL;
2462 float *rsurface_array_color4f = NULL;
2463 float *rsurface_array_texcoord3f = NULL;
2465 void R_Mesh_ResizeArrays(int newvertices)
2468 if (rsurface_array_size >= newvertices)
2470 if (rsurface_array_modelvertex3f)
2471 Mem_Free(rsurface_array_modelvertex3f);
2472 rsurface_array_size = (newvertices + 1023) & ~1023;
2473 base = (float *)Mem_Alloc(r_main_mempool, rsurface_array_size * sizeof(float[31]));
2474 rsurface_array_modelvertex3f = base + rsurface_array_size * 0;
2475 rsurface_array_modelsvector3f = base + rsurface_array_size * 3;
2476 rsurface_array_modeltvector3f = base + rsurface_array_size * 6;
2477 rsurface_array_modelnormal3f = base + rsurface_array_size * 9;
2478 rsurface_array_deformedvertex3f = base + rsurface_array_size * 12;
2479 rsurface_array_deformedsvector3f = base + rsurface_array_size * 15;
2480 rsurface_array_deformedtvector3f = base + rsurface_array_size * 18;
2481 rsurface_array_deformednormal3f = base + rsurface_array_size * 21;
2482 rsurface_array_texcoord3f = base + rsurface_array_size * 24;
2483 rsurface_array_color4f = base + rsurface_array_size * 27;
2486 float *rsurface_modelvertex3f;
2487 float *rsurface_modelsvector3f;
2488 float *rsurface_modeltvector3f;
2489 float *rsurface_modelnormal3f;
2490 float *rsurface_vertex3f;
2491 float *rsurface_svector3f;
2492 float *rsurface_tvector3f;
2493 float *rsurface_normal3f;
2494 float *rsurface_lightmapcolor4f;
2495 vec3_t rsurface_modelorg;
2496 qboolean rsurface_generatedvertex;
2497 const entity_render_t *rsurface_entity;
2498 const model_t *rsurface_model;
2499 texture_t *rsurface_texture;
2500 rtexture_t *rsurface_lightmaptexture;
2501 rsurfmode_t rsurface_mode;
2502 texture_t *rsurface_glsl_texture;
2503 qboolean rsurface_glsl_uselightmap;
2505 void RSurf_ActiveEntity(const entity_render_t *ent)
2507 Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, rsurface_modelorg);
2508 rsurface_entity = ent;
2509 rsurface_model = ent->model;
2510 if (rsurface_array_size < rsurface_model->surfmesh.num_vertices)
2511 R_Mesh_ResizeArrays(rsurface_model->surfmesh.num_vertices);
2512 R_Mesh_Matrix(&ent->matrix);
2513 Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, rsurface_modelorg);
2514 if ((rsurface_entity->frameblend[0].lerp != 1 || rsurface_entity->frameblend[0].frame != 0) && (rsurface_model->surfmesh.data_morphvertex3f || rsurface_model->surfmesh.data_vertexboneweights))
2516 rsurface_modelvertex3f = rsurface_array_modelvertex3f;
2517 rsurface_modelsvector3f = NULL;
2518 rsurface_modeltvector3f = NULL;
2519 rsurface_modelnormal3f = NULL;
2520 Mod_Alias_GetMesh_Vertex3f(rsurface_model, rsurface_entity->frameblend, rsurface_array_modelvertex3f);
2521 rsurface_generatedvertex = true;
2525 rsurface_modelvertex3f = rsurface_model->surfmesh.data_vertex3f;
2526 rsurface_modelsvector3f = rsurface_model->surfmesh.data_svector3f;
2527 rsurface_modeltvector3f = rsurface_model->surfmesh.data_tvector3f;
2528 rsurface_modelnormal3f = rsurface_model->surfmesh.data_normal3f;
2529 rsurface_generatedvertex = false;
2531 rsurface_vertex3f = rsurface_modelvertex3f;
2532 rsurface_svector3f = rsurface_modelsvector3f;
2533 rsurface_tvector3f = rsurface_modeltvector3f;
2534 rsurface_normal3f = rsurface_modelnormal3f;
2535 rsurface_mode = RSURFMODE_NONE;
2536 rsurface_lightmaptexture = NULL;
2537 rsurface_texture = NULL;
2538 rsurface_glsl_texture = NULL;
2539 rsurface_glsl_uselightmap = false;
2542 void RSurf_CleanUp(void)
2545 if (rsurface_mode == RSURFMODE_GLSL)
2547 qglUseProgramObjectARB(0);CHECKGLERROR
2549 GL_AlphaTest(false);
2550 rsurface_mode = RSURFMODE_NONE;
2551 rsurface_lightmaptexture = NULL;
2552 rsurface_texture = NULL;
2553 rsurface_glsl_texture = NULL;
2554 rsurface_glsl_uselightmap = false;
2557 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, msurface_t **texturesurfacelist)
2559 if (rsurface_generatedvertex)
2561 if (rsurface_texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
2562 generatetangents = true;
2563 if (generatetangents)
2564 generatenormals = true;
2565 if (generatenormals && !rsurface_modelnormal3f)
2567 rsurface_normal3f = rsurface_modelnormal3f = rsurface_array_modelnormal3f;
2568 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);
2570 if (generatetangents && !rsurface_modelsvector3f)
2572 rsurface_svector3f = rsurface_modelsvector3f = rsurface_array_modelsvector3f;
2573 rsurface_tvector3f = rsurface_modeltvector3f = rsurface_array_modeltvector3f;
2574 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);
2577 if (rsurface_texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
2579 int texturesurfaceindex;
2580 float center[3], forward[3], right[3], up[3], v[4][3];
2581 matrix4x4_t matrix1, imatrix1;
2582 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_viewforward, forward);
2583 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_viewright, right);
2584 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_viewup, up);
2585 // make deformed versions of only the vertices used by the specified surfaces
2586 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2589 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2590 // a single autosprite surface can contain multiple sprites...
2591 for (j = 0;j < surface->num_vertices - 3;j += 4)
2593 VectorClear(center);
2594 for (i = 0;i < 4;i++)
2595 VectorAdd(center, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
2596 VectorScale(center, 0.25f, center);
2597 if (rsurface_texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE2)
2599 forward[0] = rsurface_modelorg[0] - center[0];
2600 forward[1] = rsurface_modelorg[1] - center[1];
2602 VectorNormalize(forward);
2603 right[0] = forward[1];
2604 right[1] = -forward[0];
2606 VectorSet(up, 0, 0, 1);
2608 // FIXME: calculate vectors from triangle edges instead of using texture vectors as an easy way out?
2609 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);
2610 Matrix4x4_Invert_Simple(&imatrix1, &matrix1);
2611 for (i = 0;i < 4;i++)
2612 Matrix4x4_Transform(&imatrix1, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, v[i]);
2613 for (i = 0;i < 4;i++)
2614 VectorMAMAMAM(1, center, v[i][0], forward, v[i][1], right, v[i][2], up, rsurface_array_modelvertex3f + (surface->num_firstvertex+i+j) * 3);
2616 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);
2617 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);
2619 rsurface_vertex3f = rsurface_array_deformedvertex3f;
2620 rsurface_svector3f = rsurface_array_deformedsvector3f;
2621 rsurface_tvector3f = rsurface_array_deformedtvector3f;
2622 rsurface_normal3f = rsurface_array_deformednormal3f;
2624 R_Mesh_VertexPointer(rsurface_vertex3f);
2627 static void RSurf_Draw(const msurface_t *surface)
2629 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2630 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
2633 static void RSurf_DrawLightmap(const msurface_t *surface, float r, float g, float b, float a, int lightmode, qboolean applycolor, qboolean applyfog)
2641 vec3_t ambientcolor;
2642 vec3_t diffusecolor;
2644 VectorCopy(rsurface_entity->modellight_lightdir, lightdir);
2645 ambientcolor[0] = rsurface_entity->modellight_ambient[0] * r * 0.5f;
2646 ambientcolor[1] = rsurface_entity->modellight_ambient[1] * g * 0.5f;
2647 ambientcolor[2] = rsurface_entity->modellight_ambient[2] * b * 0.5f;
2648 diffusecolor[0] = rsurface_entity->modellight_diffuse[0] * r * 0.5f;
2649 diffusecolor[1] = rsurface_entity->modellight_diffuse[1] * g * 0.5f;
2650 diffusecolor[2] = rsurface_entity->modellight_diffuse[2] * b * 0.5f;
2651 if (VectorLength2(diffusecolor) > 0)
2653 int numverts = surface->num_vertices;
2654 v = rsurface_vertex3f + 3 * surface->num_firstvertex;
2655 c2 = rsurface_normal3f + 3 * surface->num_firstvertex;
2656 c = rsurface_array_color4f + 4 * surface->num_firstvertex;
2657 // q3-style directional shading
2658 for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
2660 if ((f = DotProduct(c2, lightdir)) > 0)
2661 VectorMA(ambientcolor, f, diffusecolor, c);
2663 VectorCopy(ambientcolor, c);
2671 rsurface_lightmapcolor4f = rsurface_array_color4f;
2675 r = ambientcolor[0];
2676 g = ambientcolor[1];
2677 b = ambientcolor[2];
2678 rsurface_lightmapcolor4f = NULL;
2681 else if (lightmode >= 1)
2683 if (surface->lightmapinfo && surface->lightmapinfo->stainsamples)
2685 for (i = 0, c = rsurface_array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
2687 if (surface->lightmapinfo->samples)
2689 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface_model->surfmesh.data_lightmapoffsets + surface->num_firstvertex)[i];
2690 float scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
2691 VectorScale(lm, scale, c);
2692 if (surface->lightmapinfo->styles[1] != 255)
2694 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
2696 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
2697 VectorMA(c, scale, lm, c);
2698 if (surface->lightmapinfo->styles[2] != 255)
2701 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
2702 VectorMA(c, scale, lm, c);
2703 if (surface->lightmapinfo->styles[3] != 255)
2706 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
2707 VectorMA(c, scale, lm, c);
2715 rsurface_lightmapcolor4f = rsurface_array_color4f;
2718 rsurface_lightmapcolor4f = rsurface_model->surfmesh.data_lightmapcolor4f;
2721 rsurface_lightmapcolor4f = NULL;
2724 if (rsurface_lightmapcolor4f)
2726 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)
2728 f = 1 - VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
2737 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)
2739 f = 1 - VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
2746 rsurface_lightmapcolor4f = rsurface_array_color4f;
2748 if (applycolor && rsurface_lightmapcolor4f)
2750 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)
2757 rsurface_lightmapcolor4f = rsurface_array_color4f;
2759 R_Mesh_ColorPointer(rsurface_lightmapcolor4f);
2760 GL_Color(r, g, b, a);
2761 RSurf_Draw(surface);
2764 static void R_DrawTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist)
2766 int texturesurfaceindex;
2768 qboolean applycolor;
2771 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_NODRAW)
2773 r_shadow_rtlight = NULL;
2774 renderstats.entities_surfaces += texturenumsurfaces;
2775 // FIXME: identify models using a better check than rsurface_model->brush.shadowmesh
2776 lightmode = ((rsurface_entity->effects & EF_FULLBRIGHT) || rsurface_model->brush.shadowmesh) ? 0 : 2;
2778 GL_DepthTest(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
2779 if ((rsurface_texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (rsurface_entity->flags & RENDER_NOCULLFACE))
2781 qglDisable(GL_CULL_FACE);CHECKGLERROR
2783 if (r_showsurfaces.integer)
2785 if (rsurface_mode != RSURFMODE_SHOWSURFACES)
2787 rsurface_mode = RSURFMODE_SHOWSURFACES;
2789 GL_BlendFunc(GL_ONE, GL_ZERO);
2790 R_Mesh_ColorPointer(NULL);
2791 R_Mesh_ResetTextureState();
2793 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
2794 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2796 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2797 int k = (int)(((size_t)surface) / sizeof(msurface_t));
2798 GL_Color((k & 15) * (1.0f / 16.0f), ((k >> 4) & 15) * (1.0f / 16.0f), ((k >> 8) & 15) * (1.0f / 16.0f), 0.2f);
2799 RSurf_Draw(surface);
2802 else if (rsurface_texture->currentmaterialflags & MATERIALFLAG_SKY)
2804 // transparent sky would be ridiculous
2805 if (!(rsurface_texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
2807 if (rsurface_mode != RSURFMODE_SKY)
2809 if (rsurface_mode == RSURFMODE_GLSL)
2811 qglUseProgramObjectARB(0);CHECKGLERROR
2813 rsurface_mode = RSURFMODE_SKY;
2816 skyrendernow = false;
2818 // restore entity matrix
2819 R_Mesh_Matrix(&rsurface_entity->matrix);
2822 // LordHavoc: HalfLife maps have freaky skypolys so don't use
2823 // skymasking on them, and Quake3 never did sky masking (unlike
2824 // software Quake and software Quake2), so disable the sky masking
2825 // in Quake3 maps as it causes problems with q3map2 sky tricks,
2826 // and skymasking also looks very bad when noclipping outside the
2827 // level, so don't use it then either.
2828 if (rsurface_model->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_worldnovis)
2830 GL_Color(fogcolor[0], fogcolor[1], fogcolor[2], 1);
2831 R_Mesh_ColorPointer(NULL);
2832 R_Mesh_ResetTextureState();
2833 if (skyrendermasked)
2835 // depth-only (masking)
2836 GL_ColorMask(0,0,0,0);
2837 // just to make sure that braindead drivers don't draw
2838 // anything despite that colormask...
2839 GL_BlendFunc(GL_ZERO, GL_ONE);
2844 GL_BlendFunc(GL_ONE, GL_ZERO);
2848 // LordHavoc: HalfLife maps have freaky skypolys so don't use
2849 // skymasking on them, and Quake3 never did sky masking (unlike
2850 // software Quake and software Quake2), so disable the sky masking
2851 // in Quake3 maps as it causes problems with q3map2 sky tricks,
2852 // and skymasking also looks very bad when noclipping outside the
2853 // level, so don't use it then either.
2854 if (rsurface_model->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_worldnovis)
2856 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
2857 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2859 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2860 RSurf_Draw(surface);
2862 if (skyrendermasked)
2863 GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
2867 else if (rsurface_texture->currentnumlayers && r_glsl.integer && gl_support_fragment_shader)
2869 if (rsurface_mode != RSURFMODE_GLSL)
2871 rsurface_mode = RSURFMODE_GLSL;
2872 rsurface_glsl_texture = NULL;
2873 rsurface_glsl_uselightmap = false;
2874 R_Mesh_ResetTextureState();
2876 if (rsurface_glsl_texture != rsurface_texture || rsurface_glsl_uselightmap != (rsurface_lightmaptexture != NULL))
2878 rsurface_glsl_texture = rsurface_texture;
2879 rsurface_glsl_uselightmap = rsurface_lightmaptexture != NULL;
2880 GL_BlendFunc(rsurface_texture->currentlayers[0].blendfunc1, rsurface_texture->currentlayers[0].blendfunc2);
2881 GL_DepthMask(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_BLENDED));
2882 GL_Color(rsurface_entity->colormod[0], rsurface_entity->colormod[1], rsurface_entity->colormod[2], rsurface_texture->currentalpha);
2883 R_SetupSurfaceShader(vec3_origin, lightmode == 2);
2884 //permutation_deluxemapping = permutation_lightmapping = R_SetupSurfaceShader(vec3_origin, lightmode == 2, false);
2885 //if (r_glsl_deluxemapping.integer)
2886 // permutation_deluxemapping = R_SetupSurfaceShader(vec3_origin, lightmode == 2, true);
2887 R_Mesh_TexCoordPointer(0, 2, rsurface_model->surfmesh.data_texcoordtexture2f);
2888 R_Mesh_TexCoordPointer(4, 2, rsurface_model->surfmesh.data_texcoordlightmap2f);
2889 GL_AlphaTest((rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2891 if (!r_glsl_permutation)
2893 RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
2894 R_Mesh_TexCoordPointer(1, 3, rsurface_svector3f);
2895 R_Mesh_TexCoordPointer(2, 3, rsurface_tvector3f);
2896 R_Mesh_TexCoordPointer(3, 3, rsurface_normal3f);
2897 if (rsurface_lightmaptexture)
2899 R_Mesh_TexBind(7, R_GetTexture(rsurface_lightmaptexture));
2900 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
2901 R_Mesh_TexBind(8, R_GetTexture(texturesurfacelist[0]->deluxemaptexture));
2902 R_Mesh_ColorPointer(NULL);
2906 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
2907 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
2908 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
2909 R_Mesh_ColorPointer(rsurface_model->surfmesh.data_lightmapcolor4f);
2911 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2913 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2914 RSurf_Draw(surface);
2917 else if (rsurface_texture->currentnumlayers)
2920 const texturelayer_t *layer;
2922 if (rsurface_mode != RSURFMODE_MULTIPASS)
2924 if (rsurface_mode == RSURFMODE_GLSL)
2926 qglUseProgramObjectARB(0);CHECKGLERROR
2928 rsurface_mode = RSURFMODE_MULTIPASS;
2930 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
2931 for (layerindex = 0, layer = rsurface_texture->currentlayers;layerindex < rsurface_texture->currentnumlayers;layerindex++, layer++)
2934 int layertexrgbscale;
2935 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2937 if (layerindex == 0)
2941 GL_AlphaTest(false);
2942 qglDepthFunc(GL_EQUAL);CHECKGLERROR
2945 GL_DepthMask(layer->depthmask);
2946 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
2947 if ((layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2) && (gl_combine.integer || layer->depthmask))
2949 layertexrgbscale = 4;
2950 VectorScale(layer->color, 0.25f, layercolor);
2952 else if ((layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1) && (gl_combine.integer || layer->depthmask))
2954 layertexrgbscale = 2;
2955 VectorScale(layer->color, 0.5f, layercolor);
2959 layertexrgbscale = 1;
2960 VectorScale(layer->color, 1.0f, layercolor);
2962 layercolor[3] = layer->color[3];
2963 R_Mesh_ColorPointer(NULL);
2964 GL_Color(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
2965 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
2966 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
2967 switch (layer->type)
2969 case TEXTURELAYERTYPE_LITTEXTURE_COMBINE:
2970 memset(&m, 0, sizeof(m));
2971 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordlightmap2f;
2972 m.tex[1] = R_GetTexture(layer->texture);
2973 m.texmatrix[1] = layer->texmatrix;
2974 m.texrgbscale[1] = layertexrgbscale;
2975 m.pointer_texcoord[1] = rsurface_model->surfmesh.data_texcoordtexture2f;
2976 R_Mesh_TextureState(&m);
2979 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2981 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2982 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2983 RSurf_DrawLightmap(surface, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 2, applycolor, applyfog);
2986 else if (rsurface_lightmaptexture)
2988 R_Mesh_TexBind(0, R_GetTexture(rsurface_lightmaptexture));
2989 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2991 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2992 RSurf_DrawLightmap(surface, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, applyfog);
2997 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2998 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3000 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3001 RSurf_DrawLightmap(surface, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 1, applycolor, applyfog);
3005 case TEXTURELAYERTYPE_LITTEXTURE_MULTIPASS:
3006 memset(&m, 0, sizeof(m));
3007 m.tex[0] = R_GetTexture(layer->texture);
3008 m.texmatrix[0] = layer->texmatrix;
3009 m.texrgbscale[0] = layertexrgbscale;
3010 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordlightmap2f;
3011 R_Mesh_TextureState(&m);
3014 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3016 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3017 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
3018 RSurf_DrawLightmap(surface, 1, 1, 1, 1, 2, false, false);
3021 else if (rsurface_lightmaptexture)
3023 R_Mesh_TexBind(0, R_GetTexture(rsurface_lightmaptexture));
3024 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3026 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3027 RSurf_DrawLightmap(surface, 1, 1, 1, 1, 0, false, false);
3032 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
3033 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3035 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3036 RSurf_DrawLightmap(surface, 1, 1, 1, 1, 1, false, false);
3039 GL_LockArrays(0, 0);
3040 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
3041 memset(&m, 0, sizeof(m));
3042 m.tex[0] = R_GetTexture(layer->texture);
3043 m.texmatrix[0] = layer->texmatrix;
3044 m.texrgbscale[0] = layertexrgbscale;
3045 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3046 R_Mesh_TextureState(&m);
3047 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3049 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3050 RSurf_DrawLightmap(surface, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, false);
3053 case TEXTURELAYERTYPE_LITTEXTURE_VERTEX:
3054 memset(&m, 0, sizeof(m));
3055 m.tex[0] = R_GetTexture(layer->texture);
3056 m.texmatrix[0] = layer->texmatrix;
3057 m.texrgbscale[0] = layertexrgbscale;
3058 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3059 R_Mesh_TextureState(&m);
3062 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3064 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3065 RSurf_DrawLightmap(surface, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 2, applycolor, applyfog);
3070 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3072 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3073 RSurf_DrawLightmap(surface, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 1, applycolor, applyfog);
3077 case TEXTURELAYERTYPE_TEXTURE:
3078 memset(&m, 0, sizeof(m));
3079 m.tex[0] = R_GetTexture(layer->texture);
3080 m.texmatrix[0] = layer->texmatrix;
3081 m.texrgbscale[0] = layertexrgbscale;
3082 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3083 R_Mesh_TextureState(&m);
3084 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3086 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3087 RSurf_DrawLightmap(surface, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, applyfog);
3090 case TEXTURELAYERTYPE_FOG:
3091 R_Mesh_ColorPointer(rsurface_array_color4f);
3094 memset(&m, 0, sizeof(m));
3095 m.tex[0] = R_GetTexture(layer->texture);
3096 m.texmatrix[0] = layer->texmatrix;
3097 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3098 R_Mesh_TextureState(&m);
3101 R_Mesh_ResetTextureState();
3102 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3106 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3107 for (i = 0, v = (rsurface_vertex3f + 3 * surface->num_firstvertex), c = (rsurface_array_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4)
3109 f = VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
3110 c[0] = layercolor[0];
3111 c[1] = layercolor[1];
3112 c[2] = layercolor[2];
3113 c[3] = f * layercolor[3];
3115 RSurf_Draw(surface);
3119 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
3121 GL_LockArrays(0, 0);
3122 // if trying to do overbright on first pass of an opaque surface
3123 // when combine is not supported, brighten as a post process
3124 if (layertexrgbscale > 1 && !gl_combine.integer && layer->depthmask)
3127 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
3128 R_Mesh_ColorPointer(NULL);
3129 GL_Color(1, 1, 1, 1);
3130 R_Mesh_ResetTextureState();
3131 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3133 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3134 for (scale = 1;scale < layertexrgbscale;scale <<= 1)
3135 RSurf_Draw(surface);
3137 GL_LockArrays(0, 0);
3141 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
3143 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3144 GL_AlphaTest(false);
3148 GL_LockArrays(0, 0);
3149 if ((rsurface_texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (rsurface_entity->flags & RENDER_NOCULLFACE))
3151 qglEnable(GL_CULL_FACE);CHECKGLERROR
3155 #define BATCHSIZE 256
3156 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
3158 int surfacelistindex;
3161 msurface_t *texturesurfacelist[BATCHSIZE];
3162 RSurf_ActiveEntity(ent);
3165 for (surfacelistindex = 0;surfacelistindex < numsurfaces;surfacelistindex++)
3167 msurface_t *surface = ent->model->data_surfaces + surfacelist[surfacelistindex];
3169 if (t != surface->texture || rsurface_lightmaptexture != surface->lightmaptexture)
3172 R_DrawTextureSurfaceList(batchcount, texturesurfacelist);
3174 t = surface->texture;
3175 rsurface_lightmaptexture = surface->lightmaptexture;
3176 R_UpdateTextureInfo(ent, t);
3177 rsurface_texture = t->currentframe;
3179 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_SKY)
3180 continue; // transparent sky is too difficult
3182 texturesurfacelist[batchcount++] = surface;
3185 R_DrawTextureSurfaceList(batchcount, texturesurfacelist);
3189 void R_QueueTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist)
3191 int texturesurfaceindex;
3192 vec3_t tempcenter, center;
3193 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_BLENDED)
3195 // drawing sky transparently would be too difficult
3196 if (!(rsurface_texture->currentmaterialflags & MATERIALFLAG_SKY))
3198 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3200 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3201 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
3202 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
3203 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
3204 Matrix4x4_Transform(&rsurface_entity->matrix, tempcenter, center);
3205 R_MeshQueue_AddTransparent(rsurface_texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_vieworigin : center, R_DrawSurface_TransparentCallback, rsurface_entity, surface - rsurface_model->data_surfaces, r_shadow_rtlight);
3210 R_DrawTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
3213 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
3214 void R_DrawSurfaces(entity_render_t *ent, qboolean skysurfaces)
3216 int i, j, f, flagsmask;
3217 int counttriangles = 0;
3219 model_t *model = ent->model;
3220 const int maxsurfacelist = 1024;
3221 int numsurfacelist = 0;
3222 msurface_t *surfacelist[1024];
3226 RSurf_ActiveEntity(ent);
3228 // update light styles
3229 if (!skysurfaces && model->brushq1.light_styleupdatechains)
3231 msurface_t *surface, **surfacechain;
3232 for (i = 0;i < model->brushq1.light_styles;i++)
3234 if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
3236 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
3237 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
3238 for (;(surface = *surfacechain);surfacechain++)
3239 surface->cached_dlight = true;
3244 R_UpdateAllTextureInfo(ent);
3245 flagsmask = skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL);
3248 rsurface_lightmaptexture = NULL;
3249 rsurface_texture = NULL;
3251 if (ent == r_refdef.worldentity)
3253 msurface_t *surface;
3254 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
3256 if (!r_worldsurfacevisible[j])
3258 if (t != surface->texture || rsurface_lightmaptexture != surface->lightmaptexture)
3262 R_QueueTextureSurfaceList(numsurfacelist, surfacelist);
3265 t = surface->texture;
3266 rsurface_lightmaptexture = surface->lightmaptexture;
3267 rsurface_texture = t->currentframe;
3268 f = rsurface_texture->currentmaterialflags & flagsmask;
3270 if (f && surface->num_triangles)
3272 // if lightmap parameters changed, rebuild lightmap texture
3273 if (surface->cached_dlight)
3274 R_BuildLightMap(ent, surface);
3275 // add face to draw list
3276 surfacelist[numsurfacelist++] = surface;
3277 counttriangles += surface->num_triangles;
3278 if (numsurfacelist >= maxsurfacelist)
3280 R_QueueTextureSurfaceList(numsurfacelist, surfacelist);
3288 msurface_t *surface;
3289 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
3291 if (t != surface->texture || rsurface_lightmaptexture != surface->lightmaptexture)
3295 R_QueueTextureSurfaceList(numsurfacelist, surfacelist);
3298 t = surface->texture;
3299 rsurface_lightmaptexture = surface->lightmaptexture;
3300 rsurface_texture = t->currentframe;
3301 f = rsurface_texture->currentmaterialflags & flagsmask;
3303 if (f && surface->num_triangles)
3305 // if lightmap parameters changed, rebuild lightmap texture
3306 if (surface->cached_dlight)
3307 R_BuildLightMap(ent, surface);
3308 // add face to draw list
3309 surfacelist[numsurfacelist++] = surface;
3310 counttriangles += surface->num_triangles;
3311 if (numsurfacelist >= maxsurfacelist)
3313 R_QueueTextureSurfaceList(numsurfacelist, surfacelist);
3320 R_QueueTextureSurfaceList(numsurfacelist, surfacelist);
3321 renderstats.entities_triangles += counttriangles;
3324 if (r_showcollisionbrushes.integer && model->brush.num_brushes && !skysurfaces)
3327 const msurface_t *surface;
3330 R_Mesh_Matrix(&ent->matrix);
3331 R_Mesh_ColorPointer(NULL);
3332 R_Mesh_ResetTextureState();
3333 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
3334 GL_DepthMask(false);
3335 GL_DepthTest(!r_showdisabledepthtest.integer);
3336 qglPolygonOffset(r_polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_polygonoffset + r_showcollisionbrushes_polygonoffset.value);CHECKGLERROR
3337 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
3338 if (brush->colbrushf && brush->colbrushf->numtriangles)
3339 R_DrawCollisionBrush(brush->colbrushf);
3340 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
3341 if (surface->num_collisiontriangles)
3342 R_DrawCollisionSurface(ent, surface);
3343 qglPolygonOffset(r_polygonfactor, r_polygonoffset);CHECKGLERROR
3346 if (r_showtris.integer || r_shownormals.integer)
3349 msurface_t *surface;
3350 const int *elements;
3355 if (r_showdisabledepthtest.integer)
3357 qglDepthFunc(GL_ALWAYS);CHECKGLERROR
3359 GL_BlendFunc(GL_ONE, GL_ZERO);
3360 R_Mesh_ColorPointer(NULL);
3361 R_Mesh_ResetTextureState();
3362 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
3364 if (ent == r_refdef.worldentity && !r_worldsurfacevisible[j])
3366 rsurface_texture = surface->texture->currentframe;
3367 if ((rsurface_texture->currentmaterialflags & flagsmask) && surface->num_triangles)
3369 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
3370 if (r_showtris.integer)
3372 if (!rsurface_texture->currentlayers->depthmask)
3373 GL_Color(r_showtris.value, 0, 0, 1);
3374 else if (ent == r_refdef.worldentity)
3375 GL_Color(r_showtris.value, r_showtris.value, r_showtris.value, 1);
3377 GL_Color(0, r_showtris.value, 0, 1);
3378 elements = (ent->model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
3381 for (k = 0;k < surface->num_triangles;k++, elements += 3)
3383 qglArrayElement(elements[0]);qglArrayElement(elements[1]);
3384 qglArrayElement(elements[1]);qglArrayElement(elements[2]);
3385 qglArrayElement(elements[2]);qglArrayElement(elements[0]);
3390 if (r_shownormals.integer)
3392 GL_Color(r_shownormals.value, 0, 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_svector3f + l * 3, v);
3399 qglVertex3f(v[0], v[1], v[2]);
3403 GL_Color(0, 0, r_shownormals.value, 1);
3405 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
3407 VectorCopy(rsurface_vertex3f + l * 3, v);
3408 qglVertex3f(v[0], v[1], v[2]);
3409 VectorMA(v, 8, rsurface_tvector3f + l * 3, v);
3410 qglVertex3f(v[0], v[1], v[2]);
3414 GL_Color(0, r_shownormals.value, 0, 1);
3416 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
3418 VectorCopy(rsurface_vertex3f + l * 3, v);
3419 qglVertex3f(v[0], v[1], v[2]);
3420 VectorMA(v, 8, rsurface_normal3f + l * 3, v);
3421 qglVertex3f(v[0], v[1], v[2]);
3428 rsurface_texture = NULL;
3429 if (r_showdisabledepthtest.integer)
3431 qglDepthFunc(GL_LEQUAL);CHECKGLERROR