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 qboolean rsurface_generatevertex;
2460 qboolean rsurface_generatetangents;
2461 qboolean rsurface_generatenormals;
2462 qboolean rsurface_deformvertex;
2463 qboolean rsurface_dynamicvertex;
2464 vec3_t rsurface_modelorg;
2465 const entity_render_t *rsurface_entity;
2466 const model_t *rsurface_model;
2467 const texture_t *rsurface_texture;
2469 void RSurf_PrepareForBatch(const entity_render_t *ent, const texture_t *texture, const vec3_t modelorg)
2471 VectorCopy(modelorg, rsurface_modelorg);
2472 rsurface_entity = ent;
2473 rsurface_model = ent->model;
2474 rsurface_texture = texture;
2477 void RSurf_SetPointersForPass(qboolean generatenormals, qboolean generatetangents)
2479 if (rsurface_array_size < rsurface_model->surfmesh.num_vertices)
2480 R_Mesh_ResizeArrays(rsurface_model->surfmesh.num_vertices);
2481 if ((rsurface_entity->frameblend[0].lerp != 1 || rsurface_entity->frameblend[0].frame != 0) && (rsurface_model->surfmesh.data_morphvertex3f || rsurface_model->surfmesh.data_vertexboneweights))
2483 rsurface_generatevertex = true;
2484 rsurface_generatetangents = false;
2485 rsurface_generatenormals = false;
2486 rsurface_vertex3f = rsurface_array_vertex3f;
2487 if (generatetangents || (rsurface_texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2)))
2489 rsurface_generatetangents = true;
2490 rsurface_svector3f = rsurface_array_svector3f;
2491 rsurface_tvector3f = rsurface_array_tvector3f;
2492 rsurface_normal3f = rsurface_array_normal3f;
2496 rsurface_svector3f = NULL;
2497 rsurface_tvector3f = NULL;
2498 if (generatenormals)
2500 rsurface_generatenormals = true;
2501 rsurface_normal3f = rsurface_array_normal3f;
2504 rsurface_normal3f = NULL;
2509 rsurface_generatevertex = false;
2510 rsurface_generatetangents = false;
2511 rsurface_generatenormals = false;
2512 rsurface_vertex3f = rsurface_model->surfmesh.data_vertex3f;
2513 rsurface_svector3f = rsurface_model->surfmesh.data_svector3f;
2514 rsurface_tvector3f = rsurface_model->surfmesh.data_tvector3f;
2515 rsurface_normal3f = rsurface_model->surfmesh.data_normal3f;
2517 if (rsurface_texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
2519 rsurface_deformvertex = true;
2520 rsurface_vertex3f = rsurface_array_vertex3f;
2521 rsurface_svector3f = rsurface_array_svector3f;
2522 rsurface_tvector3f = rsurface_array_tvector3f;
2523 rsurface_normal3f = rsurface_array_normal3f;
2526 rsurface_deformvertex = false;
2527 R_Mesh_VertexPointer(rsurface_vertex3f);
2528 rsurface_dynamicvertex = rsurface_generatevertex || rsurface_deformvertex;
2531 void RSurf_PrepareDynamicSurfaceVertices(const msurface_t *surface)
2533 float *vertex3f, *svector3f, *tvector3f, *normal3f;
2534 model_t *model = rsurface_entity->model;
2535 if (!rsurface_dynamicvertex)
2537 if (rsurface_generatevertex)
2539 Mod_Alias_GetMesh_Vertex3f(model, rsurface_entity->frameblend, rsurface_array_vertex3f);
2540 if (rsurface_generatetangents)
2541 Mod_BuildTextureVectorsAndNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface_vertex3f, model->surfmesh.data_texcoordtexture2f, model->surfmesh.data_element3i + surface->num_firsttriangle * 3, rsurface_array_svector3f, rsurface_array_tvector3f, rsurface_array_normal3f, r_smoothnormals_areaweighting.integer);
2542 else if (rsurface_generatenormals)
2543 Mod_BuildNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface_array_vertex3f, model->surfmesh.data_element3i + 3 * surface->num_firsttriangle, rsurface_array_normal3f, r_smoothnormals_areaweighting.integer);
2545 if (rsurface_deformvertex)
2548 float center[3], forward[3], right[3], up[3], v[4][3];
2549 matrix4x4_t matrix1, imatrix1;
2550 if (rsurface_generatevertex)
2552 vertex3f = rsurface_array_vertex3f;
2553 svector3f = rsurface_array_svector3f;
2554 tvector3f = rsurface_array_tvector3f;
2555 normal3f = rsurface_array_normal3f;
2559 vertex3f = rsurface_vertex3f;
2560 svector3f = rsurface_svector3f;
2561 tvector3f = rsurface_tvector3f;
2562 normal3f = rsurface_normal3f;
2564 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_viewforward, forward);
2565 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_viewright, right);
2566 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_viewup, up);
2567 // a single autosprite surface can contain multiple sprites...
2568 for (j = 0;j < surface->num_vertices - 3;j += 4)
2570 VectorClear(center);
2571 for (i = 0;i < 4;i++)
2572 VectorAdd(center, (vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
2573 VectorScale(center, 0.25f, center);
2574 // FIXME: calculate vectors from triangle edges instead of using texture vectors as an easy way out?
2575 Matrix4x4_FromVectors(&matrix1, (normal3f + 3 * surface->num_firstvertex) + j*3, (svector3f + 3 * surface->num_firstvertex) + j*3, (tvector3f + 3 * surface->num_firstvertex) + j*3, center);
2576 Matrix4x4_Invert_Simple(&imatrix1, &matrix1);
2577 for (i = 0;i < 4;i++)
2578 Matrix4x4_Transform(&imatrix1, (vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, v[i]);
2579 if (rsurface_texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE2)
2581 forward[0] = rsurface_modelorg[0] - center[0];
2582 forward[1] = rsurface_modelorg[1] - center[1];
2584 VectorNormalize(forward);
2585 right[0] = forward[1];
2586 right[1] = -forward[0];
2588 VectorSet(up, 0, 0, 1);
2590 for (i = 0;i < 4;i++)
2591 VectorMAMAMAM(1, center, v[i][0], forward, v[i][1], right, v[i][2], up, rsurface_array_vertex3f + (surface->num_firstvertex+i+j) * 3);
2593 Mod_BuildTextureVectorsAndNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface_array_vertex3f, model->surfmesh.data_texcoordtexture2f, model->surfmesh.data_element3i + surface->num_firsttriangle * 3, rsurface_array_svector3f, rsurface_array_tvector3f, rsurface_array_normal3f, r_smoothnormals_areaweighting.integer);
2597 static void RSurf_Draw(const msurface_t *surface)
2599 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2600 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
2601 GL_LockArrays(0, 0);
2604 static void RSurf_DrawLightmap(const msurface_t *surface, float r, float g, float b, float a, int lightmode, qboolean applycolor, qboolean applyfog)
2612 vec3_t ambientcolor;
2613 vec3_t diffusecolor;
2615 VectorCopy(rsurface_entity->modellight_lightdir, lightdir);
2616 ambientcolor[0] = rsurface_entity->modellight_ambient[0] * r * 0.5f;
2617 ambientcolor[1] = rsurface_entity->modellight_ambient[1] * g * 0.5f;
2618 ambientcolor[2] = rsurface_entity->modellight_ambient[2] * b * 0.5f;
2619 diffusecolor[0] = rsurface_entity->modellight_diffuse[0] * r * 0.5f;
2620 diffusecolor[1] = rsurface_entity->modellight_diffuse[1] * g * 0.5f;
2621 diffusecolor[2] = rsurface_entity->modellight_diffuse[2] * b * 0.5f;
2622 if (VectorLength2(diffusecolor) > 0)
2624 int numverts = surface->num_vertices;
2625 v = rsurface_vertex3f + 3 * surface->num_firstvertex;
2626 c2 = rsurface_normal3f + 3 * surface->num_firstvertex;
2627 c = rsurface_array_color4f + 4 * surface->num_firstvertex;
2628 // q3-style directional shading
2629 for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
2631 if ((f = DotProduct(c2, lightdir)) > 0)
2632 VectorMA(ambientcolor, f, diffusecolor, c);
2634 VectorCopy(ambientcolor, c);
2642 rsurface_lightmapcolor4f = rsurface_array_color4f;
2646 r = ambientcolor[0];
2647 g = ambientcolor[1];
2648 b = ambientcolor[2];
2649 rsurface_lightmapcolor4f = NULL;
2652 else if (lightmode >= 1)
2654 if (surface->lightmapinfo && surface->lightmapinfo->stainsamples)
2656 for (i = 0, c = rsurface_array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
2658 if (surface->lightmapinfo->samples)
2660 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface_model->surfmesh.data_lightmapoffsets + surface->num_firstvertex)[i];
2661 float scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
2662 VectorScale(lm, scale, c);
2663 if (surface->lightmapinfo->styles[1] != 255)
2665 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
2667 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
2668 VectorMA(c, scale, lm, c);
2669 if (surface->lightmapinfo->styles[2] != 255)
2672 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
2673 VectorMA(c, scale, lm, c);
2674 if (surface->lightmapinfo->styles[3] != 255)
2677 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
2678 VectorMA(c, scale, lm, c);
2686 rsurface_lightmapcolor4f = rsurface_array_color4f;
2689 rsurface_lightmapcolor4f = rsurface_model->surfmesh.data_lightmapcolor4f;
2692 rsurface_lightmapcolor4f = NULL;
2695 if (rsurface_lightmapcolor4f)
2697 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)
2699 f = 1 - VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
2708 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)
2710 f = 1 - VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
2717 rsurface_lightmapcolor4f = rsurface_array_color4f;
2719 if (applycolor && rsurface_lightmapcolor4f)
2721 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)
2728 rsurface_lightmapcolor4f = rsurface_array_color4f;
2730 R_Mesh_ColorPointer(rsurface_lightmapcolor4f);
2731 GL_Color(r, g, b, a);
2732 RSurf_Draw(surface);
2735 static void R_DrawTextureSurfaceList(const entity_render_t *ent, texture_t *texture, int texturenumsurfaces, const msurface_t **texturesurfacelist, const vec3_t modelorg)
2737 int texturesurfaceindex;
2739 const msurface_t *surface;
2740 model_t *model = ent->model;
2741 qboolean applycolor;
2744 if (texture->currentmaterialflags & MATERIALFLAG_NODRAW)
2746 r_shadow_rtlight = NULL;
2747 renderstats.entities_surfaces += texturenumsurfaces;
2748 // FIXME: identify models using a better check than model->brush.shadowmesh
2749 lightmode = ((ent->effects & EF_FULLBRIGHT) || model->brush.shadowmesh) ? 0 : 2;
2750 GL_DepthTest(!(texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
2751 if ((texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (ent->flags & RENDER_NOCULLFACE))
2752 qglDisable(GL_CULL_FACE);
2753 RSurf_PrepareForBatch(ent, texture, modelorg);
2754 if (texture->currentmaterialflags & MATERIALFLAG_SKY)
2756 // transparent sky would be ridiculous
2757 if (!(texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
2761 skyrendernow = false;
2763 // restore entity matrix
2764 R_Mesh_Matrix(&ent->matrix);
2767 // LordHavoc: HalfLife maps have freaky skypolys so don't use
2768 // skymasking on them, and Quake3 never did sky masking (unlike
2769 // software Quake and software Quake2), so disable the sky masking
2770 // in Quake3 maps as it causes problems with q3map2 sky tricks,
2771 // and skymasking also looks very bad when noclipping outside the
2772 // level, so don't use it then either.
2773 if (model->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_worldnovis)
2775 GL_Color(fogcolor[0], fogcolor[1], fogcolor[2], 1);
2776 memset(&m, 0, sizeof(m));
2778 if (skyrendermasked)
2780 // depth-only (masking)
2781 GL_ColorMask(0,0,0,0);
2782 // just to make sure that braindead drivers don't draw
2783 // anything despite that colormask...
2784 GL_BlendFunc(GL_ZERO, GL_ONE);
2789 GL_BlendFunc(GL_ONE, GL_ZERO);
2791 RSurf_SetPointersForPass(false, false);
2792 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2794 surface = texturesurfacelist[texturesurfaceindex];
2795 if (rsurface_dynamicvertex)
2796 RSurf_PrepareDynamicSurfaceVertices(surface);
2797 RSurf_Draw(surface);
2799 if (skyrendermasked)
2800 GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
2804 else if (r_glsl.integer && gl_support_fragment_shader)
2806 if (texture->currentmaterialflags & MATERIALFLAG_ADD)
2808 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2809 GL_DepthMask(false);
2811 else if (texture->currentmaterialflags & MATERIALFLAG_ALPHA)
2813 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2814 GL_DepthMask(false);
2818 GL_BlendFunc(GL_ONE, GL_ZERO);
2822 memset(&m, 0, sizeof(m));
2824 GL_Color(ent->colormod[0], ent->colormod[1], ent->colormod[2], texture->currentalpha);
2825 R_SetupSurfaceShader(ent, texture, modelorg, vec3_origin, lightmode == 2);
2826 if (!r_glsl_permutation)
2828 RSurf_SetPointersForPass(false, true);
2831 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2833 surface = texturesurfacelist[texturesurfaceindex];
2834 if (rsurface_dynamicvertex)
2835 RSurf_PrepareDynamicSurfaceVertices(surface);
2836 R_Mesh_TexCoordPointer(0, 2, model->surfmesh.data_texcoordtexture2f);
2837 R_Mesh_TexCoordPointer(1, 3, rsurface_svector3f);
2838 R_Mesh_TexCoordPointer(2, 3, rsurface_tvector3f);
2839 R_Mesh_TexCoordPointer(3, 3, rsurface_normal3f);
2840 RSurf_Draw(surface);
2845 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2847 surface = texturesurfacelist[texturesurfaceindex];
2848 if (rsurface_dynamicvertex)
2849 RSurf_PrepareDynamicSurfaceVertices(surface);
2850 R_Mesh_TexCoordPointer(0, 2, model->surfmesh.data_texcoordtexture2f);
2851 R_Mesh_TexCoordPointer(1, 3, rsurface_svector3f);
2852 R_Mesh_TexCoordPointer(2, 3, rsurface_tvector3f);
2853 R_Mesh_TexCoordPointer(3, 3, rsurface_normal3f);
2854 R_Mesh_TexCoordPointer(4, 2, model->surfmesh.data_texcoordlightmap2f);
2855 if (surface->lightmaptexture)
2857 R_Mesh_TexBind(7, R_GetTexture(surface->lightmaptexture));
2858 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
2859 R_Mesh_TexBind(8, R_GetTexture(surface->deluxemaptexture));
2860 R_Mesh_ColorPointer(NULL);
2864 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
2865 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
2866 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
2867 R_Mesh_ColorPointer(model->surfmesh.data_lightmapcolor4f);
2869 RSurf_Draw(surface);
2872 qglUseProgramObjectARB(0);
2874 else if (texture->currentnumlayers)
2877 texturelayer_t *layer;
2878 for (layerindex = 0, layer = texture->currentlayers;layerindex < texture->currentnumlayers;layerindex++, layer++)
2881 int layertexrgbscale;
2882 GL_DepthMask(layer->depthmask);
2883 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
2884 if ((layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2) && (gl_combine.integer || layer->depthmask))
2886 layertexrgbscale = 4;
2887 VectorScale(layer->color, 0.25f, layercolor);
2889 else if ((layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1) && (gl_combine.integer || layer->depthmask))
2891 layertexrgbscale = 2;
2892 VectorScale(layer->color, 0.5f, layercolor);
2896 layertexrgbscale = 1;
2897 VectorScale(layer->color, 1.0f, layercolor);
2899 layercolor[3] = layer->color[3];
2900 GL_Color(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
2901 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
2902 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
2903 switch (layer->type)
2905 case TEXTURELAYERTYPE_LITTEXTURE_COMBINE:
2906 memset(&m, 0, sizeof(m));
2907 m.tex[1] = R_GetTexture(layer->texture);
2908 m.texmatrix[1] = layer->texmatrix;
2909 m.texrgbscale[1] = layertexrgbscale;
2910 m.pointer_color = rsurface_array_color4f;
2912 RSurf_SetPointersForPass(lightmode == 2, false);
2915 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2917 surface = texturesurfacelist[texturesurfaceindex];
2918 R_Mesh_TexCoordPointer(0, 2, model->surfmesh.data_texcoordlightmap2f);
2919 R_Mesh_TexCoordPointer(1, 2, model->surfmesh.data_texcoordtexture2f);
2920 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2921 if (rsurface_dynamicvertex)
2922 RSurf_PrepareDynamicSurfaceVertices(surface);
2923 RSurf_DrawLightmap(surface, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 2, applycolor, applyfog);
2928 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2930 surface = texturesurfacelist[texturesurfaceindex];
2931 R_Mesh_TexCoordPointer(0, 2, model->surfmesh.data_texcoordlightmap2f);
2932 R_Mesh_TexCoordPointer(1, 2, model->surfmesh.data_texcoordtexture2f);
2933 if (rsurface_dynamicvertex)
2934 RSurf_PrepareDynamicSurfaceVertices(surface);
2935 if (surface->lightmaptexture)
2937 R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
2938 RSurf_DrawLightmap(surface, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, applyfog);
2942 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2943 RSurf_DrawLightmap(surface, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 1, applycolor, applyfog);
2948 case TEXTURELAYERTYPE_LITTEXTURE_MULTIPASS:
2949 memset(&m, 0, sizeof(m));
2950 m.tex[0] = R_GetTexture(layer->texture);
2951 m.texmatrix[0] = layer->texmatrix;
2952 m.pointer_color = rsurface_array_color4f;
2953 m.texrgbscale[0] = layertexrgbscale;
2955 RSurf_SetPointersForPass(lightmode == 2, false);
2958 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2960 surface = texturesurfacelist[texturesurfaceindex];
2961 R_Mesh_TexCoordPointer(0, 2, model->surfmesh.data_texcoordlightmap2f);
2962 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2963 if (rsurface_dynamicvertex)
2964 RSurf_PrepareDynamicSurfaceVertices(surface);
2965 RSurf_DrawLightmap(surface, 1, 1, 1, 1, 2, false, false);
2970 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2972 surface = texturesurfacelist[texturesurfaceindex];
2973 R_Mesh_TexCoordPointer(0, 2, model->surfmesh.data_texcoordlightmap2f);
2974 if (rsurface_dynamicvertex)
2975 RSurf_PrepareDynamicSurfaceVertices(surface);
2976 if (surface->lightmaptexture)
2978 R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
2979 RSurf_DrawLightmap(surface, 1, 1, 1, 1, 0, false, false);
2983 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2984 RSurf_DrawLightmap(surface, 1, 1, 1, 1, 1, false, false);
2988 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
2989 memset(&m, 0, sizeof(m));
2990 m.tex[0] = R_GetTexture(layer->texture);
2991 m.texmatrix[0] = layer->texmatrix;
2992 m.pointer_color = rsurface_array_color4f;
2993 m.texrgbscale[0] = layertexrgbscale;
2995 RSurf_SetPointersForPass(false, false);
2996 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2998 surface = texturesurfacelist[texturesurfaceindex];
2999 R_Mesh_TexCoordPointer(0, 2, model->surfmesh.data_texcoordtexture2f);
3000 if (rsurface_dynamicvertex)
3001 RSurf_PrepareDynamicSurfaceVertices(surface);
3002 RSurf_DrawLightmap(surface, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, false);
3005 case TEXTURELAYERTYPE_LITTEXTURE_VERTEX:
3006 memset(&m, 0, sizeof(m));
3007 m.tex[0] = R_GetTexture(layer->texture);
3008 m.texmatrix[0] = layer->texmatrix;
3009 m.texrgbscale[0] = layertexrgbscale;
3010 m.pointer_color = rsurface_array_color4f;
3012 RSurf_SetPointersForPass(lightmode == 2, false);
3015 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3017 surface = texturesurfacelist[texturesurfaceindex];
3018 R_Mesh_TexCoordPointer(0, 2, model->surfmesh.data_texcoordtexture2f);
3019 if (rsurface_dynamicvertex)
3020 RSurf_PrepareDynamicSurfaceVertices(surface);
3021 RSurf_DrawLightmap(surface, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 2, applycolor, applyfog);
3026 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3028 surface = texturesurfacelist[texturesurfaceindex];
3029 R_Mesh_TexCoordPointer(0, 2, model->surfmesh.data_texcoordtexture2f);
3030 if (rsurface_dynamicvertex)
3031 RSurf_PrepareDynamicSurfaceVertices(surface);
3032 RSurf_DrawLightmap(surface, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 1, applycolor, applyfog);
3036 case TEXTURELAYERTYPE_TEXTURE:
3037 memset(&m, 0, sizeof(m));
3038 m.tex[0] = R_GetTexture(layer->texture);
3039 m.texmatrix[0] = layer->texmatrix;
3040 m.pointer_color = rsurface_array_color4f;
3041 m.texrgbscale[0] = layertexrgbscale;
3043 RSurf_SetPointersForPass(false, false);
3044 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3046 surface = texturesurfacelist[texturesurfaceindex];
3047 R_Mesh_TexCoordPointer(0, 2, model->surfmesh.data_texcoordtexture2f);
3048 if (rsurface_dynamicvertex)
3049 RSurf_PrepareDynamicSurfaceVertices(surface);
3050 RSurf_DrawLightmap(surface, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, applyfog);
3053 case TEXTURELAYERTYPE_FOG:
3054 memset(&m, 0, sizeof(m));
3057 m.tex[0] = R_GetTexture(layer->texture);
3058 m.texmatrix[0] = layer->texmatrix;
3061 RSurf_SetPointersForPass(false, false);
3062 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3066 surface = texturesurfacelist[texturesurfaceindex];
3068 R_Mesh_TexCoordPointer(0, 2, model->surfmesh.data_texcoordtexture2f);
3069 R_Mesh_ColorPointer(rsurface_array_color4f);
3070 if (rsurface_dynamicvertex)
3071 RSurf_PrepareDynamicSurfaceVertices(surface);
3072 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)
3074 f = VERTEXFOGTABLE(VectorDistance(v, modelorg));
3075 c[0] = layercolor[0];
3076 c[1] = layercolor[1];
3077 c[2] = layercolor[2];
3078 c[3] = f * layercolor[3];
3080 RSurf_Draw(surface);
3084 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
3086 // if trying to do overbright on first pass of an opaque surface
3087 // when combine is not supported, brighten as a post process
3088 if (layertexrgbscale > 1 && !gl_combine.integer && layer->depthmask)
3091 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
3092 GL_Color(1, 1, 1, 1);
3093 memset(&m, 0, sizeof(m));
3095 RSurf_SetPointersForPass(false, false);
3096 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3098 surface = texturesurfacelist[texturesurfaceindex];
3099 if (rsurface_dynamicvertex)
3100 RSurf_PrepareDynamicSurfaceVertices(surface);
3101 for (scale = 1;scale < layertexrgbscale;scale <<= 1)
3102 RSurf_Draw(surface);
3107 if ((texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (ent->flags & RENDER_NOCULLFACE))
3108 qglEnable(GL_CULL_FACE);
3111 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight)
3113 const msurface_t *surface = ent->model->data_surfaces + surfacenumber;
3117 texture = surface->texture;
3118 if (texture->basematerialflags & MATERIALFLAG_SKY)
3119 return; // transparent sky is too difficult
3120 R_UpdateTextureInfo(ent, texture);
3122 R_Mesh_Matrix(&ent->matrix);
3123 Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
3124 R_DrawTextureSurfaceList(ent, texture->currentframe, 1, &surface, modelorg);
3127 void R_QueueTextureSurfaceList(entity_render_t *ent, texture_t *texture, int texturenumsurfaces, const msurface_t **texturesurfacelist, const vec3_t modelorg)
3129 int texturesurfaceindex;
3130 const msurface_t *surface;
3131 vec3_t tempcenter, center;
3132 if (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT)
3134 // drawing sky transparently would be too difficult
3135 if (!(texture->currentmaterialflags & MATERIALFLAG_SKY))
3137 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3139 surface = texturesurfacelist[texturesurfaceindex];
3140 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
3141 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
3142 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
3143 Matrix4x4_Transform(&ent->matrix, tempcenter, center);
3144 R_MeshQueue_AddTransparent(texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_vieworigin : center, R_DrawSurface_TransparentCallback, ent, surface - ent->model->data_surfaces, r_shadow_rtlight);
3149 R_DrawTextureSurfaceList(ent, texture, texturenumsurfaces, texturesurfacelist, modelorg);
3152 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
3153 void R_DrawSurfaces(entity_render_t *ent, qboolean skysurfaces)
3155 int i, j, f, flagsmask;
3156 int counttriangles = 0;
3157 msurface_t *surface, **surfacechain;
3158 texture_t *t, *texture;
3159 model_t *model = ent->model;
3161 const int maxsurfacelist = 1024;
3162 int numsurfacelist = 0;
3163 const msurface_t *surfacelist[1024];
3166 R_Mesh_Matrix(&ent->matrix);
3167 Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
3169 // update light styles
3170 if (!skysurfaces && model->brushq1.light_styleupdatechains)
3172 for (i = 0;i < model->brushq1.light_styles;i++)
3174 if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
3176 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
3177 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
3178 for (;(surface = *surfacechain);surfacechain++)
3179 surface->cached_dlight = true;
3184 R_UpdateAllTextureInfo(ent);
3185 flagsmask = skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL);
3190 if (r_showsurfaces.integer)
3195 GL_BlendFunc(GL_ONE, GL_ZERO);
3196 memset(&m, 0, sizeof(m));
3199 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
3201 if (ent == r_refdef.worldentity && !r_worldsurfacevisible[j])
3203 if (t != surface->texture)
3205 t = surface->texture;
3206 texture = t->currentframe;
3207 RSurf_PrepareForBatch(ent, texture, modelorg);
3208 RSurf_SetPointersForPass(false, false);
3210 if ((texture->currentmaterialflags & flagsmask) && surface->num_triangles)
3212 int k = (int)(((size_t)surface) / sizeof(msurface_t));
3213 GL_Color((k & 15) * (1.0f / 16.0f), ((k >> 4) & 15) * (1.0f / 16.0f), ((k >> 8) & 15) * (1.0f / 16.0f), 0.2f);
3214 if (rsurface_dynamicvertex)
3215 RSurf_PrepareDynamicSurfaceVertices(surface);
3216 RSurf_Draw(surface);
3217 renderstats.entities_triangles += surface->num_triangles;
3219 renderstats.entities_surfaces++;
3222 else if (ent == r_refdef.worldentity)
3224 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
3226 if (!r_worldsurfacevisible[j])
3228 if (t != surface->texture)
3232 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
3235 t = surface->texture;
3236 texture = t->currentframe;
3237 f = texture->currentmaterialflags & flagsmask;
3239 if (f && surface->num_triangles)
3241 // if lightmap parameters changed, rebuild lightmap texture
3242 if (surface->cached_dlight)
3243 R_BuildLightMap(ent, surface);
3244 // add face to draw list
3245 surfacelist[numsurfacelist++] = surface;
3246 counttriangles += surface->num_triangles;
3247 if (numsurfacelist >= maxsurfacelist)
3249 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
3257 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
3259 if (t != surface->texture)
3263 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
3266 t = surface->texture;
3267 texture = t->currentframe;
3268 f = texture->currentmaterialflags & flagsmask;
3270 if (f && surface->num_triangles)
3272 // if lightmap parameters changed, rebuild lightmap texture
3273 if (surface->cached_dlight)
3274 R_BuildLightMap(ent, surface);
3275 // add face to draw list
3276 surfacelist[numsurfacelist++] = surface;
3277 counttriangles += surface->num_triangles;
3278 if (numsurfacelist >= maxsurfacelist)
3280 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
3287 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
3288 renderstats.entities_triangles += counttriangles;
3289 if (gl_support_fragment_shader)
3290 qglUseProgramObjectARB(0);
3292 if (r_showcollisionbrushes.integer && model->brush.num_brushes && !skysurfaces)
3295 msurface_t *surface;
3297 R_Mesh_Matrix(&ent->matrix);
3298 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
3299 GL_DepthMask(false);
3300 GL_DepthTest(!r_showdisabledepthtest.integer);
3301 qglPolygonOffset(r_polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_polygonoffset + r_showcollisionbrushes_polygonoffset.value);
3302 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
3303 if (brush->colbrushf && brush->colbrushf->numtriangles)
3304 R_DrawCollisionBrush(brush->colbrushf);
3305 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
3306 if (surface->num_collisiontriangles)
3307 R_DrawCollisionSurface(ent, surface);
3308 qglPolygonOffset(r_polygonfactor, r_polygonoffset);
3311 if (r_showtris.integer || r_shownormals.integer)
3314 const int *elements;
3319 if (r_showdisabledepthtest.integer)
3320 qglDepthFunc(GL_ALWAYS);
3321 GL_BlendFunc(GL_ONE, GL_ZERO);
3322 memset(&m, 0, sizeof(m));
3324 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
3326 if (ent == r_refdef.worldentity && !r_worldsurfacevisible[j])
3328 texture = surface->texture->currentframe;
3329 if ((texture->currentmaterialflags & flagsmask) && surface->num_triangles)
3331 RSurf_PrepareForBatch(ent, texture, modelorg);
3332 RSurf_SetPointersForPass(false, r_shownormals.integer != 0);
3333 if (rsurface_dynamicvertex)
3334 RSurf_PrepareDynamicSurfaceVertices(surface);
3335 if (r_showtris.integer)
3337 if (!texture->currentlayers->depthmask)
3338 GL_Color(r_showtris.value, 0, 0, 1);
3339 else if (ent == r_refdef.worldentity)
3340 GL_Color(r_showtris.value, r_showtris.value, r_showtris.value, 1);
3342 GL_Color(0, r_showtris.value, 0, 1);
3343 elements = (ent->model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
3345 for (k = 0;k < surface->num_triangles;k++, elements += 3)
3347 qglArrayElement(elements[0]);qglArrayElement(elements[1]);
3348 qglArrayElement(elements[1]);qglArrayElement(elements[2]);
3349 qglArrayElement(elements[2]);qglArrayElement(elements[0]);
3353 if (r_shownormals.integer)
3355 GL_Color(r_shownormals.value, 0, 0, 1);
3357 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
3359 VectorCopy(rsurface_vertex3f + l * 3, v);
3360 qglVertex3f(v[0], v[1], v[2]);
3361 VectorMA(v, 8, rsurface_svector3f + l * 3, v);
3362 qglVertex3f(v[0], v[1], v[2]);
3365 GL_Color(0, 0, r_shownormals.value, 1);
3367 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
3369 VectorCopy(rsurface_vertex3f + l * 3, v);
3370 qglVertex3f(v[0], v[1], v[2]);
3371 VectorMA(v, 8, rsurface_tvector3f + l * 3, v);
3372 qglVertex3f(v[0], v[1], v[2]);
3375 GL_Color(0, r_shownormals.value, 0, 1);
3377 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
3379 VectorCopy(rsurface_vertex3f + l * 3, v);
3380 qglVertex3f(v[0], v[1], v[2]);
3381 VectorMA(v, 8, rsurface_normal3f + l * 3, v);
3382 qglVertex3f(v[0], v[1], v[2]);
3388 if (r_showdisabledepthtest.integer)
3389 qglDepthFunc(GL_LEQUAL);