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_Cube >= 0 && permutation & SHADERPERMUTATION_MODE_LIGHTSOURCE) R_Mesh_TexBindCubeMap(3, R_GetTexture(r_shadow_rtlight->currentcubemap));
956 if (r_glsl_permutation->loc_Texture_FogMask >= 0) R_Mesh_TexBind(4, R_GetTexture(r_texture_fogattenuation));
957 if (r_glsl_permutation->loc_Texture_Pants >= 0) R_Mesh_TexBind(5, R_GetTexture(texture->skin.pants));
958 if (r_glsl_permutation->loc_Texture_Shirt >= 0) R_Mesh_TexBind(6, R_GetTexture(texture->skin.shirt));
959 if (r_glsl_permutation->loc_Texture_Lightmap >= 0) R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
960 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
961 if (r_glsl_permutation->loc_Texture_Glow >= 0) R_Mesh_TexBind(9, R_GetTexture(texture->skin.glow));
962 if (r_glsl_permutation->loc_FogColor >= 0)
964 // additive passes are only darkened by fog, not tinted
965 if (r_shadow_rtlight || (texture->currentmaterialflags & MATERIALFLAG_ADD))
966 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
968 qglUniform3fARB(r_glsl_permutation->loc_FogColor, fogcolor[0], fogcolor[1], fogcolor[2]);
970 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, modelorg[0], modelorg[1], modelorg[2]);
971 if (r_glsl_permutation->loc_Color_Pants >= 0)
973 if (texture->skin.pants)
974 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, ent->colormap_pantscolor[0], ent->colormap_pantscolor[1], ent->colormap_pantscolor[2]);
976 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
978 if (r_glsl_permutation->loc_Color_Shirt >= 0)
980 if (texture->skin.shirt)
981 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, ent->colormap_shirtcolor[0], ent->colormap_shirtcolor[1], ent->colormap_shirtcolor[2]);
983 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
985 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, fograngerecip);
986 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, texture->specularpower);
987 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
991 void gl_main_start(void)
993 r_main_texturepool = R_AllocTexturePool();
994 r_bloom_texture_screen = NULL;
995 r_bloom_texture_bloom = NULL;
996 R_BuildBlankTextures();
998 if (gl_texturecubemap)
1001 R_BuildNormalizationCube();
1003 R_BuildFogTexture();
1004 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
1007 void gl_main_shutdown(void)
1009 R_FreeTexturePool(&r_main_texturepool);
1010 r_bloom_texture_screen = NULL;
1011 r_bloom_texture_bloom = NULL;
1012 r_texture_blanknormalmap = NULL;
1013 r_texture_white = NULL;
1014 r_texture_black = NULL;
1015 r_texture_whitecube = NULL;
1016 r_texture_normalizationcube = NULL;
1020 extern void CL_ParseEntityLump(char *entitystring);
1021 void gl_main_newmap(void)
1023 // FIXME: move this code to client
1025 char *entities, entname[MAX_QPATH];
1029 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
1030 l = (int)strlen(entname) - 4;
1031 if (l >= 0 && !strcmp(entname + l, ".bsp"))
1033 strcpy(entname + l, ".ent");
1034 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
1036 CL_ParseEntityLump(entities);
1041 if (cl.worldmodel->brush.entities)
1042 CL_ParseEntityLump(cl.worldmodel->brush.entities);
1046 void GL_Main_Init(void)
1048 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
1050 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed\n");
1051 FOG_registercvars(); // FIXME: move this fog stuff to client?
1052 Cvar_RegisterVariable(&r_nearclip);
1053 Cvar_RegisterVariable(&r_showsurfaces);
1054 Cvar_RegisterVariable(&r_showtris);
1055 Cvar_RegisterVariable(&r_shownormals);
1056 Cvar_RegisterVariable(&r_showlighting);
1057 Cvar_RegisterVariable(&r_showshadowvolumes);
1058 Cvar_RegisterVariable(&r_showcollisionbrushes);
1059 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
1060 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
1061 Cvar_RegisterVariable(&r_showdisabledepthtest);
1062 Cvar_RegisterVariable(&r_drawentities);
1063 Cvar_RegisterVariable(&r_drawviewmodel);
1064 Cvar_RegisterVariable(&r_speeds);
1065 Cvar_RegisterVariable(&r_fullbrights);
1066 Cvar_RegisterVariable(&r_wateralpha);
1067 Cvar_RegisterVariable(&r_dynamic);
1068 Cvar_RegisterVariable(&r_fullbright);
1069 Cvar_RegisterVariable(&r_q1bsp_skymasking);
1070 Cvar_RegisterVariable(&r_textureunits);
1071 Cvar_RegisterVariable(&r_glsl);
1072 Cvar_RegisterVariable(&r_glsl_offsetmapping);
1073 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
1074 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
1075 Cvar_RegisterVariable(&r_glsl_deluxemapping);
1076 Cvar_RegisterVariable(&r_lerpsprites);
1077 Cvar_RegisterVariable(&r_lerpmodels);
1078 Cvar_RegisterVariable(&r_waterscroll);
1079 Cvar_RegisterVariable(&r_bloom);
1080 Cvar_RegisterVariable(&r_bloom_intensity);
1081 Cvar_RegisterVariable(&r_bloom_blur);
1082 Cvar_RegisterVariable(&r_bloom_resolution);
1083 Cvar_RegisterVariable(&r_bloom_power);
1084 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
1085 Cvar_RegisterVariable(&developer_texturelogging);
1086 Cvar_RegisterVariable(&gl_lightmaps);
1087 Cvar_RegisterVariable(&r_test);
1088 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
1089 Cvar_SetValue("r_fullbrights", 0);
1090 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
1093 static vec3_t r_farclip_origin;
1094 static vec3_t r_farclip_direction;
1095 static vec_t r_farclip_directiondist;
1096 static vec_t r_farclip_meshfarclip;
1097 static int r_farclip_directionbit0;
1098 static int r_farclip_directionbit1;
1099 static int r_farclip_directionbit2;
1101 // enlarge farclip to accomodate box
1102 static void R_FarClip_Box(vec3_t mins, vec3_t maxs)
1105 d = (r_farclip_directionbit0 ? mins[0] : maxs[0]) * r_farclip_direction[0]
1106 + (r_farclip_directionbit1 ? mins[1] : maxs[1]) * r_farclip_direction[1]
1107 + (r_farclip_directionbit2 ? mins[2] : maxs[2]) * r_farclip_direction[2];
1108 if (r_farclip_meshfarclip < d)
1109 r_farclip_meshfarclip = d;
1112 // return farclip value
1113 static float R_FarClip(vec3_t origin, vec3_t direction, vec_t startfarclip)
1117 VectorCopy(origin, r_farclip_origin);
1118 VectorCopy(direction, r_farclip_direction);
1119 r_farclip_directiondist = DotProduct(r_farclip_origin, r_farclip_direction);
1120 r_farclip_directionbit0 = r_farclip_direction[0] < 0;
1121 r_farclip_directionbit1 = r_farclip_direction[1] < 0;
1122 r_farclip_directionbit2 = r_farclip_direction[2] < 0;
1123 r_farclip_meshfarclip = r_farclip_directiondist + startfarclip;
1125 if (r_refdef.worldmodel)
1126 R_FarClip_Box(r_refdef.worldmodel->normalmins, r_refdef.worldmodel->normalmaxs);
1127 for (i = 0;i < r_refdef.numentities;i++)
1128 R_FarClip_Box(r_refdef.entities[i]->mins, r_refdef.entities[i]->maxs);
1130 return r_farclip_meshfarclip - r_farclip_directiondist;
1133 extern void R_Textures_Init(void);
1134 extern void GL_Draw_Init(void);
1135 extern void GL_Main_Init(void);
1136 extern void R_Shadow_Init(void);
1137 extern void R_Sky_Init(void);
1138 extern void GL_Surf_Init(void);
1139 extern void R_Crosshairs_Init(void);
1140 extern void R_Light_Init(void);
1141 extern void R_Particles_Init(void);
1142 extern void R_Explosion_Init(void);
1143 extern void gl_backend_init(void);
1144 extern void Sbar_Init(void);
1145 extern void R_LightningBeams_Init(void);
1146 extern void Mod_RenderInit(void);
1148 void Render_Init(void)
1158 R_Crosshairs_Init();
1163 R_LightningBeams_Init();
1172 extern char *ENGINE_EXTENSIONS;
1175 VID_CheckExtensions();
1177 // LordHavoc: report supported extensions
1178 Con_DPrintf("\nengine extensions: %s\n", vm_sv_extensions );
1180 // clear to black (loading plaque will be seen over this)
1181 qglClearColor(0,0,0,1);
1182 qglClear(GL_COLOR_BUFFER_BIT);
1185 int R_CullBox(const vec3_t mins, const vec3_t maxs)
1189 for (i = 0;i < 4;i++)
1196 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1200 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1204 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1208 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1212 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1216 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1220 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1224 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1232 //==================================================================================
1234 static void R_UpdateEntityLighting(entity_render_t *ent)
1236 vec3_t tempdiffusenormal;
1237 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));
1238 VectorClear(ent->modellight_diffuse);
1239 VectorClear(ent->modellight_lightdir);
1240 if ((ent->flags & RENDER_LIGHT) && r_refdef.worldmodel && r_refdef.worldmodel->brush.LightPoint)
1241 r_refdef.worldmodel->brush.LightPoint(r_refdef.worldmodel, ent->origin, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
1243 VectorSet(ent->modellight_ambient, 1, 1, 1);
1244 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
1245 VectorNormalize(ent->modellight_lightdir);
1246 ent->modellight_ambient[0] *= ent->colormod[0] * r_lightmapintensity;
1247 ent->modellight_ambient[1] *= ent->colormod[1] * r_lightmapintensity;
1248 ent->modellight_ambient[2] *= ent->colormod[2] * r_lightmapintensity;
1249 ent->modellight_diffuse[0] *= ent->colormod[0] * r_lightmapintensity;
1250 ent->modellight_diffuse[1] *= ent->colormod[1] * r_lightmapintensity;
1251 ent->modellight_diffuse[2] *= ent->colormod[2] * r_lightmapintensity;
1254 static void R_MarkEntities (void)
1257 entity_render_t *ent;
1259 if (!r_drawentities.integer)
1262 r_refdef.worldentity->visframe = r_framecount;
1263 renderimask = envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : (chase_active.integer ? 0 : RENDER_EXTERIORMODEL);
1264 if (r_refdef.worldmodel && r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs)
1266 // worldmodel can check visibility
1267 for (i = 0;i < r_refdef.numentities;i++)
1269 ent = r_refdef.entities[i];
1270 // some of the renderer still relies on origin...
1271 Matrix4x4_OriginFromMatrix(&ent->matrix, ent->origin);
1272 // some of the renderer still relies on scale...
1273 ent->scale = Matrix4x4_ScaleFromMatrix(&ent->matrix);
1274 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)))
1276 ent->visframe = r_framecount;
1277 R_UpdateEntityLighting(ent);
1283 // no worldmodel or it can't check visibility
1284 for (i = 0;i < r_refdef.numentities;i++)
1286 ent = r_refdef.entities[i];
1287 // some of the renderer still relies on origin...
1288 Matrix4x4_OriginFromMatrix(&ent->matrix, ent->origin);
1289 // some of the renderer still relies on scale...
1290 ent->scale = Matrix4x4_ScaleFromMatrix(&ent->matrix);
1291 if (!(ent->flags & renderimask) && !R_CullBox(ent->mins, ent->maxs) && (ent->effects & EF_NODEPTHTEST))
1293 ent->visframe = r_framecount;
1294 R_UpdateEntityLighting(ent);
1300 // only used if skyrendermasked, and normally returns false
1301 int R_DrawBrushModelsSky (void)
1304 entity_render_t *ent;
1306 if (!r_drawentities.integer)
1310 for (i = 0;i < r_refdef.numentities;i++)
1312 ent = r_refdef.entities[i];
1313 if (ent->visframe == r_framecount && ent->model && ent->model->DrawSky)
1315 ent->model->DrawSky(ent);
1322 void R_DrawNoModel(entity_render_t *ent);
1323 void R_DrawModels(void)
1326 entity_render_t *ent;
1328 if (!r_drawentities.integer)
1331 for (i = 0;i < r_refdef.numentities;i++)
1333 ent = r_refdef.entities[i];
1334 if (ent->visframe == r_framecount)
1336 renderstats.entities++;
1337 if (ent->model && ent->model->Draw != NULL)
1338 ent->model->Draw(ent);
1345 static void R_SetFrustum(void)
1347 // break apart the view matrix into vectors for various purposes
1348 Matrix4x4_ToVectors(&r_view_matrix, r_viewforward, r_viewleft, r_viewup, r_vieworigin);
1349 VectorNegate(r_viewleft, r_viewright);
1352 frustum[0].normal[0] = 0 - 1.0 / r_refdef.frustum_x;
1353 frustum[0].normal[1] = 0 - 0;
1354 frustum[0].normal[2] = -1 - 0;
1355 frustum[1].normal[0] = 0 + 1.0 / r_refdef.frustum_x;
1356 frustum[1].normal[1] = 0 + 0;
1357 frustum[1].normal[2] = -1 + 0;
1358 frustum[2].normal[0] = 0 - 0;
1359 frustum[2].normal[1] = 0 - 1.0 / r_refdef.frustum_y;
1360 frustum[2].normal[2] = -1 - 0;
1361 frustum[3].normal[0] = 0 + 0;
1362 frustum[3].normal[1] = 0 + 1.0 / r_refdef.frustum_y;
1363 frustum[3].normal[2] = -1 + 0;
1367 zNear = r_nearclip.value;
1368 nudge = 1.0 - 1.0 / (1<<23);
1369 frustum[4].normal[0] = 0 - 0;
1370 frustum[4].normal[1] = 0 - 0;
1371 frustum[4].normal[2] = -1 - -nudge;
1372 frustum[4].dist = 0 - -2 * zNear * nudge;
1373 frustum[5].normal[0] = 0 + 0;
1374 frustum[5].normal[1] = 0 + 0;
1375 frustum[5].normal[2] = -1 + -nudge;
1376 frustum[5].dist = 0 + -2 * zNear * nudge;
1382 frustum[0].normal[0] = m[3] - m[0];
1383 frustum[0].normal[1] = m[7] - m[4];
1384 frustum[0].normal[2] = m[11] - m[8];
1385 frustum[0].dist = m[15] - m[12];
1387 frustum[1].normal[0] = m[3] + m[0];
1388 frustum[1].normal[1] = m[7] + m[4];
1389 frustum[1].normal[2] = m[11] + m[8];
1390 frustum[1].dist = m[15] + m[12];
1392 frustum[2].normal[0] = m[3] - m[1];
1393 frustum[2].normal[1] = m[7] - m[5];
1394 frustum[2].normal[2] = m[11] - m[9];
1395 frustum[2].dist = m[15] - m[13];
1397 frustum[3].normal[0] = m[3] + m[1];
1398 frustum[3].normal[1] = m[7] + m[5];
1399 frustum[3].normal[2] = m[11] + m[9];
1400 frustum[3].dist = m[15] + m[13];
1402 frustum[4].normal[0] = m[3] - m[2];
1403 frustum[4].normal[1] = m[7] - m[6];
1404 frustum[4].normal[2] = m[11] - m[10];
1405 frustum[4].dist = m[15] - m[14];
1407 frustum[5].normal[0] = m[3] + m[2];
1408 frustum[5].normal[1] = m[7] + m[6];
1409 frustum[5].normal[2] = m[11] + m[10];
1410 frustum[5].dist = m[15] + m[14];
1415 VectorMAM(1, r_viewforward, 1.0 / -r_refdef.frustum_x, r_viewleft, frustum[0].normal);
1416 VectorMAM(1, r_viewforward, 1.0 / r_refdef.frustum_x, r_viewleft, frustum[1].normal);
1417 VectorMAM(1, r_viewforward, 1.0 / -r_refdef.frustum_y, r_viewup, frustum[2].normal);
1418 VectorMAM(1, r_viewforward, 1.0 / r_refdef.frustum_y, r_viewup, frustum[3].normal);
1419 VectorCopy(r_viewforward, frustum[4].normal);
1420 VectorNormalize(frustum[0].normal);
1421 VectorNormalize(frustum[1].normal);
1422 VectorNormalize(frustum[2].normal);
1423 VectorNormalize(frustum[3].normal);
1424 frustum[0].dist = DotProduct (r_vieworigin, frustum[0].normal);
1425 frustum[1].dist = DotProduct (r_vieworigin, frustum[1].normal);
1426 frustum[2].dist = DotProduct (r_vieworigin, frustum[2].normal);
1427 frustum[3].dist = DotProduct (r_vieworigin, frustum[3].normal);
1428 frustum[4].dist = DotProduct (r_vieworigin, frustum[4].normal) + r_nearclip.value;
1429 PlaneClassify(&frustum[0]);
1430 PlaneClassify(&frustum[1]);
1431 PlaneClassify(&frustum[2]);
1432 PlaneClassify(&frustum[3]);
1433 PlaneClassify(&frustum[4]);
1435 // LordHavoc: note to all quake engine coders, Quake had a special case
1436 // for 90 degrees which assumed a square view (wrong), so I removed it,
1437 // Quake2 has it disabled as well.
1439 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
1440 //RotatePointAroundVector( frustum[0].normal, r_viewup, r_viewforward, -(90 - r_refdef.fov_x / 2));
1441 //frustum[0].dist = DotProduct (r_vieworigin, frustum[0].normal);
1442 //PlaneClassify(&frustum[0]);
1444 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
1445 //RotatePointAroundVector( frustum[1].normal, r_viewup, r_viewforward, (90 - r_refdef.fov_x / 2));
1446 //frustum[1].dist = DotProduct (r_vieworigin, frustum[1].normal);
1447 //PlaneClassify(&frustum[1]);
1449 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
1450 //RotatePointAroundVector( frustum[2].normal, r_viewleft, r_viewforward, -(90 - r_refdef.fov_y / 2));
1451 //frustum[2].dist = DotProduct (r_vieworigin, frustum[2].normal);
1452 //PlaneClassify(&frustum[2]);
1454 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
1455 //RotatePointAroundVector( frustum[3].normal, r_viewleft, r_viewforward, (90 - r_refdef.fov_y / 2));
1456 //frustum[3].dist = DotProduct (r_vieworigin, frustum[3].normal);
1457 //PlaneClassify(&frustum[3]);
1460 //VectorCopy(r_viewforward, frustum[4].normal);
1461 //frustum[4].dist = DotProduct (r_vieworigin, frustum[4].normal) + r_nearclip.value;
1462 //PlaneClassify(&frustum[4]);
1465 static void R_BlendView(void)
1467 int screenwidth, screenheight;
1471 float texcoord2f[3][8];
1473 // set the (poorly named) screenwidth and screenheight variables to
1474 // a power of 2 at least as large as the screen, these will define the
1475 // size of the texture to allocate
1476 for (screenwidth = 1;screenwidth < vid.width;screenwidth *= 2);
1477 for (screenheight = 1;screenheight < vid.height;screenheight *= 2);
1479 doblend = r_refdef.viewblend[3] >= 0.01f;
1480 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;
1482 if (!dobloom && !doblend)
1485 GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
1487 GL_DepthTest(false);
1488 R_Mesh_Matrix(&identitymatrix);
1489 // vertex coordinates for a quad that covers the screen exactly
1490 vertex3f[0] = 0;vertex3f[1] = 0;vertex3f[2] = 0;
1491 vertex3f[3] = 1;vertex3f[4] = 0;vertex3f[5] = 0;
1492 vertex3f[6] = 1;vertex3f[7] = 1;vertex3f[8] = 0;
1493 vertex3f[9] = 0;vertex3f[10] = 1;vertex3f[11] = 0;
1494 R_Mesh_VertexPointer(vertex3f);
1495 R_Mesh_ColorPointer(NULL);
1496 R_Mesh_ResetTextureState();
1499 int bloomwidth, bloomheight, x, range;
1500 float xoffset, yoffset, r;
1501 renderstats.bloom++;
1502 // allocate textures as needed
1503 if (!r_bloom_texture_screen)
1504 r_bloom_texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", screenwidth, screenheight, NULL, TEXTYPE_RGBA, TEXF_FORCENEAREST | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
1505 if (!r_bloom_texture_bloom)
1506 r_bloom_texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", screenwidth, screenheight, NULL, TEXTYPE_RGBA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
1507 // set bloomwidth and bloomheight to the bloom resolution that will be
1508 // used (often less than the screen resolution for faster rendering)
1509 bloomwidth = min(r_view_width, r_bloom_resolution.integer);
1510 bloomheight = min(r_view_height, bloomwidth * r_view_height / r_view_width);
1511 // set up a texcoord array for the full resolution screen image
1512 // (we have to keep this around to copy back during final render)
1513 texcoord2f[0][0] = 0;
1514 texcoord2f[0][1] = (float)r_view_height / (float)screenheight;
1515 texcoord2f[0][2] = (float)r_view_width / (float)screenwidth;
1516 texcoord2f[0][3] = (float)r_view_height / (float)screenheight;
1517 texcoord2f[0][4] = (float)r_view_width / (float)screenwidth;
1518 texcoord2f[0][5] = 0;
1519 texcoord2f[0][6] = 0;
1520 texcoord2f[0][7] = 0;
1521 // set up a texcoord array for the reduced resolution bloom image
1522 // (which will be additive blended over the screen image)
1523 texcoord2f[1][0] = 0;
1524 texcoord2f[1][1] = (float)bloomheight / (float)screenheight;
1525 texcoord2f[1][2] = (float)bloomwidth / (float)screenwidth;
1526 texcoord2f[1][3] = (float)bloomheight / (float)screenheight;
1527 texcoord2f[1][4] = (float)bloomwidth / (float)screenwidth;
1528 texcoord2f[1][5] = 0;
1529 texcoord2f[1][6] = 0;
1530 texcoord2f[1][7] = 0;
1531 R_Mesh_TexCoordPointer(0, 2, texcoord2f[0]);
1532 R_Mesh_TexBind(0, R_GetTexture(r_bloom_texture_screen));
1533 // copy view into the full resolution screen image texture
1534 GL_ActiveTexture(0);
1535 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
1536 renderstats.bloom_copypixels += r_view_width * r_view_height;
1537 // now scale it down to the bloom size and raise to a power of itself
1538 // to darken it (this leaves the really bright stuff bright, and
1539 // everything else becomes very dark)
1540 // TODO: optimize with multitexture or GLSL
1541 qglViewport(r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
1542 GL_BlendFunc(GL_ONE, GL_ZERO);
1543 GL_Color(1, 1, 1, 1);
1544 R_Mesh_Draw(0, 4, 2, polygonelements);
1545 renderstats.bloom_drawpixels += bloomwidth * bloomheight;
1546 // render multiple times with a multiply blendfunc to raise to a power
1547 GL_BlendFunc(GL_DST_COLOR, GL_ZERO);
1548 for (x = 1;x < r_bloom_power.integer;x++)
1550 R_Mesh_Draw(0, 4, 2, polygonelements);
1551 renderstats.bloom_drawpixels += bloomwidth * bloomheight;
1553 // we now have a darkened bloom image in the framebuffer, copy it into
1554 // the bloom image texture for more processing
1555 R_Mesh_TexBind(0, R_GetTexture(r_bloom_texture_bloom));
1556 R_Mesh_TexCoordPointer(0, 2, texcoord2f[2]);
1557 GL_ActiveTexture(0);
1558 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
1559 renderstats.bloom_copypixels += bloomwidth * bloomheight;
1560 // blend on at multiple vertical offsets to achieve a vertical blur
1561 // TODO: do offset blends using GLSL
1562 range = r_bloom_blur.integer * bloomwidth / 320;
1563 GL_BlendFunc(GL_ONE, GL_ZERO);
1564 for (x = -range;x <= range;x++)
1566 xoffset = 0 / (float)bloomwidth * (float)bloomwidth / (float)screenwidth;
1567 yoffset = x / (float)bloomheight * (float)bloomheight / (float)screenheight;
1568 // compute a texcoord array with the specified x and y offset
1569 texcoord2f[2][0] = xoffset+0;
1570 texcoord2f[2][1] = yoffset+(float)bloomheight / (float)screenheight;
1571 texcoord2f[2][2] = xoffset+(float)bloomwidth / (float)screenwidth;
1572 texcoord2f[2][3] = yoffset+(float)bloomheight / (float)screenheight;
1573 texcoord2f[2][4] = xoffset+(float)bloomwidth / (float)screenwidth;
1574 texcoord2f[2][5] = yoffset+0;
1575 texcoord2f[2][6] = xoffset+0;
1576 texcoord2f[2][7] = yoffset+0;
1577 // this r value looks like a 'dot' particle, fading sharply to
1578 // black at the edges
1579 // (probably not realistic but looks good enough)
1580 r = r_bloom_intensity.value/(range*2+1)*(1 - x*x/(float)(range*range));
1583 GL_Color(r, r, r, 1);
1584 R_Mesh_Draw(0, 4, 2, polygonelements);
1585 renderstats.bloom_drawpixels += bloomwidth * bloomheight;
1586 GL_BlendFunc(GL_ONE, GL_ONE);
1588 // copy the vertically blurred bloom view to a texture
1589 GL_ActiveTexture(0);
1590 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
1591 renderstats.bloom_copypixels += bloomwidth * bloomheight;
1592 // blend the vertically blurred image at multiple offsets horizontally
1593 // to finish the blur effect
1594 // TODO: do offset blends using GLSL
1595 range = r_bloom_blur.integer * bloomwidth / 320;
1596 GL_BlendFunc(GL_ONE, GL_ZERO);
1597 for (x = -range;x <= range;x++)
1599 xoffset = x / (float)bloomwidth * (float)bloomwidth / (float)screenwidth;
1600 yoffset = 0 / (float)bloomheight * (float)bloomheight / (float)screenheight;
1601 // compute a texcoord array with the specified x and y offset
1602 texcoord2f[2][0] = xoffset+0;
1603 texcoord2f[2][1] = yoffset+(float)bloomheight / (float)screenheight;
1604 texcoord2f[2][2] = xoffset+(float)bloomwidth / (float)screenwidth;
1605 texcoord2f[2][3] = yoffset+(float)bloomheight / (float)screenheight;
1606 texcoord2f[2][4] = xoffset+(float)bloomwidth / (float)screenwidth;
1607 texcoord2f[2][5] = yoffset+0;
1608 texcoord2f[2][6] = xoffset+0;
1609 texcoord2f[2][7] = yoffset+0;
1610 // this r value looks like a 'dot' particle, fading sharply to
1611 // black at the edges
1612 // (probably not realistic but looks good enough)
1613 r = r_bloom_intensity.value/(range*2+1)*(1 - x*x/(float)(range*range));
1616 GL_Color(r, r, r, 1);
1617 R_Mesh_Draw(0, 4, 2, polygonelements);
1618 renderstats.bloom_drawpixels += bloomwidth * bloomheight;
1619 GL_BlendFunc(GL_ONE, GL_ONE);
1621 // copy the blurred bloom view to a texture
1622 GL_ActiveTexture(0);
1623 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
1624 renderstats.bloom_copypixels += bloomwidth * bloomheight;
1625 // go back to full view area
1626 qglViewport(r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
1627 // put the original screen image back in place and blend the bloom
1630 GL_BlendFunc(GL_ONE, GL_ZERO);
1631 // do both in one pass if possible
1632 R_Mesh_TexBind(0, R_GetTexture(r_bloom_texture_screen));
1633 R_Mesh_TexCoordPointer(0, 2, texcoord2f[0]);
1634 if (r_textureunits.integer >= 2 && gl_combine.integer)
1636 R_Mesh_TexCombine(1, GL_ADD, GL_ADD, 1, 1);
1637 R_Mesh_TexBind(1, R_GetTexture(r_bloom_texture_bloom));
1638 R_Mesh_TexCoordPointer(1, 2, texcoord2f[1]);
1642 R_Mesh_Draw(0, 4, 2, polygonelements);
1643 renderstats.bloom_drawpixels += r_view_width * r_view_height;
1644 // now blend on the bloom texture
1645 GL_BlendFunc(GL_ONE, GL_ONE);
1646 R_Mesh_TexBind(0, R_GetTexture(r_bloom_texture_bloom));
1647 R_Mesh_TexCoordPointer(0, 2, texcoord2f[1]);
1649 R_Mesh_Draw(0, 4, 2, polygonelements);
1650 renderstats.bloom_drawpixels += r_view_width * r_view_height;
1654 // apply a color tint to the whole view
1655 R_Mesh_ResetTextureState();
1656 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1657 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
1658 R_Mesh_Draw(0, 4, 2, polygonelements);
1662 void R_RenderScene(void);
1664 matrix4x4_t r_waterscrollmatrix;
1671 void R_RenderView(void)
1673 if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
1674 return; //Host_Error ("R_RenderView: NULL worldmodel");
1676 r_view_width = bound(0, r_refdef.width, vid.width);
1677 r_view_height = bound(0, r_refdef.height, vid.height);
1679 r_view_x = bound(0, r_refdef.x, vid.width - r_refdef.width);
1680 r_view_y = bound(0, r_refdef.y, vid.height - r_refdef.height);
1682 r_view_matrix = r_refdef.viewentitymatrix;
1683 GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
1684 r_rtworld = r_shadow_realtime_world.integer;
1685 r_rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
1686 r_rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer;
1687 r_rtdlightshadows = r_rtdlight && (r_rtworld ? r_shadow_realtime_world_dlightshadows.integer : r_shadow_realtime_dlight_shadows.integer) && gl_stencil;
1688 r_lightmapintensity = r_rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
1689 r_polygonfactor = 0;
1690 r_polygonoffset = 0;
1691 r_shadowpolygonfactor = r_polygonfactor + r_shadow_shadow_polygonfactor.value;
1692 r_shadowpolygonoffset = r_polygonoffset + r_shadow_shadow_polygonoffset.value;
1693 if (r_showsurfaces.integer)
1696 r_rtworldshadows = false;
1698 r_rtdlightshadows = false;
1699 r_lightmapintensity = 0;
1702 // GL is weird because it's bottom to top, r_view_y is top to bottom
1703 qglViewport(r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
1704 GL_Scissor(r_view_x, r_view_y, r_view_width, r_view_height);
1705 GL_ScissorTest(true);
1710 if (r_timereport_active)
1711 R_TimeReport("setup");
1713 qglDepthFunc(GL_LEQUAL);
1714 qglPolygonOffset(r_polygonfactor, r_polygonoffset);
1715 qglEnable(GL_POLYGON_OFFSET_FILL);
1719 qglPolygonOffset(r_polygonfactor, r_polygonoffset);
1720 qglDisable(GL_POLYGON_OFFSET_FILL);
1723 if (r_timereport_active)
1724 R_TimeReport("blendview");
1726 GL_Scissor(0, 0, vid.width, vid.height);
1727 GL_ScissorTest(false);
1731 void CSQC_R_ClearScreen (void)
1733 if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
1734 return; //Host_Error ("R_RenderView: NULL worldmodel");
1736 r_view_width = bound(0, r_refdef.width, vid.width);
1737 r_view_height = bound(0, r_refdef.height, vid.height);
1739 r_view_x = bound(0, r_refdef.x, vid.width - r_refdef.width);
1740 r_view_y = bound(0, r_refdef.y, vid.height - r_refdef.height);
1742 r_view_matrix = r_refdef.viewentitymatrix;
1743 GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
1744 r_rtworld = r_shadow_realtime_world.integer;
1745 r_rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
1746 r_rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer;
1747 r_rtdlightshadows = r_rtdlight && (r_rtworld ? r_shadow_realtime_world_dlightshadows.integer : r_shadow_realtime_dlight_shadows.integer) && gl_stencil;
1748 r_lightmapintensity = r_rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
1749 r_polygonfactor = 0;
1750 r_polygonoffset = 0;
1751 r_shadowpolygonfactor = r_polygonfactor + r_shadow_shadow_polygonfactor.value;
1752 r_shadowpolygonoffset = r_polygonoffset + r_shadow_shadow_polygonoffset.value;
1753 if (r_showsurfaces.integer)
1756 r_rtworldshadows = false;
1758 r_rtdlightshadows = false;
1759 r_lightmapintensity = 0;
1762 // GL is weird because it's bottom to top, r_view_y is top to bottom
1763 qglViewport(r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
1764 GL_Scissor(r_view_x, r_view_y, r_view_width, r_view_height);
1765 GL_ScissorTest(true);
1770 if (r_timereport_active)
1771 R_TimeReport("setup");
1775 void CSQC_R_RenderScene (void)
1777 qglDepthFunc(GL_LEQUAL);
1778 qglPolygonOffset(r_polygonfactor, r_polygonoffset);
1779 qglEnable(GL_POLYGON_OFFSET_FILL);
1783 qglPolygonOffset(r_polygonfactor, r_polygonoffset);
1784 qglDisable(GL_POLYGON_OFFSET_FILL);
1787 if (r_timereport_active)
1788 R_TimeReport("blendview");
1790 GL_Scissor(0, 0, vid.width, vid.height);
1791 GL_ScissorTest(false);
1794 extern void R_DrawLightningBeams (void);
1795 extern void VM_AddPolygonsToMeshQueue (void);
1796 void R_RenderScene(void)
1800 // don't let sound skip if going slow
1801 if (r_refdef.extraupdate)
1806 if (gl_support_fragment_shader)
1807 qglUseProgramObjectARB(0);
1809 R_MeshQueue_BeginScene();
1813 r_farclip = R_FarClip(r_vieworigin, r_viewforward, 768.0f) + 256.0f;
1814 nearclip = bound (0.001f, r_nearclip.value, r_farclip - 1.0f);
1816 if (r_rtworldshadows || r_rtdlightshadows)
1817 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_refdef.frustum_x, r_refdef.frustum_y, nearclip);
1819 GL_SetupView_Mode_Perspective(r_refdef.frustum_x, r_refdef.frustum_y, nearclip, r_farclip);
1821 GL_SetupView_Orientation_FromEntity(&r_view_matrix);
1823 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);
1827 R_WorldVisibility();
1828 if (r_timereport_active)
1829 R_TimeReport("worldvis");
1832 if (r_timereport_active)
1833 R_TimeReport("markentity");
1835 R_Shadow_UpdateWorldLightSelection();
1837 if (cl.csqc_vidvars.drawworld)
1839 // don't let sound skip if going slow
1840 if (r_refdef.extraupdate)
1843 if (r_refdef.worldmodel && r_refdef.worldmodel->DrawSky)
1845 r_refdef.worldmodel->DrawSky(r_refdef.worldentity);
1846 if (r_timereport_active)
1847 R_TimeReport("worldsky");
1850 if (R_DrawBrushModelsSky() && r_timereport_active)
1851 R_TimeReport("bmodelsky");
1853 if (r_refdef.worldmodel && r_refdef.worldmodel->Draw)
1855 r_refdef.worldmodel->Draw(r_refdef.worldentity);
1856 if (r_timereport_active)
1857 R_TimeReport("world");
1861 // don't let sound skip if going slow
1862 if (r_refdef.extraupdate)
1866 if (r_timereport_active)
1867 R_TimeReport("models");
1869 // don't let sound skip if going slow
1870 if (r_refdef.extraupdate)
1873 R_ShadowVolumeLighting(false);
1874 if (r_timereport_active)
1875 R_TimeReport("rtlights");
1877 // don't let sound skip if going slow
1878 if (r_refdef.extraupdate)
1881 if (cl.csqc_vidvars.drawworld)
1883 R_DrawLightningBeams();
1884 if (r_timereport_active)
1885 R_TimeReport("lightning");
1888 if (r_timereport_active)
1889 R_TimeReport("particles");
1892 if (r_timereport_active)
1893 R_TimeReport("explosions");
1896 R_MeshQueue_RenderTransparent();
1897 if (r_timereport_active)
1898 R_TimeReport("drawtrans");
1900 if (cl.csqc_vidvars.drawworld)
1903 if (r_timereport_active)
1904 R_TimeReport("coronas");
1906 if(cl.csqc_vidvars.drawcrosshair)
1908 R_DrawWorldCrosshair();
1909 if (r_timereport_active)
1910 R_TimeReport("crosshair");
1913 VM_AddPolygonsToMeshQueue();
1915 R_MeshQueue_Render();
1917 R_MeshQueue_EndScene();
1919 // don't let sound skip if going slow
1920 if (r_refdef.extraupdate)
1923 if (gl_support_fragment_shader)
1924 qglUseProgramObjectARB(0);
1928 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
1931 float *v, *c, f1, f2, diff[3], vertex3f[8*3], color4f[8*4];
1932 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1933 GL_DepthMask(false);
1935 R_Mesh_Matrix(&identitymatrix);
1937 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2];
1938 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
1939 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
1940 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
1941 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
1942 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
1943 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
1944 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
1945 R_FillColors(color, 8, cr, cg, cb, ca);
1948 for (i = 0, v = vertex, c = color;i < 8;i++, v += 4, c += 4)
1950 f2 = VERTEXFOGTABLE(VectorDistance(v, r_vieworigin));
1952 c[0] = c[0] * f1 + fogcolor[0] * f2;
1953 c[1] = c[1] * f1 + fogcolor[1] * f2;
1954 c[2] = c[2] * f1 + fogcolor[2] * f2;
1957 R_Mesh_VertexPointer(vertex3f);
1958 R_Mesh_ColorPointer(color);
1959 R_Mesh_ResetTextureState();
1964 int nomodelelements[24] =
1976 float nomodelvertex3f[6*3] =
1986 float nomodelcolor4f[6*4] =
1988 0.0f, 0.0f, 0.5f, 1.0f,
1989 0.0f, 0.0f, 0.5f, 1.0f,
1990 0.0f, 0.5f, 0.0f, 1.0f,
1991 0.0f, 0.5f, 0.0f, 1.0f,
1992 0.5f, 0.0f, 0.0f, 1.0f,
1993 0.5f, 0.0f, 0.0f, 1.0f
1996 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight)
2001 R_Mesh_Matrix(&ent->matrix);
2003 if (ent->flags & EF_ADDITIVE)
2005 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2006 GL_DepthMask(false);
2008 else if (ent->alpha < 1)
2010 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2011 GL_DepthMask(false);
2015 GL_BlendFunc(GL_ONE, GL_ZERO);
2018 GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
2019 R_Mesh_VertexPointer(nomodelvertex3f);
2022 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
2023 R_Mesh_ColorPointer(color4f);
2024 f2 = VERTEXFOGTABLE(VectorDistance(ent->origin, r_vieworigin));
2026 for (i = 0, c = color4f;i < 6;i++, c += 4)
2028 c[0] = (c[0] * f1 + fogcolor[0] * f2);
2029 c[1] = (c[1] * f1 + fogcolor[1] * f2);
2030 c[2] = (c[2] * f1 + fogcolor[2] * f2);
2034 else if (ent->alpha != 1)
2036 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
2037 R_Mesh_ColorPointer(color4f);
2038 for (i = 0, c = color4f;i < 6;i++, c += 4)
2042 R_Mesh_ColorPointer(nomodelcolor4f);
2043 R_Mesh_ResetTextureState();
2044 R_Mesh_Draw(0, 6, 8, nomodelelements);
2047 void R_DrawNoModel(entity_render_t *ent)
2049 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
2050 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_vieworigin : ent->origin, R_DrawNoModel_TransparentCallback, ent, 0, r_shadow_rtlight);
2052 // R_DrawNoModelCallback(ent, 0);
2055 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
2057 vec3_t right1, right2, diff, normal;
2059 VectorSubtract (org2, org1, normal);
2061 // calculate 'right' vector for start
2062 VectorSubtract (r_vieworigin, org1, diff);
2063 CrossProduct (normal, diff, right1);
2064 VectorNormalize (right1);
2066 // calculate 'right' vector for end
2067 VectorSubtract (r_vieworigin, org2, diff);
2068 CrossProduct (normal, diff, right2);
2069 VectorNormalize (right2);
2071 vert[ 0] = org1[0] + width * right1[0];
2072 vert[ 1] = org1[1] + width * right1[1];
2073 vert[ 2] = org1[2] + width * right1[2];
2074 vert[ 3] = org1[0] - width * right1[0];
2075 vert[ 4] = org1[1] - width * right1[1];
2076 vert[ 5] = org1[2] - width * right1[2];
2077 vert[ 6] = org2[0] - width * right2[0];
2078 vert[ 7] = org2[1] - width * right2[1];
2079 vert[ 8] = org2[2] - width * right2[2];
2080 vert[ 9] = org2[0] + width * right2[0];
2081 vert[10] = org2[1] + width * right2[1];
2082 vert[11] = org2[2] + width * right2[2];
2085 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
2087 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)
2089 float fog = 0.0f, ifog;
2093 fog = VERTEXFOGTABLE(VectorDistance(origin, r_vieworigin));
2096 R_Mesh_Matrix(&identitymatrix);
2097 GL_BlendFunc(blendfunc1, blendfunc2);
2098 GL_DepthMask(false);
2099 GL_DepthTest(!depthdisable);
2101 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
2102 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
2103 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
2104 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
2105 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
2106 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
2107 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
2108 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
2109 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
2110 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
2111 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
2112 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
2114 R_Mesh_VertexPointer(vertex3f);
2115 R_Mesh_ColorPointer(NULL);
2116 R_Mesh_ResetTextureState();
2117 R_Mesh_TexBind(0, R_GetTexture(texture));
2118 R_Mesh_TexCoordPointer(0, 2, spritetexcoord2f);
2119 GL_Color(cr * ifog, cg * ifog, cb * ifog, ca);
2120 R_Mesh_Draw(0, 4, 2, polygonelements);
2122 if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
2124 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
2125 GL_BlendFunc(blendfunc1, GL_ONE);
2126 GL_Color(fogcolor[0] * fog, fogcolor[1] * fog, fogcolor[2] * fog, ca);
2127 R_Mesh_Draw(0, 4, 2, polygonelements);
2131 int R_Mesh_AddVertex3f(rmesh_t *mesh, const float *v)
2135 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
2136 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
2138 if (i == mesh->numvertices)
2140 if (mesh->numvertices < mesh->maxvertices)
2142 VectorCopy(v, vertex3f);
2143 mesh->numvertices++;
2145 return mesh->numvertices;
2151 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
2155 element[0] = R_Mesh_AddVertex3f(mesh, vertex3f);vertex3f += 3;
2156 element[1] = R_Mesh_AddVertex3f(mesh, vertex3f);vertex3f += 3;
2157 e = mesh->element3i + mesh->numtriangles * 3;
2158 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
2160 element[2] = R_Mesh_AddVertex3f(mesh, vertex3f);
2161 if (mesh->numtriangles < mesh->maxtriangles)
2166 mesh->numtriangles++;
2168 element[1] = element[2];
2172 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
2174 int planenum, planenum2;
2177 mplane_t *plane, *plane2;
2178 float temppoints[2][256*3];
2179 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
2183 PolygonF_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->normal[3], 1024.0*1024.0*1024.0);
2184 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
2186 if (planenum2 == planenum)
2188 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);
2191 if (tempnumpoints < 3)
2193 // generate elements forming a triangle fan for this polygon
2194 R_Mesh_AddPolygon3f(mesh, tempnumpoints, temppoints[w]);
2198 static void R_DrawCollisionBrush(colbrushf_t *brush)
2201 R_Mesh_VertexPointer(brush->points->v);
2202 i = (int)(((size_t)brush) / sizeof(colbrushf_t));
2203 GL_Color((i & 31) * (1.0f / 32.0f), ((i >> 5) & 31) * (1.0f / 32.0f), ((i >> 10) & 31) * (1.0f / 32.0f), 0.2f);
2204 GL_LockArrays(0, brush->numpoints);
2205 R_Mesh_Draw(0, brush->numpoints, brush->numtriangles, brush->elements);
2206 GL_LockArrays(0, 0);
2209 static void R_DrawCollisionSurface(entity_render_t *ent, msurface_t *surface)
2212 if (!surface->num_collisiontriangles)
2214 R_Mesh_VertexPointer(surface->data_collisionvertex3f);
2215 i = (int)(((size_t)surface) / sizeof(msurface_t));
2216 GL_Color((i & 31) * (1.0f / 32.0f), ((i >> 5) & 31) * (1.0f / 32.0f), ((i >> 10) & 31) * (1.0f / 32.0f), 0.2f);
2217 GL_LockArrays(0, surface->num_collisionvertices);
2218 R_Mesh_Draw(0, surface->num_collisionvertices, surface->num_collisiontriangles, surface->data_collisionelement3i);
2219 GL_LockArrays(0, 0);
2222 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)
2224 texturelayer_t *layer;
2225 layer = t->currentlayers + t->currentnumlayers++;
2227 layer->depthmask = depthmask;
2228 layer->blendfunc1 = blendfunc1;
2229 layer->blendfunc2 = blendfunc2;
2230 layer->texture = texture;
2231 layer->texmatrix = *matrix;
2232 layer->color[0] = r;
2233 layer->color[1] = g;
2234 layer->color[2] = b;
2235 layer->color[3] = a;
2238 void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
2240 // FIXME: identify models using a better check than ent->model->brush.shadowmesh
2241 //int lightmode = ((ent->effects & EF_FULLBRIGHT) || ent->model->brush.shadowmesh) ? 0 : 2;
2244 texture_t *texture = t;
2245 model_t *model = ent->model;
2246 int s = ent->skinnum;
2247 if ((unsigned int)s >= (unsigned int)model->numskins)
2249 if (model->skinscenes)
2251 if (model->skinscenes[s].framecount > 1)
2252 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
2254 s = model->skinscenes[s].firstframe;
2257 t = t + s * model->num_surfaces;
2259 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];
2260 texture->currentframe = t;
2263 t->currentmaterialflags = t->basematerialflags;
2264 t->currentalpha = ent->alpha;
2265 if (t->basematerialflags & MATERIALFLAG_WATERALPHA)
2266 t->currentalpha *= r_wateralpha.value;
2267 if (!(ent->flags & RENDER_LIGHT))
2268 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
2269 if (ent->effects & EF_ADDITIVE)
2270 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_TRANSPARENT;
2271 else if (t->currentalpha < 1)
2272 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_TRANSPARENT;
2273 if (ent->effects & EF_NODEPTHTEST)
2274 t->currentmaterialflags |= MATERIALFLAG_NODEPTHTEST;
2275 if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
2276 t->currenttexmatrix = r_waterscrollmatrix;
2278 t->currenttexmatrix = identitymatrix;
2280 t->colormapping = VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f);
2281 t->basetexture = (!t->colormapping && t->skin.merged) ? t->skin.merged : t->skin.base;
2282 t->glosstexture = r_texture_white;
2283 t->specularpower = 8;
2284 t->specularscale = 0;
2285 if (r_shadow_gloss.integer > 0)
2289 if (r_shadow_glossintensity.value > 0)
2291 t->glosstexture = t->skin.gloss;
2292 t->specularscale = r_shadow_glossintensity.value;
2295 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
2296 t->specularscale = r_shadow_gloss2intensity.value;
2299 t->currentnumlayers = 0;
2300 if (!(t->currentmaterialflags & MATERIALFLAG_NODRAW))
2302 if (gl_lightmaps.integer)
2303 R_Texture_AddLayer(t, true, GL_ONE, GL_ZERO, TEXTURELAYERTYPE_LITTEXTURE_MULTIPASS, r_texture_white, &identitymatrix, 1, 1, 1, 1);
2304 else if (!(t->currentmaterialflags & MATERIALFLAG_SKY))
2306 int blendfunc1, blendfunc2, depthmask;
2307 if (t->currentmaterialflags & MATERIALFLAG_ADD)
2309 blendfunc1 = GL_SRC_ALPHA;
2310 blendfunc2 = GL_ONE;
2313 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
2315 blendfunc1 = GL_SRC_ALPHA;
2316 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
2321 blendfunc1 = GL_ONE;
2322 blendfunc2 = GL_ZERO;
2325 if (t->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL))
2327 rtexture_t *currentbasetexture;
2329 if (fogenabled && (t->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
2330 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
2331 currentbasetexture = (VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) < (1.0f / 1048576.0f) && t->skin.merged) ? t->skin.merged : t->skin.base;
2332 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2334 // fullbright is not affected by r_lightmapintensity
2335 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
2336 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->skin.pants)
2337 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);
2338 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->skin.shirt)
2339 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);
2345 // q3bsp has no lightmap updates, so the lightstylevalue that
2346 // would normally be baked into the lightmaptexture must be
2347 // applied to the color
2348 if (ent->model->type == mod_brushq3)
2349 colorscale *= r_refdef.lightstylevalue[0] * (1.0f / 256.0f);
2350 colorscale *= r_lightmapintensity;
2351 if (r_textureunits.integer >= 2 && gl_combine.integer)
2352 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);
2353 else if ((t->currentmaterialflags & MATERIALFLAG_TRANSPARENT) == 0)
2354 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);
2356 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);
2357 if (r_ambient.value >= (1.0f/64.0f))
2358 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);
2359 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->skin.pants)
2361 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);
2362 if (r_ambient.value >= (1.0f/64.0f))
2363 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);
2365 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->skin.shirt)
2367 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);
2368 if (r_ambient.value >= (1.0f/64.0f))
2369 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);
2372 if (t->skin.glow != NULL)
2373 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.glow, &t->currenttexmatrix, 1, 1, 1, t->currentalpha);
2374 if (fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
2376 // if this is opaque use alpha blend which will darken the earlier
2379 // if this is an alpha blended material, all the earlier passes
2380 // were darkened by fog already, so we only need to add the fog
2381 // color ontop through the fog mask texture
2383 // if this is an additive blended material, all the earlier passes
2384 // were darkened by fog already, and we should not add fog color
2385 // (because the background was not darkened, there is no fog color
2386 // that was lost behind it).
2387 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);
2394 void R_UpdateAllTextureInfo(entity_render_t *ent)
2398 for (i = 0;i < ent->model->num_textures;i++)
2399 R_UpdateTextureInfo(ent, ent->model->data_textures + i);
2402 int rsurface_array_size = 0;
2403 float *rsurface_array_vertex3f = NULL;
2404 float *rsurface_array_svector3f = NULL;
2405 float *rsurface_array_tvector3f = NULL;
2406 float *rsurface_array_normal3f = NULL;
2407 float *rsurface_array_color4f = NULL;
2408 float *rsurface_array_texcoord3f = NULL;
2410 void R_Mesh_ResizeArrays(int newvertices)
2412 if (rsurface_array_size >= newvertices)
2414 if (rsurface_array_vertex3f)
2415 Mem_Free(rsurface_array_vertex3f);
2416 rsurface_array_size = (newvertices + 1023) & ~1023;
2417 rsurface_array_vertex3f = (float *)Mem_Alloc(r_main_mempool, rsurface_array_size * sizeof(float[19]));
2418 rsurface_array_svector3f = rsurface_array_vertex3f + rsurface_array_size * 3;
2419 rsurface_array_tvector3f = rsurface_array_vertex3f + rsurface_array_size * 6;
2420 rsurface_array_normal3f = rsurface_array_vertex3f + rsurface_array_size * 9;
2421 rsurface_array_color4f = rsurface_array_vertex3f + rsurface_array_size * 12;
2422 rsurface_array_texcoord3f = rsurface_array_vertex3f + rsurface_array_size * 16;
2425 float *rsurface_vertex3f;
2426 float *rsurface_svector3f;
2427 float *rsurface_tvector3f;
2428 float *rsurface_normal3f;
2429 float *rsurface_lightmapcolor4f;
2430 vec3_t rsurface_modelorg;
2431 const entity_render_t *rsurface_entity;
2432 const model_t *rsurface_model;
2433 const texture_t *rsurface_texture;
2435 void RSurf_PrepareVerticesForBatch(const entity_render_t *ent, const texture_t *texture, const vec3_t modelorg, qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, msurface_t **texturesurfacelist)
2437 VectorCopy(modelorg, rsurface_modelorg);
2438 rsurface_entity = ent;
2439 rsurface_model = ent->model;
2440 rsurface_texture = texture;
2441 if (rsurface_array_size < rsurface_model->surfmesh.num_vertices)
2442 R_Mesh_ResizeArrays(rsurface_model->surfmesh.num_vertices);
2443 if ((rsurface_entity->frameblend[0].lerp != 1 || rsurface_entity->frameblend[0].frame != 0) && (rsurface_model->surfmesh.data_morphvertex3f || rsurface_model->surfmesh.data_vertexboneweights))
2445 rsurface_vertex3f = rsurface_array_vertex3f;
2446 rsurface_svector3f = NULL;
2447 rsurface_tvector3f = NULL;
2448 rsurface_normal3f = NULL;
2449 Mod_Alias_GetMesh_Vertex3f(rsurface_model, rsurface_entity->frameblend, rsurface_array_vertex3f);
2450 if (rsurface_texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
2451 generatetangents = true;
2452 if (generatetangents)
2453 generatenormals = true;
2454 if (generatenormals && !rsurface_normal3f)
2456 rsurface_normal3f = rsurface_array_normal3f;
2457 Mod_BuildNormals(0, rsurface_model->surfmesh.num_vertices, rsurface_model->surfmesh.num_triangles, rsurface_array_vertex3f, rsurface_model->surfmesh.data_element3i, rsurface_array_normal3f, r_smoothnormals_areaweighting.integer);
2459 if (generatetangents && !rsurface_svector3f)
2461 Mod_BuildTextureVectorsFromNormals(0, rsurface_model->surfmesh.num_vertices, rsurface_model->surfmesh.num_triangles, rsurface_array_vertex3f, rsurface_model->surfmesh.data_texcoordtexture2f, rsurface_normal3f, rsurface_model->surfmesh.data_element3i, rsurface_array_svector3f, rsurface_array_tvector3f, r_smoothnormals_areaweighting.integer);
2462 rsurface_svector3f = rsurface_array_svector3f;
2463 rsurface_tvector3f = rsurface_array_tvector3f;
2468 rsurface_vertex3f = rsurface_model->surfmesh.data_vertex3f;
2469 rsurface_svector3f = rsurface_model->surfmesh.data_svector3f;
2470 rsurface_tvector3f = rsurface_model->surfmesh.data_tvector3f;
2471 rsurface_normal3f = rsurface_model->surfmesh.data_normal3f;
2473 if (rsurface_texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
2475 int texturesurfaceindex;
2476 float center[3], forward[3], right[3], up[3], v[4][3];
2477 matrix4x4_t matrix1, imatrix1;
2478 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_viewforward, forward);
2479 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_viewright, right);
2480 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_viewup, up);
2481 if (rsurface_texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE2)
2483 forward[0] = rsurface_modelorg[0] - center[0];
2484 forward[1] = rsurface_modelorg[1] - center[1];
2486 VectorNormalize(forward);
2487 right[0] = forward[1];
2488 right[1] = -forward[0];
2490 VectorSet(up, 0, 0, 1);
2492 // make deformed versions of only the vertices used by the specified surfaces
2493 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2496 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2497 // a single autosprite surface can contain multiple sprites...
2498 for (j = 0;j < surface->num_vertices - 3;j += 4)
2500 VectorClear(center);
2501 for (i = 0;i < 4;i++)
2502 VectorAdd(center, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
2503 VectorScale(center, 0.25f, center);
2504 // FIXME: calculate vectors from triangle edges instead of using texture vectors as an easy way out?
2505 Matrix4x4_FromVectors(&matrix1, (rsurface_normal3f + 3 * surface->num_firstvertex) + j*3, (rsurface_svector3f + 3 * surface->num_firstvertex) + j*3, (rsurface_tvector3f + 3 * surface->num_firstvertex) + j*3, center);
2506 Matrix4x4_Invert_Simple(&imatrix1, &matrix1);
2507 for (i = 0;i < 4;i++)
2508 Matrix4x4_Transform(&imatrix1, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, v[i]);
2509 for (i = 0;i < 4;i++)
2510 VectorMAMAMAM(1, center, v[i][0], forward, v[i][1], right, v[i][2], up, rsurface_array_vertex3f + (surface->num_firstvertex+i+j) * 3);
2512 Mod_BuildNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface_array_vertex3f, rsurface_model->surfmesh.data_element3i + surface->num_firsttriangle * 3, rsurface_array_normal3f, r_smoothnormals_areaweighting.integer);
2513 Mod_BuildTextureVectorsFromNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface_array_vertex3f, rsurface_model->surfmesh.data_texcoordtexture2f, rsurface_array_normal3f, rsurface_model->surfmesh.data_element3i + surface->num_firsttriangle * 3, rsurface_array_svector3f, rsurface_array_tvector3f, r_smoothnormals_areaweighting.integer);
2515 rsurface_vertex3f = rsurface_array_vertex3f;
2516 rsurface_svector3f = rsurface_array_svector3f;
2517 rsurface_tvector3f = rsurface_array_tvector3f;
2518 rsurface_normal3f = rsurface_array_normal3f;
2520 R_Mesh_VertexPointer(rsurface_vertex3f);
2523 static void RSurf_Draw(const msurface_t *surface)
2525 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2526 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
2529 static void RSurf_DrawLightmap(const msurface_t *surface, float r, float g, float b, float a, int lightmode, qboolean applycolor, qboolean applyfog)
2537 vec3_t ambientcolor;
2538 vec3_t diffusecolor;
2540 VectorCopy(rsurface_entity->modellight_lightdir, lightdir);
2541 ambientcolor[0] = rsurface_entity->modellight_ambient[0] * r * 0.5f;
2542 ambientcolor[1] = rsurface_entity->modellight_ambient[1] * g * 0.5f;
2543 ambientcolor[2] = rsurface_entity->modellight_ambient[2] * b * 0.5f;
2544 diffusecolor[0] = rsurface_entity->modellight_diffuse[0] * r * 0.5f;
2545 diffusecolor[1] = rsurface_entity->modellight_diffuse[1] * g * 0.5f;
2546 diffusecolor[2] = rsurface_entity->modellight_diffuse[2] * b * 0.5f;
2547 if (VectorLength2(diffusecolor) > 0)
2549 int numverts = surface->num_vertices;
2550 v = rsurface_vertex3f + 3 * surface->num_firstvertex;
2551 c2 = rsurface_normal3f + 3 * surface->num_firstvertex;
2552 c = rsurface_array_color4f + 4 * surface->num_firstvertex;
2553 // q3-style directional shading
2554 for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
2556 if ((f = DotProduct(c2, lightdir)) > 0)
2557 VectorMA(ambientcolor, f, diffusecolor, c);
2559 VectorCopy(ambientcolor, c);
2567 rsurface_lightmapcolor4f = rsurface_array_color4f;
2571 r = ambientcolor[0];
2572 g = ambientcolor[1];
2573 b = ambientcolor[2];
2574 rsurface_lightmapcolor4f = NULL;
2577 else if (lightmode >= 1)
2579 if (surface->lightmapinfo && surface->lightmapinfo->stainsamples)
2581 for (i = 0, c = rsurface_array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
2583 if (surface->lightmapinfo->samples)
2585 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface_model->surfmesh.data_lightmapoffsets + surface->num_firstvertex)[i];
2586 float scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
2587 VectorScale(lm, scale, c);
2588 if (surface->lightmapinfo->styles[1] != 255)
2590 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
2592 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
2593 VectorMA(c, scale, lm, c);
2594 if (surface->lightmapinfo->styles[2] != 255)
2597 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
2598 VectorMA(c, scale, lm, c);
2599 if (surface->lightmapinfo->styles[3] != 255)
2602 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
2603 VectorMA(c, scale, lm, c);
2611 rsurface_lightmapcolor4f = rsurface_array_color4f;
2614 rsurface_lightmapcolor4f = rsurface_model->surfmesh.data_lightmapcolor4f;
2617 rsurface_lightmapcolor4f = NULL;
2620 if (rsurface_lightmapcolor4f)
2622 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)
2624 f = 1 - VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
2633 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)
2635 f = 1 - VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
2642 rsurface_lightmapcolor4f = rsurface_array_color4f;
2644 if (applycolor && rsurface_lightmapcolor4f)
2646 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)
2653 rsurface_lightmapcolor4f = rsurface_array_color4f;
2655 R_Mesh_ColorPointer(rsurface_lightmapcolor4f);
2656 GL_Color(r, g, b, a);
2657 RSurf_Draw(surface);
2660 static void R_DrawTextureSurfaceList(const entity_render_t *ent, texture_t *texture, int texturenumsurfaces, msurface_t **texturesurfacelist, const vec3_t modelorg)
2662 int texturesurfaceindex;
2664 const msurface_t *surface;
2665 model_t *model = ent->model;
2666 qboolean applycolor;
2669 if (texture->currentmaterialflags & MATERIALFLAG_NODRAW)
2671 r_shadow_rtlight = NULL;
2672 renderstats.entities_surfaces += texturenumsurfaces;
2673 // FIXME: identify models using a better check than model->brush.shadowmesh
2674 lightmode = ((ent->effects & EF_FULLBRIGHT) || model->brush.shadowmesh) ? 0 : 2;
2675 GL_DepthTest(!(texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
2676 if ((texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (ent->flags & RENDER_NOCULLFACE))
2677 qglDisable(GL_CULL_FACE);
2678 if (r_showsurfaces.integer)
2681 GL_BlendFunc(GL_ONE, GL_ZERO);
2682 R_Mesh_ColorPointer(NULL);
2683 R_Mesh_ResetTextureState();
2684 RSurf_PrepareVerticesForBatch(ent, texture, modelorg, false, false, texturenumsurfaces, texturesurfacelist);
2685 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2687 int k = (int)(((size_t)surface) / sizeof(msurface_t));
2688 GL_Color((k & 15) * (1.0f / 16.0f), ((k >> 4) & 15) * (1.0f / 16.0f), ((k >> 8) & 15) * (1.0f / 16.0f), 0.2f);
2689 surface = texturesurfacelist[texturesurfaceindex];
2690 RSurf_Draw(surface);
2693 else if (texture->currentmaterialflags & MATERIALFLAG_SKY)
2695 // transparent sky would be ridiculous
2696 if (!(texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
2700 skyrendernow = false;
2702 // restore entity matrix
2703 R_Mesh_Matrix(&ent->matrix);
2706 // LordHavoc: HalfLife maps have freaky skypolys so don't use
2707 // skymasking on them, and Quake3 never did sky masking (unlike
2708 // software Quake and software Quake2), so disable the sky masking
2709 // in Quake3 maps as it causes problems with q3map2 sky tricks,
2710 // and skymasking also looks very bad when noclipping outside the
2711 // level, so don't use it then either.
2712 if (model->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_worldnovis)
2714 GL_Color(fogcolor[0], fogcolor[1], fogcolor[2], 1);
2715 R_Mesh_ColorPointer(NULL);
2716 R_Mesh_ResetTextureState();
2717 if (skyrendermasked)
2719 // depth-only (masking)
2720 GL_ColorMask(0,0,0,0);
2721 // just to make sure that braindead drivers don't draw
2722 // anything despite that colormask...
2723 GL_BlendFunc(GL_ZERO, GL_ONE);
2728 GL_BlendFunc(GL_ONE, GL_ZERO);
2730 RSurf_PrepareVerticesForBatch(ent, texture, modelorg, false, false, texturenumsurfaces, texturesurfacelist);
2731 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2733 surface = texturesurfacelist[texturesurfaceindex];
2734 RSurf_Draw(surface);
2736 if (skyrendermasked)
2737 GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
2741 else if (r_glsl.integer && gl_support_fragment_shader)
2743 if (texture->currentmaterialflags & MATERIALFLAG_ADD)
2745 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2746 GL_DepthMask(false);
2748 else if (texture->currentmaterialflags & MATERIALFLAG_ALPHA)
2750 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2751 GL_DepthMask(false);
2755 GL_BlendFunc(GL_ONE, GL_ZERO);
2759 R_Mesh_ColorPointer(NULL);
2760 R_Mesh_ResetTextureState();
2761 GL_Color(ent->colormod[0], ent->colormod[1], ent->colormod[2], texture->currentalpha);
2762 R_SetupSurfaceShader(ent, texture, modelorg, vec3_origin, lightmode == 2);
2763 if (!r_glsl_permutation)
2765 RSurf_PrepareVerticesForBatch(ent, texture, modelorg, true, true, texturenumsurfaces, texturesurfacelist);
2766 R_Mesh_TexCoordPointer(0, 2, model->surfmesh.data_texcoordtexture2f);
2767 R_Mesh_TexCoordPointer(1, 3, rsurface_svector3f);
2768 R_Mesh_TexCoordPointer(2, 3, rsurface_tvector3f);
2769 R_Mesh_TexCoordPointer(3, 3, rsurface_normal3f);
2772 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2774 surface = texturesurfacelist[texturesurfaceindex];
2775 RSurf_Draw(surface);
2780 R_Mesh_TexCoordPointer(4, 2, model->surfmesh.data_texcoordlightmap2f);
2781 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2783 surface = texturesurfacelist[texturesurfaceindex];
2784 if (surface->lightmaptexture)
2786 R_Mesh_TexBind(7, R_GetTexture(surface->lightmaptexture));
2787 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
2788 R_Mesh_TexBind(8, R_GetTexture(surface->deluxemaptexture));
2789 R_Mesh_ColorPointer(NULL);
2793 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
2794 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
2795 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
2796 R_Mesh_ColorPointer(model->surfmesh.data_lightmapcolor4f);
2798 RSurf_Draw(surface);
2801 qglUseProgramObjectARB(0);
2803 else if (texture->currentnumlayers)
2806 texturelayer_t *layer;
2807 RSurf_PrepareVerticesForBatch(ent, texture, modelorg, true, false, texturenumsurfaces, texturesurfacelist);
2808 for (layerindex = 0, layer = texture->currentlayers;layerindex < texture->currentnumlayers;layerindex++, layer++)
2811 int layertexrgbscale;
2812 GL_DepthMask(layer->depthmask);
2813 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
2814 if ((layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2) && (gl_combine.integer || layer->depthmask))
2816 layertexrgbscale = 4;
2817 VectorScale(layer->color, 0.25f, layercolor);
2819 else if ((layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1) && (gl_combine.integer || layer->depthmask))
2821 layertexrgbscale = 2;
2822 VectorScale(layer->color, 0.5f, layercolor);
2826 layertexrgbscale = 1;
2827 VectorScale(layer->color, 1.0f, layercolor);
2829 layercolor[3] = layer->color[3];
2830 R_Mesh_ColorPointer(NULL);
2831 GL_Color(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
2832 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
2833 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
2834 switch (layer->type)
2836 case TEXTURELAYERTYPE_LITTEXTURE_COMBINE:
2837 memset(&m, 0, sizeof(m));
2838 m.pointer_texcoord[0] = model->surfmesh.data_texcoordlightmap2f;
2839 m.tex[1] = R_GetTexture(layer->texture);
2840 m.texmatrix[1] = layer->texmatrix;
2841 m.texrgbscale[1] = layertexrgbscale;
2842 m.pointer_texcoord[1] = model->surfmesh.data_texcoordtexture2f;
2843 R_Mesh_TextureState(&m);
2846 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2848 surface = texturesurfacelist[texturesurfaceindex];
2849 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2850 RSurf_DrawLightmap(surface, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 2, applycolor, applyfog);
2855 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2857 surface = texturesurfacelist[texturesurfaceindex];
2858 if (surface->lightmaptexture)
2860 R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
2861 RSurf_DrawLightmap(surface, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, applyfog);
2865 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2866 RSurf_DrawLightmap(surface, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 1, applycolor, applyfog);
2871 case TEXTURELAYERTYPE_LITTEXTURE_MULTIPASS:
2872 memset(&m, 0, sizeof(m));
2873 m.tex[0] = R_GetTexture(layer->texture);
2874 m.texmatrix[0] = layer->texmatrix;
2875 m.texrgbscale[0] = layertexrgbscale;
2876 m.pointer_texcoord[0] = model->surfmesh.data_texcoordlightmap2f;
2877 R_Mesh_TextureState(&m);
2880 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2882 surface = texturesurfacelist[texturesurfaceindex];
2883 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2884 RSurf_DrawLightmap(surface, 1, 1, 1, 1, 2, false, false);
2889 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2891 surface = texturesurfacelist[texturesurfaceindex];
2892 if (surface->lightmaptexture)
2894 R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
2895 RSurf_DrawLightmap(surface, 1, 1, 1, 1, 0, false, false);
2899 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2900 RSurf_DrawLightmap(surface, 1, 1, 1, 1, 1, false, false);
2904 GL_LockArrays(0, 0);
2905 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
2906 memset(&m, 0, sizeof(m));
2907 m.tex[0] = R_GetTexture(layer->texture);
2908 m.texmatrix[0] = layer->texmatrix;
2909 m.texrgbscale[0] = layertexrgbscale;
2910 m.pointer_texcoord[0] = model->surfmesh.data_texcoordtexture2f;
2911 R_Mesh_TextureState(&m);
2912 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2914 surface = texturesurfacelist[texturesurfaceindex];
2915 RSurf_DrawLightmap(surface, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, false);
2918 case TEXTURELAYERTYPE_LITTEXTURE_VERTEX:
2919 memset(&m, 0, sizeof(m));
2920 m.tex[0] = R_GetTexture(layer->texture);
2921 m.texmatrix[0] = layer->texmatrix;
2922 m.texrgbscale[0] = layertexrgbscale;
2923 m.pointer_texcoord[0] = model->surfmesh.data_texcoordtexture2f;
2924 R_Mesh_TextureState(&m);
2927 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2929 surface = texturesurfacelist[texturesurfaceindex];
2930 RSurf_DrawLightmap(surface, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 2, applycolor, applyfog);
2935 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2937 surface = texturesurfacelist[texturesurfaceindex];
2938 RSurf_DrawLightmap(surface, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 1, applycolor, applyfog);
2942 case TEXTURELAYERTYPE_TEXTURE:
2943 memset(&m, 0, sizeof(m));
2944 m.tex[0] = R_GetTexture(layer->texture);
2945 m.texmatrix[0] = layer->texmatrix;
2946 m.texrgbscale[0] = layertexrgbscale;
2947 m.pointer_texcoord[0] = model->surfmesh.data_texcoordtexture2f;
2948 R_Mesh_TextureState(&m);
2949 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2951 surface = texturesurfacelist[texturesurfaceindex];
2952 RSurf_DrawLightmap(surface, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, applyfog);
2955 case TEXTURELAYERTYPE_FOG:
2956 R_Mesh_ColorPointer(rsurface_array_color4f);
2959 memset(&m, 0, sizeof(m));
2960 m.tex[0] = R_GetTexture(layer->texture);
2961 m.texmatrix[0] = layer->texmatrix;
2962 m.pointer_texcoord[0] = model->surfmesh.data_texcoordtexture2f;
2963 R_Mesh_TextureState(&m);
2966 R_Mesh_ResetTextureState();
2967 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2971 surface = texturesurfacelist[texturesurfaceindex];
2972 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)
2974 f = VERTEXFOGTABLE(VectorDistance(v, modelorg));
2975 c[0] = layercolor[0];
2976 c[1] = layercolor[1];
2977 c[2] = layercolor[2];
2978 c[3] = f * layercolor[3];
2980 RSurf_Draw(surface);
2984 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
2986 GL_LockArrays(0, 0);
2987 // if trying to do overbright on first pass of an opaque surface
2988 // when combine is not supported, brighten as a post process
2989 if (layertexrgbscale > 1 && !gl_combine.integer && layer->depthmask)
2992 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
2993 R_Mesh_ColorPointer(NULL);
2994 GL_Color(1, 1, 1, 1);
2995 R_Mesh_ResetTextureState();
2996 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2998 surface = texturesurfacelist[texturesurfaceindex];
2999 for (scale = 1;scale < layertexrgbscale;scale <<= 1)
3000 RSurf_Draw(surface);
3002 GL_LockArrays(0, 0);
3006 GL_LockArrays(0, 0);
3007 if ((texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (ent->flags & RENDER_NOCULLFACE))
3008 qglEnable(GL_CULL_FACE);
3011 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight)
3013 msurface_t *surface = ent->model->data_surfaces + surfacenumber;
3017 texture = surface->texture;
3018 if (texture->basematerialflags & MATERIALFLAG_SKY)
3019 return; // transparent sky is too difficult
3020 R_UpdateTextureInfo(ent, texture);
3022 R_Mesh_Matrix(&ent->matrix);
3023 Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
3024 R_DrawTextureSurfaceList(ent, texture->currentframe, 1, &surface, modelorg);
3027 void R_QueueTextureSurfaceList(entity_render_t *ent, texture_t *texture, int texturenumsurfaces, msurface_t **texturesurfacelist, const vec3_t modelorg)
3029 int texturesurfaceindex;
3030 const msurface_t *surface;
3031 vec3_t tempcenter, center;
3032 if (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT)
3034 // drawing sky transparently would be too difficult
3035 if (!(texture->currentmaterialflags & MATERIALFLAG_SKY))
3037 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3039 surface = texturesurfacelist[texturesurfaceindex];
3040 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
3041 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
3042 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
3043 Matrix4x4_Transform(&ent->matrix, tempcenter, center);
3044 R_MeshQueue_AddTransparent(texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_vieworigin : center, R_DrawSurface_TransparentCallback, ent, surface - ent->model->data_surfaces, r_shadow_rtlight);
3049 R_DrawTextureSurfaceList(ent, texture, texturenumsurfaces, texturesurfacelist, modelorg);
3052 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
3053 void R_DrawSurfaces(entity_render_t *ent, qboolean skysurfaces)
3055 int i, j, f, flagsmask;
3056 int counttriangles = 0;
3057 msurface_t *surface, **surfacechain;
3058 texture_t *t, *texture;
3059 model_t *model = ent->model;
3061 const int maxsurfacelist = 1024;
3062 int numsurfacelist = 0;
3063 msurface_t *surfacelist[1024];
3066 R_Mesh_Matrix(&ent->matrix);
3067 Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
3069 // update light styles
3070 if (!skysurfaces && model->brushq1.light_styleupdatechains)
3072 for (i = 0;i < model->brushq1.light_styles;i++)
3074 if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
3076 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
3077 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
3078 for (;(surface = *surfacechain);surfacechain++)
3079 surface->cached_dlight = true;
3084 R_UpdateAllTextureInfo(ent);
3085 flagsmask = skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL);
3090 if (ent == r_refdef.worldentity)
3092 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
3094 if (!r_worldsurfacevisible[j])
3096 if (t != surface->texture)
3100 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
3103 t = surface->texture;
3104 texture = t->currentframe;
3105 f = texture->currentmaterialflags & flagsmask;
3107 if (f && surface->num_triangles)
3109 // if lightmap parameters changed, rebuild lightmap texture
3110 if (surface->cached_dlight)
3111 R_BuildLightMap(ent, surface);
3112 // add face to draw list
3113 surfacelist[numsurfacelist++] = surface;
3114 counttriangles += surface->num_triangles;
3115 if (numsurfacelist >= maxsurfacelist)
3117 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
3125 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
3127 if (t != surface->texture)
3131 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
3134 t = surface->texture;
3135 texture = t->currentframe;
3136 f = texture->currentmaterialflags & flagsmask;
3138 if (f && surface->num_triangles)
3140 // if lightmap parameters changed, rebuild lightmap texture
3141 if (surface->cached_dlight)
3142 R_BuildLightMap(ent, surface);
3143 // add face to draw list
3144 surfacelist[numsurfacelist++] = surface;
3145 counttriangles += surface->num_triangles;
3146 if (numsurfacelist >= maxsurfacelist)
3148 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
3155 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
3156 renderstats.entities_triangles += counttriangles;
3157 if (gl_support_fragment_shader)
3158 qglUseProgramObjectARB(0);
3160 if (r_showcollisionbrushes.integer && model->brush.num_brushes && !skysurfaces)
3163 msurface_t *surface;
3165 R_Mesh_Matrix(&ent->matrix);
3166 R_Mesh_ColorPointer(NULL);
3167 R_Mesh_ResetTextureState();
3168 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
3169 GL_DepthMask(false);
3170 GL_DepthTest(!r_showdisabledepthtest.integer);
3171 qglPolygonOffset(r_polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_polygonoffset + r_showcollisionbrushes_polygonoffset.value);
3172 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
3173 if (brush->colbrushf && brush->colbrushf->numtriangles)
3174 R_DrawCollisionBrush(brush->colbrushf);
3175 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
3176 if (surface->num_collisiontriangles)
3177 R_DrawCollisionSurface(ent, surface);
3178 qglPolygonOffset(r_polygonfactor, r_polygonoffset);
3181 if (r_showtris.integer || r_shownormals.integer)
3184 const int *elements;
3188 if (r_showdisabledepthtest.integer)
3189 qglDepthFunc(GL_ALWAYS);
3190 GL_BlendFunc(GL_ONE, GL_ZERO);
3191 R_Mesh_ColorPointer(NULL);
3192 R_Mesh_ResetTextureState();
3193 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
3195 if (ent == r_refdef.worldentity && !r_worldsurfacevisible[j])
3197 texture = surface->texture->currentframe;
3198 if ((texture->currentmaterialflags & flagsmask) && surface->num_triangles)
3200 RSurf_PrepareVerticesForBatch(ent, texture, modelorg, false, r_shownormals.integer != 0, 1, &surface);
3201 if (r_showtris.integer)
3203 if (!texture->currentlayers->depthmask)
3204 GL_Color(r_showtris.value, 0, 0, 1);
3205 else if (ent == r_refdef.worldentity)
3206 GL_Color(r_showtris.value, r_showtris.value, r_showtris.value, 1);
3208 GL_Color(0, r_showtris.value, 0, 1);
3209 elements = (ent->model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
3211 for (k = 0;k < surface->num_triangles;k++, elements += 3)
3213 qglArrayElement(elements[0]);qglArrayElement(elements[1]);
3214 qglArrayElement(elements[1]);qglArrayElement(elements[2]);
3215 qglArrayElement(elements[2]);qglArrayElement(elements[0]);
3219 if (r_shownormals.integer)
3221 GL_Color(r_shownormals.value, 0, 0, 1);
3223 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
3225 VectorCopy(rsurface_vertex3f + l * 3, v);
3226 qglVertex3f(v[0], v[1], v[2]);
3227 VectorMA(v, 8, rsurface_svector3f + l * 3, v);
3228 qglVertex3f(v[0], v[1], v[2]);
3231 GL_Color(0, 0, r_shownormals.value, 1);
3233 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
3235 VectorCopy(rsurface_vertex3f + l * 3, v);
3236 qglVertex3f(v[0], v[1], v[2]);
3237 VectorMA(v, 8, rsurface_tvector3f + l * 3, v);
3238 qglVertex3f(v[0], v[1], v[2]);
3241 GL_Color(0, r_shownormals.value, 0, 1);
3243 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
3245 VectorCopy(rsurface_vertex3f + l * 3, v);
3246 qglVertex3f(v[0], v[1], v[2]);
3247 VectorMA(v, 8, rsurface_normal3f + l * 3, v);
3248 qglVertex3f(v[0], v[1], v[2]);
3254 if (r_showdisabledepthtest.integer)
3255 qglDepthFunc(GL_LEQUAL);