2 Copyright (C) 1996-1997 Id Software, Inc.
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26 mempool_t *r_main_mempool;
27 rtexturepool_t *r_main_texturepool;
29 // used for dlight push checking and other things
34 renderstats_t renderstats;
36 // true during envmap command capture
39 // maximum visible distance (recalculated from world box each frame)
41 // brightness of world lightmaps and related lighting
42 // (often reduced when world rtlights are enabled)
43 float r_lightmapintensity;
44 // whether to draw world lights realtime, dlights realtime, and their shadows
46 qboolean r_rtworldshadows;
48 qboolean r_rtdlightshadows;
63 matrix4x4_t r_view_matrix;
64 float r_polygonfactor;
65 float r_polygonoffset;
66 float r_shadowpolygonfactor;
67 float r_shadowpolygonoffset;
73 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
74 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "shows surfaces as different colors"};
75 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
76 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
77 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
78 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
79 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
80 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
81 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
82 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing\n"};
83 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
84 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
85 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
86 cvar_t r_fullbright = {0, "r_fullbright","0", "make everything bright cheat (not allowed in multiplayer)"};
87 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
88 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
89 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
90 cvar_t r_q1bsp_skymasking = {0, "r_qb1sp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
92 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
93 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
94 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
95 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
96 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
97 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
98 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
100 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of hardware texture units reported by driver (note: setting this to 1 turns off gl_combine)"};
102 cvar_t r_glsl = {0, "r_glsl", "1", "enables use of OpenGL 2.0 pixel shaders for lighting"};
103 cvar_t r_glsl_offsetmapping = {0, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
104 cvar_t r_glsl_offsetmapping_reliefmapping = {0, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
105 cvar_t r_glsl_offsetmapping_scale = {0, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
106 cvar_t r_glsl_deluxemapping = {0, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"};
108 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1", "enables animation smoothing on sprites (requires r_lerpmodels 1)"};
109 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
110 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
112 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
113 cvar_t r_bloom_intensity = {CVAR_SAVE, "r_bloom_intensity", "1.5", "how bright the glow is"};
114 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
115 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
116 cvar_t r_bloom_power = {CVAR_SAVE, "r_bloom_power", "2", "how much to darken the image before blurring to make the bloom effect"};
118 cvar_t r_smoothnormals_areaweighting = {0, "r_smoothnormals_areaweighting", "1", "uses significantly faster (and supposedly higher quality) area-weighted vertex normals and tangent vectors rather than summing normalized triangle normals and tangents"};
120 cvar_t developer_texturelogging = {0, "developer_texturelogging", "0", "produces a textures.log file containing names of skins and map textures the engine tried to load"};
122 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
124 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"}; // used for testing renderer code changes, otherwise does nothing
126 rtexture_t *r_bloom_texture_screen;
127 rtexture_t *r_bloom_texture_bloom;
128 rtexture_t *r_texture_blanknormalmap;
129 rtexture_t *r_texture_white;
130 rtexture_t *r_texture_black;
131 rtexture_t *r_texture_notexture;
132 rtexture_t *r_texture_whitecube;
133 rtexture_t *r_texture_normalizationcube;
134 rtexture_t *r_texture_fogattenuation;
135 rtexture_t *r_texture_fogintensity;
137 // information about each possible shader permutation
138 r_glsl_permutation_t r_glsl_permutations[SHADERPERMUTATION_COUNT];
139 // currently selected permutation
140 r_glsl_permutation_t *r_glsl_permutation;
142 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
145 for (i = 0;i < verts;i++)
156 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
159 for (i = 0;i < verts;i++)
174 vec_t fogtabledistmultiplier;
175 float fogtable[FOGTABLEWIDTH];
176 float fog_density, fog_red, fog_green, fog_blue;
178 qboolean oldgl_fogenable;
179 void R_UpdateFog(void)
181 if (gamemode == GAME_NEHAHRA)
183 if (gl_fogenable.integer)
185 oldgl_fogenable = true;
186 fog_density = gl_fogdensity.value;
187 fog_red = gl_fogred.value;
188 fog_green = gl_foggreen.value;
189 fog_blue = gl_fogblue.value;
191 else if (oldgl_fogenable)
193 oldgl_fogenable = false;
202 fogcolor[0] = fog_red = bound(0.0f, fog_red , 1.0f);
203 fogcolor[1] = fog_green = bound(0.0f, fog_green, 1.0f);
204 fogcolor[2] = fog_blue = bound(0.0f, fog_blue , 1.0f);
209 fogdensity = -4000.0f / (fog_density * fog_density);
210 // this is the point where the fog reaches 0.9986 alpha, which we
211 // consider a good enough cutoff point for the texture
212 // (0.9986 * 256 == 255.6)
213 fogrange = 400 / fog_density;
214 fograngerecip = 1.0f / fogrange;
215 fogtabledistmultiplier = FOGTABLEWIDTH * fograngerecip;
216 // fog color was already set
222 // FIXME: move this to client?
225 if (gamemode == GAME_NEHAHRA)
227 Cvar_Set("gl_fogenable", "0");
228 Cvar_Set("gl_fogdensity", "0.2");
229 Cvar_Set("gl_fogred", "0.3");
230 Cvar_Set("gl_foggreen", "0.3");
231 Cvar_Set("gl_fogblue", "0.3");
233 fog_density = fog_red = fog_green = fog_blue = 0.0f;
236 // FIXME: move this to client?
237 void FOG_registercvars(void)
242 if (gamemode == GAME_NEHAHRA)
244 Cvar_RegisterVariable (&gl_fogenable);
245 Cvar_RegisterVariable (&gl_fogdensity);
246 Cvar_RegisterVariable (&gl_fogred);
247 Cvar_RegisterVariable (&gl_foggreen);
248 Cvar_RegisterVariable (&gl_fogblue);
249 Cvar_RegisterVariable (&gl_fogstart);
250 Cvar_RegisterVariable (&gl_fogend);
253 r = (-1.0/256.0) * (FOGTABLEWIDTH * FOGTABLEWIDTH);
254 for (x = 0;x < FOGTABLEWIDTH;x++)
256 alpha = exp(r / ((double)x*(double)x));
257 if (x == FOGTABLEWIDTH - 1)
259 fogtable[x] = bound(0, alpha, 1);
263 static void R_BuildBlankTextures(void)
265 unsigned char data[4];
266 data[0] = 128; // normal X
267 data[1] = 128; // normal Y
268 data[2] = 255; // normal Z
269 data[3] = 128; // height
270 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
275 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
280 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
283 static void R_BuildNoTexture(void)
286 unsigned char pix[16][16][4];
287 // this makes a light grey/dark grey checkerboard texture
288 for (y = 0;y < 16;y++)
290 for (x = 0;x < 16;x++)
292 if ((y < 8) ^ (x < 8))
308 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_RGBA, TEXF_MIPMAP, NULL);
311 static void R_BuildWhiteCube(void)
313 unsigned char data[6*1*1*4];
314 data[ 0] = 255;data[ 1] = 255;data[ 2] = 255;data[ 3] = 255;
315 data[ 4] = 255;data[ 5] = 255;data[ 6] = 255;data[ 7] = 255;
316 data[ 8] = 255;data[ 9] = 255;data[10] = 255;data[11] = 255;
317 data[12] = 255;data[13] = 255;data[14] = 255;data[15] = 255;
318 data[16] = 255;data[17] = 255;data[18] = 255;data[19] = 255;
319 data[20] = 255;data[21] = 255;data[22] = 255;data[23] = 255;
320 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
323 static void R_BuildNormalizationCube(void)
327 vec_t s, t, intensity;
329 unsigned char data[6][NORMSIZE][NORMSIZE][4];
330 for (side = 0;side < 6;side++)
332 for (y = 0;y < NORMSIZE;y++)
334 for (x = 0;x < NORMSIZE;x++)
336 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
337 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
372 intensity = 127.0f / sqrt(DotProduct(v, v));
373 data[side][y][x][0] = (unsigned char)(128.0f + intensity * v[0]);
374 data[side][y][x][1] = (unsigned char)(128.0f + intensity * v[1]);
375 data[side][y][x][2] = (unsigned char)(128.0f + intensity * v[2]);
376 data[side][y][x][3] = 255;
380 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, &data[0][0][0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
383 static void R_BuildFogTexture(void)
388 unsigned char data1[FOGWIDTH][4];
389 unsigned char data2[FOGWIDTH][4];
390 r = (-1.0/256.0) * (FOGWIDTH * FOGWIDTH);
391 for (x = 0;x < FOGWIDTH;x++)
393 alpha = exp(r / ((double)x*(double)x));
394 if (x == FOGWIDTH - 1)
396 b = (int)(256.0 * alpha);
397 b = bound(0, b, 255);
398 data1[x][0] = 255 - b;
399 data1[x][1] = 255 - b;
400 data1[x][2] = 255 - b;
407 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
408 r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
411 static const char *builtinshaderstring =
412 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
413 "// written by Forest 'LordHavoc' Hale\n"
415 "// common definitions between vertex shader and fragment shader:\n"
417 "varying vec2 TexCoord;\n"
418 "varying vec2 TexCoordLightmap;\n"
420 "varying vec3 CubeVector;\n"
421 "varying vec3 LightVector;\n"
422 "varying vec3 EyeVector;\n"
424 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
425 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
426 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
431 "// vertex shader specific:\n"
432 "#ifdef VERTEX_SHADER\n"
434 "uniform vec3 LightPosition;\n"
435 "uniform vec3 EyePosition;\n"
436 "uniform vec3 LightDir;\n"
438 "// TODO: get rid of tangentt (texcoord2) and use a crossproduct to regenerate it from tangents (texcoord1) and normal (texcoord3)\n"
442 " gl_FrontColor = gl_Color;\n"
443 " // copy the surface texcoord\n"
444 " TexCoord = vec2(gl_TextureMatrix[0] * gl_MultiTexCoord0);\n"
445 "#if !defined(MODE_LIGHTSOURCE) && !defined(MODE_LIGHTDIRECTION)\n"
446 " TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
449 "#ifdef MODE_LIGHTSOURCE\n"
450 " // transform vertex position into light attenuation/cubemap space\n"
451 " // (-1 to +1 across the light box)\n"
452 " CubeVector = vec3(gl_TextureMatrix[3] * gl_Vertex);\n"
454 " // transform unnormalized light direction into tangent space\n"
455 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
456 " // normalize it per pixel)\n"
457 " vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
458 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
459 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
460 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
463 "#ifdef MODE_LIGHTDIRECTION\n"
464 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
465 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
466 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
469 " // transform unnormalized eye direction into tangent space\n"
470 " vec3 eyeminusvertex = EyePosition - gl_Vertex.xyz;\n"
471 " EyeVector.x = dot(eyeminusvertex, gl_MultiTexCoord1.xyz);\n"
472 " EyeVector.y = dot(eyeminusvertex, gl_MultiTexCoord2.xyz);\n"
473 " EyeVector.z = dot(eyeminusvertex, gl_MultiTexCoord3.xyz);\n"
475 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
476 " VectorS = gl_MultiTexCoord1.xyz;\n"
477 " VectorT = gl_MultiTexCoord2.xyz;\n"
478 " VectorR = gl_MultiTexCoord3.xyz;\n"
481 " // transform vertex to camera space, using ftransform to match non-VS\n"
483 " gl_Position = ftransform();\n"
486 "#endif // VERTEX_SHADER\n"
491 "// fragment shader specific:\n"
492 "#ifdef FRAGMENT_SHADER\n"
494 "uniform sampler2D Texture_Normal;\n"
495 "uniform sampler2D Texture_Color;\n"
496 "uniform sampler2D Texture_Gloss;\n"
497 "uniform samplerCube Texture_Cube;\n"
498 "uniform sampler2D Texture_FogMask;\n"
499 "uniform sampler2D Texture_Pants;\n"
500 "uniform sampler2D Texture_Shirt;\n"
501 "uniform sampler2D Texture_Lightmap;\n"
502 "uniform sampler2D Texture_Deluxemap;\n"
503 "uniform sampler2D Texture_Glow;\n"
505 "uniform vec3 LightColor;\n"
506 "uniform vec3 AmbientColor;\n"
507 "uniform vec3 DiffuseColor;\n"
508 "uniform vec3 SpecularColor;\n"
509 "uniform vec3 Color_Pants;\n"
510 "uniform vec3 Color_Shirt;\n"
511 "uniform vec3 FogColor;\n"
513 "uniform float OffsetMapping_Scale;\n"
514 "uniform float OffsetMapping_Bias;\n"
515 "uniform float FogRangeRecip;\n"
517 "uniform float AmbientScale;\n"
518 "uniform float DiffuseScale;\n"
519 "uniform float SpecularScale;\n"
520 "uniform float SpecularPower;\n"
524 " // apply offsetmapping\n"
525 "#ifdef USEOFFSETMAPPING\n"
526 " vec2 TexCoordOffset = TexCoord;\n"
527 "#define TexCoord TexCoordOffset\n"
529 " vec3 eyedir = vec3(normalize(EyeVector));\n"
530 " float depthbias = 1.0 - eyedir.z; // should this be a -?\n"
531 " depthbias = 1.0 - depthbias * depthbias;\n"
533 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
534 " // 14 sample relief mapping: linear search and then binary search\n"
535 " vec3 OffsetVector = vec3(EyeVector.xy * (1.0 / EyeVector.z) * depthbias * OffsetMapping_Scale * vec2(-0.1, 0.1), -0.1);\n"
536 " vec3 RT = vec3(TexCoord - OffsetVector.xy * 10.0, 1.0) + OffsetVector;\n"
537 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
538 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
539 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
540 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
541 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
542 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
543 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
544 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
545 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;OffsetVector *= 0.5;RT -= OffsetVector;\n"
546 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;OffsetVector *= 0.5;RT -= OffsetVector;\n"
547 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;OffsetVector *= 0.5;RT -= OffsetVector;\n"
548 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;OffsetVector *= 0.5;RT -= OffsetVector;\n"
549 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;OffsetVector *= 0.5;RT -= OffsetVector;\n"
550 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;OffsetVector *= 0.5;RT -= OffsetVector;\n"
551 " TexCoord = RT.xy;\n"
553 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
554 " vec2 OffsetVector = vec2((EyeVector.xy * (1.0 / EyeVector.z) * depthbias) * OffsetMapping_Scale * vec2(-0.333, 0.333));\n"
555 " //TexCoord += OffsetVector * 3.0;\n"
556 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
557 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
558 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
562 " // combine the diffuse textures (base, pants, shirt)\n"
563 " vec4 color = vec4(texture2D(Texture_Color, TexCoord));\n"
564 "#ifdef USECOLORMAPPING\n"
565 " color.rgb += vec3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + vec3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
571 "#ifdef MODE_LIGHTSOURCE\n"
574 " // get the surface normal and light normal\n"
575 " vec3 surfacenormal = normalize(vec3(texture2D(Texture_Normal, TexCoord)) - 0.5);\n"
576 " vec3 diffusenormal = vec3(normalize(LightVector));\n"
578 " // calculate directional shading\n"
579 " color.rgb *= (AmbientScale + DiffuseScale * max(dot(surfacenormal, diffusenormal), 0.0));\n"
580 "#ifdef USESPECULAR\n"
581 " vec3 specularnormal = vec3(normalize(diffusenormal + vec3(normalize(EyeVector))));\n"
582 " color.rgb += vec3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(max(dot(surfacenormal, specularnormal), 0.0), SpecularPower);\n"
585 "#ifdef USECUBEFILTER\n"
586 " // apply light cubemap filter\n"
587 " //color.rgb *= normalize(CubeVector) * 0.5 + 0.5;//vec3(textureCube(Texture_Cube, CubeVector));\n"
588 " color.rgb *= vec3(textureCube(Texture_Cube, CubeVector));\n"
591 " // apply light color\n"
592 " color.rgb *= LightColor;\n"
594 " // apply attenuation\n"
596 " // the attenuation is (1-(x*x+y*y+z*z)) which gives a large bright\n"
597 " // center and sharp falloff at the edge, this is about the most efficient\n"
598 " // we can get away with as far as providing illumination.\n"
600 " // pow(1-(x*x+y*y+z*z), 4) is far more realistic but needs large lights to\n"
601 " // provide significant illumination, large = slow = pain.\n"
602 " color.rgb *= max(1.0 - dot(CubeVector, CubeVector), 0.0);\n"
607 "#elif defined(MODE_LIGHTDIRECTION)\n"
608 " // directional model lighting\n"
610 " // get the surface normal and light normal\n"
611 " vec3 surfacenormal = normalize(vec3(texture2D(Texture_Normal, TexCoord)) - 0.5);\n"
612 " vec3 diffusenormal = vec3(normalize(LightVector));\n"
614 " // calculate directional shading\n"
615 " color.rgb *= AmbientColor + DiffuseColor * max(dot(surfacenormal, diffusenormal), 0.0);\n"
616 "#ifdef USESPECULAR\n"
617 " vec3 specularnormal = vec3(normalize(diffusenormal + vec3(normalize(EyeVector))));\n"
618 " color.rgb += vec3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(max(dot(surfacenormal, specularnormal), 0.0), SpecularPower);\n"
624 "#elif defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE)\n"
625 " // deluxemap lightmapping using light vectors in modelspace (evil q3map2)\n"
627 " // get the surface normal and light normal\n"
628 " vec3 surfacenormal = normalize(vec3(texture2D(Texture_Normal, TexCoord)) - 0.5);\n"
629 " vec3 diffusenormal_modelspace = vec3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - 0.5;\n"
630 " vec3 diffusenormal = normalize(vec3(dot(diffusenormal_modelspace, VectorS), dot(diffusenormal_modelspace, VectorT), dot(diffusenormal_modelspace, VectorR)));\n"
632 " // calculate directional shading\n"
633 " vec3 tempcolor = color.rgb * (DiffuseScale * max(dot(surfacenormal, diffusenormal), 0.0));\n"
634 "#ifdef USESPECULAR\n"
635 " vec3 specularnormal = vec3(normalize(diffusenormal + vec3(normalize(EyeVector))));\n"
636 " tempcolor += vec3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(max(dot(surfacenormal, specularnormal), 0.0), SpecularPower);\n"
639 " // apply lightmap color\n"
640 " color.rgb = tempcolor * vec3(texture2D(Texture_Lightmap, TexCoordLightmap)) + color.rgb * vec3(AmbientScale);\n"
645 "#elif defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
646 " // deluxemap lightmapping using light vectors in tangentspace\n"
648 " // get the surface normal and light normal\n"
649 " vec3 surfacenormal = normalize(vec3(texture2D(Texture_Normal, TexCoord)) - 0.5);\n"
650 " vec3 diffusenormal = normalize(vec3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - 0.5);\n"
652 " // calculate directional shading\n"
653 " vec3 tempcolor = color.rgb * (DiffuseScale * max(dot(surfacenormal, diffusenormal), 0.0));\n"
654 "#ifdef USESPECULAR\n"
655 " vec3 specularnormal = vec3(normalize(diffusenormal + vec3(normalize(EyeVector))));\n"
656 " tempcolor += vec3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(max(dot(surfacenormal, specularnormal), 0.0), SpecularPower);\n"
659 " // apply lightmap color\n"
660 " color.rgb = tempcolor * vec3(texture2D(Texture_Lightmap, TexCoordLightmap)) + color.rgb * vec3(AmbientScale);\n"
665 "#else // MODE none (lightmap)\n"
666 " // apply lightmap color\n"
667 " color.rgb *= vec3(texture2D(Texture_Lightmap, TexCoordLightmap)) * DiffuseScale + vec3(AmbientScale);\n"
671 " color.rgb += vec3(texture2D(Texture_Glow, TexCoord));\n"
676 " float fog = texture2D(Texture_FogMask, vec2(length(EyeVector)*FogRangeRecip, 0.0)).x;\n"
677 " color.rgb = color.rgb * fog + FogColor * (1.0 - fog);\n"
680 " gl_FragColor = color * gl_Color;\n"
683 "#endif // FRAGMENT_SHADER\n"
686 void R_GLSL_CompilePermutation(int permutation)
688 r_glsl_permutation_t *p = r_glsl_permutations + permutation;
689 int vertstrings_count;
690 int fragstrings_count;
692 const char *vertstrings_list[SHADERPERMUTATION_COUNT+1];
693 const char *fragstrings_list[SHADERPERMUTATION_COUNT+1];
694 char permutationname[256];
698 vertstrings_list[0] = "#define VERTEX_SHADER\n";
699 fragstrings_list[0] = "#define FRAGMENT_SHADER\n";
700 vertstrings_count = 1;
701 fragstrings_count = 1;
702 permutationname[0] = 0;
703 if (permutation & SHADERPERMUTATION_MODE_LIGHTSOURCE)
705 vertstrings_list[vertstrings_count++] = "#define MODE_LIGHTSOURCE\n";
706 fragstrings_list[fragstrings_count++] = "#define MODE_LIGHTSOURCE\n";
707 strlcat(permutationname, " lightsource", sizeof(permutationname));
709 if (permutation & SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_MODELSPACE)
711 vertstrings_list[vertstrings_count++] = "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n";
712 fragstrings_list[fragstrings_count++] = "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n";
713 strlcat(permutationname, " lightdirectionmap_modelspace", sizeof(permutationname));
715 if (permutation & SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)
717 vertstrings_list[vertstrings_count++] = "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n";
718 fragstrings_list[fragstrings_count++] = "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n";
719 strlcat(permutationname, " lightdirectionmap_tangentspace", sizeof(permutationname));
721 if (permutation & SHADERPERMUTATION_MODE_LIGHTDIRECTION)
723 vertstrings_list[vertstrings_count++] = "#define MODE_LIGHTDIRECTION\n";
724 fragstrings_list[fragstrings_count++] = "#define MODE_LIGHTDIRECTION\n";
725 strlcat(permutationname, " lightdirection", sizeof(permutationname));
727 if (permutation & SHADERPERMUTATION_GLOW)
729 vertstrings_list[vertstrings_count++] = "#define USEGLOW\n";
730 fragstrings_list[fragstrings_count++] = "#define USEGLOW\n";
731 strlcat(permutationname, " glow", sizeof(permutationname));
733 if (permutation & SHADERPERMUTATION_COLORMAPPING)
735 vertstrings_list[vertstrings_count++] = "#define USECOLORMAPPING\n";
736 fragstrings_list[fragstrings_count++] = "#define USECOLORMAPPING\n";
737 strlcat(permutationname, " colormapping", sizeof(permutationname));
739 if (permutation & SHADERPERMUTATION_SPECULAR)
741 vertstrings_list[vertstrings_count++] = "#define USESPECULAR\n";
742 fragstrings_list[fragstrings_count++] = "#define USESPECULAR\n";
743 strlcat(permutationname, " specular", sizeof(permutationname));
745 if (permutation & SHADERPERMUTATION_FOG)
747 vertstrings_list[vertstrings_count++] = "#define USEFOG\n";
748 fragstrings_list[fragstrings_count++] = "#define USEFOG\n";
749 strlcat(permutationname, " fog", sizeof(permutationname));
751 if (permutation & SHADERPERMUTATION_CUBEFILTER)
753 vertstrings_list[vertstrings_count++] = "#define USECUBEFILTER\n";
754 fragstrings_list[fragstrings_count++] = "#define USECUBEFILTER\n";
755 strlcat(permutationname, " cubefilter", sizeof(permutationname));
757 if (permutation & SHADERPERMUTATION_OFFSETMAPPING)
759 vertstrings_list[vertstrings_count++] = "#define USEOFFSETMAPPING\n";
760 fragstrings_list[fragstrings_count++] = "#define USEOFFSETMAPPING\n";
761 strlcat(permutationname, " offsetmapping", sizeof(permutationname));
763 if (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING)
765 vertstrings_list[vertstrings_count++] = "#define USEOFFSETMAPPING_RELIEFMAPPING\n";
766 fragstrings_list[fragstrings_count++] = "#define USEOFFSETMAPPING_RELIEFMAPPING\n";
767 strlcat(permutationname, " OFFSETMAPPING_RELIEFMAPPING", sizeof(permutationname));
769 shaderstring = (char *)FS_LoadFile("glsl/default.glsl", r_main_mempool, false, NULL);
772 Con_DPrintf("GLSL shader text loaded from disk\n");
773 vertstrings_list[vertstrings_count++] = shaderstring;
774 fragstrings_list[fragstrings_count++] = shaderstring;
778 vertstrings_list[vertstrings_count++] = builtinshaderstring;
779 fragstrings_list[fragstrings_count++] = builtinshaderstring;
781 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, fragstrings_count, fragstrings_list);
785 qglUseProgramObjectARB(p->program);
786 p->loc_Texture_Normal = qglGetUniformLocationARB(p->program, "Texture_Normal");
787 p->loc_Texture_Color = qglGetUniformLocationARB(p->program, "Texture_Color");
788 p->loc_Texture_Gloss = qglGetUniformLocationARB(p->program, "Texture_Gloss");
789 p->loc_Texture_Cube = qglGetUniformLocationARB(p->program, "Texture_Cube");
790 p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
791 p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
792 p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
793 p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
794 p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
795 p->loc_Texture_Glow = qglGetUniformLocationARB(p->program, "Texture_Glow");
796 p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
797 p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
798 p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
799 p->loc_LightColor = qglGetUniformLocationARB(p->program, "LightColor");
800 p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants");
801 p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt");
802 p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip");
803 p->loc_AmbientScale = qglGetUniformLocationARB(p->program, "AmbientScale");
804 p->loc_DiffuseScale = qglGetUniformLocationARB(p->program, "DiffuseScale");
805 p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
806 p->loc_SpecularScale = qglGetUniformLocationARB(p->program, "SpecularScale");
807 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
808 p->loc_AmbientColor = qglGetUniformLocationARB(p->program, "AmbientColor");
809 p->loc_DiffuseColor = qglGetUniformLocationARB(p->program, "DiffuseColor");
810 p->loc_SpecularColor = qglGetUniformLocationARB(p->program, "SpecularColor");
811 p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
812 if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal, 0);
813 if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color, 1);
814 if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss, 2);
815 if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube, 3);
816 if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask, 4);
817 if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants, 5);
818 if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt, 6);
819 if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap, 7);
820 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap, 8);
821 if (p->loc_Texture_Glow >= 0) qglUniform1iARB(p->loc_Texture_Glow, 9);
822 qglUseProgramObjectARB(0);
826 Con_Printf("permutation%s failed for shader %s, some features may not work properly!\n", permutationname, "glsl/default.glsl");
828 Mem_Free(shaderstring);
831 void R_GLSL_Restart_f(void)
834 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
835 if (r_glsl_permutations[i].program)
836 GL_Backend_FreeProgram(r_glsl_permutations[i].program);
837 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
840 void R_SetupSurfaceShader(const entity_render_t *ent, const texture_t *texture, const vec3_t modelorg, const vec3_t lightcolorbase, qboolean modellighting)
842 // select a permutation of the lighting shader appropriate to this
843 // combination of texture, entity, light source, and fogging, only use the
844 // minimum features necessary to avoid wasting rendering time in the
845 // fragment shader on features that are not being used
847 float specularscale = texture->specularscale;
848 r_glsl_permutation = NULL;
849 if (r_shadow_rtlight)
851 permutation |= SHADERPERMUTATION_MODE_LIGHTSOURCE;
852 specularscale *= r_shadow_rtlight->specularscale;
853 if (r_shadow_rtlight->currentcubemap != r_texture_whitecube)
854 permutation |= SHADERPERMUTATION_CUBEFILTER;
859 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTION;
860 else if (r_glsl_deluxemapping.integer >= 1 && r_refdef.worldmodel && r_refdef.worldmodel->brushq3.deluxemapping)
862 if (r_refdef.worldmodel->brushq3.deluxemapping_modelspace)
863 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_MODELSPACE;
865 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
867 else if (r_glsl_deluxemapping.integer >= 2) // fake mode
868 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
869 if (texture->skin.glow)
870 permutation |= SHADERPERMUTATION_GLOW;
872 if (specularscale > 0)
873 permutation |= SHADERPERMUTATION_SPECULAR;
875 permutation |= SHADERPERMUTATION_FOG;
876 if (texture->colormapping)
877 permutation |= SHADERPERMUTATION_COLORMAPPING;
878 if (r_glsl_offsetmapping.integer)
880 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
881 if (r_glsl_offsetmapping_reliefmapping.integer)
882 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
884 if (!r_glsl_permutations[permutation].program)
886 if (!r_glsl_permutations[permutation].compiled)
887 R_GLSL_CompilePermutation(permutation);
888 if (!r_glsl_permutations[permutation].program)
890 // remove features until we find a valid permutation
892 for (i = SHADERPERMUTATION_COUNT-1;;i>>=1)
894 // reduce i more quickly whenever it would not remove any bits
898 if (!r_glsl_permutations[permutation].compiled)
899 R_GLSL_CompilePermutation(permutation);
900 if (r_glsl_permutations[permutation].program)
903 return; // utterly failed
907 r_glsl_permutation = r_glsl_permutations + permutation;
909 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
910 R_Mesh_TexMatrix(0, &texture->currenttexmatrix);
911 if (permutation & SHADERPERMUTATION_MODE_LIGHTSOURCE)
913 R_Mesh_TexMatrix(3, &r_shadow_entitytolight);
914 //if (r_glsl_permutation->loc_Texture_Cube >= 0) R_Mesh_TexBindCubeMap(3, R_GetTexture(r_shadow_rtlight->currentcubemap));
915 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]);
916 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
917 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_shadow_rtlight->ambientscale);
918 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_shadow_rtlight->diffusescale);
919 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, specularscale);
921 else if (permutation & SHADERPERMUTATION_MODE_LIGHTDIRECTION)
923 if (texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
925 if (r_glsl_permutation->loc_AmbientColor >= 0)
926 qglUniform3fARB(r_glsl_permutation->loc_AmbientColor, 1, 1, 1);
927 if (r_glsl_permutation->loc_DiffuseColor >= 0)
928 qglUniform3fARB(r_glsl_permutation->loc_DiffuseColor, 0, 0, 0);
929 if (r_glsl_permutation->loc_SpecularColor >= 0)
930 qglUniform3fARB(r_glsl_permutation->loc_SpecularColor, 0, 0, 0);
931 if (r_glsl_permutation->loc_LightDir >= 0)
932 qglUniform3fARB(r_glsl_permutation->loc_LightDir, 0, 0, -1);
936 if (r_glsl_permutation->loc_AmbientColor >= 0)
937 qglUniform3fARB(r_glsl_permutation->loc_AmbientColor, ent->modellight_ambient[0], ent->modellight_ambient[1], ent->modellight_ambient[2]);
938 if (r_glsl_permutation->loc_DiffuseColor >= 0)
939 qglUniform3fARB(r_glsl_permutation->loc_DiffuseColor, ent->modellight_diffuse[0], ent->modellight_diffuse[1], ent->modellight_diffuse[2]);
940 if (r_glsl_permutation->loc_SpecularColor >= 0)
941 qglUniform3fARB(r_glsl_permutation->loc_SpecularColor, ent->modellight_diffuse[0] * texture->specularscale, ent->modellight_diffuse[1] * texture->specularscale, ent->modellight_diffuse[2] * texture->specularscale);
942 if (r_glsl_permutation->loc_LightDir >= 0)
943 qglUniform3fARB(r_glsl_permutation->loc_LightDir, ent->modellight_lightdir[0], ent->modellight_lightdir[1], ent->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(texture->skin.nmap));
953 if (r_glsl_permutation->loc_Texture_Color >= 0) R_Mesh_TexBind(1, R_GetTexture(texture->basetexture));
954 if (r_glsl_permutation->loc_Texture_Gloss >= 0) R_Mesh_TexBind(2, R_GetTexture(texture->glosstexture));
955 if (r_glsl_permutation->loc_Texture_FogMask >= 0) R_Mesh_TexBind(4, R_GetTexture(r_texture_fogattenuation));
956 if (r_glsl_permutation->loc_Texture_Pants >= 0) R_Mesh_TexBind(5, R_GetTexture(texture->skin.pants));
957 if (r_glsl_permutation->loc_Texture_Shirt >= 0) R_Mesh_TexBind(6, R_GetTexture(texture->skin.shirt));
958 if (r_glsl_permutation->loc_Texture_Glow >= 0) R_Mesh_TexBind(9, R_GetTexture(texture->skin.glow));
959 if (r_glsl_permutation->loc_FogColor >= 0)
961 // additive passes are only darkened by fog, not tinted
962 if (r_shadow_rtlight || (texture->currentmaterialflags & MATERIALFLAG_ADD))
963 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
965 qglUniform3fARB(r_glsl_permutation->loc_FogColor, fogcolor[0], fogcolor[1], fogcolor[2]);
967 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, modelorg[0], modelorg[1], modelorg[2]);
968 if (r_glsl_permutation->loc_Color_Pants >= 0)
970 if (texture->skin.pants)
971 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, ent->colormap_pantscolor[0], ent->colormap_pantscolor[1], ent->colormap_pantscolor[2]);
973 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
975 if (r_glsl_permutation->loc_Color_Shirt >= 0)
977 if (texture->skin.shirt)
978 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, ent->colormap_shirtcolor[0], ent->colormap_shirtcolor[1], ent->colormap_shirtcolor[2]);
980 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
982 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, fograngerecip);
983 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, texture->specularpower);
984 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
988 void gl_main_start(void)
990 r_main_texturepool = R_AllocTexturePool();
991 r_bloom_texture_screen = NULL;
992 r_bloom_texture_bloom = NULL;
993 R_BuildBlankTextures();
995 if (gl_texturecubemap)
998 R_BuildNormalizationCube();
1000 R_BuildFogTexture();
1001 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
1004 void gl_main_shutdown(void)
1006 R_FreeTexturePool(&r_main_texturepool);
1007 r_bloom_texture_screen = NULL;
1008 r_bloom_texture_bloom = NULL;
1009 r_texture_blanknormalmap = NULL;
1010 r_texture_white = NULL;
1011 r_texture_black = NULL;
1012 r_texture_whitecube = NULL;
1013 r_texture_normalizationcube = NULL;
1017 extern void CL_ParseEntityLump(char *entitystring);
1018 void gl_main_newmap(void)
1020 // FIXME: move this code to client
1022 char *entities, entname[MAX_QPATH];
1026 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
1027 l = (int)strlen(entname) - 4;
1028 if (l >= 0 && !strcmp(entname + l, ".bsp"))
1030 strcpy(entname + l, ".ent");
1031 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
1033 CL_ParseEntityLump(entities);
1038 if (cl.worldmodel->brush.entities)
1039 CL_ParseEntityLump(cl.worldmodel->brush.entities);
1043 void GL_Main_Init(void)
1045 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
1047 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed\n");
1048 FOG_registercvars(); // FIXME: move this fog stuff to client?
1049 Cvar_RegisterVariable(&r_nearclip);
1050 Cvar_RegisterVariable(&r_showsurfaces);
1051 Cvar_RegisterVariable(&r_showtris);
1052 Cvar_RegisterVariable(&r_shownormals);
1053 Cvar_RegisterVariable(&r_showlighting);
1054 Cvar_RegisterVariable(&r_showshadowvolumes);
1055 Cvar_RegisterVariable(&r_showcollisionbrushes);
1056 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
1057 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
1058 Cvar_RegisterVariable(&r_showdisabledepthtest);
1059 Cvar_RegisterVariable(&r_drawentities);
1060 Cvar_RegisterVariable(&r_drawviewmodel);
1061 Cvar_RegisterVariable(&r_speeds);
1062 Cvar_RegisterVariable(&r_fullbrights);
1063 Cvar_RegisterVariable(&r_wateralpha);
1064 Cvar_RegisterVariable(&r_dynamic);
1065 Cvar_RegisterVariable(&r_fullbright);
1066 Cvar_RegisterVariable(&r_q1bsp_skymasking);
1067 Cvar_RegisterVariable(&r_textureunits);
1068 Cvar_RegisterVariable(&r_glsl);
1069 Cvar_RegisterVariable(&r_glsl_offsetmapping);
1070 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
1071 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
1072 Cvar_RegisterVariable(&r_glsl_deluxemapping);
1073 Cvar_RegisterVariable(&r_lerpsprites);
1074 Cvar_RegisterVariable(&r_lerpmodels);
1075 Cvar_RegisterVariable(&r_waterscroll);
1076 Cvar_RegisterVariable(&r_bloom);
1077 Cvar_RegisterVariable(&r_bloom_intensity);
1078 Cvar_RegisterVariable(&r_bloom_blur);
1079 Cvar_RegisterVariable(&r_bloom_resolution);
1080 Cvar_RegisterVariable(&r_bloom_power);
1081 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
1082 Cvar_RegisterVariable(&developer_texturelogging);
1083 Cvar_RegisterVariable(&gl_lightmaps);
1084 Cvar_RegisterVariable(&r_test);
1085 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
1086 Cvar_SetValue("r_fullbrights", 0);
1087 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
1090 static vec3_t r_farclip_origin;
1091 static vec3_t r_farclip_direction;
1092 static vec_t r_farclip_directiondist;
1093 static vec_t r_farclip_meshfarclip;
1094 static int r_farclip_directionbit0;
1095 static int r_farclip_directionbit1;
1096 static int r_farclip_directionbit2;
1098 // enlarge farclip to accomodate box
1099 static void R_FarClip_Box(vec3_t mins, vec3_t maxs)
1102 d = (r_farclip_directionbit0 ? mins[0] : maxs[0]) * r_farclip_direction[0]
1103 + (r_farclip_directionbit1 ? mins[1] : maxs[1]) * r_farclip_direction[1]
1104 + (r_farclip_directionbit2 ? mins[2] : maxs[2]) * r_farclip_direction[2];
1105 if (r_farclip_meshfarclip < d)
1106 r_farclip_meshfarclip = d;
1109 // return farclip value
1110 static float R_FarClip(vec3_t origin, vec3_t direction, vec_t startfarclip)
1114 VectorCopy(origin, r_farclip_origin);
1115 VectorCopy(direction, r_farclip_direction);
1116 r_farclip_directiondist = DotProduct(r_farclip_origin, r_farclip_direction);
1117 r_farclip_directionbit0 = r_farclip_direction[0] < 0;
1118 r_farclip_directionbit1 = r_farclip_direction[1] < 0;
1119 r_farclip_directionbit2 = r_farclip_direction[2] < 0;
1120 r_farclip_meshfarclip = r_farclip_directiondist + startfarclip;
1122 if (r_refdef.worldmodel)
1123 R_FarClip_Box(r_refdef.worldmodel->normalmins, r_refdef.worldmodel->normalmaxs);
1124 for (i = 0;i < r_refdef.numentities;i++)
1125 R_FarClip_Box(r_refdef.entities[i]->mins, r_refdef.entities[i]->maxs);
1127 return r_farclip_meshfarclip - r_farclip_directiondist;
1130 extern void R_Textures_Init(void);
1131 extern void GL_Draw_Init(void);
1132 extern void GL_Main_Init(void);
1133 extern void R_Shadow_Init(void);
1134 extern void R_Sky_Init(void);
1135 extern void GL_Surf_Init(void);
1136 extern void R_Crosshairs_Init(void);
1137 extern void R_Light_Init(void);
1138 extern void R_Particles_Init(void);
1139 extern void R_Explosion_Init(void);
1140 extern void gl_backend_init(void);
1141 extern void Sbar_Init(void);
1142 extern void R_LightningBeams_Init(void);
1143 extern void Mod_RenderInit(void);
1145 void Render_Init(void)
1155 R_Crosshairs_Init();
1160 R_LightningBeams_Init();
1169 extern char *ENGINE_EXTENSIONS;
1172 VID_CheckExtensions();
1174 // LordHavoc: report supported extensions
1175 Con_DPrintf("\nengine extensions: %s\n", vm_sv_extensions );
1177 // clear to black (loading plaque will be seen over this)
1178 qglClearColor(0,0,0,1);
1179 qglClear(GL_COLOR_BUFFER_BIT);
1182 int R_CullBox(const vec3_t mins, const vec3_t maxs)
1186 for (i = 0;i < 4;i++)
1193 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1197 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1201 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1205 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1209 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1213 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1217 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1221 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1229 //==================================================================================
1231 static void R_UpdateEntityLighting(entity_render_t *ent)
1233 vec3_t tempdiffusenormal;
1234 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));
1235 VectorClear(ent->modellight_diffuse);
1236 VectorClear(ent->modellight_lightdir);
1237 if ((ent->flags & RENDER_LIGHT) && r_refdef.worldmodel && r_refdef.worldmodel->brush.LightPoint)
1238 r_refdef.worldmodel->brush.LightPoint(r_refdef.worldmodel, ent->origin, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
1240 VectorSet(ent->modellight_ambient, 1, 1, 1);
1241 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
1242 VectorNormalize(ent->modellight_lightdir);
1243 ent->modellight_ambient[0] *= ent->colormod[0] * r_lightmapintensity;
1244 ent->modellight_ambient[1] *= ent->colormod[1] * r_lightmapintensity;
1245 ent->modellight_ambient[2] *= ent->colormod[2] * r_lightmapintensity;
1246 ent->modellight_diffuse[0] *= ent->colormod[0] * r_lightmapintensity;
1247 ent->modellight_diffuse[1] *= ent->colormod[1] * r_lightmapintensity;
1248 ent->modellight_diffuse[2] *= ent->colormod[2] * r_lightmapintensity;
1251 static void R_MarkEntities (void)
1254 entity_render_t *ent;
1256 if (!r_drawentities.integer)
1259 r_refdef.worldentity->visframe = r_framecount;
1260 renderimask = envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : (chase_active.integer ? 0 : RENDER_EXTERIORMODEL);
1261 if (r_refdef.worldmodel && r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs)
1263 // worldmodel can check visibility
1264 for (i = 0;i < r_refdef.numentities;i++)
1266 ent = r_refdef.entities[i];
1267 // some of the renderer still relies on origin...
1268 Matrix4x4_OriginFromMatrix(&ent->matrix, ent->origin);
1269 // some of the renderer still relies on scale...
1270 ent->scale = Matrix4x4_ScaleFromMatrix(&ent->matrix);
1271 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)))
1273 ent->visframe = r_framecount;
1274 R_UpdateEntityLighting(ent);
1280 // no worldmodel or it can't 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))
1290 ent->visframe = r_framecount;
1291 R_UpdateEntityLighting(ent);
1297 // only used if skyrendermasked, and normally returns false
1298 int R_DrawBrushModelsSky (void)
1301 entity_render_t *ent;
1303 if (!r_drawentities.integer)
1307 for (i = 0;i < r_refdef.numentities;i++)
1309 ent = r_refdef.entities[i];
1310 if (ent->visframe == r_framecount && ent->model && ent->model->DrawSky)
1312 ent->model->DrawSky(ent);
1319 void R_DrawNoModel(entity_render_t *ent);
1320 void R_DrawModels(void)
1323 entity_render_t *ent;
1325 if (!r_drawentities.integer)
1328 for (i = 0;i < r_refdef.numentities;i++)
1330 ent = r_refdef.entities[i];
1331 if (ent->visframe == r_framecount)
1333 renderstats.entities++;
1334 if (ent->model && ent->model->Draw != NULL)
1335 ent->model->Draw(ent);
1342 static void R_SetFrustum(void)
1344 // break apart the view matrix into vectors for various purposes
1345 Matrix4x4_ToVectors(&r_view_matrix, r_viewforward, r_viewleft, r_viewup, r_vieworigin);
1346 VectorNegate(r_viewleft, r_viewright);
1349 frustum[0].normal[0] = 0 - 1.0 / r_refdef.frustum_x;
1350 frustum[0].normal[1] = 0 - 0;
1351 frustum[0].normal[2] = -1 - 0;
1352 frustum[1].normal[0] = 0 + 1.0 / r_refdef.frustum_x;
1353 frustum[1].normal[1] = 0 + 0;
1354 frustum[1].normal[2] = -1 + 0;
1355 frustum[2].normal[0] = 0 - 0;
1356 frustum[2].normal[1] = 0 - 1.0 / r_refdef.frustum_y;
1357 frustum[2].normal[2] = -1 - 0;
1358 frustum[3].normal[0] = 0 + 0;
1359 frustum[3].normal[1] = 0 + 1.0 / r_refdef.frustum_y;
1360 frustum[3].normal[2] = -1 + 0;
1364 zNear = r_nearclip.value;
1365 nudge = 1.0 - 1.0 / (1<<23);
1366 frustum[4].normal[0] = 0 - 0;
1367 frustum[4].normal[1] = 0 - 0;
1368 frustum[4].normal[2] = -1 - -nudge;
1369 frustum[4].dist = 0 - -2 * zNear * nudge;
1370 frustum[5].normal[0] = 0 + 0;
1371 frustum[5].normal[1] = 0 + 0;
1372 frustum[5].normal[2] = -1 + -nudge;
1373 frustum[5].dist = 0 + -2 * zNear * nudge;
1379 frustum[0].normal[0] = m[3] - m[0];
1380 frustum[0].normal[1] = m[7] - m[4];
1381 frustum[0].normal[2] = m[11] - m[8];
1382 frustum[0].dist = m[15] - m[12];
1384 frustum[1].normal[0] = m[3] + m[0];
1385 frustum[1].normal[1] = m[7] + m[4];
1386 frustum[1].normal[2] = m[11] + m[8];
1387 frustum[1].dist = m[15] + m[12];
1389 frustum[2].normal[0] = m[3] - m[1];
1390 frustum[2].normal[1] = m[7] - m[5];
1391 frustum[2].normal[2] = m[11] - m[9];
1392 frustum[2].dist = m[15] - m[13];
1394 frustum[3].normal[0] = m[3] + m[1];
1395 frustum[3].normal[1] = m[7] + m[5];
1396 frustum[3].normal[2] = m[11] + m[9];
1397 frustum[3].dist = m[15] + m[13];
1399 frustum[4].normal[0] = m[3] - m[2];
1400 frustum[4].normal[1] = m[7] - m[6];
1401 frustum[4].normal[2] = m[11] - m[10];
1402 frustum[4].dist = m[15] - m[14];
1404 frustum[5].normal[0] = m[3] + m[2];
1405 frustum[5].normal[1] = m[7] + m[6];
1406 frustum[5].normal[2] = m[11] + m[10];
1407 frustum[5].dist = m[15] + m[14];
1412 VectorMAM(1, r_viewforward, 1.0 / -r_refdef.frustum_x, r_viewleft, frustum[0].normal);
1413 VectorMAM(1, r_viewforward, 1.0 / r_refdef.frustum_x, r_viewleft, frustum[1].normal);
1414 VectorMAM(1, r_viewforward, 1.0 / -r_refdef.frustum_y, r_viewup, frustum[2].normal);
1415 VectorMAM(1, r_viewforward, 1.0 / r_refdef.frustum_y, r_viewup, frustum[3].normal);
1416 VectorCopy(r_viewforward, frustum[4].normal);
1417 VectorNormalize(frustum[0].normal);
1418 VectorNormalize(frustum[1].normal);
1419 VectorNormalize(frustum[2].normal);
1420 VectorNormalize(frustum[3].normal);
1421 frustum[0].dist = DotProduct (r_vieworigin, frustum[0].normal);
1422 frustum[1].dist = DotProduct (r_vieworigin, frustum[1].normal);
1423 frustum[2].dist = DotProduct (r_vieworigin, frustum[2].normal);
1424 frustum[3].dist = DotProduct (r_vieworigin, frustum[3].normal);
1425 frustum[4].dist = DotProduct (r_vieworigin, frustum[4].normal) + r_nearclip.value;
1426 PlaneClassify(&frustum[0]);
1427 PlaneClassify(&frustum[1]);
1428 PlaneClassify(&frustum[2]);
1429 PlaneClassify(&frustum[3]);
1430 PlaneClassify(&frustum[4]);
1432 // LordHavoc: note to all quake engine coders, Quake had a special case
1433 // for 90 degrees which assumed a square view (wrong), so I removed it,
1434 // Quake2 has it disabled as well.
1436 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
1437 //RotatePointAroundVector( frustum[0].normal, r_viewup, r_viewforward, -(90 - r_refdef.fov_x / 2));
1438 //frustum[0].dist = DotProduct (r_vieworigin, frustum[0].normal);
1439 //PlaneClassify(&frustum[0]);
1441 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
1442 //RotatePointAroundVector( frustum[1].normal, r_viewup, r_viewforward, (90 - r_refdef.fov_x / 2));
1443 //frustum[1].dist = DotProduct (r_vieworigin, frustum[1].normal);
1444 //PlaneClassify(&frustum[1]);
1446 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
1447 //RotatePointAroundVector( frustum[2].normal, r_viewleft, r_viewforward, -(90 - r_refdef.fov_y / 2));
1448 //frustum[2].dist = DotProduct (r_vieworigin, frustum[2].normal);
1449 //PlaneClassify(&frustum[2]);
1451 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
1452 //RotatePointAroundVector( frustum[3].normal, r_viewleft, r_viewforward, (90 - r_refdef.fov_y / 2));
1453 //frustum[3].dist = DotProduct (r_vieworigin, frustum[3].normal);
1454 //PlaneClassify(&frustum[3]);
1457 //VectorCopy(r_viewforward, frustum[4].normal);
1458 //frustum[4].dist = DotProduct (r_vieworigin, frustum[4].normal) + r_nearclip.value;
1459 //PlaneClassify(&frustum[4]);
1462 static void R_BlendView(void)
1464 int screenwidth, screenheight;
1469 float texcoord2f[3][8];
1471 // set the (poorly named) screenwidth and screenheight variables to
1472 // a power of 2 at least as large as the screen, these will define the
1473 // size of the texture to allocate
1474 for (screenwidth = 1;screenwidth < vid.width;screenwidth *= 2);
1475 for (screenheight = 1;screenheight < vid.height;screenheight *= 2);
1477 doblend = r_refdef.viewblend[3] >= 0.01f;
1478 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;
1480 if (!dobloom && !doblend)
1483 GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
1485 GL_DepthTest(false);
1486 R_Mesh_Matrix(&identitymatrix);
1487 // vertex coordinates for a quad that covers the screen exactly
1488 vertex3f[0] = 0;vertex3f[1] = 0;vertex3f[2] = 0;
1489 vertex3f[3] = 1;vertex3f[4] = 0;vertex3f[5] = 0;
1490 vertex3f[6] = 1;vertex3f[7] = 1;vertex3f[8] = 0;
1491 vertex3f[9] = 0;vertex3f[10] = 1;vertex3f[11] = 0;
1494 int bloomwidth, bloomheight, x, dobloomblend, range;
1495 float xoffset, yoffset, r;
1496 renderstats.bloom++;
1497 // allocate textures as needed
1498 if (!r_bloom_texture_screen)
1499 r_bloom_texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", screenwidth, screenheight, NULL, TEXTYPE_RGBA, TEXF_FORCENEAREST | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
1500 if (!r_bloom_texture_bloom)
1501 r_bloom_texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", screenwidth, screenheight, NULL, TEXTYPE_RGBA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
1502 // set bloomwidth and bloomheight to the bloom resolution that will be
1503 // used (often less than the screen resolution for faster rendering)
1504 bloomwidth = min(r_view_width, r_bloom_resolution.integer);
1505 bloomheight = min(r_view_height, bloomwidth * r_view_height / r_view_width);
1506 // set up a texcoord array for the full resolution screen image
1507 // (we have to keep this around to copy back during final render)
1508 texcoord2f[0][0] = 0;
1509 texcoord2f[0][1] = (float)r_view_height / (float)screenheight;
1510 texcoord2f[0][2] = (float)r_view_width / (float)screenwidth;
1511 texcoord2f[0][3] = (float)r_view_height / (float)screenheight;
1512 texcoord2f[0][4] = (float)r_view_width / (float)screenwidth;
1513 texcoord2f[0][5] = 0;
1514 texcoord2f[0][6] = 0;
1515 texcoord2f[0][7] = 0;
1516 // set up a texcoord array for the reduced resolution bloom image
1517 // (which will be additive blended over the screen image)
1518 texcoord2f[1][0] = 0;
1519 texcoord2f[1][1] = (float)bloomheight / (float)screenheight;
1520 texcoord2f[1][2] = (float)bloomwidth / (float)screenwidth;
1521 texcoord2f[1][3] = (float)bloomheight / (float)screenheight;
1522 texcoord2f[1][4] = (float)bloomwidth / (float)screenwidth;
1523 texcoord2f[1][5] = 0;
1524 texcoord2f[1][6] = 0;
1525 texcoord2f[1][7] = 0;
1526 memset(&m, 0, sizeof(m));
1527 m.pointer_vertex = vertex3f;
1528 m.pointer_texcoord[0] = texcoord2f[0];
1529 m.tex[0] = R_GetTexture(r_bloom_texture_screen);
1531 // copy view into the full resolution screen image texture
1532 GL_ActiveTexture(0);
1533 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
1534 renderstats.bloom_copypixels += r_view_width * r_view_height;
1535 // now scale it down to the bloom size and raise to a power of itself
1536 // to darken it (this leaves the really bright stuff bright, and
1537 // everything else becomes very dark)
1538 // TODO: optimize with multitexture or GLSL
1539 qglViewport(r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
1540 GL_BlendFunc(GL_ONE, GL_ZERO);
1541 GL_Color(1, 1, 1, 1);
1542 R_Mesh_Draw(0, 4, 2, polygonelements);
1543 renderstats.bloom_drawpixels += bloomwidth * bloomheight;
1544 // render multiple times with a multiply blendfunc to raise to a power
1545 GL_BlendFunc(GL_DST_COLOR, GL_ZERO);
1546 for (x = 1;x < r_bloom_power.integer;x++)
1548 R_Mesh_Draw(0, 4, 2, polygonelements);
1549 renderstats.bloom_drawpixels += bloomwidth * bloomheight;
1551 // we now have a darkened bloom image in the framebuffer, copy it into
1552 // the bloom image texture for more processing
1553 memset(&m, 0, sizeof(m));
1554 m.pointer_vertex = vertex3f;
1555 m.tex[0] = R_GetTexture(r_bloom_texture_bloom);
1556 m.pointer_texcoord[0] = texcoord2f[2];
1558 GL_ActiveTexture(0);
1559 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
1560 renderstats.bloom_copypixels += bloomwidth * bloomheight;
1561 // blend on at multiple vertical offsets to achieve a vertical blur
1562 // TODO: do offset blends using GLSL
1563 range = r_bloom_blur.integer * bloomwidth / 320;
1564 GL_BlendFunc(GL_ONE, GL_ZERO);
1565 for (x = -range;x <= range;x++)
1567 xoffset = 0 / (float)bloomwidth * (float)bloomwidth / (float)screenwidth;
1568 yoffset = x / (float)bloomheight * (float)bloomheight / (float)screenheight;
1569 // compute a texcoord array with the specified x and y offset
1570 texcoord2f[2][0] = xoffset+0;
1571 texcoord2f[2][1] = yoffset+(float)bloomheight / (float)screenheight;
1572 texcoord2f[2][2] = xoffset+(float)bloomwidth / (float)screenwidth;
1573 texcoord2f[2][3] = yoffset+(float)bloomheight / (float)screenheight;
1574 texcoord2f[2][4] = xoffset+(float)bloomwidth / (float)screenwidth;
1575 texcoord2f[2][5] = yoffset+0;
1576 texcoord2f[2][6] = xoffset+0;
1577 texcoord2f[2][7] = yoffset+0;
1578 // this r value looks like a 'dot' particle, fading sharply to
1579 // black at the edges
1580 // (probably not realistic but looks good enough)
1581 r = r_bloom_intensity.value/(range*2+1)*(1 - x*x/(float)(range*range));
1584 GL_Color(r, r, r, 1);
1585 R_Mesh_Draw(0, 4, 2, polygonelements);
1586 renderstats.bloom_drawpixels += bloomwidth * bloomheight;
1587 GL_BlendFunc(GL_ONE, GL_ONE);
1589 // copy the vertically blurred bloom view to a texture
1590 GL_ActiveTexture(0);
1591 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
1592 renderstats.bloom_copypixels += bloomwidth * bloomheight;
1593 // blend the vertically blurred image at multiple offsets horizontally
1594 // to finish the blur effect
1595 // TODO: do offset blends using GLSL
1596 range = r_bloom_blur.integer * bloomwidth / 320;
1597 GL_BlendFunc(GL_ONE, GL_ZERO);
1598 for (x = -range;x <= range;x++)
1600 xoffset = x / (float)bloomwidth * (float)bloomwidth / (float)screenwidth;
1601 yoffset = 0 / (float)bloomheight * (float)bloomheight / (float)screenheight;
1602 // compute a texcoord array with the specified x and y offset
1603 texcoord2f[2][0] = xoffset+0;
1604 texcoord2f[2][1] = yoffset+(float)bloomheight / (float)screenheight;
1605 texcoord2f[2][2] = xoffset+(float)bloomwidth / (float)screenwidth;
1606 texcoord2f[2][3] = yoffset+(float)bloomheight / (float)screenheight;
1607 texcoord2f[2][4] = xoffset+(float)bloomwidth / (float)screenwidth;
1608 texcoord2f[2][5] = yoffset+0;
1609 texcoord2f[2][6] = xoffset+0;
1610 texcoord2f[2][7] = yoffset+0;
1611 // this r value looks like a 'dot' particle, fading sharply to
1612 // black at the edges
1613 // (probably not realistic but looks good enough)
1614 r = r_bloom_intensity.value/(range*2+1)*(1 - x*x/(float)(range*range));
1617 GL_Color(r, r, r, 1);
1618 R_Mesh_Draw(0, 4, 2, polygonelements);
1619 renderstats.bloom_drawpixels += bloomwidth * bloomheight;
1620 GL_BlendFunc(GL_ONE, GL_ONE);
1622 // copy the blurred bloom view to a texture
1623 GL_ActiveTexture(0);
1624 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
1625 renderstats.bloom_copypixels += bloomwidth * bloomheight;
1626 // go back to full view area
1627 qglViewport(r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
1628 // put the original screen image back in place and blend the bloom
1630 memset(&m, 0, sizeof(m));
1631 m.pointer_vertex = vertex3f;
1632 m.tex[0] = R_GetTexture(r_bloom_texture_screen);
1633 m.pointer_texcoord[0] = texcoord2f[0];
1635 dobloomblend = false;
1637 // do both in one pass if possible
1638 if (r_textureunits.integer >= 2 && gl_combine.integer)
1640 dobloomblend = false;
1641 m.texcombinergb[1] = GL_ADD;
1642 m.tex[1] = R_GetTexture(r_bloom_texture_bloom);
1643 m.pointer_texcoord[1] = texcoord2f[1];
1646 dobloomblend = true;
1649 GL_BlendFunc(GL_ONE, GL_ZERO);
1651 R_Mesh_Draw(0, 4, 2, polygonelements);
1652 renderstats.bloom_drawpixels += r_view_width * r_view_height;
1653 // now blend on the bloom texture if multipass
1656 memset(&m, 0, sizeof(m));
1657 m.pointer_vertex = vertex3f;
1658 m.tex[0] = R_GetTexture(r_bloom_texture_bloom);
1659 m.pointer_texcoord[0] = texcoord2f[1];
1661 GL_BlendFunc(GL_ONE, GL_ONE);
1663 R_Mesh_Draw(0, 4, 2, polygonelements);
1664 renderstats.bloom_drawpixels += r_view_width * r_view_height;
1669 // apply a color tint to the whole view
1670 memset(&m, 0, sizeof(m));
1671 m.pointer_vertex = vertex3f;
1673 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1674 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
1675 R_Mesh_Draw(0, 4, 2, polygonelements);
1679 void R_RenderScene(void);
1681 matrix4x4_t r_waterscrollmatrix;
1688 void R_RenderView(void)
1690 if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
1691 return; //Host_Error ("R_RenderView: NULL worldmodel");
1693 r_view_width = bound(0, r_refdef.width, vid.width);
1694 r_view_height = bound(0, r_refdef.height, vid.height);
1696 r_view_x = bound(0, r_refdef.x, vid.width - r_refdef.width);
1697 r_view_y = bound(0, r_refdef.y, vid.height - r_refdef.height);
1699 r_view_matrix = r_refdef.viewentitymatrix;
1700 GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
1701 r_rtworld = r_shadow_realtime_world.integer;
1702 r_rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
1703 r_rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer;
1704 r_rtdlightshadows = r_rtdlight && (r_rtworld ? r_shadow_realtime_world_dlightshadows.integer : r_shadow_realtime_dlight_shadows.integer) && gl_stencil;
1705 r_lightmapintensity = r_rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
1706 r_polygonfactor = 0;
1707 r_polygonoffset = 0;
1708 r_shadowpolygonfactor = r_polygonfactor + r_shadow_shadow_polygonfactor.value;
1709 r_shadowpolygonoffset = r_polygonoffset + r_shadow_shadow_polygonoffset.value;
1710 if (r_showsurfaces.integer)
1713 r_rtworldshadows = false;
1715 r_rtdlightshadows = false;
1716 r_lightmapintensity = 0;
1719 // GL is weird because it's bottom to top, r_view_y is top to bottom
1720 qglViewport(r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
1721 GL_Scissor(r_view_x, r_view_y, r_view_width, r_view_height);
1722 GL_ScissorTest(true);
1727 if (r_timereport_active)
1728 R_TimeReport("setup");
1730 qglDepthFunc(GL_LEQUAL);
1731 qglPolygonOffset(r_polygonfactor, r_polygonoffset);
1732 qglEnable(GL_POLYGON_OFFSET_FILL);
1736 qglPolygonOffset(r_polygonfactor, r_polygonoffset);
1737 qglDisable(GL_POLYGON_OFFSET_FILL);
1740 if (r_timereport_active)
1741 R_TimeReport("blendview");
1743 GL_Scissor(0, 0, vid.width, vid.height);
1744 GL_ScissorTest(false);
1748 void CSQC_R_ClearScreen (void)
1750 if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
1751 return; //Host_Error ("R_RenderView: NULL worldmodel");
1753 r_view_width = bound(0, r_refdef.width, vid.width);
1754 r_view_height = bound(0, r_refdef.height, vid.height);
1756 r_view_x = bound(0, r_refdef.x, vid.width - r_refdef.width);
1757 r_view_y = bound(0, r_refdef.y, vid.height - r_refdef.height);
1759 r_view_matrix = r_refdef.viewentitymatrix;
1760 GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
1761 r_rtworld = r_shadow_realtime_world.integer;
1762 r_rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
1763 r_rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer;
1764 r_rtdlightshadows = r_rtdlight && (r_rtworld ? r_shadow_realtime_world_dlightshadows.integer : r_shadow_realtime_dlight_shadows.integer) && gl_stencil;
1765 r_lightmapintensity = r_rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
1766 r_polygonfactor = 0;
1767 r_polygonoffset = 0;
1768 r_shadowpolygonfactor = r_polygonfactor + r_shadow_shadow_polygonfactor.value;
1769 r_shadowpolygonoffset = r_polygonoffset + r_shadow_shadow_polygonoffset.value;
1770 if (r_showsurfaces.integer)
1773 r_rtworldshadows = false;
1775 r_rtdlightshadows = false;
1776 r_lightmapintensity = 0;
1779 // GL is weird because it's bottom to top, r_view_y is top to bottom
1780 qglViewport(r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
1781 GL_Scissor(r_view_x, r_view_y, r_view_width, r_view_height);
1782 GL_ScissorTest(true);
1787 if (r_timereport_active)
1788 R_TimeReport("setup");
1792 void CSQC_R_RenderScene (void)
1794 qglDepthFunc(GL_LEQUAL);
1795 qglPolygonOffset(r_polygonfactor, r_polygonoffset);
1796 qglEnable(GL_POLYGON_OFFSET_FILL);
1800 qglPolygonOffset(r_polygonfactor, r_polygonoffset);
1801 qglDisable(GL_POLYGON_OFFSET_FILL);
1804 if (r_timereport_active)
1805 R_TimeReport("blendview");
1807 GL_Scissor(0, 0, vid.width, vid.height);
1808 GL_ScissorTest(false);
1811 extern void R_DrawLightningBeams (void);
1812 extern void VM_AddPolygonsToMeshQueue (void);
1813 void R_RenderScene(void)
1817 // don't let sound skip if going slow
1818 if (r_refdef.extraupdate)
1823 if (gl_support_fragment_shader)
1824 qglUseProgramObjectARB(0);
1826 R_MeshQueue_BeginScene();
1830 r_farclip = R_FarClip(r_vieworigin, r_viewforward, 768.0f) + 256.0f;
1831 nearclip = bound (0.001f, r_nearclip.value, r_farclip - 1.0f);
1833 if (r_rtworldshadows || r_rtdlightshadows)
1834 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_refdef.frustum_x, r_refdef.frustum_y, nearclip);
1836 GL_SetupView_Mode_Perspective(r_refdef.frustum_x, r_refdef.frustum_y, nearclip, r_farclip);
1838 GL_SetupView_Orientation_FromEntity(&r_view_matrix);
1840 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);
1844 R_WorldVisibility();
1845 if (r_timereport_active)
1846 R_TimeReport("worldvis");
1849 if (r_timereport_active)
1850 R_TimeReport("markentity");
1852 R_Shadow_UpdateWorldLightSelection();
1854 if (cl.csqc_vidvars.drawworld)
1856 // don't let sound skip if going slow
1857 if (r_refdef.extraupdate)
1860 if (r_refdef.worldmodel && r_refdef.worldmodel->DrawSky)
1862 r_refdef.worldmodel->DrawSky(r_refdef.worldentity);
1863 if (r_timereport_active)
1864 R_TimeReport("worldsky");
1867 if (R_DrawBrushModelsSky() && r_timereport_active)
1868 R_TimeReport("bmodelsky");
1870 if (r_refdef.worldmodel && r_refdef.worldmodel->Draw)
1872 r_refdef.worldmodel->Draw(r_refdef.worldentity);
1873 if (r_timereport_active)
1874 R_TimeReport("world");
1878 // don't let sound skip if going slow
1879 if (r_refdef.extraupdate)
1883 if (r_timereport_active)
1884 R_TimeReport("models");
1886 // don't let sound skip if going slow
1887 if (r_refdef.extraupdate)
1890 R_ShadowVolumeLighting(false);
1891 if (r_timereport_active)
1892 R_TimeReport("rtlights");
1894 // don't let sound skip if going slow
1895 if (r_refdef.extraupdate)
1898 if (cl.csqc_vidvars.drawworld)
1900 R_DrawLightningBeams();
1901 if (r_timereport_active)
1902 R_TimeReport("lightning");
1905 if (r_timereport_active)
1906 R_TimeReport("particles");
1909 if (r_timereport_active)
1910 R_TimeReport("explosions");
1913 R_MeshQueue_RenderTransparent();
1914 if (r_timereport_active)
1915 R_TimeReport("drawtrans");
1917 if (cl.csqc_vidvars.drawworld)
1920 if (r_timereport_active)
1921 R_TimeReport("coronas");
1923 if(cl.csqc_vidvars.drawcrosshair)
1925 R_DrawWorldCrosshair();
1926 if (r_timereport_active)
1927 R_TimeReport("crosshair");
1930 VM_AddPolygonsToMeshQueue();
1932 R_MeshQueue_Render();
1934 R_MeshQueue_EndScene();
1936 // don't let sound skip if going slow
1937 if (r_refdef.extraupdate)
1940 if (gl_support_fragment_shader)
1941 qglUseProgramObjectARB(0);
1945 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
1948 float *v, *c, f1, f2, diff[3], vertex3f[8*3], color4f[8*4];
1950 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1951 GL_DepthMask(false);
1953 R_Mesh_Matrix(&identitymatrix);
1955 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2];
1956 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
1957 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
1958 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
1959 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
1960 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
1961 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
1962 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
1963 R_FillColors(color, 8, cr, cg, cb, ca);
1966 for (i = 0, v = vertex, c = color;i < 8;i++, v += 4, c += 4)
1968 f2 = VERTEXFOGTABLE(VectorDistance(v, r_vieworigin));
1970 c[0] = c[0] * f1 + fogcolor[0] * f2;
1971 c[1] = c[1] * f1 + fogcolor[1] * f2;
1972 c[2] = c[2] * f1 + fogcolor[2] * f2;
1975 memset(&m, 0, sizeof(m));
1976 m.pointer_vertex = vertex3f;
1977 m.pointer_color = color;
1983 int nomodelelements[24] =
1995 float nomodelvertex3f[6*3] =
2005 float nomodelcolor4f[6*4] =
2007 0.0f, 0.0f, 0.5f, 1.0f,
2008 0.0f, 0.0f, 0.5f, 1.0f,
2009 0.0f, 0.5f, 0.0f, 1.0f,
2010 0.0f, 0.5f, 0.0f, 1.0f,
2011 0.5f, 0.0f, 0.0f, 1.0f,
2012 0.5f, 0.0f, 0.0f, 1.0f
2015 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight)
2021 R_Mesh_Matrix(&ent->matrix);
2023 memset(&m, 0, sizeof(m));
2024 m.pointer_vertex = nomodelvertex3f;
2026 if (ent->flags & EF_ADDITIVE)
2028 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2029 GL_DepthMask(false);
2031 else if (ent->alpha < 1)
2033 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2034 GL_DepthMask(false);
2038 GL_BlendFunc(GL_ONE, GL_ZERO);
2041 GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
2044 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
2045 m.pointer_color = color4f;
2046 f2 = VERTEXFOGTABLE(VectorDistance(ent->origin, r_vieworigin));
2048 for (i = 0, c = color4f;i < 6;i++, c += 4)
2050 c[0] = (c[0] * f1 + fogcolor[0] * f2);
2051 c[1] = (c[1] * f1 + fogcolor[1] * f2);
2052 c[2] = (c[2] * f1 + fogcolor[2] * f2);
2056 else if (ent->alpha != 1)
2058 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
2059 m.pointer_color = color4f;
2060 for (i = 0, c = color4f;i < 6;i++, c += 4)
2064 m.pointer_color = nomodelcolor4f;
2066 R_Mesh_Draw(0, 6, 8, nomodelelements);
2069 void R_DrawNoModel(entity_render_t *ent)
2071 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
2072 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_vieworigin : ent->origin, R_DrawNoModel_TransparentCallback, ent, 0, r_shadow_rtlight);
2074 // R_DrawNoModelCallback(ent, 0);
2077 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
2079 vec3_t right1, right2, diff, normal;
2081 VectorSubtract (org2, org1, normal);
2083 // calculate 'right' vector for start
2084 VectorSubtract (r_vieworigin, org1, diff);
2085 CrossProduct (normal, diff, right1);
2086 VectorNormalize (right1);
2088 // calculate 'right' vector for end
2089 VectorSubtract (r_vieworigin, org2, diff);
2090 CrossProduct (normal, diff, right2);
2091 VectorNormalize (right2);
2093 vert[ 0] = org1[0] + width * right1[0];
2094 vert[ 1] = org1[1] + width * right1[1];
2095 vert[ 2] = org1[2] + width * right1[2];
2096 vert[ 3] = org1[0] - width * right1[0];
2097 vert[ 4] = org1[1] - width * right1[1];
2098 vert[ 5] = org1[2] - width * right1[2];
2099 vert[ 6] = org2[0] - width * right2[0];
2100 vert[ 7] = org2[1] - width * right2[1];
2101 vert[ 8] = org2[2] - width * right2[2];
2102 vert[ 9] = org2[0] + width * right2[0];
2103 vert[10] = org2[1] + width * right2[1];
2104 vert[11] = org2[2] + width * right2[2];
2107 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
2109 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)
2111 float fog = 0.0f, ifog;
2116 fog = VERTEXFOGTABLE(VectorDistance(origin, r_vieworigin));
2119 R_Mesh_Matrix(&identitymatrix);
2120 GL_BlendFunc(blendfunc1, blendfunc2);
2121 GL_DepthMask(false);
2122 GL_DepthTest(!depthdisable);
2124 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
2125 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
2126 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
2127 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
2128 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
2129 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
2130 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
2131 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
2132 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
2133 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
2134 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
2135 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
2137 memset(&m, 0, sizeof(m));
2138 m.tex[0] = R_GetTexture(texture);
2139 m.pointer_texcoord[0] = spritetexcoord2f;
2140 m.pointer_vertex = vertex3f;
2142 GL_Color(cr * ifog, cg * ifog, cb * ifog, ca);
2143 R_Mesh_Draw(0, 4, 2, polygonelements);
2145 if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
2147 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
2148 GL_BlendFunc(blendfunc1, GL_ONE);
2149 GL_Color(fogcolor[0] * fog, fogcolor[1] * fog, fogcolor[2] * fog, ca);
2150 R_Mesh_Draw(0, 4, 2, polygonelements);
2154 int R_Mesh_AddVertex3f(rmesh_t *mesh, const float *v)
2158 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
2159 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
2161 if (i == mesh->numvertices)
2163 if (mesh->numvertices < mesh->maxvertices)
2165 VectorCopy(v, vertex3f);
2166 mesh->numvertices++;
2168 return mesh->numvertices;
2174 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
2178 element[0] = R_Mesh_AddVertex3f(mesh, vertex3f);vertex3f += 3;
2179 element[1] = R_Mesh_AddVertex3f(mesh, vertex3f);vertex3f += 3;
2180 e = mesh->element3i + mesh->numtriangles * 3;
2181 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
2183 element[2] = R_Mesh_AddVertex3f(mesh, vertex3f);
2184 if (mesh->numtriangles < mesh->maxtriangles)
2189 mesh->numtriangles++;
2191 element[1] = element[2];
2195 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
2197 int planenum, planenum2;
2200 mplane_t *plane, *plane2;
2201 float temppoints[2][256*3];
2202 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
2206 PolygonF_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->normal[3], 1024.0*1024.0*1024.0);
2207 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
2209 if (planenum2 == planenum)
2211 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);
2214 if (tempnumpoints < 3)
2216 // generate elements forming a triangle fan for this polygon
2217 R_Mesh_AddPolygon3f(mesh, tempnumpoints, temppoints[w]);
2221 static void R_DrawCollisionBrush(colbrushf_t *brush)
2225 memset(&m, 0, sizeof(m));
2226 m.pointer_vertex = brush->points->v;
2228 i = (int)(((size_t)brush) / sizeof(colbrushf_t));
2229 GL_Color((i & 31) * (1.0f / 32.0f), ((i >> 5) & 31) * (1.0f / 32.0f), ((i >> 10) & 31) * (1.0f / 32.0f), 0.2f);
2230 GL_LockArrays(0, brush->numpoints);
2231 R_Mesh_Draw(0, brush->numpoints, brush->numtriangles, brush->elements);
2232 GL_LockArrays(0, 0);
2235 static void R_DrawCollisionSurface(entity_render_t *ent, msurface_t *surface)
2239 if (!surface->num_collisiontriangles)
2241 memset(&m, 0, sizeof(m));
2242 m.pointer_vertex = surface->data_collisionvertex3f;
2244 i = (int)(((size_t)surface) / sizeof(msurface_t));
2245 GL_Color((i & 31) * (1.0f / 32.0f), ((i >> 5) & 31) * (1.0f / 32.0f), ((i >> 10) & 31) * (1.0f / 32.0f), 0.2f);
2246 GL_LockArrays(0, surface->num_collisionvertices);
2247 R_Mesh_Draw(0, surface->num_collisionvertices, surface->num_collisiontriangles, surface->data_collisionelement3i);
2248 GL_LockArrays(0, 0);
2251 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)
2253 texturelayer_t *layer;
2254 layer = t->currentlayers + t->currentnumlayers++;
2256 layer->depthmask = depthmask;
2257 layer->blendfunc1 = blendfunc1;
2258 layer->blendfunc2 = blendfunc2;
2259 layer->texture = texture;
2260 layer->texmatrix = *matrix;
2261 layer->color[0] = r;
2262 layer->color[1] = g;
2263 layer->color[2] = b;
2264 layer->color[3] = a;
2267 void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
2269 // FIXME: identify models using a better check than ent->model->brush.shadowmesh
2270 //int lightmode = ((ent->effects & EF_FULLBRIGHT) || ent->model->brush.shadowmesh) ? 0 : 2;
2273 texture_t *texture = t;
2274 model_t *model = ent->model;
2275 int s = ent->skinnum;
2276 if ((unsigned int)s >= (unsigned int)model->numskins)
2278 if (model->skinscenes)
2280 if (model->skinscenes[s].framecount > 1)
2281 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
2283 s = model->skinscenes[s].firstframe;
2286 t = t + s * model->num_surfaces;
2288 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];
2289 texture->currentframe = t;
2292 t->currentmaterialflags = t->basematerialflags;
2293 t->currentalpha = ent->alpha;
2294 if (t->basematerialflags & MATERIALFLAG_WATERALPHA)
2295 t->currentalpha *= r_wateralpha.value;
2296 if (!(ent->flags & RENDER_LIGHT))
2297 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
2298 if (ent->effects & EF_ADDITIVE)
2299 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_TRANSPARENT;
2300 else if (t->currentalpha < 1)
2301 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_TRANSPARENT;
2302 if (ent->effects & EF_NODEPTHTEST)
2303 t->currentmaterialflags |= MATERIALFLAG_NODEPTHTEST;
2304 if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
2305 t->currenttexmatrix = r_waterscrollmatrix;
2307 t->currenttexmatrix = identitymatrix;
2309 t->colormapping = VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f);
2310 t->basetexture = (!t->colormapping && t->skin.merged) ? t->skin.merged : t->skin.base;
2311 t->glosstexture = r_texture_white;
2312 t->specularpower = 8;
2313 t->specularscale = 0;
2314 if (r_shadow_gloss.integer > 0)
2318 if (r_shadow_glossintensity.value > 0)
2320 t->glosstexture = t->skin.gloss;
2321 t->specularscale = r_shadow_glossintensity.value;
2324 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
2325 t->specularscale = r_shadow_gloss2intensity.value;
2328 t->currentnumlayers = 0;
2329 if (!(t->currentmaterialflags & MATERIALFLAG_NODRAW))
2331 if (gl_lightmaps.integer)
2332 R_Texture_AddLayer(t, true, GL_ONE, GL_ZERO, TEXTURELAYERTYPE_LITTEXTURE_MULTIPASS, r_texture_white, &identitymatrix, 1, 1, 1, 1);
2333 else if (!(t->currentmaterialflags & MATERIALFLAG_SKY))
2335 int blendfunc1, blendfunc2, depthmask;
2336 if (t->currentmaterialflags & MATERIALFLAG_ADD)
2338 blendfunc1 = GL_SRC_ALPHA;
2339 blendfunc2 = GL_ONE;
2342 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
2344 blendfunc1 = GL_SRC_ALPHA;
2345 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
2350 blendfunc1 = GL_ONE;
2351 blendfunc2 = GL_ZERO;
2354 if (t->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL))
2356 rtexture_t *currentbasetexture;
2358 if (fogenabled && (t->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
2359 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
2360 currentbasetexture = (VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) < (1.0f / 1048576.0f) && t->skin.merged) ? t->skin.merged : t->skin.base;
2361 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2363 // fullbright is not affected by r_lightmapintensity
2364 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
2365 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->skin.pants)
2366 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);
2367 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->skin.shirt)
2368 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);
2374 // q3bsp has no lightmap updates, so the lightstylevalue that
2375 // would normally be baked into the lightmaptexture must be
2376 // applied to the color
2377 if (ent->model->type == mod_brushq3)
2378 colorscale *= r_refdef.lightstylevalue[0] * (1.0f / 256.0f);
2379 colorscale *= r_lightmapintensity;
2380 if (r_textureunits.integer >= 2 && gl_combine.integer)
2381 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_LITTEXTURE_COMBINE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0] * colorscale, ent->colormod[1] * colorscale, ent->colormod[2] * colorscale, t->currentalpha);
2382 else if ((t->currentmaterialflags & MATERIALFLAG_TRANSPARENT) == 0)
2383 R_Texture_AddLayer(t, true, GL_ONE, GL_ZERO, TEXTURELAYERTYPE_LITTEXTURE_MULTIPASS, currentbasetexture, &t->currenttexmatrix, ent->colormod[0] * colorscale * 0.5f, ent->colormod[1] * colorscale * 0.5f, ent->colormod[2] * colorscale * 0.5f, t->currentalpha);
2385 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_LITTEXTURE_VERTEX, currentbasetexture, &t->currenttexmatrix, ent->colormod[0] * colorscale, ent->colormod[1] * colorscale, ent->colormod[2] * colorscale, t->currentalpha);
2386 if (r_ambient.value >= (1.0f/64.0f))
2387 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);
2388 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->skin.pants)
2390 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE_VERTEX, t->skin.pants, &t->currenttexmatrix, ent->colormap_pantscolor[0] * ent->colormod[0] * colorscale, ent->colormap_pantscolor[1] * ent->colormod[1] * colorscale, ent->colormap_pantscolor[2] * ent->colormod[2] * colorscale, t->currentalpha);
2391 if (r_ambient.value >= (1.0f/64.0f))
2392 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);
2394 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->skin.shirt)
2396 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE_VERTEX, t->skin.shirt, &t->currenttexmatrix, ent->colormap_shirtcolor[0] * ent->colormod[0] * colorscale, ent->colormap_shirtcolor[1] * ent->colormod[1] * colorscale, ent->colormap_shirtcolor[2] * ent->colormod[2] * colorscale, t->currentalpha);
2397 if (r_ambient.value >= (1.0f/64.0f))
2398 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);
2401 if (t->skin.glow != NULL)
2402 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.glow, &t->currenttexmatrix, 1, 1, 1, t->currentalpha);
2403 if (fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
2405 // if this is opaque use alpha blend which will darken the earlier
2408 // if this is an alpha blended material, all the earlier passes
2409 // were darkened by fog already, so we only need to add the fog
2410 // color ontop through the fog mask texture
2412 // if this is an additive blended material, all the earlier passes
2413 // were darkened by fog already, and we should not add fog color
2414 // (because the background was not darkened, there is no fog color
2415 // that was lost behind it).
2416 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, (t->currentmaterialflags & MATERIALFLAG_TRANSPARENT) ? GL_ONE : GL_ONE_MINUS_SRC_ALPHA, TEXTURELAYERTYPE_FOG, t->skin.fog, &identitymatrix, fogcolor[0], fogcolor[1], fogcolor[2], t->currentalpha);
2423 void R_UpdateAllTextureInfo(entity_render_t *ent)
2427 for (i = 0;i < ent->model->num_textures;i++)
2428 R_UpdateTextureInfo(ent, ent->model->data_textures + i);
2431 int rsurface_array_size = 0;
2432 float *rsurface_array_vertex3f = NULL;
2433 float *rsurface_array_svector3f = NULL;
2434 float *rsurface_array_tvector3f = NULL;
2435 float *rsurface_array_normal3f = NULL;
2436 float *rsurface_array_color4f = NULL;
2437 float *rsurface_array_texcoord3f = NULL;
2439 void R_Mesh_ResizeArrays(int newvertices)
2441 if (rsurface_array_size >= newvertices)
2443 if (rsurface_array_vertex3f)
2444 Mem_Free(rsurface_array_vertex3f);
2445 rsurface_array_size = (newvertices + 1023) & ~1023;
2446 rsurface_array_vertex3f = (float *)Mem_Alloc(r_main_mempool, rsurface_array_size * sizeof(float[19]));
2447 rsurface_array_svector3f = rsurface_array_vertex3f + rsurface_array_size * 3;
2448 rsurface_array_tvector3f = rsurface_array_vertex3f + rsurface_array_size * 6;
2449 rsurface_array_normal3f = rsurface_array_vertex3f + rsurface_array_size * 9;
2450 rsurface_array_color4f = rsurface_array_vertex3f + rsurface_array_size * 12;
2451 rsurface_array_texcoord3f = rsurface_array_vertex3f + rsurface_array_size * 16;
2454 float *rsurface_vertex3f;
2455 float *rsurface_svector3f;
2456 float *rsurface_tvector3f;
2457 float *rsurface_normal3f;
2458 float *rsurface_lightmapcolor4f;
2459 vec3_t rsurface_modelorg;
2460 const entity_render_t *rsurface_entity;
2461 const model_t *rsurface_model;
2462 const texture_t *rsurface_texture;
2464 void RSurf_PrepareVerticesForBatch(const entity_render_t *ent, const texture_t *texture, const vec3_t modelorg, qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, msurface_t **texturesurfacelist)
2466 VectorCopy(modelorg, rsurface_modelorg);
2467 rsurface_entity = ent;
2468 rsurface_model = ent->model;
2469 rsurface_texture = texture;
2470 if (rsurface_array_size < rsurface_model->surfmesh.num_vertices)
2471 R_Mesh_ResizeArrays(rsurface_model->surfmesh.num_vertices);
2472 if ((rsurface_entity->frameblend[0].lerp != 1 || rsurface_entity->frameblend[0].frame != 0) && (rsurface_model->surfmesh.data_morphvertex3f || rsurface_model->surfmesh.data_vertexboneweights))
2474 rsurface_vertex3f = rsurface_array_vertex3f;
2475 Mod_Alias_GetMesh_Vertex3f(rsurface_model, rsurface_entity->frameblend, rsurface_array_vertex3f);
2476 if (generatetangents || (rsurface_texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2)))
2478 rsurface_svector3f = rsurface_array_svector3f;
2479 rsurface_tvector3f = rsurface_array_tvector3f;
2480 rsurface_normal3f = rsurface_array_normal3f;
2481 Mod_BuildTextureVectorsAndNormals(0, rsurface_model->surfmesh.num_vertices, rsurface_model->surfmesh.num_triangles, rsurface_array_vertex3f, rsurface_model->surfmesh.data_texcoordtexture2f, rsurface_model->surfmesh.data_element3i, rsurface_array_svector3f, rsurface_array_tvector3f, rsurface_array_normal3f, r_smoothnormals_areaweighting.integer);
2485 rsurface_svector3f = NULL;
2486 rsurface_tvector3f = NULL;
2487 if (generatenormals)
2489 rsurface_normal3f = rsurface_array_normal3f;
2490 Mod_BuildNormals(0, rsurface_model->surfmesh.num_vertices, rsurface_model->surfmesh.num_triangles, rsurface_array_vertex3f, rsurface_model->surfmesh.data_element3i, rsurface_array_normal3f, r_smoothnormals_areaweighting.integer);
2493 rsurface_normal3f = NULL;
2498 rsurface_vertex3f = rsurface_model->surfmesh.data_vertex3f;
2499 rsurface_svector3f = rsurface_model->surfmesh.data_svector3f;
2500 rsurface_tvector3f = rsurface_model->surfmesh.data_tvector3f;
2501 rsurface_normal3f = rsurface_model->surfmesh.data_normal3f;
2503 if (rsurface_texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
2505 int texturesurfaceindex;
2506 float center[3], forward[3], right[3], up[3], v[4][3];
2507 matrix4x4_t matrix1, imatrix1;
2508 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_viewforward, forward);
2509 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_viewright, right);
2510 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_viewup, up);
2511 if (rsurface_texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE2)
2513 forward[0] = rsurface_modelorg[0] - center[0];
2514 forward[1] = rsurface_modelorg[1] - center[1];
2516 VectorNormalize(forward);
2517 right[0] = forward[1];
2518 right[1] = -forward[0];
2520 VectorSet(up, 0, 0, 1);
2522 // make deformed versions of only the vertices used by the specified surfaces
2523 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2526 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2527 // a single autosprite surface can contain multiple sprites...
2528 for (j = 0;j < surface->num_vertices - 3;j += 4)
2530 VectorClear(center);
2531 for (i = 0;i < 4;i++)
2532 VectorAdd(center, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
2533 VectorScale(center, 0.25f, center);
2534 // FIXME: calculate vectors from triangle edges instead of using texture vectors as an easy way out?
2535 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);
2536 Matrix4x4_Invert_Simple(&imatrix1, &matrix1);
2537 for (i = 0;i < 4;i++)
2538 Matrix4x4_Transform(&imatrix1, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, v[i]);
2539 for (i = 0;i < 4;i++)
2540 VectorMAMAMAM(1, center, v[i][0], forward, v[i][1], right, v[i][2], up, rsurface_array_vertex3f + (surface->num_firstvertex+i+j) * 3);
2542 Mod_BuildTextureVectorsAndNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface_array_vertex3f, rsurface_model->surfmesh.data_texcoordtexture2f, rsurface_model->surfmesh.data_element3i + surface->num_firsttriangle * 3, rsurface_array_svector3f, rsurface_array_tvector3f, rsurface_array_normal3f, r_smoothnormals_areaweighting.integer);
2544 rsurface_vertex3f = rsurface_array_vertex3f;
2545 rsurface_svector3f = rsurface_array_svector3f;
2546 rsurface_tvector3f = rsurface_array_tvector3f;
2547 rsurface_normal3f = rsurface_array_normal3f;
2549 R_Mesh_VertexPointer(rsurface_vertex3f);
2552 static void RSurf_Draw(const msurface_t *surface)
2554 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2555 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
2556 GL_LockArrays(0, 0);
2559 static void RSurf_DrawLightmap(const msurface_t *surface, float r, float g, float b, float a, int lightmode, qboolean applycolor, qboolean applyfog)
2567 vec3_t ambientcolor;
2568 vec3_t diffusecolor;
2570 VectorCopy(rsurface_entity->modellight_lightdir, lightdir);
2571 ambientcolor[0] = rsurface_entity->modellight_ambient[0] * r * 0.5f;
2572 ambientcolor[1] = rsurface_entity->modellight_ambient[1] * g * 0.5f;
2573 ambientcolor[2] = rsurface_entity->modellight_ambient[2] * b * 0.5f;
2574 diffusecolor[0] = rsurface_entity->modellight_diffuse[0] * r * 0.5f;
2575 diffusecolor[1] = rsurface_entity->modellight_diffuse[1] * g * 0.5f;
2576 diffusecolor[2] = rsurface_entity->modellight_diffuse[2] * b * 0.5f;
2577 if (VectorLength2(diffusecolor) > 0)
2579 int numverts = surface->num_vertices;
2580 v = rsurface_vertex3f + 3 * surface->num_firstvertex;
2581 c2 = rsurface_normal3f + 3 * surface->num_firstvertex;
2582 c = rsurface_array_color4f + 4 * surface->num_firstvertex;
2583 // q3-style directional shading
2584 for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
2586 if ((f = DotProduct(c2, lightdir)) > 0)
2587 VectorMA(ambientcolor, f, diffusecolor, c);
2589 VectorCopy(ambientcolor, c);
2597 rsurface_lightmapcolor4f = rsurface_array_color4f;
2601 r = ambientcolor[0];
2602 g = ambientcolor[1];
2603 b = ambientcolor[2];
2604 rsurface_lightmapcolor4f = NULL;
2607 else if (lightmode >= 1)
2609 if (surface->lightmapinfo && surface->lightmapinfo->stainsamples)
2611 for (i = 0, c = rsurface_array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
2613 if (surface->lightmapinfo->samples)
2615 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface_model->surfmesh.data_lightmapoffsets + surface->num_firstvertex)[i];
2616 float scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
2617 VectorScale(lm, scale, c);
2618 if (surface->lightmapinfo->styles[1] != 255)
2620 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
2622 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
2623 VectorMA(c, scale, lm, c);
2624 if (surface->lightmapinfo->styles[2] != 255)
2627 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
2628 VectorMA(c, scale, lm, c);
2629 if (surface->lightmapinfo->styles[3] != 255)
2632 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
2633 VectorMA(c, scale, lm, c);
2641 rsurface_lightmapcolor4f = rsurface_array_color4f;
2644 rsurface_lightmapcolor4f = rsurface_model->surfmesh.data_lightmapcolor4f;
2647 rsurface_lightmapcolor4f = NULL;
2650 if (rsurface_lightmapcolor4f)
2652 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)
2654 f = 1 - VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
2663 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)
2665 f = 1 - VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
2672 rsurface_lightmapcolor4f = rsurface_array_color4f;
2674 if (applycolor && rsurface_lightmapcolor4f)
2676 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)
2683 rsurface_lightmapcolor4f = rsurface_array_color4f;
2685 R_Mesh_ColorPointer(rsurface_lightmapcolor4f);
2686 GL_Color(r, g, b, a);
2687 RSurf_Draw(surface);
2690 static void R_DrawTextureSurfaceList(const entity_render_t *ent, texture_t *texture, int texturenumsurfaces, msurface_t **texturesurfacelist, const vec3_t modelorg)
2692 int texturesurfaceindex;
2694 const msurface_t *surface;
2695 model_t *model = ent->model;
2696 qboolean applycolor;
2699 if (texture->currentmaterialflags & MATERIALFLAG_NODRAW)
2701 r_shadow_rtlight = NULL;
2702 renderstats.entities_surfaces += texturenumsurfaces;
2703 // FIXME: identify models using a better check than model->brush.shadowmesh
2704 lightmode = ((ent->effects & EF_FULLBRIGHT) || model->brush.shadowmesh) ? 0 : 2;
2705 GL_DepthTest(!(texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
2706 if ((texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (ent->flags & RENDER_NOCULLFACE))
2707 qglDisable(GL_CULL_FACE);
2708 if (r_showsurfaces.integer)
2711 GL_BlendFunc(GL_ONE, GL_ZERO);
2712 memset(&m, 0, sizeof(m));
2714 RSurf_PrepareVerticesForBatch(ent, texture, modelorg, false, false, texturenumsurfaces, texturesurfacelist);
2715 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2717 int k = (int)(((size_t)surface) / sizeof(msurface_t));
2718 GL_Color((k & 15) * (1.0f / 16.0f), ((k >> 4) & 15) * (1.0f / 16.0f), ((k >> 8) & 15) * (1.0f / 16.0f), 0.2f);
2719 surface = texturesurfacelist[texturesurfaceindex];
2720 RSurf_Draw(surface);
2723 else if (texture->currentmaterialflags & MATERIALFLAG_SKY)
2725 // transparent sky would be ridiculous
2726 if (!(texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
2730 skyrendernow = false;
2732 // restore entity matrix
2733 R_Mesh_Matrix(&ent->matrix);
2736 // LordHavoc: HalfLife maps have freaky skypolys so don't use
2737 // skymasking on them, and Quake3 never did sky masking (unlike
2738 // software Quake and software Quake2), so disable the sky masking
2739 // in Quake3 maps as it causes problems with q3map2 sky tricks,
2740 // and skymasking also looks very bad when noclipping outside the
2741 // level, so don't use it then either.
2742 if (model->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_worldnovis)
2744 GL_Color(fogcolor[0], fogcolor[1], fogcolor[2], 1);
2745 memset(&m, 0, sizeof(m));
2747 if (skyrendermasked)
2749 // depth-only (masking)
2750 GL_ColorMask(0,0,0,0);
2751 // just to make sure that braindead drivers don't draw
2752 // anything despite that colormask...
2753 GL_BlendFunc(GL_ZERO, GL_ONE);
2758 GL_BlendFunc(GL_ONE, GL_ZERO);
2760 RSurf_PrepareVerticesForBatch(ent, texture, modelorg, false, false, texturenumsurfaces, texturesurfacelist);
2761 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2763 surface = texturesurfacelist[texturesurfaceindex];
2764 RSurf_Draw(surface);
2766 if (skyrendermasked)
2767 GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
2771 else if (r_glsl.integer && gl_support_fragment_shader)
2773 if (texture->currentmaterialflags & MATERIALFLAG_ADD)
2775 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2776 GL_DepthMask(false);
2778 else if (texture->currentmaterialflags & MATERIALFLAG_ALPHA)
2780 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2781 GL_DepthMask(false);
2785 GL_BlendFunc(GL_ONE, GL_ZERO);
2789 memset(&m, 0, sizeof(m));
2791 GL_Color(ent->colormod[0], ent->colormod[1], ent->colormod[2], texture->currentalpha);
2792 R_SetupSurfaceShader(ent, texture, modelorg, vec3_origin, lightmode == 2);
2793 if (!r_glsl_permutation)
2795 RSurf_PrepareVerticesForBatch(ent, texture, modelorg, true, true, texturenumsurfaces, texturesurfacelist);
2798 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2800 surface = texturesurfacelist[texturesurfaceindex];
2801 R_Mesh_TexCoordPointer(0, 2, model->surfmesh.data_texcoordtexture2f);
2802 R_Mesh_TexCoordPointer(1, 3, rsurface_svector3f);
2803 R_Mesh_TexCoordPointer(2, 3, rsurface_tvector3f);
2804 R_Mesh_TexCoordPointer(3, 3, rsurface_normal3f);
2805 RSurf_Draw(surface);
2810 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2812 surface = texturesurfacelist[texturesurfaceindex];
2813 R_Mesh_TexCoordPointer(0, 2, model->surfmesh.data_texcoordtexture2f);
2814 R_Mesh_TexCoordPointer(1, 3, rsurface_svector3f);
2815 R_Mesh_TexCoordPointer(2, 3, rsurface_tvector3f);
2816 R_Mesh_TexCoordPointer(3, 3, rsurface_normal3f);
2817 R_Mesh_TexCoordPointer(4, 2, model->surfmesh.data_texcoordlightmap2f);
2818 if (surface->lightmaptexture)
2820 R_Mesh_TexBind(7, R_GetTexture(surface->lightmaptexture));
2821 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
2822 R_Mesh_TexBind(8, R_GetTexture(surface->deluxemaptexture));
2823 R_Mesh_ColorPointer(NULL);
2827 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
2828 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
2829 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
2830 R_Mesh_ColorPointer(model->surfmesh.data_lightmapcolor4f);
2832 RSurf_Draw(surface);
2835 qglUseProgramObjectARB(0);
2837 else if (texture->currentnumlayers)
2840 texturelayer_t *layer;
2841 RSurf_PrepareVerticesForBatch(ent, texture, modelorg, true, false, texturenumsurfaces, texturesurfacelist);
2842 for (layerindex = 0, layer = texture->currentlayers;layerindex < texture->currentnumlayers;layerindex++, layer++)
2845 int layertexrgbscale;
2846 GL_DepthMask(layer->depthmask);
2847 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
2848 if ((layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2) && (gl_combine.integer || layer->depthmask))
2850 layertexrgbscale = 4;
2851 VectorScale(layer->color, 0.25f, layercolor);
2853 else if ((layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1) && (gl_combine.integer || layer->depthmask))
2855 layertexrgbscale = 2;
2856 VectorScale(layer->color, 0.5f, layercolor);
2860 layertexrgbscale = 1;
2861 VectorScale(layer->color, 1.0f, layercolor);
2863 layercolor[3] = layer->color[3];
2864 GL_Color(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
2865 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
2866 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
2867 switch (layer->type)
2869 case TEXTURELAYERTYPE_LITTEXTURE_COMBINE:
2870 memset(&m, 0, sizeof(m));
2871 m.tex[1] = R_GetTexture(layer->texture);
2872 m.texmatrix[1] = layer->texmatrix;
2873 m.texrgbscale[1] = layertexrgbscale;
2874 m.pointer_color = rsurface_array_color4f;
2875 m.pointer_vertex = rsurface_vertex3f;
2879 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2881 surface = texturesurfacelist[texturesurfaceindex];
2882 R_Mesh_TexCoordPointer(0, 2, model->surfmesh.data_texcoordlightmap2f);
2883 R_Mesh_TexCoordPointer(1, 2, model->surfmesh.data_texcoordtexture2f);
2884 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2885 RSurf_DrawLightmap(surface, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 2, applycolor, applyfog);
2890 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2892 surface = texturesurfacelist[texturesurfaceindex];
2893 R_Mesh_TexCoordPointer(0, 2, model->surfmesh.data_texcoordlightmap2f);
2894 R_Mesh_TexCoordPointer(1, 2, model->surfmesh.data_texcoordtexture2f);
2895 if (surface->lightmaptexture)
2897 R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
2898 RSurf_DrawLightmap(surface, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, applyfog);
2902 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2903 RSurf_DrawLightmap(surface, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 1, applycolor, applyfog);
2908 case TEXTURELAYERTYPE_LITTEXTURE_MULTIPASS:
2909 memset(&m, 0, sizeof(m));
2910 m.tex[0] = R_GetTexture(layer->texture);
2911 m.texmatrix[0] = layer->texmatrix;
2912 m.pointer_color = rsurface_array_color4f;
2913 m.texrgbscale[0] = layertexrgbscale;
2914 m.pointer_vertex = rsurface_vertex3f;
2918 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2920 surface = texturesurfacelist[texturesurfaceindex];
2921 R_Mesh_TexCoordPointer(0, 2, model->surfmesh.data_texcoordlightmap2f);
2922 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2923 RSurf_DrawLightmap(surface, 1, 1, 1, 1, 2, false, false);
2928 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2930 surface = texturesurfacelist[texturesurfaceindex];
2931 R_Mesh_TexCoordPointer(0, 2, model->surfmesh.data_texcoordlightmap2f);
2932 if (surface->lightmaptexture)
2934 R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
2935 RSurf_DrawLightmap(surface, 1, 1, 1, 1, 0, false, false);
2939 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2940 RSurf_DrawLightmap(surface, 1, 1, 1, 1, 1, false, false);
2944 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
2945 memset(&m, 0, sizeof(m));
2946 m.tex[0] = R_GetTexture(layer->texture);
2947 m.texmatrix[0] = layer->texmatrix;
2948 m.pointer_color = rsurface_array_color4f;
2949 m.texrgbscale[0] = layertexrgbscale;
2950 m.pointer_vertex = rsurface_vertex3f;
2952 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2954 surface = texturesurfacelist[texturesurfaceindex];
2955 R_Mesh_TexCoordPointer(0, 2, model->surfmesh.data_texcoordtexture2f);
2956 RSurf_DrawLightmap(surface, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, false);
2959 case TEXTURELAYERTYPE_LITTEXTURE_VERTEX:
2960 memset(&m, 0, sizeof(m));
2961 m.tex[0] = R_GetTexture(layer->texture);
2962 m.texmatrix[0] = layer->texmatrix;
2963 m.texrgbscale[0] = layertexrgbscale;
2964 m.pointer_color = rsurface_array_color4f;
2965 m.pointer_vertex = rsurface_vertex3f;
2969 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2971 surface = texturesurfacelist[texturesurfaceindex];
2972 R_Mesh_TexCoordPointer(0, 2, model->surfmesh.data_texcoordtexture2f);
2973 RSurf_DrawLightmap(surface, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 2, applycolor, applyfog);
2978 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2980 surface = texturesurfacelist[texturesurfaceindex];
2981 R_Mesh_TexCoordPointer(0, 2, model->surfmesh.data_texcoordtexture2f);
2982 RSurf_DrawLightmap(surface, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 1, applycolor, applyfog);
2986 case TEXTURELAYERTYPE_TEXTURE:
2987 memset(&m, 0, sizeof(m));
2988 m.tex[0] = R_GetTexture(layer->texture);
2989 m.texmatrix[0] = layer->texmatrix;
2990 m.pointer_color = rsurface_array_color4f;
2991 m.texrgbscale[0] = layertexrgbscale;
2992 m.pointer_vertex = rsurface_vertex3f;
2994 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2996 surface = texturesurfacelist[texturesurfaceindex];
2997 R_Mesh_TexCoordPointer(0, 2, model->surfmesh.data_texcoordtexture2f);
2998 RSurf_DrawLightmap(surface, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, applyfog);
3001 case TEXTURELAYERTYPE_FOG:
3002 memset(&m, 0, sizeof(m));
3005 m.tex[0] = R_GetTexture(layer->texture);
3006 m.texmatrix[0] = layer->texmatrix;
3008 m.pointer_vertex = rsurface_vertex3f;
3010 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3014 surface = texturesurfacelist[texturesurfaceindex];
3016 R_Mesh_TexCoordPointer(0, 2, model->surfmesh.data_texcoordtexture2f);
3017 R_Mesh_ColorPointer(rsurface_array_color4f);
3018 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)
3020 f = VERTEXFOGTABLE(VectorDistance(v, modelorg));
3021 c[0] = layercolor[0];
3022 c[1] = layercolor[1];
3023 c[2] = layercolor[2];
3024 c[3] = f * layercolor[3];
3026 RSurf_Draw(surface);
3030 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
3032 // if trying to do overbright on first pass of an opaque surface
3033 // when combine is not supported, brighten as a post process
3034 if (layertexrgbscale > 1 && !gl_combine.integer && layer->depthmask)
3037 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
3038 GL_Color(1, 1, 1, 1);
3039 memset(&m, 0, sizeof(m));
3040 m.pointer_vertex = rsurface_vertex3f;
3042 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3044 surface = texturesurfacelist[texturesurfaceindex];
3045 for (scale = 1;scale < layertexrgbscale;scale <<= 1)
3046 RSurf_Draw(surface);
3051 if ((texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (ent->flags & RENDER_NOCULLFACE))
3052 qglEnable(GL_CULL_FACE);
3055 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight)
3057 msurface_t *surface = ent->model->data_surfaces + surfacenumber;
3061 texture = surface->texture;
3062 if (texture->basematerialflags & MATERIALFLAG_SKY)
3063 return; // transparent sky is too difficult
3064 R_UpdateTextureInfo(ent, texture);
3066 R_Mesh_Matrix(&ent->matrix);
3067 Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
3068 R_DrawTextureSurfaceList(ent, texture->currentframe, 1, &surface, modelorg);
3071 void R_QueueTextureSurfaceList(entity_render_t *ent, texture_t *texture, int texturenumsurfaces, msurface_t **texturesurfacelist, const vec3_t modelorg)
3073 int texturesurfaceindex;
3074 const msurface_t *surface;
3075 vec3_t tempcenter, center;
3076 if (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT)
3078 // drawing sky transparently would be too difficult
3079 if (!(texture->currentmaterialflags & MATERIALFLAG_SKY))
3081 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3083 surface = texturesurfacelist[texturesurfaceindex];
3084 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
3085 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
3086 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
3087 Matrix4x4_Transform(&ent->matrix, tempcenter, center);
3088 R_MeshQueue_AddTransparent(texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_vieworigin : center, R_DrawSurface_TransparentCallback, ent, surface - ent->model->data_surfaces, r_shadow_rtlight);
3093 R_DrawTextureSurfaceList(ent, texture, texturenumsurfaces, texturesurfacelist, modelorg);
3096 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
3097 void R_DrawSurfaces(entity_render_t *ent, qboolean skysurfaces)
3099 int i, j, f, flagsmask;
3100 int counttriangles = 0;
3101 msurface_t *surface, **surfacechain;
3102 texture_t *t, *texture;
3103 model_t *model = ent->model;
3105 const int maxsurfacelist = 1024;
3106 int numsurfacelist = 0;
3107 msurface_t *surfacelist[1024];
3110 R_Mesh_Matrix(&ent->matrix);
3111 Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
3113 // update light styles
3114 if (!skysurfaces && model->brushq1.light_styleupdatechains)
3116 for (i = 0;i < model->brushq1.light_styles;i++)
3118 if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
3120 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
3121 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
3122 for (;(surface = *surfacechain);surfacechain++)
3123 surface->cached_dlight = true;
3128 R_UpdateAllTextureInfo(ent);
3129 flagsmask = skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL);
3134 if (ent == r_refdef.worldentity)
3136 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
3138 if (!r_worldsurfacevisible[j])
3140 if (t != surface->texture)
3144 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
3147 t = surface->texture;
3148 texture = t->currentframe;
3149 f = texture->currentmaterialflags & flagsmask;
3151 if (f && surface->num_triangles)
3153 // if lightmap parameters changed, rebuild lightmap texture
3154 if (surface->cached_dlight)
3155 R_BuildLightMap(ent, surface);
3156 // add face to draw list
3157 surfacelist[numsurfacelist++] = surface;
3158 counttriangles += surface->num_triangles;
3159 if (numsurfacelist >= maxsurfacelist)
3161 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
3169 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
3171 if (t != surface->texture)
3175 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
3178 t = surface->texture;
3179 texture = t->currentframe;
3180 f = texture->currentmaterialflags & flagsmask;
3182 if (f && surface->num_triangles)
3184 // if lightmap parameters changed, rebuild lightmap texture
3185 if (surface->cached_dlight)
3186 R_BuildLightMap(ent, surface);
3187 // add face to draw list
3188 surfacelist[numsurfacelist++] = surface;
3189 counttriangles += surface->num_triangles;
3190 if (numsurfacelist >= maxsurfacelist)
3192 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
3199 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
3200 renderstats.entities_triangles += counttriangles;
3201 if (gl_support_fragment_shader)
3202 qglUseProgramObjectARB(0);
3204 if (r_showcollisionbrushes.integer && model->brush.num_brushes && !skysurfaces)
3207 msurface_t *surface;
3209 R_Mesh_Matrix(&ent->matrix);
3210 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
3211 GL_DepthMask(false);
3212 GL_DepthTest(!r_showdisabledepthtest.integer);
3213 qglPolygonOffset(r_polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_polygonoffset + r_showcollisionbrushes_polygonoffset.value);
3214 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
3215 if (brush->colbrushf && brush->colbrushf->numtriangles)
3216 R_DrawCollisionBrush(brush->colbrushf);
3217 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
3218 if (surface->num_collisiontriangles)
3219 R_DrawCollisionSurface(ent, surface);
3220 qglPolygonOffset(r_polygonfactor, r_polygonoffset);
3223 if (r_showtris.integer || r_shownormals.integer)
3226 const int *elements;
3231 if (r_showdisabledepthtest.integer)
3232 qglDepthFunc(GL_ALWAYS);
3233 GL_BlendFunc(GL_ONE, GL_ZERO);
3234 memset(&m, 0, sizeof(m));
3236 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
3238 if (ent == r_refdef.worldentity && !r_worldsurfacevisible[j])
3240 texture = surface->texture->currentframe;
3241 if ((texture->currentmaterialflags & flagsmask) && surface->num_triangles)
3243 RSurf_PrepareVerticesForBatch(ent, texture, modelorg, false, r_shownormals.integer != 0, 1, &surface);
3244 if (r_showtris.integer)
3246 if (!texture->currentlayers->depthmask)
3247 GL_Color(r_showtris.value, 0, 0, 1);
3248 else if (ent == r_refdef.worldentity)
3249 GL_Color(r_showtris.value, r_showtris.value, r_showtris.value, 1);
3251 GL_Color(0, r_showtris.value, 0, 1);
3252 elements = (ent->model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
3254 for (k = 0;k < surface->num_triangles;k++, elements += 3)
3256 qglArrayElement(elements[0]);qglArrayElement(elements[1]);
3257 qglArrayElement(elements[1]);qglArrayElement(elements[2]);
3258 qglArrayElement(elements[2]);qglArrayElement(elements[0]);
3262 if (r_shownormals.integer)
3264 GL_Color(r_shownormals.value, 0, 0, 1);
3266 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
3268 VectorCopy(rsurface_vertex3f + l * 3, v);
3269 qglVertex3f(v[0], v[1], v[2]);
3270 VectorMA(v, 8, rsurface_svector3f + l * 3, v);
3271 qglVertex3f(v[0], v[1], v[2]);
3274 GL_Color(0, 0, r_shownormals.value, 1);
3276 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
3278 VectorCopy(rsurface_vertex3f + l * 3, v);
3279 qglVertex3f(v[0], v[1], v[2]);
3280 VectorMA(v, 8, rsurface_tvector3f + l * 3, v);
3281 qglVertex3f(v[0], v[1], v[2]);
3284 GL_Color(0, r_shownormals.value, 0, 1);
3286 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
3288 VectorCopy(rsurface_vertex3f + l * 3, v);
3289 qglVertex3f(v[0], v[1], v[2]);
3290 VectorMA(v, 8, rsurface_normal3f + l * 3, v);
3291 qglVertex3f(v[0], v[1], v[2]);
3297 if (r_showdisabledepthtest.integer)
3298 qglDepthFunc(GL_LEQUAL);