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
125 cvar_t r_batchmode = {0, "r_batchmode", "1", "selects method of rendering multiple surfaces with one driver call (values are 0, 1, 2, etc...)"};
127 rtexture_t *r_bloom_texture_screen;
128 rtexture_t *r_bloom_texture_bloom;
129 rtexture_t *r_texture_blanknormalmap;
130 rtexture_t *r_texture_white;
131 rtexture_t *r_texture_black;
132 rtexture_t *r_texture_notexture;
133 rtexture_t *r_texture_whitecube;
134 rtexture_t *r_texture_normalizationcube;
135 rtexture_t *r_texture_fogattenuation;
136 //rtexture_t *r_texture_fogintensity;
138 // information about each possible shader permutation
139 r_glsl_permutation_t r_glsl_permutations[SHADERPERMUTATION_COUNT];
140 // currently selected permutation
141 r_glsl_permutation_t *r_glsl_permutation;
143 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
146 for (i = 0;i < verts;i++)
157 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
160 for (i = 0;i < verts;i++)
175 vec_t fogtabledistmultiplier;
176 float fogtable[FOGTABLEWIDTH];
177 float fog_density, fog_red, fog_green, fog_blue;
179 qboolean oldgl_fogenable;
180 void R_UpdateFog(void)
182 if (gamemode == GAME_NEHAHRA)
184 if (gl_fogenable.integer)
186 oldgl_fogenable = true;
187 fog_density = gl_fogdensity.value;
188 fog_red = gl_fogred.value;
189 fog_green = gl_foggreen.value;
190 fog_blue = gl_fogblue.value;
192 else if (oldgl_fogenable)
194 oldgl_fogenable = false;
203 fogcolor[0] = fog_red = bound(0.0f, fog_red , 1.0f);
204 fogcolor[1] = fog_green = bound(0.0f, fog_green, 1.0f);
205 fogcolor[2] = fog_blue = bound(0.0f, fog_blue , 1.0f);
210 fogdensity = -4000.0f / (fog_density * fog_density);
211 // this is the point where the fog reaches 0.9986 alpha, which we
212 // consider a good enough cutoff point for the texture
213 // (0.9986 * 256 == 255.6)
214 fogrange = 400 / fog_density;
215 fograngerecip = 1.0f / fogrange;
216 fogtabledistmultiplier = FOGTABLEWIDTH * fograngerecip;
217 // fog color was already set
223 // FIXME: move this to client?
226 if (gamemode == GAME_NEHAHRA)
228 Cvar_Set("gl_fogenable", "0");
229 Cvar_Set("gl_fogdensity", "0.2");
230 Cvar_Set("gl_fogred", "0.3");
231 Cvar_Set("gl_foggreen", "0.3");
232 Cvar_Set("gl_fogblue", "0.3");
234 fog_density = fog_red = fog_green = fog_blue = 0.0f;
237 // FIXME: move this to client?
238 void FOG_registercvars(void)
243 if (gamemode == GAME_NEHAHRA)
245 Cvar_RegisterVariable (&gl_fogenable);
246 Cvar_RegisterVariable (&gl_fogdensity);
247 Cvar_RegisterVariable (&gl_fogred);
248 Cvar_RegisterVariable (&gl_foggreen);
249 Cvar_RegisterVariable (&gl_fogblue);
250 Cvar_RegisterVariable (&gl_fogstart);
251 Cvar_RegisterVariable (&gl_fogend);
254 r = (-1.0/256.0) * (FOGTABLEWIDTH * FOGTABLEWIDTH);
255 for (x = 0;x < FOGTABLEWIDTH;x++)
257 alpha = exp(r / ((double)x*(double)x));
258 if (x == FOGTABLEWIDTH - 1)
260 fogtable[x] = bound(0, alpha, 1);
264 static void R_BuildBlankTextures(void)
266 unsigned char data[4];
267 data[0] = 128; // normal X
268 data[1] = 128; // normal Y
269 data[2] = 255; // normal Z
270 data[3] = 128; // height
271 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
276 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
281 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
284 static void R_BuildNoTexture(void)
287 unsigned char pix[16][16][4];
288 // this makes a light grey/dark grey checkerboard texture
289 for (y = 0;y < 16;y++)
291 for (x = 0;x < 16;x++)
293 if ((y < 8) ^ (x < 8))
309 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_RGBA, TEXF_MIPMAP, NULL);
312 static void R_BuildWhiteCube(void)
314 unsigned char data[6*1*1*4];
315 data[ 0] = 255;data[ 1] = 255;data[ 2] = 255;data[ 3] = 255;
316 data[ 4] = 255;data[ 5] = 255;data[ 6] = 255;data[ 7] = 255;
317 data[ 8] = 255;data[ 9] = 255;data[10] = 255;data[11] = 255;
318 data[12] = 255;data[13] = 255;data[14] = 255;data[15] = 255;
319 data[16] = 255;data[17] = 255;data[18] = 255;data[19] = 255;
320 data[20] = 255;data[21] = 255;data[22] = 255;data[23] = 255;
321 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
324 static void R_BuildNormalizationCube(void)
328 vec_t s, t, intensity;
330 unsigned char data[6][NORMSIZE][NORMSIZE][4];
331 for (side = 0;side < 6;side++)
333 for (y = 0;y < NORMSIZE;y++)
335 for (x = 0;x < NORMSIZE;x++)
337 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
338 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
373 intensity = 127.0f / sqrt(DotProduct(v, v));
374 data[side][y][x][0] = (unsigned char)(128.0f + intensity * v[0]);
375 data[side][y][x][1] = (unsigned char)(128.0f + intensity * v[1]);
376 data[side][y][x][2] = (unsigned char)(128.0f + intensity * v[2]);
377 data[side][y][x][3] = 255;
381 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, &data[0][0][0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
384 static void R_BuildFogTexture(void)
389 unsigned char data1[FOGWIDTH][4];
390 //unsigned char data2[FOGWIDTH][4];
391 r = (-1.0/256.0) * (FOGWIDTH * FOGWIDTH);
392 for (x = 0;x < FOGWIDTH;x++)
394 alpha = exp(r / ((double)x*(double)x));
395 if (x == FOGWIDTH - 1)
397 b = (int)(256.0 * alpha);
398 b = bound(0, b, 255);
399 data1[x][0] = 255 - b;
400 data1[x][1] = 255 - b;
401 data1[x][2] = 255 - b;
408 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
409 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
412 static const char *builtinshaderstring =
413 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
414 "// written by Forest 'LordHavoc' Hale\n"
416 "// common definitions between vertex shader and fragment shader:\n"
418 "varying vec2 TexCoord;\n"
419 "varying vec2 TexCoordLightmap;\n"
421 "varying vec3 CubeVector;\n"
422 "varying vec3 LightVector;\n"
423 "varying vec3 EyeVector;\n"
425 "varying vec3 EyeVectorModelSpace;\n"
428 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
429 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
430 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
435 "// vertex shader specific:\n"
436 "#ifdef VERTEX_SHADER\n"
438 "uniform vec3 LightPosition;\n"
439 "uniform vec3 EyePosition;\n"
440 "uniform vec3 LightDir;\n"
442 "// TODO: get rid of tangentt (texcoord2) and use a crossproduct to regenerate it from tangents (texcoord1) and normal (texcoord3)\n"
446 " gl_FrontColor = gl_Color;\n"
447 " // copy the surface texcoord\n"
448 " TexCoord = vec2(gl_TextureMatrix[0] * gl_MultiTexCoord0);\n"
449 "#if !defined(MODE_LIGHTSOURCE) && !defined(MODE_LIGHTDIRECTION)\n"
450 " TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
453 "#ifdef MODE_LIGHTSOURCE\n"
454 " // transform vertex position into light attenuation/cubemap space\n"
455 " // (-1 to +1 across the light box)\n"
456 " CubeVector = vec3(gl_TextureMatrix[3] * gl_Vertex);\n"
458 " // transform unnormalized light direction into tangent space\n"
459 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
460 " // normalize it per pixel)\n"
461 " vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
462 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
463 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
464 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
467 "#ifdef MODE_LIGHTDIRECTION\n"
468 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
469 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
470 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
473 " // transform unnormalized eye direction into tangent space\n"
475 " vec3 EyeVectorModelSpace;\n"
477 " EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
478 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
479 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
480 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
482 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
483 " VectorS = gl_MultiTexCoord1.xyz;\n"
484 " VectorT = gl_MultiTexCoord2.xyz;\n"
485 " VectorR = gl_MultiTexCoord3.xyz;\n"
488 " // transform vertex to camera space, using ftransform to match non-VS\n"
490 " gl_Position = ftransform();\n"
493 "#endif // VERTEX_SHADER\n"
498 "// fragment shader specific:\n"
499 "#ifdef FRAGMENT_SHADER\n"
501 "uniform sampler2D Texture_Normal;\n"
502 "uniform sampler2D Texture_Color;\n"
503 "uniform sampler2D Texture_Gloss;\n"
504 "uniform samplerCube Texture_Cube;\n"
505 "uniform sampler2D Texture_FogMask;\n"
506 "uniform sampler2D Texture_Pants;\n"
507 "uniform sampler2D Texture_Shirt;\n"
508 "uniform sampler2D Texture_Lightmap;\n"
509 "uniform sampler2D Texture_Deluxemap;\n"
510 "uniform sampler2D Texture_Glow;\n"
512 "uniform vec3 LightColor;\n"
513 "uniform vec3 AmbientColor;\n"
514 "uniform vec3 DiffuseColor;\n"
515 "uniform vec3 SpecularColor;\n"
516 "uniform vec3 Color_Pants;\n"
517 "uniform vec3 Color_Shirt;\n"
518 "uniform vec3 FogColor;\n"
520 "uniform float OffsetMapping_Scale;\n"
521 "uniform float OffsetMapping_Bias;\n"
522 "uniform float FogRangeRecip;\n"
524 "uniform float AmbientScale;\n"
525 "uniform float DiffuseScale;\n"
526 "uniform float SpecularScale;\n"
527 "uniform float SpecularPower;\n"
531 " // apply offsetmapping\n"
532 "#ifdef USEOFFSETMAPPING\n"
533 " vec2 TexCoordOffset = TexCoord;\n"
534 "#define TexCoord TexCoordOffset\n"
536 " vec3 eyedir = vec3(normalize(EyeVector));\n"
537 " float depthbias = 1.0 - eyedir.z; // should this be a -?\n"
538 " depthbias = 1.0 - depthbias * depthbias;\n"
540 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
541 " // 14 sample relief mapping: linear search and then binary search\n"
542 " vec3 OffsetVector = vec3(EyeVector.xy * (1.0 / EyeVector.z) * depthbias * OffsetMapping_Scale * vec2(-0.1, 0.1), -0.1);\n"
543 " vec3 RT = vec3(TexCoord - OffsetVector.xy * 10.0, 1.0) + 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;\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 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;OffsetVector *= 0.5;RT -= OffsetVector;\n"
558 " TexCoord = RT.xy;\n"
560 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
561 " vec2 OffsetVector = vec2((EyeVector.xy * (1.0 / EyeVector.z) * depthbias) * OffsetMapping_Scale * vec2(-0.333, 0.333));\n"
562 " //TexCoord += OffsetVector * 3.0;\n"
563 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
564 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
565 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
569 " // combine the diffuse textures (base, pants, shirt)\n"
570 " vec4 color = vec4(texture2D(Texture_Color, TexCoord));\n"
571 "#ifdef USECOLORMAPPING\n"
572 " color.rgb += vec3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + vec3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
578 "#ifdef MODE_LIGHTSOURCE\n"
581 " // get the surface normal and light normal\n"
582 " vec3 surfacenormal = normalize(vec3(texture2D(Texture_Normal, TexCoord)) - 0.5);\n"
583 " vec3 diffusenormal = vec3(normalize(LightVector));\n"
585 " // calculate directional shading\n"
586 " color.rgb *= (AmbientScale + DiffuseScale * max(dot(surfacenormal, diffusenormal), 0.0));\n"
587 "#ifdef USESPECULAR\n"
588 " vec3 specularnormal = vec3(normalize(diffusenormal + vec3(normalize(EyeVector))));\n"
589 " color.rgb += vec3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(max(dot(surfacenormal, specularnormal), 0.0), SpecularPower);\n"
592 "#ifdef USECUBEFILTER\n"
593 " // apply light cubemap filter\n"
594 " //color.rgb *= normalize(CubeVector) * 0.5 + 0.5;//vec3(textureCube(Texture_Cube, CubeVector));\n"
595 " color.rgb *= vec3(textureCube(Texture_Cube, CubeVector));\n"
598 " // apply light color\n"
599 " color.rgb *= LightColor;\n"
601 " // apply attenuation\n"
603 " // the attenuation is (1-(x*x+y*y+z*z)) which gives a large bright\n"
604 " // center and sharp falloff at the edge, this is about the most efficient\n"
605 " // we can get away with as far as providing illumination.\n"
607 " // pow(1-(x*x+y*y+z*z), 4) is far more realistic but needs large lights to\n"
608 " // provide significant illumination, large = slow = pain.\n"
609 " color.rgb *= max(1.0 - dot(CubeVector, CubeVector), 0.0);\n"
614 "#elif defined(MODE_LIGHTDIRECTION)\n"
615 " // directional model lighting\n"
617 " // get the surface normal and light normal\n"
618 " vec3 surfacenormal = normalize(vec3(texture2D(Texture_Normal, TexCoord)) - 0.5);\n"
619 " vec3 diffusenormal = vec3(normalize(LightVector));\n"
621 " // calculate directional shading\n"
622 " color.rgb *= AmbientColor + DiffuseColor * max(dot(surfacenormal, diffusenormal), 0.0);\n"
623 "#ifdef USESPECULAR\n"
624 " vec3 specularnormal = vec3(normalize(diffusenormal + vec3(normalize(EyeVector))));\n"
625 " color.rgb += vec3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(max(dot(surfacenormal, specularnormal), 0.0), SpecularPower);\n"
631 "#elif defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE)\n"
632 " // deluxemap lightmapping using light vectors in modelspace (evil q3map2)\n"
634 " // get the surface normal and light normal\n"
635 " vec3 surfacenormal = normalize(vec3(texture2D(Texture_Normal, TexCoord)) - 0.5);\n"
636 " vec3 diffusenormal_modelspace = vec3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - 0.5;\n"
637 " vec3 diffusenormal = normalize(vec3(dot(diffusenormal_modelspace, VectorS), dot(diffusenormal_modelspace, VectorT), dot(diffusenormal_modelspace, VectorR)));\n"
639 " // calculate directional shading\n"
640 " vec3 tempcolor = color.rgb * (DiffuseScale * max(dot(surfacenormal, diffusenormal), 0.0));\n"
641 "#ifdef USESPECULAR\n"
642 " vec3 specularnormal = vec3(normalize(diffusenormal + vec3(normalize(EyeVector))));\n"
643 " tempcolor += vec3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(max(dot(surfacenormal, specularnormal), 0.0), SpecularPower);\n"
646 " // apply lightmap color\n"
647 " color.rgb = tempcolor * vec3(texture2D(Texture_Lightmap, TexCoordLightmap)) + color.rgb * vec3(AmbientScale);\n"
652 "#elif defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
653 " // deluxemap lightmapping using light vectors in tangentspace\n"
655 " // get the surface normal and light normal\n"
656 " vec3 surfacenormal = normalize(vec3(texture2D(Texture_Normal, TexCoord)) - 0.5);\n"
657 " vec3 diffusenormal = normalize(vec3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - 0.5);\n"
659 " // calculate directional shading\n"
660 " vec3 tempcolor = color.rgb * (DiffuseScale * max(dot(surfacenormal, diffusenormal), 0.0));\n"
661 "#ifdef USESPECULAR\n"
662 " vec3 specularnormal = vec3(normalize(diffusenormal + vec3(normalize(EyeVector))));\n"
663 " tempcolor += vec3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(max(dot(surfacenormal, specularnormal), 0.0), SpecularPower);\n"
666 " // apply lightmap color\n"
667 " color.rgb = tempcolor * vec3(texture2D(Texture_Lightmap, TexCoordLightmap)) + color.rgb * vec3(AmbientScale);\n"
672 "#else // MODE none (lightmap)\n"
673 " // apply lightmap color\n"
674 " color.rgb *= vec3(texture2D(Texture_Lightmap, TexCoordLightmap)) * DiffuseScale + vec3(AmbientScale);\n"
677 " color *= gl_Color;\n"
680 " color.rgb += vec3(texture2D(Texture_Glow, TexCoord));\n"
685 " float fog = texture2D(Texture_FogMask, vec2(length(EyeVectorModelSpace)*FogRangeRecip, 0.0)).x;\n"
686 " color.rgb = color.rgb * fog + FogColor * (1.0 - fog);\n"
689 " gl_FragColor = color;\n"
692 "#endif // FRAGMENT_SHADER\n"
695 void R_GLSL_CompilePermutation(int permutation)
697 r_glsl_permutation_t *p = r_glsl_permutations + permutation;
698 int vertstrings_count;
699 int fragstrings_count;
701 const char *vertstrings_list[SHADERPERMUTATION_COUNT+1];
702 const char *fragstrings_list[SHADERPERMUTATION_COUNT+1];
703 char permutationname[256];
707 vertstrings_list[0] = "#define VERTEX_SHADER\n";
708 fragstrings_list[0] = "#define FRAGMENT_SHADER\n";
709 vertstrings_count = 1;
710 fragstrings_count = 1;
711 permutationname[0] = 0;
712 if (permutation & SHADERPERMUTATION_MODE_LIGHTSOURCE)
714 vertstrings_list[vertstrings_count++] = "#define MODE_LIGHTSOURCE\n";
715 fragstrings_list[fragstrings_count++] = "#define MODE_LIGHTSOURCE\n";
716 strlcat(permutationname, " lightsource", sizeof(permutationname));
718 if (permutation & SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_MODELSPACE)
720 vertstrings_list[vertstrings_count++] = "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n";
721 fragstrings_list[fragstrings_count++] = "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n";
722 strlcat(permutationname, " lightdirectionmap_modelspace", sizeof(permutationname));
724 if (permutation & SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)
726 vertstrings_list[vertstrings_count++] = "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n";
727 fragstrings_list[fragstrings_count++] = "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n";
728 strlcat(permutationname, " lightdirectionmap_tangentspace", sizeof(permutationname));
730 if (permutation & SHADERPERMUTATION_MODE_LIGHTDIRECTION)
732 vertstrings_list[vertstrings_count++] = "#define MODE_LIGHTDIRECTION\n";
733 fragstrings_list[fragstrings_count++] = "#define MODE_LIGHTDIRECTION\n";
734 strlcat(permutationname, " lightdirection", sizeof(permutationname));
736 if (permutation & SHADERPERMUTATION_GLOW)
738 vertstrings_list[vertstrings_count++] = "#define USEGLOW\n";
739 fragstrings_list[fragstrings_count++] = "#define USEGLOW\n";
740 strlcat(permutationname, " glow", sizeof(permutationname));
742 if (permutation & SHADERPERMUTATION_COLORMAPPING)
744 vertstrings_list[vertstrings_count++] = "#define USECOLORMAPPING\n";
745 fragstrings_list[fragstrings_count++] = "#define USECOLORMAPPING\n";
746 strlcat(permutationname, " colormapping", sizeof(permutationname));
748 if (permutation & SHADERPERMUTATION_SPECULAR)
750 vertstrings_list[vertstrings_count++] = "#define USESPECULAR\n";
751 fragstrings_list[fragstrings_count++] = "#define USESPECULAR\n";
752 strlcat(permutationname, " specular", sizeof(permutationname));
754 if (permutation & SHADERPERMUTATION_FOG)
756 vertstrings_list[vertstrings_count++] = "#define USEFOG\n";
757 fragstrings_list[fragstrings_count++] = "#define USEFOG\n";
758 strlcat(permutationname, " fog", sizeof(permutationname));
760 if (permutation & SHADERPERMUTATION_CUBEFILTER)
762 vertstrings_list[vertstrings_count++] = "#define USECUBEFILTER\n";
763 fragstrings_list[fragstrings_count++] = "#define USECUBEFILTER\n";
764 strlcat(permutationname, " cubefilter", sizeof(permutationname));
766 if (permutation & SHADERPERMUTATION_OFFSETMAPPING)
768 vertstrings_list[vertstrings_count++] = "#define USEOFFSETMAPPING\n";
769 fragstrings_list[fragstrings_count++] = "#define USEOFFSETMAPPING\n";
770 strlcat(permutationname, " offsetmapping", sizeof(permutationname));
772 if (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING)
774 vertstrings_list[vertstrings_count++] = "#define USEOFFSETMAPPING_RELIEFMAPPING\n";
775 fragstrings_list[fragstrings_count++] = "#define USEOFFSETMAPPING_RELIEFMAPPING\n";
776 strlcat(permutationname, " OFFSETMAPPING_RELIEFMAPPING", sizeof(permutationname));
778 shaderstring = (char *)FS_LoadFile("glsl/default.glsl", r_main_mempool, false, NULL);
781 Con_DPrintf("GLSL shader text loaded from disk\n");
782 vertstrings_list[vertstrings_count++] = shaderstring;
783 fragstrings_list[fragstrings_count++] = shaderstring;
787 vertstrings_list[vertstrings_count++] = builtinshaderstring;
788 fragstrings_list[fragstrings_count++] = builtinshaderstring;
790 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, fragstrings_count, fragstrings_list);
794 qglUseProgramObjectARB(p->program);CHECKGLERROR
795 p->loc_Texture_Normal = qglGetUniformLocationARB(p->program, "Texture_Normal");
796 p->loc_Texture_Color = qglGetUniformLocationARB(p->program, "Texture_Color");
797 p->loc_Texture_Gloss = qglGetUniformLocationARB(p->program, "Texture_Gloss");
798 p->loc_Texture_Cube = qglGetUniformLocationARB(p->program, "Texture_Cube");
799 p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
800 p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
801 p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
802 p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
803 p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
804 p->loc_Texture_Glow = qglGetUniformLocationARB(p->program, "Texture_Glow");
805 p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
806 p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
807 p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
808 p->loc_LightColor = qglGetUniformLocationARB(p->program, "LightColor");
809 p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants");
810 p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt");
811 p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip");
812 p->loc_AmbientScale = qglGetUniformLocationARB(p->program, "AmbientScale");
813 p->loc_DiffuseScale = qglGetUniformLocationARB(p->program, "DiffuseScale");
814 p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
815 p->loc_SpecularScale = qglGetUniformLocationARB(p->program, "SpecularScale");
816 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
817 p->loc_AmbientColor = qglGetUniformLocationARB(p->program, "AmbientColor");
818 p->loc_DiffuseColor = qglGetUniformLocationARB(p->program, "DiffuseColor");
819 p->loc_SpecularColor = qglGetUniformLocationARB(p->program, "SpecularColor");
820 p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
821 if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal, 0);
822 if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color, 1);
823 if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss, 2);
824 if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube, 3);
825 if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask, 4);
826 if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants, 5);
827 if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt, 6);
828 if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap, 7);
829 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap, 8);
830 if (p->loc_Texture_Glow >= 0) qglUniform1iARB(p->loc_Texture_Glow, 9);
832 qglUseProgramObjectARB(0);CHECKGLERROR
835 Con_Printf("permutation%s failed for shader %s, some features may not work properly!\n", permutationname, "glsl/default.glsl");
837 Mem_Free(shaderstring);
840 void R_GLSL_Restart_f(void)
843 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
844 if (r_glsl_permutations[i].program)
845 GL_Backend_FreeProgram(r_glsl_permutations[i].program);
846 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
849 int R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting)
851 // select a permutation of the lighting shader appropriate to this
852 // combination of texture, entity, light source, and fogging, only use the
853 // minimum features necessary to avoid wasting rendering time in the
854 // fragment shader on features that are not being used
856 float specularscale = rsurface_texture->specularscale;
857 r_glsl_permutation = NULL;
858 if (r_shadow_rtlight)
860 permutation |= SHADERPERMUTATION_MODE_LIGHTSOURCE;
861 specularscale *= r_shadow_rtlight->specularscale;
862 if (r_shadow_rtlight->currentcubemap != r_texture_whitecube)
863 permutation |= SHADERPERMUTATION_CUBEFILTER;
867 if (!(rsurface_texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
870 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTION;
873 if (r_glsl_deluxemapping.integer >= 1 && r_refdef.worldmodel && r_refdef.worldmodel->brushq3.deluxemapping && rsurface_lightmaptexture)
875 if (r_refdef.worldmodel->brushq3.deluxemapping_modelspace)
876 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_MODELSPACE;
878 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
880 else if (r_glsl_deluxemapping.integer >= 2) // fake mode
881 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
884 if (rsurface_texture->skin.glow)
885 permutation |= SHADERPERMUTATION_GLOW;
887 if (specularscale > 0)
888 permutation |= SHADERPERMUTATION_SPECULAR;
890 permutation |= SHADERPERMUTATION_FOG;
891 if (rsurface_texture->colormapping)
892 permutation |= SHADERPERMUTATION_COLORMAPPING;
893 if (r_glsl_offsetmapping.integer)
895 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
896 if (r_glsl_offsetmapping_reliefmapping.integer)
897 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
899 if (!r_glsl_permutations[permutation].program)
901 if (!r_glsl_permutations[permutation].compiled)
902 R_GLSL_CompilePermutation(permutation);
903 if (!r_glsl_permutations[permutation].program)
905 // remove features until we find a valid permutation
907 for (i = SHADERPERMUTATION_COUNT-1;;i>>=1)
909 // reduce i more quickly whenever it would not remove any bits
913 if (!r_glsl_permutations[permutation].compiled)
914 R_GLSL_CompilePermutation(permutation);
915 if (r_glsl_permutations[permutation].program)
918 return 0; // utterly failed
922 r_glsl_permutation = r_glsl_permutations + permutation;
924 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
925 R_Mesh_TexMatrix(0, &rsurface_texture->currenttexmatrix);
926 if (permutation & SHADERPERMUTATION_MODE_LIGHTSOURCE)
928 if (r_glsl_permutation->loc_Texture_Cube >= 0 && r_shadow_rtlight) R_Mesh_TexBindCubeMap(3, R_GetTexture(r_shadow_rtlight->currentcubemap));
929 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]);
930 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
931 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_shadow_rtlight->ambientscale);
932 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_shadow_rtlight->diffusescale);
933 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, specularscale);
935 else if (permutation & SHADERPERMUTATION_MODE_LIGHTDIRECTION)
937 if (r_glsl_permutation->loc_AmbientColor >= 0)
938 qglUniform3fARB(r_glsl_permutation->loc_AmbientColor, rsurface_entity->modellight_ambient[0], rsurface_entity->modellight_ambient[1], rsurface_entity->modellight_ambient[2]);
939 if (r_glsl_permutation->loc_DiffuseColor >= 0)
940 qglUniform3fARB(r_glsl_permutation->loc_DiffuseColor, rsurface_entity->modellight_diffuse[0], rsurface_entity->modellight_diffuse[1], rsurface_entity->modellight_diffuse[2]);
941 if (r_glsl_permutation->loc_SpecularColor >= 0)
942 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);
943 if (r_glsl_permutation->loc_LightDir >= 0)
944 qglUniform3fARB(r_glsl_permutation->loc_LightDir, rsurface_entity->modellight_lightdir[0], rsurface_entity->modellight_lightdir[1], rsurface_entity->modellight_lightdir[2]);
948 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_ambient.value * 2.0f / 128.0f);
949 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_lightmapintensity * 2.0f);
950 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, r_lightmapintensity * specularscale * 2.0f);
952 if (r_glsl_permutation->loc_Texture_Normal >= 0) R_Mesh_TexBind(0, R_GetTexture(rsurface_texture->skin.nmap));
953 if (r_glsl_permutation->loc_Texture_Color >= 0) R_Mesh_TexBind(1, R_GetTexture(rsurface_texture->basetexture));
954 if (r_glsl_permutation->loc_Texture_Gloss >= 0) R_Mesh_TexBind(2, R_GetTexture(rsurface_texture->glosstexture));
955 //if (r_glsl_permutation->loc_Texture_Cube >= 0 && permutation & SHADERPERMUTATION_MODE_LIGHTSOURCE) R_Mesh_TexBindCubeMap(3, R_GetTexture(r_shadow_rtlight->currentcubemap));
956 if (r_glsl_permutation->loc_Texture_FogMask >= 0) R_Mesh_TexBind(4, R_GetTexture(r_texture_fogattenuation));
957 if (r_glsl_permutation->loc_Texture_Pants >= 0) R_Mesh_TexBind(5, R_GetTexture(rsurface_texture->skin.pants));
958 if (r_glsl_permutation->loc_Texture_Shirt >= 0) R_Mesh_TexBind(6, R_GetTexture(rsurface_texture->skin.shirt));
959 //if (r_glsl_permutation->loc_Texture_Lightmap >= 0) R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
960 //if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
961 if (r_glsl_permutation->loc_Texture_Glow >= 0) R_Mesh_TexBind(9, R_GetTexture(rsurface_texture->skin.glow));
962 if (r_glsl_permutation->loc_FogColor >= 0)
964 // additive passes are only darkened by fog, not tinted
965 if (r_shadow_rtlight || (rsurface_texture->currentmaterialflags & MATERIALFLAG_ADD))
966 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
968 qglUniform3fARB(r_glsl_permutation->loc_FogColor, fogcolor[0], fogcolor[1], fogcolor[2]);
970 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface_modelorg[0], rsurface_modelorg[1], rsurface_modelorg[2]);
971 if (r_glsl_permutation->loc_Color_Pants >= 0)
973 if (rsurface_texture->skin.pants)
974 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface_entity->colormap_pantscolor[0], rsurface_entity->colormap_pantscolor[1], rsurface_entity->colormap_pantscolor[2]);
976 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
978 if (r_glsl_permutation->loc_Color_Shirt >= 0)
980 if (rsurface_texture->skin.shirt)
981 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface_entity->colormap_shirtcolor[0], rsurface_entity->colormap_shirtcolor[1], rsurface_entity->colormap_shirtcolor[2]);
983 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
985 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, fograngerecip);
986 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface_texture->specularpower);
987 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
992 void R_SwitchSurfaceShader(int permutation)
994 if (r_glsl_permutation != r_glsl_permutations + permutation)
996 r_glsl_permutation = r_glsl_permutations + permutation;
998 qglUseProgramObjectARB(r_glsl_permutation->program);
1003 void gl_main_start(void)
1005 r_main_texturepool = R_AllocTexturePool();
1006 r_bloom_texture_screen = NULL;
1007 r_bloom_texture_bloom = NULL;
1008 R_BuildBlankTextures();
1010 if (gl_texturecubemap)
1013 R_BuildNormalizationCube();
1015 R_BuildFogTexture();
1016 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
1019 void gl_main_shutdown(void)
1021 R_FreeTexturePool(&r_main_texturepool);
1022 r_bloom_texture_screen = NULL;
1023 r_bloom_texture_bloom = NULL;
1024 r_texture_blanknormalmap = NULL;
1025 r_texture_white = NULL;
1026 r_texture_black = NULL;
1027 r_texture_whitecube = NULL;
1028 r_texture_normalizationcube = NULL;
1032 extern void CL_ParseEntityLump(char *entitystring);
1033 void gl_main_newmap(void)
1035 // FIXME: move this code to client
1037 char *entities, entname[MAX_QPATH];
1041 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
1042 l = (int)strlen(entname) - 4;
1043 if (l >= 0 && !strcmp(entname + l, ".bsp"))
1045 strcpy(entname + l, ".ent");
1046 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
1048 CL_ParseEntityLump(entities);
1053 if (cl.worldmodel->brush.entities)
1054 CL_ParseEntityLump(cl.worldmodel->brush.entities);
1058 void GL_Main_Init(void)
1060 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
1062 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed\n");
1063 FOG_registercvars(); // FIXME: move this fog stuff to client?
1064 Cvar_RegisterVariable(&r_nearclip);
1065 Cvar_RegisterVariable(&r_showsurfaces);
1066 Cvar_RegisterVariable(&r_showtris);
1067 Cvar_RegisterVariable(&r_shownormals);
1068 Cvar_RegisterVariable(&r_showlighting);
1069 Cvar_RegisterVariable(&r_showshadowvolumes);
1070 Cvar_RegisterVariable(&r_showcollisionbrushes);
1071 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
1072 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
1073 Cvar_RegisterVariable(&r_showdisabledepthtest);
1074 Cvar_RegisterVariable(&r_drawentities);
1075 Cvar_RegisterVariable(&r_drawviewmodel);
1076 Cvar_RegisterVariable(&r_speeds);
1077 Cvar_RegisterVariable(&r_fullbrights);
1078 Cvar_RegisterVariable(&r_wateralpha);
1079 Cvar_RegisterVariable(&r_dynamic);
1080 Cvar_RegisterVariable(&r_fullbright);
1081 Cvar_RegisterVariable(&r_q1bsp_skymasking);
1082 Cvar_RegisterVariable(&r_textureunits);
1083 Cvar_RegisterVariable(&r_glsl);
1084 Cvar_RegisterVariable(&r_glsl_offsetmapping);
1085 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
1086 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
1087 Cvar_RegisterVariable(&r_glsl_deluxemapping);
1088 Cvar_RegisterVariable(&r_lerpsprites);
1089 Cvar_RegisterVariable(&r_lerpmodels);
1090 Cvar_RegisterVariable(&r_waterscroll);
1091 Cvar_RegisterVariable(&r_bloom);
1092 Cvar_RegisterVariable(&r_bloom_intensity);
1093 Cvar_RegisterVariable(&r_bloom_blur);
1094 Cvar_RegisterVariable(&r_bloom_resolution);
1095 Cvar_RegisterVariable(&r_bloom_power);
1096 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
1097 Cvar_RegisterVariable(&developer_texturelogging);
1098 Cvar_RegisterVariable(&gl_lightmaps);
1099 Cvar_RegisterVariable(&r_test);
1100 Cvar_RegisterVariable(&r_batchmode);
1101 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
1102 Cvar_SetValue("r_fullbrights", 0);
1103 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
1106 static vec3_t r_farclip_origin;
1107 static vec3_t r_farclip_direction;
1108 static vec_t r_farclip_directiondist;
1109 static vec_t r_farclip_meshfarclip;
1110 static int r_farclip_directionbit0;
1111 static int r_farclip_directionbit1;
1112 static int r_farclip_directionbit2;
1114 // enlarge farclip to accomodate box
1115 static void R_FarClip_Box(vec3_t mins, vec3_t maxs)
1118 d = (r_farclip_directionbit0 ? mins[0] : maxs[0]) * r_farclip_direction[0]
1119 + (r_farclip_directionbit1 ? mins[1] : maxs[1]) * r_farclip_direction[1]
1120 + (r_farclip_directionbit2 ? mins[2] : maxs[2]) * r_farclip_direction[2];
1121 if (r_farclip_meshfarclip < d)
1122 r_farclip_meshfarclip = d;
1125 // return farclip value
1126 static float R_FarClip(vec3_t origin, vec3_t direction, vec_t startfarclip)
1130 VectorCopy(origin, r_farclip_origin);
1131 VectorCopy(direction, r_farclip_direction);
1132 r_farclip_directiondist = DotProduct(r_farclip_origin, r_farclip_direction);
1133 r_farclip_directionbit0 = r_farclip_direction[0] < 0;
1134 r_farclip_directionbit1 = r_farclip_direction[1] < 0;
1135 r_farclip_directionbit2 = r_farclip_direction[2] < 0;
1136 r_farclip_meshfarclip = r_farclip_directiondist + startfarclip;
1138 if (r_refdef.worldmodel)
1139 R_FarClip_Box(r_refdef.worldmodel->normalmins, r_refdef.worldmodel->normalmaxs);
1140 for (i = 0;i < r_refdef.numentities;i++)
1141 R_FarClip_Box(r_refdef.entities[i]->mins, r_refdef.entities[i]->maxs);
1143 return r_farclip_meshfarclip - r_farclip_directiondist;
1146 extern void R_Textures_Init(void);
1147 extern void GL_Draw_Init(void);
1148 extern void GL_Main_Init(void);
1149 extern void R_Shadow_Init(void);
1150 extern void R_Sky_Init(void);
1151 extern void GL_Surf_Init(void);
1152 extern void R_Crosshairs_Init(void);
1153 extern void R_Light_Init(void);
1154 extern void R_Particles_Init(void);
1155 extern void R_Explosion_Init(void);
1156 extern void gl_backend_init(void);
1157 extern void Sbar_Init(void);
1158 extern void R_LightningBeams_Init(void);
1159 extern void Mod_RenderInit(void);
1161 void Render_Init(void)
1171 R_Crosshairs_Init();
1176 R_LightningBeams_Init();
1185 extern char *ENGINE_EXTENSIONS;
1188 VID_CheckExtensions();
1190 // LordHavoc: report supported extensions
1191 Con_DPrintf("\nengine extensions: %s\n", vm_sv_extensions );
1193 // clear to black (loading plaque will be seen over this)
1195 qglClearColor(0,0,0,1);CHECKGLERROR
1196 qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
1199 int R_CullBox(const vec3_t mins, const vec3_t maxs)
1203 for (i = 0;i < 4;i++)
1210 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1214 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1218 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1222 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1226 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1230 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1234 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1238 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1246 //==================================================================================
1248 static void R_UpdateEntityLighting(entity_render_t *ent)
1250 vec3_t tempdiffusenormal;
1251 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));
1252 VectorClear(ent->modellight_diffuse);
1253 VectorClear(ent->modellight_lightdir);
1254 if ((ent->flags & RENDER_LIGHT) && r_refdef.worldmodel && r_refdef.worldmodel->brush.LightPoint)
1255 r_refdef.worldmodel->brush.LightPoint(r_refdef.worldmodel, ent->origin, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
1257 VectorSet(ent->modellight_ambient, 1, 1, 1);
1258 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
1259 VectorNormalize(ent->modellight_lightdir);
1260 ent->modellight_ambient[0] *= ent->colormod[0] * r_lightmapintensity;
1261 ent->modellight_ambient[1] *= ent->colormod[1] * r_lightmapintensity;
1262 ent->modellight_ambient[2] *= ent->colormod[2] * r_lightmapintensity;
1263 ent->modellight_diffuse[0] *= ent->colormod[0] * r_lightmapintensity;
1264 ent->modellight_diffuse[1] *= ent->colormod[1] * r_lightmapintensity;
1265 ent->modellight_diffuse[2] *= ent->colormod[2] * r_lightmapintensity;
1268 static void R_MarkEntities (void)
1271 entity_render_t *ent;
1273 if (!r_drawentities.integer)
1276 r_refdef.worldentity->visframe = r_framecount;
1277 renderimask = envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : (chase_active.integer ? 0 : RENDER_EXTERIORMODEL);
1278 if (r_refdef.worldmodel && r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs)
1280 // worldmodel can check visibility
1281 for (i = 0;i < r_refdef.numentities;i++)
1283 ent = r_refdef.entities[i];
1284 // some of the renderer still relies on origin...
1285 Matrix4x4_OriginFromMatrix(&ent->matrix, ent->origin);
1286 // some of the renderer still relies on scale...
1287 ent->scale = Matrix4x4_ScaleFromMatrix(&ent->matrix);
1288 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)))
1290 ent->visframe = r_framecount;
1291 R_UpdateEntityLighting(ent);
1297 // no worldmodel or it can't check visibility
1298 for (i = 0;i < r_refdef.numentities;i++)
1300 ent = r_refdef.entities[i];
1301 // some of the renderer still relies on origin...
1302 Matrix4x4_OriginFromMatrix(&ent->matrix, ent->origin);
1303 // some of the renderer still relies on scale...
1304 ent->scale = Matrix4x4_ScaleFromMatrix(&ent->matrix);
1305 if (!(ent->flags & renderimask) && !R_CullBox(ent->mins, ent->maxs) && (ent->effects & EF_NODEPTHTEST))
1307 ent->visframe = r_framecount;
1308 R_UpdateEntityLighting(ent);
1314 // only used if skyrendermasked, and normally returns false
1315 int R_DrawBrushModelsSky (void)
1318 entity_render_t *ent;
1320 if (!r_drawentities.integer)
1324 for (i = 0;i < r_refdef.numentities;i++)
1326 ent = r_refdef.entities[i];
1327 if (ent->visframe == r_framecount && ent->model && ent->model->DrawSky)
1329 ent->model->DrawSky(ent);
1336 void R_DrawNoModel(entity_render_t *ent);
1337 void R_DrawModels(void)
1340 entity_render_t *ent;
1342 if (!r_drawentities.integer)
1345 for (i = 0;i < r_refdef.numentities;i++)
1347 ent = r_refdef.entities[i];
1348 if (ent->visframe == r_framecount)
1350 renderstats.entities++;
1351 if (ent->model && ent->model->Draw != NULL)
1352 ent->model->Draw(ent);
1359 static void R_SetFrustum(void)
1361 // break apart the view matrix into vectors for various purposes
1362 Matrix4x4_ToVectors(&r_view_matrix, r_viewforward, r_viewleft, r_viewup, r_vieworigin);
1363 VectorNegate(r_viewleft, r_viewright);
1366 frustum[0].normal[0] = 0 - 1.0 / r_refdef.frustum_x;
1367 frustum[0].normal[1] = 0 - 0;
1368 frustum[0].normal[2] = -1 - 0;
1369 frustum[1].normal[0] = 0 + 1.0 / r_refdef.frustum_x;
1370 frustum[1].normal[1] = 0 + 0;
1371 frustum[1].normal[2] = -1 + 0;
1372 frustum[2].normal[0] = 0 - 0;
1373 frustum[2].normal[1] = 0 - 1.0 / r_refdef.frustum_y;
1374 frustum[2].normal[2] = -1 - 0;
1375 frustum[3].normal[0] = 0 + 0;
1376 frustum[3].normal[1] = 0 + 1.0 / r_refdef.frustum_y;
1377 frustum[3].normal[2] = -1 + 0;
1381 zNear = r_nearclip.value;
1382 nudge = 1.0 - 1.0 / (1<<23);
1383 frustum[4].normal[0] = 0 - 0;
1384 frustum[4].normal[1] = 0 - 0;
1385 frustum[4].normal[2] = -1 - -nudge;
1386 frustum[4].dist = 0 - -2 * zNear * nudge;
1387 frustum[5].normal[0] = 0 + 0;
1388 frustum[5].normal[1] = 0 + 0;
1389 frustum[5].normal[2] = -1 + -nudge;
1390 frustum[5].dist = 0 + -2 * zNear * nudge;
1396 frustum[0].normal[0] = m[3] - m[0];
1397 frustum[0].normal[1] = m[7] - m[4];
1398 frustum[0].normal[2] = m[11] - m[8];
1399 frustum[0].dist = m[15] - m[12];
1401 frustum[1].normal[0] = m[3] + m[0];
1402 frustum[1].normal[1] = m[7] + m[4];
1403 frustum[1].normal[2] = m[11] + m[8];
1404 frustum[1].dist = m[15] + m[12];
1406 frustum[2].normal[0] = m[3] - m[1];
1407 frustum[2].normal[1] = m[7] - m[5];
1408 frustum[2].normal[2] = m[11] - m[9];
1409 frustum[2].dist = m[15] - m[13];
1411 frustum[3].normal[0] = m[3] + m[1];
1412 frustum[3].normal[1] = m[7] + m[5];
1413 frustum[3].normal[2] = m[11] + m[9];
1414 frustum[3].dist = m[15] + m[13];
1416 frustum[4].normal[0] = m[3] - m[2];
1417 frustum[4].normal[1] = m[7] - m[6];
1418 frustum[4].normal[2] = m[11] - m[10];
1419 frustum[4].dist = m[15] - m[14];
1421 frustum[5].normal[0] = m[3] + m[2];
1422 frustum[5].normal[1] = m[7] + m[6];
1423 frustum[5].normal[2] = m[11] + m[10];
1424 frustum[5].dist = m[15] + m[14];
1429 VectorMAM(1, r_viewforward, 1.0 / -r_refdef.frustum_x, r_viewleft, frustum[0].normal);
1430 VectorMAM(1, r_viewforward, 1.0 / r_refdef.frustum_x, r_viewleft, frustum[1].normal);
1431 VectorMAM(1, r_viewforward, 1.0 / -r_refdef.frustum_y, r_viewup, frustum[2].normal);
1432 VectorMAM(1, r_viewforward, 1.0 / r_refdef.frustum_y, r_viewup, frustum[3].normal);
1433 VectorCopy(r_viewforward, frustum[4].normal);
1434 VectorNormalize(frustum[0].normal);
1435 VectorNormalize(frustum[1].normal);
1436 VectorNormalize(frustum[2].normal);
1437 VectorNormalize(frustum[3].normal);
1438 frustum[0].dist = DotProduct (r_vieworigin, frustum[0].normal);
1439 frustum[1].dist = DotProduct (r_vieworigin, frustum[1].normal);
1440 frustum[2].dist = DotProduct (r_vieworigin, frustum[2].normal);
1441 frustum[3].dist = DotProduct (r_vieworigin, frustum[3].normal);
1442 frustum[4].dist = DotProduct (r_vieworigin, frustum[4].normal) + r_nearclip.value;
1443 PlaneClassify(&frustum[0]);
1444 PlaneClassify(&frustum[1]);
1445 PlaneClassify(&frustum[2]);
1446 PlaneClassify(&frustum[3]);
1447 PlaneClassify(&frustum[4]);
1449 // LordHavoc: note to all quake engine coders, Quake had a special case
1450 // for 90 degrees which assumed a square view (wrong), so I removed it,
1451 // Quake2 has it disabled as well.
1453 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
1454 //RotatePointAroundVector( frustum[0].normal, r_viewup, r_viewforward, -(90 - r_refdef.fov_x / 2));
1455 //frustum[0].dist = DotProduct (r_vieworigin, frustum[0].normal);
1456 //PlaneClassify(&frustum[0]);
1458 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
1459 //RotatePointAroundVector( frustum[1].normal, r_viewup, r_viewforward, (90 - r_refdef.fov_x / 2));
1460 //frustum[1].dist = DotProduct (r_vieworigin, frustum[1].normal);
1461 //PlaneClassify(&frustum[1]);
1463 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
1464 //RotatePointAroundVector( frustum[2].normal, r_viewleft, r_viewforward, -(90 - r_refdef.fov_y / 2));
1465 //frustum[2].dist = DotProduct (r_vieworigin, frustum[2].normal);
1466 //PlaneClassify(&frustum[2]);
1468 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
1469 //RotatePointAroundVector( frustum[3].normal, r_viewleft, r_viewforward, (90 - r_refdef.fov_y / 2));
1470 //frustum[3].dist = DotProduct (r_vieworigin, frustum[3].normal);
1471 //PlaneClassify(&frustum[3]);
1474 //VectorCopy(r_viewforward, frustum[4].normal);
1475 //frustum[4].dist = DotProduct (r_vieworigin, frustum[4].normal) + r_nearclip.value;
1476 //PlaneClassify(&frustum[4]);
1479 static void R_BlendView(void)
1481 int screenwidth, screenheight;
1485 float texcoord2f[3][8];
1487 // set the (poorly named) screenwidth and screenheight variables to
1488 // a power of 2 at least as large as the screen, these will define the
1489 // size of the texture to allocate
1490 for (screenwidth = 1;screenwidth < vid.width;screenwidth *= 2);
1491 for (screenheight = 1;screenheight < vid.height;screenheight *= 2);
1493 doblend = r_refdef.viewblend[3] >= 0.01f;
1494 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;
1496 if (!dobloom && !doblend)
1499 GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
1501 GL_DepthTest(false);
1502 R_Mesh_Matrix(&identitymatrix);
1503 // vertex coordinates for a quad that covers the screen exactly
1504 vertex3f[0] = 0;vertex3f[1] = 0;vertex3f[2] = 0;
1505 vertex3f[3] = 1;vertex3f[4] = 0;vertex3f[5] = 0;
1506 vertex3f[6] = 1;vertex3f[7] = 1;vertex3f[8] = 0;
1507 vertex3f[9] = 0;vertex3f[10] = 1;vertex3f[11] = 0;
1508 R_Mesh_VertexPointer(vertex3f);
1509 R_Mesh_ColorPointer(NULL);
1510 R_Mesh_ResetTextureState();
1513 int bloomwidth, bloomheight, x, range;
1514 float xoffset, yoffset, r;
1515 renderstats.bloom++;
1516 // allocate textures as needed
1517 if (!r_bloom_texture_screen)
1518 r_bloom_texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", screenwidth, screenheight, NULL, TEXTYPE_RGBA, TEXF_FORCENEAREST | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
1519 if (!r_bloom_texture_bloom)
1520 r_bloom_texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", screenwidth, screenheight, NULL, TEXTYPE_RGBA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
1521 // set bloomwidth and bloomheight to the bloom resolution that will be
1522 // used (often less than the screen resolution for faster rendering)
1523 bloomwidth = min(r_view_width, r_bloom_resolution.integer);
1524 bloomheight = min(r_view_height, bloomwidth * r_view_height / r_view_width);
1525 // set up a texcoord array for the full resolution screen image
1526 // (we have to keep this around to copy back during final render)
1527 texcoord2f[0][0] = 0;
1528 texcoord2f[0][1] = (float)r_view_height / (float)screenheight;
1529 texcoord2f[0][2] = (float)r_view_width / (float)screenwidth;
1530 texcoord2f[0][3] = (float)r_view_height / (float)screenheight;
1531 texcoord2f[0][4] = (float)r_view_width / (float)screenwidth;
1532 texcoord2f[0][5] = 0;
1533 texcoord2f[0][6] = 0;
1534 texcoord2f[0][7] = 0;
1535 // set up a texcoord array for the reduced resolution bloom image
1536 // (which will be additive blended over the screen image)
1537 texcoord2f[1][0] = 0;
1538 texcoord2f[1][1] = (float)bloomheight / (float)screenheight;
1539 texcoord2f[1][2] = (float)bloomwidth / (float)screenwidth;
1540 texcoord2f[1][3] = (float)bloomheight / (float)screenheight;
1541 texcoord2f[1][4] = (float)bloomwidth / (float)screenwidth;
1542 texcoord2f[1][5] = 0;
1543 texcoord2f[1][6] = 0;
1544 texcoord2f[1][7] = 0;
1545 R_Mesh_TexCoordPointer(0, 2, texcoord2f[0]);
1546 R_Mesh_TexBind(0, R_GetTexture(r_bloom_texture_screen));
1547 // copy view into the full resolution screen image texture
1548 GL_ActiveTexture(0);
1550 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
1551 renderstats.bloom_copypixels += r_view_width * r_view_height;
1552 // now scale it down to the bloom size and raise to a power of itself
1553 // to darken it (this leaves the really bright stuff bright, and
1554 // everything else becomes very dark)
1555 // TODO: optimize with multitexture or GLSL
1557 qglViewport(r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);CHECKGLERROR
1558 GL_BlendFunc(GL_ONE, GL_ZERO);
1559 GL_Color(1, 1, 1, 1);
1560 R_Mesh_Draw(0, 4, 2, polygonelements);
1561 renderstats.bloom_drawpixels += bloomwidth * bloomheight;
1562 // render multiple times with a multiply blendfunc to raise to a power
1563 GL_BlendFunc(GL_DST_COLOR, GL_ZERO);
1564 for (x = 1;x < r_bloom_power.integer;x++)
1566 R_Mesh_Draw(0, 4, 2, polygonelements);
1567 renderstats.bloom_drawpixels += bloomwidth * bloomheight;
1569 // we now have a darkened bloom image in the framebuffer, copy it into
1570 // the bloom image texture for more processing
1571 R_Mesh_TexBind(0, R_GetTexture(r_bloom_texture_bloom));
1572 R_Mesh_TexCoordPointer(0, 2, texcoord2f[2]);
1573 GL_ActiveTexture(0);
1575 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);CHECKGLERROR
1576 renderstats.bloom_copypixels += bloomwidth * bloomheight;
1577 // blend on at multiple vertical offsets to achieve a vertical blur
1578 // TODO: do offset blends using GLSL
1579 range = r_bloom_blur.integer * bloomwidth / 320;
1580 GL_BlendFunc(GL_ONE, GL_ZERO);
1581 for (x = -range;x <= range;x++)
1583 xoffset = 0 / (float)bloomwidth * (float)bloomwidth / (float)screenwidth;
1584 yoffset = x / (float)bloomheight * (float)bloomheight / (float)screenheight;
1585 // compute a texcoord array with the specified x and y offset
1586 texcoord2f[2][0] = xoffset+0;
1587 texcoord2f[2][1] = yoffset+(float)bloomheight / (float)screenheight;
1588 texcoord2f[2][2] = xoffset+(float)bloomwidth / (float)screenwidth;
1589 texcoord2f[2][3] = yoffset+(float)bloomheight / (float)screenheight;
1590 texcoord2f[2][4] = xoffset+(float)bloomwidth / (float)screenwidth;
1591 texcoord2f[2][5] = yoffset+0;
1592 texcoord2f[2][6] = xoffset+0;
1593 texcoord2f[2][7] = yoffset+0;
1594 // this r value looks like a 'dot' particle, fading sharply to
1595 // black at the edges
1596 // (probably not realistic but looks good enough)
1597 r = r_bloom_intensity.value/(range*2+1)*(1 - x*x/(float)(range*range));
1600 GL_Color(r, r, r, 1);
1601 R_Mesh_Draw(0, 4, 2, polygonelements);
1602 renderstats.bloom_drawpixels += bloomwidth * bloomheight;
1603 GL_BlendFunc(GL_ONE, GL_ONE);
1605 // copy the vertically blurred bloom view to a texture
1606 GL_ActiveTexture(0);
1608 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);CHECKGLERROR
1609 renderstats.bloom_copypixels += bloomwidth * bloomheight;
1610 // blend the vertically blurred image at multiple offsets horizontally
1611 // to finish the blur effect
1612 // TODO: do offset blends using GLSL
1613 range = r_bloom_blur.integer * bloomwidth / 320;
1614 GL_BlendFunc(GL_ONE, GL_ZERO);
1615 for (x = -range;x <= range;x++)
1617 xoffset = x / (float)bloomwidth * (float)bloomwidth / (float)screenwidth;
1618 yoffset = 0 / (float)bloomheight * (float)bloomheight / (float)screenheight;
1619 // compute a texcoord array with the specified x and y offset
1620 texcoord2f[2][0] = xoffset+0;
1621 texcoord2f[2][1] = yoffset+(float)bloomheight / (float)screenheight;
1622 texcoord2f[2][2] = xoffset+(float)bloomwidth / (float)screenwidth;
1623 texcoord2f[2][3] = yoffset+(float)bloomheight / (float)screenheight;
1624 texcoord2f[2][4] = xoffset+(float)bloomwidth / (float)screenwidth;
1625 texcoord2f[2][5] = yoffset+0;
1626 texcoord2f[2][6] = xoffset+0;
1627 texcoord2f[2][7] = yoffset+0;
1628 // this r value looks like a 'dot' particle, fading sharply to
1629 // black at the edges
1630 // (probably not realistic but looks good enough)
1631 r = r_bloom_intensity.value/(range*2+1)*(1 - x*x/(float)(range*range));
1634 GL_Color(r, r, r, 1);
1635 R_Mesh_Draw(0, 4, 2, polygonelements);
1636 renderstats.bloom_drawpixels += bloomwidth * bloomheight;
1637 GL_BlendFunc(GL_ONE, GL_ONE);
1639 // copy the blurred bloom view to a texture
1640 GL_ActiveTexture(0);
1642 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);CHECKGLERROR
1643 renderstats.bloom_copypixels += bloomwidth * bloomheight;
1644 // go back to full view area
1645 qglViewport(r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);CHECKGLERROR
1646 // put the original screen image back in place and blend the bloom
1649 GL_BlendFunc(GL_ONE, GL_ZERO);
1650 // do both in one pass if possible
1651 R_Mesh_TexBind(0, R_GetTexture(r_bloom_texture_screen));
1652 R_Mesh_TexCoordPointer(0, 2, texcoord2f[0]);
1653 if (r_textureunits.integer >= 2 && gl_combine.integer)
1655 R_Mesh_TexCombine(1, GL_ADD, GL_ADD, 1, 1);
1656 R_Mesh_TexBind(1, R_GetTexture(r_bloom_texture_bloom));
1657 R_Mesh_TexCoordPointer(1, 2, texcoord2f[1]);
1661 R_Mesh_Draw(0, 4, 2, polygonelements);
1662 renderstats.bloom_drawpixels += r_view_width * r_view_height;
1663 // now blend on the bloom texture
1664 GL_BlendFunc(GL_ONE, GL_ONE);
1665 R_Mesh_TexBind(0, R_GetTexture(r_bloom_texture_bloom));
1666 R_Mesh_TexCoordPointer(0, 2, texcoord2f[1]);
1668 R_Mesh_Draw(0, 4, 2, polygonelements);
1669 renderstats.bloom_drawpixels += r_view_width * r_view_height;
1673 // apply a color tint to the whole view
1674 R_Mesh_ResetTextureState();
1675 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1676 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
1677 R_Mesh_Draw(0, 4, 2, polygonelements);
1681 void R_RenderScene(void);
1683 matrix4x4_t r_waterscrollmatrix;
1690 void R_RenderView(void)
1692 if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
1693 return; //Host_Error ("R_RenderView: NULL worldmodel");
1695 r_view_width = bound(0, r_refdef.width, vid.width);
1696 r_view_height = bound(0, r_refdef.height, vid.height);
1698 r_view_x = bound(0, r_refdef.x, vid.width - r_refdef.width);
1699 r_view_y = bound(0, r_refdef.y, vid.height - r_refdef.height);
1701 r_view_matrix = r_refdef.viewentitymatrix;
1702 GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
1703 r_rtworld = r_shadow_realtime_world.integer;
1704 r_rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
1705 r_rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer;
1706 r_rtdlightshadows = r_rtdlight && (r_rtworld ? r_shadow_realtime_world_dlightshadows.integer : r_shadow_realtime_dlight_shadows.integer) && gl_stencil;
1707 r_lightmapintensity = r_rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
1708 r_polygonfactor = 0;
1709 r_polygonoffset = 0;
1710 r_shadowpolygonfactor = r_polygonfactor + r_shadow_shadow_polygonfactor.value;
1711 r_shadowpolygonoffset = r_polygonoffset + r_shadow_shadow_polygonoffset.value;
1712 if (r_showsurfaces.integer)
1715 r_rtworldshadows = false;
1717 r_rtdlightshadows = false;
1718 r_lightmapintensity = 0;
1721 // GL is weird because it's bottom to top, r_view_y is top to bottom
1723 qglViewport(r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);CHECKGLERROR
1724 GL_Scissor(r_view_x, r_view_y, r_view_width, r_view_height);
1725 GL_ScissorTest(true);
1730 if (r_timereport_active)
1731 R_TimeReport("setup");
1734 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
1735 qglPolygonOffset(r_polygonfactor, r_polygonoffset);CHECKGLERROR
1736 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
1741 qglPolygonOffset(r_polygonfactor, r_polygonoffset);CHECKGLERROR
1742 qglDisable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
1745 if (r_timereport_active)
1746 R_TimeReport("blendview");
1748 GL_Scissor(0, 0, vid.width, vid.height);
1749 GL_ScissorTest(false);
1754 void CSQC_R_ClearScreen (void)
1756 if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
1757 return; //Host_Error ("R_RenderView: NULL worldmodel");
1759 r_view_width = bound(0, r_refdef.width, vid.width);
1760 r_view_height = bound(0, r_refdef.height, vid.height);
1762 r_view_x = bound(0, r_refdef.x, vid.width - r_refdef.width);
1763 r_view_y = bound(0, r_refdef.y, vid.height - r_refdef.height);
1765 r_view_matrix = r_refdef.viewentitymatrix;
1766 GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
1767 r_rtworld = r_shadow_realtime_world.integer;
1768 r_rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
1769 r_rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer;
1770 r_rtdlightshadows = r_rtdlight && (r_rtworld ? r_shadow_realtime_world_dlightshadows.integer : r_shadow_realtime_dlight_shadows.integer) && gl_stencil;
1771 r_lightmapintensity = r_rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
1772 r_polygonfactor = 0;
1773 r_polygonoffset = 0;
1774 r_shadowpolygonfactor = r_polygonfactor + r_shadow_shadow_polygonfactor.value;
1775 r_shadowpolygonoffset = r_polygonoffset + r_shadow_shadow_polygonoffset.value;
1776 if (r_showsurfaces.integer)
1779 r_rtworldshadows = false;
1781 r_rtdlightshadows = false;
1782 r_lightmapintensity = 0;
1785 // GL is weird because it's bottom to top, r_view_y is top to bottom
1787 qglViewport(r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);CHECKGLERROR
1788 GL_Scissor(r_view_x, r_view_y, r_view_width, r_view_height);
1789 GL_ScissorTest(true);
1794 if (r_timereport_active)
1795 R_TimeReport("setup");
1800 void CSQC_R_RenderScene (void)
1803 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
1804 qglPolygonOffset(r_polygonfactor, r_polygonoffset);CHECKGLERROR
1805 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
1810 qglPolygonOffset(r_polygonfactor, r_polygonoffset);CHECKGLERROR
1811 qglDisable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
1814 if (r_timereport_active)
1815 R_TimeReport("blendview");
1817 GL_Scissor(0, 0, vid.width, vid.height);
1818 GL_ScissorTest(false);
1822 extern void R_DrawLightningBeams (void);
1823 extern void VM_AddPolygonsToMeshQueue (void);
1824 void R_RenderScene(void)
1828 // don't let sound skip if going slow
1829 if (r_refdef.extraupdate)
1835 if (gl_support_fragment_shader)
1837 qglUseProgramObjectARB(0);CHECKGLERROR
1840 R_MeshQueue_BeginScene();
1844 r_farclip = R_FarClip(r_vieworigin, r_viewforward, 768.0f) + 256.0f;
1845 nearclip = bound (0.001f, r_nearclip.value, r_farclip - 1.0f);
1847 if (r_rtworldshadows || r_rtdlightshadows)
1848 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_refdef.frustum_x, r_refdef.frustum_y, nearclip);
1850 GL_SetupView_Mode_Perspective(r_refdef.frustum_x, r_refdef.frustum_y, nearclip, r_farclip);
1852 GL_SetupView_Orientation_FromEntity(&r_view_matrix);
1854 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);
1858 R_WorldVisibility();
1859 if (r_timereport_active)
1860 R_TimeReport("worldvis");
1863 if (r_timereport_active)
1864 R_TimeReport("markentity");
1866 R_Shadow_UpdateWorldLightSelection();
1868 if (cl.csqc_vidvars.drawworld)
1870 // don't let sound skip if going slow
1871 if (r_refdef.extraupdate)
1874 if (r_refdef.worldmodel && r_refdef.worldmodel->DrawSky)
1876 r_refdef.worldmodel->DrawSky(r_refdef.worldentity);
1877 if (r_timereport_active)
1878 R_TimeReport("worldsky");
1881 if (R_DrawBrushModelsSky() && r_timereport_active)
1882 R_TimeReport("bmodelsky");
1884 if (r_refdef.worldmodel && r_refdef.worldmodel->Draw)
1886 r_refdef.worldmodel->Draw(r_refdef.worldentity);
1887 if (r_timereport_active)
1888 R_TimeReport("world");
1892 // don't let sound skip if going slow
1893 if (r_refdef.extraupdate)
1897 if (r_timereport_active)
1898 R_TimeReport("models");
1900 // don't let sound skip if going slow
1901 if (r_refdef.extraupdate)
1904 R_ShadowVolumeLighting(false);
1905 if (r_timereport_active)
1906 R_TimeReport("rtlights");
1908 // don't let sound skip if going slow
1909 if (r_refdef.extraupdate)
1912 if (cl.csqc_vidvars.drawworld)
1914 R_DrawLightningBeams();
1915 if (r_timereport_active)
1916 R_TimeReport("lightning");
1919 if (r_timereport_active)
1920 R_TimeReport("particles");
1923 if (r_timereport_active)
1924 R_TimeReport("explosions");
1927 R_MeshQueue_RenderTransparent();
1928 if (r_timereport_active)
1929 R_TimeReport("drawtrans");
1931 if (cl.csqc_vidvars.drawworld)
1934 if (r_timereport_active)
1935 R_TimeReport("coronas");
1937 if(cl.csqc_vidvars.drawcrosshair)
1939 R_DrawWorldCrosshair();
1940 if (r_timereport_active)
1941 R_TimeReport("crosshair");
1944 VM_AddPolygonsToMeshQueue();
1946 R_MeshQueue_Render();
1948 R_MeshQueue_EndScene();
1950 // don't let sound skip if going slow
1951 if (r_refdef.extraupdate)
1955 if (gl_support_fragment_shader)
1957 qglUseProgramObjectARB(0);CHECKGLERROR
1962 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
1965 float *v, *c, f1, f2, diff[3], vertex3f[8*3], color4f[8*4];
1966 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1967 GL_DepthMask(false);
1969 R_Mesh_Matrix(&identitymatrix);
1971 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2];
1972 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
1973 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
1974 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
1975 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
1976 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
1977 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
1978 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
1979 R_FillColors(color, 8, cr, cg, cb, ca);
1982 for (i = 0, v = vertex, c = color;i < 8;i++, v += 4, c += 4)
1984 f2 = VERTEXFOGTABLE(VectorDistance(v, r_vieworigin));
1986 c[0] = c[0] * f1 + fogcolor[0] * f2;
1987 c[1] = c[1] * f1 + fogcolor[1] * f2;
1988 c[2] = c[2] * f1 + fogcolor[2] * f2;
1991 R_Mesh_VertexPointer(vertex3f);
1992 R_Mesh_ColorPointer(color);
1993 R_Mesh_ResetTextureState();
1998 int nomodelelements[24] =
2010 float nomodelvertex3f[6*3] =
2020 float nomodelcolor4f[6*4] =
2022 0.0f, 0.0f, 0.5f, 1.0f,
2023 0.0f, 0.0f, 0.5f, 1.0f,
2024 0.0f, 0.5f, 0.0f, 1.0f,
2025 0.0f, 0.5f, 0.0f, 1.0f,
2026 0.5f, 0.0f, 0.0f, 1.0f,
2027 0.5f, 0.0f, 0.0f, 1.0f
2030 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
2035 // this is only called once per entity so numsurfaces is always 1, and
2036 // surfacelist is always {0}, so this code does not handle batches
2037 R_Mesh_Matrix(&ent->matrix);
2039 if (ent->flags & EF_ADDITIVE)
2041 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2042 GL_DepthMask(false);
2044 else if (ent->alpha < 1)
2046 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2047 GL_DepthMask(false);
2051 GL_BlendFunc(GL_ONE, GL_ZERO);
2054 GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
2055 R_Mesh_VertexPointer(nomodelvertex3f);
2058 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
2059 R_Mesh_ColorPointer(color4f);
2060 f2 = VERTEXFOGTABLE(VectorDistance(ent->origin, r_vieworigin));
2062 for (i = 0, c = color4f;i < 6;i++, c += 4)
2064 c[0] = (c[0] * f1 + fogcolor[0] * f2);
2065 c[1] = (c[1] * f1 + fogcolor[1] * f2);
2066 c[2] = (c[2] * f1 + fogcolor[2] * f2);
2070 else if (ent->alpha != 1)
2072 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
2073 R_Mesh_ColorPointer(color4f);
2074 for (i = 0, c = color4f;i < 6;i++, c += 4)
2078 R_Mesh_ColorPointer(nomodelcolor4f);
2079 R_Mesh_ResetTextureState();
2080 R_Mesh_Draw(0, 6, 8, nomodelelements);
2083 void R_DrawNoModel(entity_render_t *ent)
2085 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
2086 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_vieworigin : ent->origin, R_DrawNoModel_TransparentCallback, ent, 0, r_shadow_rtlight);
2088 // R_DrawNoModelCallback(ent, 0);
2091 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
2093 vec3_t right1, right2, diff, normal;
2095 VectorSubtract (org2, org1, normal);
2097 // calculate 'right' vector for start
2098 VectorSubtract (r_vieworigin, org1, diff);
2099 CrossProduct (normal, diff, right1);
2100 VectorNormalize (right1);
2102 // calculate 'right' vector for end
2103 VectorSubtract (r_vieworigin, org2, diff);
2104 CrossProduct (normal, diff, right2);
2105 VectorNormalize (right2);
2107 vert[ 0] = org1[0] + width * right1[0];
2108 vert[ 1] = org1[1] + width * right1[1];
2109 vert[ 2] = org1[2] + width * right1[2];
2110 vert[ 3] = org1[0] - width * right1[0];
2111 vert[ 4] = org1[1] - width * right1[1];
2112 vert[ 5] = org1[2] - width * right1[2];
2113 vert[ 6] = org2[0] - width * right2[0];
2114 vert[ 7] = org2[1] - width * right2[1];
2115 vert[ 8] = org2[2] - width * right2[2];
2116 vert[ 9] = org2[0] + width * right2[0];
2117 vert[10] = org2[1] + width * right2[1];
2118 vert[11] = org2[2] + width * right2[2];
2121 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
2123 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)
2125 float fog = 0.0f, ifog;
2129 fog = VERTEXFOGTABLE(VectorDistance(origin, r_vieworigin));
2132 R_Mesh_Matrix(&identitymatrix);
2133 GL_BlendFunc(blendfunc1, blendfunc2);
2134 GL_DepthMask(false);
2135 GL_DepthTest(!depthdisable);
2137 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
2138 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
2139 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
2140 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
2141 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
2142 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
2143 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
2144 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
2145 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
2146 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
2147 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
2148 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
2150 R_Mesh_VertexPointer(vertex3f);
2151 R_Mesh_ColorPointer(NULL);
2152 R_Mesh_ResetTextureState();
2153 R_Mesh_TexBind(0, R_GetTexture(texture));
2154 R_Mesh_TexCoordPointer(0, 2, spritetexcoord2f);
2155 GL_Color(cr * ifog, cg * ifog, cb * ifog, ca);
2156 R_Mesh_Draw(0, 4, 2, polygonelements);
2158 if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
2160 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
2161 GL_BlendFunc(blendfunc1, GL_ONE);
2162 GL_Color(fogcolor[0] * fog, fogcolor[1] * fog, fogcolor[2] * fog, ca);
2163 R_Mesh_Draw(0, 4, 2, polygonelements);
2167 int R_Mesh_AddVertex3f(rmesh_t *mesh, const float *v)
2171 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
2172 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
2174 if (i == mesh->numvertices)
2176 if (mesh->numvertices < mesh->maxvertices)
2178 VectorCopy(v, vertex3f);
2179 mesh->numvertices++;
2181 return mesh->numvertices;
2187 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
2191 element[0] = R_Mesh_AddVertex3f(mesh, vertex3f);vertex3f += 3;
2192 element[1] = R_Mesh_AddVertex3f(mesh, vertex3f);vertex3f += 3;
2193 e = mesh->element3i + mesh->numtriangles * 3;
2194 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
2196 element[2] = R_Mesh_AddVertex3f(mesh, vertex3f);
2197 if (mesh->numtriangles < mesh->maxtriangles)
2202 mesh->numtriangles++;
2204 element[1] = element[2];
2208 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
2210 int planenum, planenum2;
2213 mplane_t *plane, *plane2;
2214 float temppoints[2][256*3];
2215 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
2219 PolygonF_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->normal[3], 1024.0*1024.0*1024.0);
2220 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
2222 if (planenum2 == planenum)
2224 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);
2227 if (tempnumpoints < 3)
2229 // generate elements forming a triangle fan for this polygon
2230 R_Mesh_AddPolygon3f(mesh, tempnumpoints, temppoints[w]);
2234 static void R_DrawCollisionBrush(const colbrushf_t *brush)
2237 R_Mesh_VertexPointer(brush->points->v);
2238 i = (int)(((size_t)brush) / sizeof(colbrushf_t));
2239 GL_Color((i & 31) * (1.0f / 32.0f), ((i >> 5) & 31) * (1.0f / 32.0f), ((i >> 10) & 31) * (1.0f / 32.0f), 0.2f);
2240 GL_LockArrays(0, brush->numpoints);
2241 R_Mesh_Draw(0, brush->numpoints, brush->numtriangles, brush->elements);
2242 GL_LockArrays(0, 0);
2245 static void R_DrawCollisionSurface(const entity_render_t *ent, const msurface_t *surface)
2248 if (!surface->num_collisiontriangles)
2250 R_Mesh_VertexPointer(surface->data_collisionvertex3f);
2251 i = (int)(((size_t)surface) / sizeof(msurface_t));
2252 GL_Color((i & 31) * (1.0f / 32.0f), ((i >> 5) & 31) * (1.0f / 32.0f), ((i >> 10) & 31) * (1.0f / 32.0f), 0.2f);
2253 GL_LockArrays(0, surface->num_collisionvertices);
2254 R_Mesh_Draw(0, surface->num_collisionvertices, surface->num_collisiontriangles, surface->data_collisionelement3i);
2255 GL_LockArrays(0, 0);
2258 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)
2260 texturelayer_t *layer;
2261 layer = t->currentlayers + t->currentnumlayers++;
2263 layer->depthmask = depthmask;
2264 layer->blendfunc1 = blendfunc1;
2265 layer->blendfunc2 = blendfunc2;
2266 layer->texture = texture;
2267 layer->texmatrix = *matrix;
2268 layer->color[0] = r;
2269 layer->color[1] = g;
2270 layer->color[2] = b;
2271 layer->color[3] = a;
2274 void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
2276 // FIXME: identify models using a better check than ent->model->brush.shadowmesh
2277 //int lightmode = ((ent->effects & EF_FULLBRIGHT) || ent->model->brush.shadowmesh) ? 0 : 2;
2280 texture_t *texture = t;
2281 model_t *model = ent->model;
2282 int s = ent->skinnum;
2283 if ((unsigned int)s >= (unsigned int)model->numskins)
2285 if (model->skinscenes)
2287 if (model->skinscenes[s].framecount > 1)
2288 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
2290 s = model->skinscenes[s].firstframe;
2293 t = t + s * model->num_surfaces;
2295 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];
2296 texture->currentframe = t;
2299 t->currentmaterialflags = t->basematerialflags;
2300 t->currentalpha = ent->alpha;
2301 if (t->basematerialflags & MATERIALFLAG_WATERALPHA)
2302 t->currentalpha *= r_wateralpha.value;
2303 if (!(ent->flags & RENDER_LIGHT))
2304 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
2305 if (ent->effects & EF_ADDITIVE)
2306 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_TRANSPARENT;
2307 else if (t->currentalpha < 1)
2308 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_TRANSPARENT;
2309 if (ent->effects & EF_NODEPTHTEST)
2310 t->currentmaterialflags |= MATERIALFLAG_NODEPTHTEST;
2311 if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
2312 t->currenttexmatrix = r_waterscrollmatrix;
2314 t->currenttexmatrix = identitymatrix;
2316 t->colormapping = VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f);
2317 t->basetexture = (!t->colormapping && t->skin.merged) ? t->skin.merged : t->skin.base;
2318 t->glosstexture = r_texture_white;
2319 t->specularpower = 8;
2320 t->specularscale = 0;
2321 if (r_shadow_gloss.integer > 0)
2325 if (r_shadow_glossintensity.value > 0)
2327 t->glosstexture = t->skin.gloss;
2328 t->specularscale = r_shadow_glossintensity.value;
2331 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
2332 t->specularscale = r_shadow_gloss2intensity.value;
2335 t->currentnumlayers = 0;
2336 if (!(t->currentmaterialflags & MATERIALFLAG_NODRAW))
2338 if (gl_lightmaps.integer)
2339 R_Texture_AddLayer(t, true, GL_ONE, GL_ZERO, TEXTURELAYERTYPE_LITTEXTURE, r_texture_white, &identitymatrix, 1, 1, 1, 1);
2340 else if (!(t->currentmaterialflags & MATERIALFLAG_SKY))
2342 int blendfunc1, blendfunc2, depthmask;
2343 if (t->currentmaterialflags & MATERIALFLAG_ADD)
2345 blendfunc1 = GL_SRC_ALPHA;
2346 blendfunc2 = GL_ONE;
2348 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
2350 blendfunc1 = GL_SRC_ALPHA;
2351 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
2353 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
2355 blendfunc1 = t->customblendfunc[0];
2356 blendfunc2 = t->customblendfunc[1];
2360 blendfunc1 = GL_ONE;
2361 blendfunc2 = GL_ZERO;
2363 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
2364 if (t->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL))
2366 rtexture_t *currentbasetexture;
2368 if (fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED))
2369 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
2370 currentbasetexture = (VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) < (1.0f / 1048576.0f) && t->skin.merged) ? t->skin.merged : t->skin.base;
2371 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2373 // fullbright is not affected by r_lightmapintensity
2374 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
2375 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->skin.pants)
2376 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);
2377 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->skin.shirt)
2378 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);
2384 // q3bsp has no lightmap updates, so the lightstylevalue that
2385 // would normally be baked into the lightmap must be
2386 // applied to the color
2387 if (ent->model->type == mod_brushq3)
2388 colorscale *= r_refdef.lightstylevalue[0] * (1.0f / 256.0f);
2389 colorscale *= r_lightmapintensity;
2390 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_LITTEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0] * colorscale, ent->colormod[1] * colorscale, ent->colormod[2] * colorscale, t->currentalpha);
2391 if (r_ambient.value >= (1.0f/64.0f))
2392 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);
2393 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->skin.pants)
2395 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->skin.pants, &t->currenttexmatrix, ent->colormap_pantscolor[0] * ent->colormod[0] * colorscale, ent->colormap_pantscolor[1] * ent->colormod[1] * colorscale, ent->colormap_pantscolor[2] * ent->colormod[2] * colorscale, t->currentalpha);
2396 if (r_ambient.value >= (1.0f/64.0f))
2397 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);
2399 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->skin.shirt)
2401 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->skin.shirt, &t->currenttexmatrix, ent->colormap_shirtcolor[0] * ent->colormod[0] * colorscale, ent->colormap_shirtcolor[1] * ent->colormod[1] * colorscale, ent->colormap_shirtcolor[2] * ent->colormod[2] * colorscale, t->currentalpha);
2402 if (r_ambient.value >= (1.0f/64.0f))
2403 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);
2406 if (t->skin.glow != NULL)
2407 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.glow, &t->currenttexmatrix, 1, 1, 1, t->currentalpha);
2408 if (fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
2410 // if this is opaque use alpha blend which will darken the earlier
2413 // if this is an alpha blended material, all the earlier passes
2414 // were darkened by fog already, so we only need to add the fog
2415 // color ontop through the fog mask texture
2417 // if this is an additive blended material, all the earlier passes
2418 // were darkened by fog already, and we should not add fog color
2419 // (because the background was not darkened, there is no fog color
2420 // that was lost behind it).
2421 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);
2428 void R_UpdateAllTextureInfo(entity_render_t *ent)
2432 for (i = 0;i < ent->model->num_textures;i++)
2433 R_UpdateTextureInfo(ent, ent->model->data_textures + i);
2436 int rsurface_array_size = 0;
2437 float *rsurface_array_modelvertex3f = NULL;
2438 float *rsurface_array_modelsvector3f = NULL;
2439 float *rsurface_array_modeltvector3f = NULL;
2440 float *rsurface_array_modelnormal3f = NULL;
2441 float *rsurface_array_deformedvertex3f = NULL;
2442 float *rsurface_array_deformedsvector3f = NULL;
2443 float *rsurface_array_deformedtvector3f = NULL;
2444 float *rsurface_array_deformednormal3f = NULL;
2445 float *rsurface_array_color4f = NULL;
2446 float *rsurface_array_texcoord3f = NULL;
2448 void R_Mesh_ResizeArrays(int newvertices)
2451 if (rsurface_array_size >= newvertices)
2453 if (rsurface_array_modelvertex3f)
2454 Mem_Free(rsurface_array_modelvertex3f);
2455 rsurface_array_size = (newvertices + 1023) & ~1023;
2456 base = (float *)Mem_Alloc(r_main_mempool, rsurface_array_size * sizeof(float[31]));
2457 rsurface_array_modelvertex3f = base + rsurface_array_size * 0;
2458 rsurface_array_modelsvector3f = base + rsurface_array_size * 3;
2459 rsurface_array_modeltvector3f = base + rsurface_array_size * 6;
2460 rsurface_array_modelnormal3f = base + rsurface_array_size * 9;
2461 rsurface_array_deformedvertex3f = base + rsurface_array_size * 12;
2462 rsurface_array_deformedsvector3f = base + rsurface_array_size * 15;
2463 rsurface_array_deformedtvector3f = base + rsurface_array_size * 18;
2464 rsurface_array_deformednormal3f = base + rsurface_array_size * 21;
2465 rsurface_array_texcoord3f = base + rsurface_array_size * 24;
2466 rsurface_array_color4f = base + rsurface_array_size * 27;
2469 float *rsurface_modelvertex3f;
2470 float *rsurface_modelsvector3f;
2471 float *rsurface_modeltvector3f;
2472 float *rsurface_modelnormal3f;
2473 float *rsurface_vertex3f;
2474 float *rsurface_svector3f;
2475 float *rsurface_tvector3f;
2476 float *rsurface_normal3f;
2477 float *rsurface_lightmapcolor4f;
2478 vec3_t rsurface_modelorg;
2479 qboolean rsurface_generatedvertex;
2480 const entity_render_t *rsurface_entity;
2481 const model_t *rsurface_model;
2482 texture_t *rsurface_texture;
2483 rtexture_t *rsurface_lightmaptexture;
2484 rsurfmode_t rsurface_mode;
2485 texture_t *rsurface_glsl_texture;
2486 qboolean rsurface_glsl_uselightmap;
2488 void RSurf_ActiveEntity(const entity_render_t *ent)
2490 Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, rsurface_modelorg);
2491 rsurface_entity = ent;
2492 rsurface_model = ent->model;
2493 if (rsurface_array_size < rsurface_model->surfmesh.num_vertices)
2494 R_Mesh_ResizeArrays(rsurface_model->surfmesh.num_vertices);
2495 R_Mesh_Matrix(&ent->matrix);
2496 Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, rsurface_modelorg);
2497 if ((rsurface_entity->frameblend[0].lerp != 1 || rsurface_entity->frameblend[0].frame != 0) && (rsurface_model->surfmesh.data_morphvertex3f || rsurface_model->surfmesh.data_vertexboneweights))
2499 rsurface_modelvertex3f = rsurface_array_modelvertex3f;
2500 rsurface_modelsvector3f = NULL;
2501 rsurface_modeltvector3f = NULL;
2502 rsurface_modelnormal3f = NULL;
2503 Mod_Alias_GetMesh_Vertex3f(rsurface_model, rsurface_entity->frameblend, rsurface_array_modelvertex3f);
2504 rsurface_generatedvertex = true;
2508 rsurface_modelvertex3f = rsurface_model->surfmesh.data_vertex3f;
2509 rsurface_modelsvector3f = rsurface_model->surfmesh.data_svector3f;
2510 rsurface_modeltvector3f = rsurface_model->surfmesh.data_tvector3f;
2511 rsurface_modelnormal3f = rsurface_model->surfmesh.data_normal3f;
2512 rsurface_generatedvertex = false;
2514 rsurface_vertex3f = rsurface_modelvertex3f;
2515 rsurface_svector3f = rsurface_modelsvector3f;
2516 rsurface_tvector3f = rsurface_modeltvector3f;
2517 rsurface_normal3f = rsurface_modelnormal3f;
2518 rsurface_mode = RSURFMODE_NONE;
2519 rsurface_lightmaptexture = NULL;
2520 rsurface_texture = NULL;
2521 rsurface_glsl_texture = NULL;
2522 rsurface_glsl_uselightmap = false;
2525 void RSurf_CleanUp(void)
2528 if (rsurface_mode == RSURFMODE_GLSL)
2530 qglUseProgramObjectARB(0);CHECKGLERROR
2532 GL_AlphaTest(false);
2533 rsurface_mode = RSURFMODE_NONE;
2534 rsurface_lightmaptexture = NULL;
2535 rsurface_texture = NULL;
2536 rsurface_glsl_texture = NULL;
2537 rsurface_glsl_uselightmap = false;
2540 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, msurface_t **texturesurfacelist)
2542 if (rsurface_generatedvertex)
2544 if (rsurface_texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
2545 generatetangents = true;
2546 if (generatetangents)
2547 generatenormals = true;
2548 if (generatenormals && !rsurface_modelnormal3f)
2550 rsurface_normal3f = rsurface_modelnormal3f = rsurface_array_modelnormal3f;
2551 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);
2553 if (generatetangents && !rsurface_modelsvector3f)
2555 rsurface_svector3f = rsurface_modelsvector3f = rsurface_array_modelsvector3f;
2556 rsurface_tvector3f = rsurface_modeltvector3f = rsurface_array_modeltvector3f;
2557 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);
2560 if (rsurface_texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
2562 int texturesurfaceindex;
2563 float center[3], forward[3], right[3], up[3], v[4][3];
2564 matrix4x4_t matrix1, imatrix1;
2565 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_viewforward, forward);
2566 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_viewright, right);
2567 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_viewup, up);
2568 // make deformed versions of only the vertices used by the specified surfaces
2569 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2572 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2573 // a single autosprite surface can contain multiple sprites...
2574 for (j = 0;j < surface->num_vertices - 3;j += 4)
2576 VectorClear(center);
2577 for (i = 0;i < 4;i++)
2578 VectorAdd(center, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
2579 VectorScale(center, 0.25f, center);
2580 if (rsurface_texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE2)
2582 forward[0] = rsurface_modelorg[0] - center[0];
2583 forward[1] = rsurface_modelorg[1] - center[1];
2585 VectorNormalize(forward);
2586 right[0] = forward[1];
2587 right[1] = -forward[0];
2589 VectorSet(up, 0, 0, 1);
2591 // FIXME: calculate vectors from triangle edges instead of using texture vectors as an easy way out?
2592 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);
2593 Matrix4x4_Invert_Simple(&imatrix1, &matrix1);
2594 for (i = 0;i < 4;i++)
2595 Matrix4x4_Transform(&imatrix1, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, v[i]);
2596 for (i = 0;i < 4;i++)
2597 VectorMAMAMAM(1, center, v[i][0], forward, v[i][1], right, v[i][2], up, rsurface_array_modelvertex3f + (surface->num_firstvertex+i+j) * 3);
2599 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);
2600 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);
2602 rsurface_vertex3f = rsurface_array_deformedvertex3f;
2603 rsurface_svector3f = rsurface_array_deformedsvector3f;
2604 rsurface_tvector3f = rsurface_array_deformedtvector3f;
2605 rsurface_normal3f = rsurface_array_deformednormal3f;
2607 R_Mesh_VertexPointer(rsurface_vertex3f);
2610 void RSurf_DrawBatch_Simple(int texturenumsurfaces, msurface_t **texturesurfacelist)
2612 int texturesurfaceindex;
2613 const msurface_t *surface = texturesurfacelist[0];
2614 int firstvertex = surface->num_firstvertex;
2615 int endvertex = surface->num_firstvertex + surface->num_vertices;
2616 if (texturenumsurfaces == 1)
2618 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2619 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
2621 else if (r_batchmode.integer == 2)
2623 #define MAXBATCHTRIANGLES 4096
2624 int batchtriangles = 0;
2625 int batchelements[MAXBATCHTRIANGLES*3];
2626 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2628 surface = texturesurfacelist[texturesurfaceindex];
2629 if (surface->num_triangles >= 256 || (batchtriangles == 0 && texturesurfaceindex + 1 >= texturenumsurfaces))
2631 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
2634 if (batchtriangles + surface->num_triangles > MAXBATCHTRIANGLES)
2636 R_Mesh_Draw(firstvertex, endvertex - firstvertex, batchtriangles, batchelements);
2638 firstvertex = surface->num_firstvertex;
2639 endvertex = surface->num_firstvertex + surface->num_vertices;
2643 firstvertex = min(firstvertex, surface->num_firstvertex);
2644 endvertex = max(endvertex, surface->num_firstvertex + surface->num_vertices);
2646 memcpy(batchelements + batchtriangles * 3, rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
2647 batchtriangles += surface->num_triangles;
2650 R_Mesh_Draw(firstvertex, endvertex - firstvertex, batchtriangles, batchelements);
2652 else if (r_batchmode.integer == 1)
2654 int firsttriangle = 0;
2655 int endtriangle = -1;
2656 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2658 surface = texturesurfacelist[texturesurfaceindex];
2659 if (surface->num_firsttriangle != endtriangle)
2661 if (endtriangle > firsttriangle)
2663 GL_LockArrays(firstvertex, endvertex - firstvertex);
2664 R_Mesh_Draw(firstvertex, endvertex - firstvertex, endtriangle - firsttriangle, (rsurface_model->surfmesh.data_element3i + 3 * firsttriangle));
2666 firstvertex = surface->num_firstvertex;
2667 endvertex = surface->num_firstvertex + surface->num_vertices;
2668 firsttriangle = surface->num_firsttriangle;
2672 firstvertex = min(firstvertex, surface->num_firstvertex);
2673 endvertex = max(endvertex, surface->num_firstvertex + surface->num_vertices);
2675 endtriangle = surface->num_firsttriangle + surface->num_triangles;
2677 if (endtriangle > firsttriangle)
2679 GL_LockArrays(firstvertex, endvertex - firstvertex);
2680 R_Mesh_Draw(firstvertex, endvertex - firstvertex, endtriangle - firsttriangle, (rsurface_model->surfmesh.data_element3i + 3 * firsttriangle));
2685 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2687 surface = texturesurfacelist[texturesurfaceindex];
2688 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2689 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
2694 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
2696 int texturesurfaceindex;
2697 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2699 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2700 int k = (int)(((size_t)surface) / sizeof(msurface_t));
2701 GL_Color((k & 15) * (1.0f / 16.0f), ((k >> 4) & 15) * (1.0f / 16.0f), ((k >> 8) & 15) * (1.0f / 16.0f), 0.2f);
2702 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2703 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
2707 static void RSurf_DrawBatch_Lightmap(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, int lightmode, qboolean applycolor, qboolean applyfog)
2709 int texturesurfaceindex;
2717 vec3_t ambientcolor;
2718 vec3_t diffusecolor;
2720 VectorCopy(rsurface_entity->modellight_lightdir, lightdir);
2721 ambientcolor[0] = rsurface_entity->modellight_ambient[0] * r * 0.5f;
2722 ambientcolor[1] = rsurface_entity->modellight_ambient[1] * g * 0.5f;
2723 ambientcolor[2] = rsurface_entity->modellight_ambient[2] * b * 0.5f;
2724 diffusecolor[0] = rsurface_entity->modellight_diffuse[0] * r * 0.5f;
2725 diffusecolor[1] = rsurface_entity->modellight_diffuse[1] * g * 0.5f;
2726 diffusecolor[2] = rsurface_entity->modellight_diffuse[2] * b * 0.5f;
2727 if (VectorLength2(diffusecolor) > 0)
2729 // generate color arrays for the surfaces in this list
2730 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2732 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2733 int numverts = surface->num_vertices;
2734 v = rsurface_vertex3f + 3 * surface->num_firstvertex;
2735 c2 = rsurface_normal3f + 3 * surface->num_firstvertex;
2736 c = rsurface_array_color4f + 4 * surface->num_firstvertex;
2737 // q3-style directional shading
2738 for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
2740 if ((f = DotProduct(c2, lightdir)) > 0)
2741 VectorMA(ambientcolor, f, diffusecolor, c);
2743 VectorCopy(ambientcolor, c);
2752 rsurface_lightmapcolor4f = rsurface_array_color4f;
2756 r = ambientcolor[0];
2757 g = ambientcolor[1];
2758 b = ambientcolor[2];
2759 rsurface_lightmapcolor4f = NULL;
2762 else if (lightmode >= 1 || !rsurface_lightmaptexture)
2764 if (texturesurfacelist[0]->lightmapinfo && texturesurfacelist[0]->lightmapinfo->stainsamples)
2766 // generate color arrays for the surfaces in this list
2767 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2769 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2770 for (i = 0, c = rsurface_array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
2772 if (surface->lightmapinfo->samples)
2774 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface_model->surfmesh.data_lightmapoffsets + surface->num_firstvertex)[i];
2775 float scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
2776 VectorScale(lm, scale, c);
2777 if (surface->lightmapinfo->styles[1] != 255)
2779 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
2781 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
2782 VectorMA(c, scale, lm, c);
2783 if (surface->lightmapinfo->styles[2] != 255)
2786 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
2787 VectorMA(c, scale, lm, c);
2788 if (surface->lightmapinfo->styles[3] != 255)
2791 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
2792 VectorMA(c, scale, lm, c);
2802 rsurface_lightmapcolor4f = rsurface_array_color4f;
2805 rsurface_lightmapcolor4f = rsurface_model->surfmesh.data_lightmapcolor4f;
2810 rsurface_lightmapcolor4f = NULL;
2814 if (rsurface_lightmapcolor4f)
2816 // generate color arrays for the surfaces in this list
2817 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2819 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2820 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)
2822 f = 1 - VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
2832 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2834 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2835 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)
2837 f = 1 - VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
2845 rsurface_lightmapcolor4f = rsurface_array_color4f;
2847 if (applycolor && rsurface_lightmapcolor4f)
2849 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2851 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2852 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)
2860 rsurface_lightmapcolor4f = rsurface_array_color4f;
2862 R_Mesh_ColorPointer(rsurface_lightmapcolor4f);
2863 GL_Color(r, g, b, a);
2864 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
2867 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
2869 if (rsurface_mode != RSURFMODE_SHOWSURFACES)
2871 rsurface_mode = RSURFMODE_SHOWSURFACES;
2873 GL_BlendFunc(GL_ONE, GL_ZERO);
2874 R_Mesh_ColorPointer(NULL);
2875 R_Mesh_ResetTextureState();
2877 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
2878 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
2881 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, msurface_t **texturesurfacelist)
2883 // transparent sky would be ridiculous
2884 if ((rsurface_texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
2886 if (rsurface_mode != RSURFMODE_SKY)
2888 if (rsurface_mode == RSURFMODE_GLSL)
2890 qglUseProgramObjectARB(0);CHECKGLERROR
2892 rsurface_mode = RSURFMODE_SKY;
2896 skyrendernow = false;
2898 // restore entity matrix
2899 R_Mesh_Matrix(&rsurface_entity->matrix);
2902 // LordHavoc: HalfLife maps have freaky skypolys so don't use
2903 // skymasking on them, and Quake3 never did sky masking (unlike
2904 // software Quake and software Quake2), so disable the sky masking
2905 // in Quake3 maps as it causes problems with q3map2 sky tricks,
2906 // and skymasking also looks very bad when noclipping outside the
2907 // level, so don't use it then either.
2908 if (rsurface_model->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_worldnovis)
2910 GL_Color(fogcolor[0], fogcolor[1], fogcolor[2], 1);
2911 R_Mesh_ColorPointer(NULL);
2912 R_Mesh_ResetTextureState();
2913 if (skyrendermasked)
2915 // depth-only (masking)
2916 GL_ColorMask(0,0,0,0);
2917 // just to make sure that braindead drivers don't draw
2918 // anything despite that colormask...
2919 GL_BlendFunc(GL_ZERO, GL_ONE);
2924 GL_BlendFunc(GL_ONE, GL_ZERO);
2927 // LordHavoc: HalfLife maps have freaky skypolys so don't use
2928 // skymasking on them, and Quake3 never did sky masking (unlike
2929 // software Quake and software Quake2), so disable the sky masking
2930 // in Quake3 maps as it causes problems with q3map2 sky tricks,
2931 // and skymasking also looks very bad when noclipping outside the
2932 // level, so don't use it then either.
2933 if (rsurface_model->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_worldnovis)
2935 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
2936 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
2937 if (skyrendermasked)
2938 GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
2942 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, msurface_t **texturesurfacelist)
2945 // FIXME: identify models using a better check than rsurface_model->brush.shadowmesh
2946 lightmode = ((rsurface_entity->effects & EF_FULLBRIGHT) || rsurface_model->brush.shadowmesh) ? 0 : 2;
2947 if (rsurface_mode != RSURFMODE_GLSL)
2949 rsurface_mode = RSURFMODE_GLSL;
2950 rsurface_glsl_texture = NULL;
2951 rsurface_glsl_uselightmap = false;
2952 R_Mesh_ResetTextureState();
2954 if (rsurface_glsl_texture != rsurface_texture || rsurface_glsl_uselightmap != (rsurface_lightmaptexture != NULL))
2956 rsurface_glsl_texture = rsurface_texture;
2957 rsurface_glsl_uselightmap = rsurface_lightmaptexture != NULL;
2958 GL_BlendFunc(rsurface_texture->currentlayers[0].blendfunc1, rsurface_texture->currentlayers[0].blendfunc2);
2959 GL_DepthMask(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_BLENDED));
2960 GL_Color(rsurface_entity->colormod[0], rsurface_entity->colormod[1], rsurface_entity->colormod[2], rsurface_texture->currentalpha);
2961 R_SetupSurfaceShader(vec3_origin, lightmode == 2);
2962 //permutation_deluxemapping = permutation_lightmapping = R_SetupSurfaceShader(vec3_origin, lightmode == 2, false);
2963 //if (r_glsl_deluxemapping.integer)
2964 // permutation_deluxemapping = R_SetupSurfaceShader(vec3_origin, lightmode == 2, true);
2965 R_Mesh_TexCoordPointer(0, 2, rsurface_model->surfmesh.data_texcoordtexture2f);
2966 R_Mesh_TexCoordPointer(4, 2, rsurface_model->surfmesh.data_texcoordlightmap2f);
2967 GL_AlphaTest((rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2969 if (!r_glsl_permutation)
2971 RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
2972 R_Mesh_TexCoordPointer(1, 3, rsurface_svector3f);
2973 R_Mesh_TexCoordPointer(2, 3, rsurface_tvector3f);
2974 R_Mesh_TexCoordPointer(3, 3, rsurface_normal3f);
2975 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2977 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
2978 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
2979 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
2980 R_Mesh_ColorPointer(NULL);
2982 else if (rsurface_lightmaptexture)
2984 R_Mesh_TexBind(7, R_GetTexture(rsurface_lightmaptexture));
2985 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
2986 R_Mesh_TexBind(8, R_GetTexture(texturesurfacelist[0]->deluxemaptexture));
2987 R_Mesh_ColorPointer(NULL);
2991 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
2992 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
2993 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
2994 R_Mesh_ColorPointer(rsurface_model->surfmesh.data_lightmapcolor4f);
2996 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
2999 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, msurface_t **texturesurfacelist)
3001 // OpenGL 1.3 path - anything not completely ancient
3002 int texturesurfaceindex;
3004 qboolean applycolor;
3008 const texturelayer_t *layer;
3010 // FIXME: identify models using a better check than rsurface_model->brush.shadowmesh
3011 lightmode = ((rsurface_entity->effects & EF_FULLBRIGHT) || rsurface_model->brush.shadowmesh) ? 0 : 2;
3012 if (rsurface_mode != RSURFMODE_MULTIPASS)
3013 rsurface_mode = RSURFMODE_MULTIPASS;
3014 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
3015 for (layerindex = 0, layer = rsurface_texture->currentlayers;layerindex < rsurface_texture->currentnumlayers;layerindex++, layer++)
3018 int layertexrgbscale;
3019 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
3021 if (layerindex == 0)
3025 GL_AlphaTest(false);
3026 qglDepthFunc(GL_EQUAL);CHECKGLERROR
3029 GL_DepthMask(layer->depthmask);
3030 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
3031 if ((layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2) && (gl_combine.integer || layer->depthmask))
3033 layertexrgbscale = 4;
3034 VectorScale(layer->color, 0.25f, layercolor);
3036 else if ((layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1) && (gl_combine.integer || layer->depthmask))
3038 layertexrgbscale = 2;
3039 VectorScale(layer->color, 0.5f, layercolor);
3043 layertexrgbscale = 1;
3044 VectorScale(layer->color, 1.0f, layercolor);
3046 layercolor[3] = layer->color[3];
3047 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
3048 R_Mesh_ColorPointer(NULL);
3049 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
3050 switch (layer->type)
3052 case TEXTURELAYERTYPE_LITTEXTURE:
3053 memset(&m, 0, sizeof(m));
3054 if (lightmode >= 1 || !rsurface_lightmaptexture)
3055 m.tex[0] = R_GetTexture(r_texture_white);
3057 m.tex[0] = R_GetTexture(rsurface_lightmaptexture);
3058 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordlightmap2f;
3059 m.tex[1] = R_GetTexture(layer->texture);
3060 m.texmatrix[1] = layer->texmatrix;
3061 m.texrgbscale[1] = layertexrgbscale;
3062 m.pointer_texcoord[1] = rsurface_model->surfmesh.data_texcoordtexture2f;
3063 R_Mesh_TextureState(&m);
3064 RSurf_DrawBatch_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], lightmode, applycolor, applyfog);
3066 case TEXTURELAYERTYPE_TEXTURE:
3067 memset(&m, 0, sizeof(m));
3068 m.tex[0] = R_GetTexture(layer->texture);
3069 m.texmatrix[0] = layer->texmatrix;
3070 m.texrgbscale[0] = layertexrgbscale;
3071 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3072 R_Mesh_TextureState(&m);
3073 RSurf_DrawBatch_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, applyfog);
3075 case TEXTURELAYERTYPE_FOG:
3076 memset(&m, 0, sizeof(m));
3077 m.texrgbscale[0] = layertexrgbscale;
3080 m.tex[0] = R_GetTexture(layer->texture);
3081 m.texmatrix[0] = layer->texmatrix;
3082 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3084 R_Mesh_TextureState(&m);
3085 // generate a color array for the fog pass
3086 R_Mesh_ColorPointer(rsurface_array_color4f);
3087 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3091 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3092 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)
3094 f = VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
3095 c[0] = layercolor[0];
3096 c[1] = layercolor[1];
3097 c[2] = layercolor[2];
3098 c[3] = f * layercolor[3];
3101 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3104 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
3106 GL_LockArrays(0, 0);
3109 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
3111 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3112 GL_AlphaTest(false);
3116 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, msurface_t **texturesurfacelist)
3118 // OpenGL 1.1 - crusty old voodoo path
3119 int texturesurfaceindex;
3124 const texturelayer_t *layer;
3126 // FIXME: identify models using a better check than rsurface_model->brush.shadowmesh
3127 lightmode = ((rsurface_entity->effects & EF_FULLBRIGHT) || rsurface_model->brush.shadowmesh) ? 0 : 2;
3128 if (rsurface_mode != RSURFMODE_MULTIPASS)
3129 rsurface_mode = RSURFMODE_MULTIPASS;
3130 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
3131 for (layerindex = 0, layer = rsurface_texture->currentlayers;layerindex < rsurface_texture->currentnumlayers;layerindex++, layer++)
3133 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
3135 if (layerindex == 0)
3139 GL_AlphaTest(false);
3140 qglDepthFunc(GL_EQUAL);CHECKGLERROR
3143 GL_DepthMask(layer->depthmask);
3144 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
3145 R_Mesh_ColorPointer(NULL);
3146 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
3147 switch (layer->type)
3149 case TEXTURELAYERTYPE_LITTEXTURE:
3150 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
3152 // two-pass lit texture with 2x rgbscale
3153 // first the lightmap pass
3154 memset(&m, 0, sizeof(m));
3155 if (lightmode >= 1 || !rsurface_lightmaptexture)
3156 m.tex[0] = R_GetTexture(r_texture_white);
3158 m.tex[0] = R_GetTexture(rsurface_lightmaptexture);
3159 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordlightmap2f;
3160 R_Mesh_TextureState(&m);
3161 RSurf_DrawBatch_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, lightmode, false, false);
3162 GL_LockArrays(0, 0);
3163 // then apply the texture to it
3164 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
3165 memset(&m, 0, sizeof(m));
3166 m.tex[0] = R_GetTexture(layer->texture);
3167 m.texmatrix[0] = layer->texmatrix;
3168 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3169 R_Mesh_TextureState(&m);
3170 RSurf_DrawBatch_Lightmap(texturenumsurfaces, texturesurfacelist, layer->color[0] * 0.5f, layer->color[1] * 0.5f, layer->color[2] * 0.5f, layer->color[3], 0, layer->color[0] != 2 || layer->color[1] != 2 || layer->color[2] != 2 || layer->color[3] != 1, false);
3174 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
3175 memset(&m, 0, sizeof(m));
3176 m.tex[0] = R_GetTexture(layer->texture);
3177 m.texmatrix[0] = layer->texmatrix;
3178 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3179 R_Mesh_TextureState(&m);
3180 RSurf_DrawBatch_Lightmap(texturenumsurfaces, texturesurfacelist, layer->color[0], layer->color[1], layer->color[2], layer->color[3], lightmode == 2 ? 2 : 1, layer->color[0] != 1 || layer->color[1] != 1 || layer->color[2] != 1 || layer->color[3] != 1, applyfog);
3183 case TEXTURELAYERTYPE_TEXTURE:
3184 // singletexture unlit texture with transparency support
3185 memset(&m, 0, sizeof(m));
3186 m.tex[0] = R_GetTexture(layer->texture);
3187 m.texmatrix[0] = layer->texmatrix;
3188 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3189 R_Mesh_TextureState(&m);
3190 RSurf_DrawBatch_Lightmap(texturenumsurfaces, texturesurfacelist, layer->color[0], layer->color[1], layer->color[2], layer->color[3], 0, layer->color[0] != 1 || layer->color[1] != 1 || layer->color[2] != 1 || layer->color[3] != 1, applyfog);
3192 case TEXTURELAYERTYPE_FOG:
3193 // singletexture fogging
3194 R_Mesh_ColorPointer(rsurface_array_color4f);
3197 memset(&m, 0, sizeof(m));
3198 m.tex[0] = R_GetTexture(layer->texture);
3199 m.texmatrix[0] = layer->texmatrix;
3200 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3201 R_Mesh_TextureState(&m);
3204 R_Mesh_ResetTextureState();
3205 // generate a color array for the fog pass
3206 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3210 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3211 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)
3213 f = VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
3214 c[0] = layer->color[0];
3215 c[1] = layer->color[1];
3216 c[2] = layer->color[2];
3217 c[3] = f * layer->color[3];
3220 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3223 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
3225 GL_LockArrays(0, 0);
3228 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
3230 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3231 GL_AlphaTest(false);
3235 static void R_DrawTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist)
3237 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_NODRAW)
3239 r_shadow_rtlight = NULL;
3240 renderstats.entities_surfaces += texturenumsurfaces;
3242 GL_DepthTest(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
3243 if ((rsurface_texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (rsurface_entity->flags & RENDER_NOCULLFACE))
3245 qglDisable(GL_CULL_FACE);CHECKGLERROR
3247 if (r_showsurfaces.integer)
3248 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
3249 else if (rsurface_texture->currentmaterialflags & MATERIALFLAG_SKY)
3250 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
3251 else if (rsurface_texture->currentnumlayers)
3253 if (r_glsl.integer && gl_support_fragment_shader)
3254 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist);
3255 else if (gl_combine.integer && r_textureunits.integer >= 2)
3256 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist);
3258 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist);
3261 GL_LockArrays(0, 0);
3262 if ((rsurface_texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (rsurface_entity->flags & RENDER_NOCULLFACE))
3264 qglEnable(GL_CULL_FACE);CHECKGLERROR
3268 #define BATCHSIZE 256
3269 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
3271 int surfacelistindex;
3274 msurface_t *texturesurfacelist[BATCHSIZE];
3275 RSurf_ActiveEntity(ent);
3278 for (surfacelistindex = 0;surfacelistindex < numsurfaces;surfacelistindex++)
3280 msurface_t *surface = ent->model->data_surfaces + surfacelist[surfacelistindex];
3282 if (t != surface->texture || rsurface_lightmaptexture != surface->lightmaptexture)
3285 R_DrawTextureSurfaceList(batchcount, texturesurfacelist);
3287 t = surface->texture;
3288 rsurface_lightmaptexture = surface->lightmaptexture;
3289 R_UpdateTextureInfo(ent, t);
3290 rsurface_texture = t->currentframe;
3292 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_SKY)
3293 continue; // transparent sky is too difficult
3295 texturesurfacelist[batchcount++] = surface;
3298 R_DrawTextureSurfaceList(batchcount, texturesurfacelist);
3302 void R_QueueTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist)
3304 int texturesurfaceindex;
3305 vec3_t tempcenter, center;
3306 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_BLENDED)
3308 // drawing sky transparently would be too difficult
3309 if (!(rsurface_texture->currentmaterialflags & MATERIALFLAG_SKY))
3311 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3313 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3314 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
3315 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
3316 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
3317 Matrix4x4_Transform(&rsurface_entity->matrix, tempcenter, center);
3318 R_MeshQueue_AddTransparent(rsurface_texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_vieworigin : center, R_DrawSurface_TransparentCallback, rsurface_entity, surface - rsurface_model->data_surfaces, r_shadow_rtlight);
3323 R_DrawTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
3326 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
3327 void R_DrawSurfaces(entity_render_t *ent, qboolean skysurfaces)
3329 int i, j, f, flagsmask;
3330 int counttriangles = 0;
3332 model_t *model = ent->model;
3333 const int maxsurfacelist = 1024;
3334 int numsurfacelist = 0;
3335 msurface_t *surfacelist[1024];
3339 RSurf_ActiveEntity(ent);
3341 // update light styles
3342 if (!skysurfaces && model->brushq1.light_styleupdatechains)
3344 msurface_t *surface, **surfacechain;
3345 for (i = 0;i < model->brushq1.light_styles;i++)
3347 if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
3349 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
3350 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
3351 for (;(surface = *surfacechain);surfacechain++)
3352 surface->cached_dlight = true;
3357 R_UpdateAllTextureInfo(ent);
3358 flagsmask = skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL);
3361 rsurface_lightmaptexture = NULL;
3362 rsurface_texture = NULL;
3364 if (ent == r_refdef.worldentity)
3366 msurface_t *surface;
3367 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
3369 if (!r_worldsurfacevisible[j])
3371 if (t != surface->texture || rsurface_lightmaptexture != surface->lightmaptexture)
3375 R_QueueTextureSurfaceList(numsurfacelist, surfacelist);
3378 t = surface->texture;
3379 rsurface_lightmaptexture = surface->lightmaptexture;
3380 rsurface_texture = t->currentframe;
3381 f = rsurface_texture->currentmaterialflags & flagsmask;
3383 if (f && surface->num_triangles)
3385 // if lightmap parameters changed, rebuild lightmap texture
3386 if (surface->cached_dlight)
3387 R_BuildLightMap(ent, surface);
3388 // add face to draw list
3389 surfacelist[numsurfacelist++] = surface;
3390 counttriangles += surface->num_triangles;
3391 if (numsurfacelist >= maxsurfacelist)
3393 R_QueueTextureSurfaceList(numsurfacelist, surfacelist);
3401 msurface_t *surface;
3402 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
3404 if (t != surface->texture || rsurface_lightmaptexture != surface->lightmaptexture)
3408 R_QueueTextureSurfaceList(numsurfacelist, surfacelist);
3411 t = surface->texture;
3412 rsurface_lightmaptexture = surface->lightmaptexture;
3413 rsurface_texture = t->currentframe;
3414 f = rsurface_texture->currentmaterialflags & flagsmask;
3416 if (f && surface->num_triangles)
3418 // if lightmap parameters changed, rebuild lightmap texture
3419 if (surface->cached_dlight)
3420 R_BuildLightMap(ent, surface);
3421 // add face to draw list
3422 surfacelist[numsurfacelist++] = surface;
3423 counttriangles += surface->num_triangles;
3424 if (numsurfacelist >= maxsurfacelist)
3426 R_QueueTextureSurfaceList(numsurfacelist, surfacelist);
3433 R_QueueTextureSurfaceList(numsurfacelist, surfacelist);
3434 renderstats.entities_triangles += counttriangles;
3437 if (r_showcollisionbrushes.integer && model->brush.num_brushes && !skysurfaces)
3440 const msurface_t *surface;
3443 R_Mesh_Matrix(&ent->matrix);
3444 R_Mesh_ColorPointer(NULL);
3445 R_Mesh_ResetTextureState();
3446 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
3447 GL_DepthMask(false);
3448 GL_DepthTest(!r_showdisabledepthtest.integer);
3449 qglPolygonOffset(r_polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_polygonoffset + r_showcollisionbrushes_polygonoffset.value);CHECKGLERROR
3450 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
3451 if (brush->colbrushf && brush->colbrushf->numtriangles)
3452 R_DrawCollisionBrush(brush->colbrushf);
3453 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
3454 if (surface->num_collisiontriangles)
3455 R_DrawCollisionSurface(ent, surface);
3456 qglPolygonOffset(r_polygonfactor, r_polygonoffset);CHECKGLERROR
3459 if (r_showtris.integer || r_shownormals.integer)
3462 msurface_t *surface;
3463 const int *elements;
3468 if (r_showdisabledepthtest.integer)
3470 qglDepthFunc(GL_ALWAYS);CHECKGLERROR
3472 GL_BlendFunc(GL_ONE, GL_ZERO);
3473 R_Mesh_ColorPointer(NULL);
3474 R_Mesh_ResetTextureState();
3475 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
3477 if (ent == r_refdef.worldentity && !r_worldsurfacevisible[j])
3479 rsurface_texture = surface->texture->currentframe;
3480 if ((rsurface_texture->currentmaterialflags & flagsmask) && surface->num_triangles)
3482 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
3483 if (r_showtris.integer)
3485 if (!rsurface_texture->currentlayers->depthmask)
3486 GL_Color(r_showtris.value, 0, 0, 1);
3487 else if (ent == r_refdef.worldentity)
3488 GL_Color(r_showtris.value, r_showtris.value, r_showtris.value, 1);
3490 GL_Color(0, r_showtris.value, 0, 1);
3491 elements = (ent->model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
3494 for (k = 0;k < surface->num_triangles;k++, elements += 3)
3496 qglArrayElement(elements[0]);qglArrayElement(elements[1]);
3497 qglArrayElement(elements[1]);qglArrayElement(elements[2]);
3498 qglArrayElement(elements[2]);qglArrayElement(elements[0]);
3503 if (r_shownormals.integer)
3505 GL_Color(r_shownormals.value, 0, 0, 1);
3507 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
3509 VectorCopy(rsurface_vertex3f + l * 3, v);
3510 qglVertex3f(v[0], v[1], v[2]);
3511 VectorMA(v, 8, rsurface_svector3f + l * 3, v);
3512 qglVertex3f(v[0], v[1], v[2]);
3516 GL_Color(0, 0, r_shownormals.value, 1);
3518 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
3520 VectorCopy(rsurface_vertex3f + l * 3, v);
3521 qglVertex3f(v[0], v[1], v[2]);
3522 VectorMA(v, 8, rsurface_tvector3f + l * 3, v);
3523 qglVertex3f(v[0], v[1], v[2]);
3527 GL_Color(0, r_shownormals.value, 0, 1);
3529 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
3531 VectorCopy(rsurface_vertex3f + l * 3, v);
3532 qglVertex3f(v[0], v[1], v[2]);
3533 VectorMA(v, 8, rsurface_normal3f + l * 3, v);
3534 qglVertex3f(v[0], v[1], v[2]);
3541 rsurface_texture = NULL;
3542 if (r_showdisabledepthtest.integer)
3544 qglDepthFunc(GL_LEQUAL);CHECKGLERROR