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)"};
91 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
92 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
93 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
94 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
95 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
96 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
97 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
99 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)"};
101 cvar_t r_glsl = {0, "r_glsl", "1", "enables use of OpenGL 2.0 pixel shaders for lighting"};
102 cvar_t r_glsl_offsetmapping = {0, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
103 cvar_t r_glsl_offsetmapping_reliefmapping = {0, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
104 cvar_t r_glsl_offsetmapping_scale = {0, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
105 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)"};
107 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1", "enables animation smoothing on sprites (requires r_lerpmodels 1)"};
108 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
109 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
111 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
112 cvar_t r_bloom_intensity = {CVAR_SAVE, "r_bloom_intensity", "1.5", "how bright the glow is"};
113 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
114 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
115 cvar_t r_bloom_power = {CVAR_SAVE, "r_bloom_power", "2", "how much to darken the image before blurring to make the bloom effect"};
117 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"};
119 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"};
121 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
123 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"}; // used for testing renderer code changes, otherwise does nothing
125 rtexture_t *r_bloom_texture_screen;
126 rtexture_t *r_bloom_texture_bloom;
127 rtexture_t *r_texture_blanknormalmap;
128 rtexture_t *r_texture_white;
129 rtexture_t *r_texture_black;
130 rtexture_t *r_texture_notexture;
131 rtexture_t *r_texture_whitecube;
132 rtexture_t *r_texture_normalizationcube;
133 rtexture_t *r_texture_fogattenuation;
134 rtexture_t *r_texture_fogintensity;
136 // information about each possible shader permutation
137 r_glsl_permutation_t r_glsl_permutations[SHADERPERMUTATION_COUNT];
138 // currently selected permutation
139 r_glsl_permutation_t *r_glsl_permutation;
141 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
144 for (i = 0;i < verts;i++)
155 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
158 for (i = 0;i < verts;i++)
173 vec_t fogtabledistmultiplier;
174 float fogtable[FOGTABLEWIDTH];
175 float fog_density, fog_red, fog_green, fog_blue;
177 qboolean oldgl_fogenable;
178 void R_UpdateFog(void)
180 if (gamemode == GAME_NEHAHRA)
182 if (gl_fogenable.integer)
184 oldgl_fogenable = true;
185 fog_density = gl_fogdensity.value;
186 fog_red = gl_fogred.value;
187 fog_green = gl_foggreen.value;
188 fog_blue = gl_fogblue.value;
190 else if (oldgl_fogenable)
192 oldgl_fogenable = false;
201 fogcolor[0] = fog_red = bound(0.0f, fog_red , 1.0f);
202 fogcolor[1] = fog_green = bound(0.0f, fog_green, 1.0f);
203 fogcolor[2] = fog_blue = bound(0.0f, fog_blue , 1.0f);
208 fogdensity = -4000.0f / (fog_density * fog_density);
209 // this is the point where the fog reaches 0.9986 alpha, which we
210 // consider a good enough cutoff point for the texture
211 // (0.9986 * 256 == 255.6)
212 fogrange = 400 / fog_density;
213 fograngerecip = 1.0f / fogrange;
214 fogtabledistmultiplier = FOGTABLEWIDTH * fograngerecip;
215 // fog color was already set
221 // FIXME: move this to client?
224 if (gamemode == GAME_NEHAHRA)
226 Cvar_Set("gl_fogenable", "0");
227 Cvar_Set("gl_fogdensity", "0.2");
228 Cvar_Set("gl_fogred", "0.3");
229 Cvar_Set("gl_foggreen", "0.3");
230 Cvar_Set("gl_fogblue", "0.3");
232 fog_density = fog_red = fog_green = fog_blue = 0.0f;
235 // FIXME: move this to client?
236 void FOG_registercvars(void)
241 if (gamemode == GAME_NEHAHRA)
243 Cvar_RegisterVariable (&gl_fogenable);
244 Cvar_RegisterVariable (&gl_fogdensity);
245 Cvar_RegisterVariable (&gl_fogred);
246 Cvar_RegisterVariable (&gl_foggreen);
247 Cvar_RegisterVariable (&gl_fogblue);
248 Cvar_RegisterVariable (&gl_fogstart);
249 Cvar_RegisterVariable (&gl_fogend);
252 r = (-1.0/256.0) * (FOGTABLEWIDTH * FOGTABLEWIDTH);
253 for (x = 0;x < FOGTABLEWIDTH;x++)
255 alpha = exp(r / ((double)x*(double)x));
256 if (x == FOGTABLEWIDTH - 1)
258 fogtable[x] = bound(0, alpha, 1);
262 static void R_BuildBlankTextures(void)
264 unsigned char data[4];
265 data[0] = 128; // normal X
266 data[1] = 128; // normal Y
267 data[2] = 255; // normal Z
268 data[3] = 128; // height
269 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
274 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
279 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
282 static void R_BuildNoTexture(void)
285 unsigned char pix[16][16][4];
286 // this makes a light grey/dark grey checkerboard texture
287 for (y = 0;y < 16;y++)
289 for (x = 0;x < 16;x++)
291 if ((y < 8) ^ (x < 8))
307 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_RGBA, TEXF_MIPMAP, NULL);
310 static void R_BuildWhiteCube(void)
312 unsigned char data[6*1*1*4];
313 data[ 0] = 255;data[ 1] = 255;data[ 2] = 255;data[ 3] = 255;
314 data[ 4] = 255;data[ 5] = 255;data[ 6] = 255;data[ 7] = 255;
315 data[ 8] = 255;data[ 9] = 255;data[10] = 255;data[11] = 255;
316 data[12] = 255;data[13] = 255;data[14] = 255;data[15] = 255;
317 data[16] = 255;data[17] = 255;data[18] = 255;data[19] = 255;
318 data[20] = 255;data[21] = 255;data[22] = 255;data[23] = 255;
319 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
322 static void R_BuildNormalizationCube(void)
326 vec_t s, t, intensity;
328 unsigned char data[6][NORMSIZE][NORMSIZE][4];
329 for (side = 0;side < 6;side++)
331 for (y = 0;y < NORMSIZE;y++)
333 for (x = 0;x < NORMSIZE;x++)
335 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
336 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
371 intensity = 127.0f / sqrt(DotProduct(v, v));
372 data[side][y][x][0] = 128.0f + intensity * v[0];
373 data[side][y][x][1] = 128.0f + intensity * v[1];
374 data[side][y][x][2] = 128.0f + intensity * v[2];
375 data[side][y][x][3] = 255;
379 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, &data[0][0][0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
382 static void R_BuildFogTexture(void)
387 unsigned char data1[FOGWIDTH][4];
388 unsigned char data2[FOGWIDTH][4];
389 r = (-1.0/256.0) * (FOGWIDTH * FOGWIDTH);
390 for (x = 0;x < FOGWIDTH;x++)
392 alpha = exp(r / ((double)x*(double)x));
393 if (x == FOGWIDTH - 1)
395 b = (int)(256.0 * alpha);
396 b = bound(0, b, 255);
397 data1[x][0] = 255 - b;
398 data1[x][1] = 255 - b;
399 data1[x][2] = 255 - b;
406 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
407 r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
410 static const char *builtinshaderstring =
411 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
412 "// written by Forest 'LordHavoc' Hale\n"
414 "// common definitions between vertex shader and fragment shader:\n"
416 "varying vec2 TexCoord;\n"
417 "varying vec2 TexCoordLightmap;\n"
419 "varying vec3 CubeVector;\n"
420 "varying vec3 LightVector;\n"
421 "varying vec3 EyeVector;\n"
423 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
424 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
425 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
430 "// vertex shader specific:\n"
431 "#ifdef VERTEX_SHADER\n"
433 "uniform vec3 LightPosition;\n"
434 "uniform vec3 EyePosition;\n"
435 "uniform vec3 LightDir;\n"
437 "// TODO: get rid of tangentt (texcoord2) and use a crossproduct to regenerate it from tangents (texcoord1) and normal (texcoord3)\n"
441 " gl_FrontColor = gl_Color;\n"
442 " // copy the surface texcoord\n"
443 " TexCoord = vec2(gl_TextureMatrix[0] * gl_MultiTexCoord0);\n"
444 "#if !defined(MODE_LIGHTSOURCE) && !defined(MODE_LIGHTDIRECTION)\n"
445 " TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
448 "#ifdef MODE_LIGHTSOURCE\n"
449 " // transform vertex position into light attenuation/cubemap space\n"
450 " // (-1 to +1 across the light box)\n"
451 " CubeVector = vec3(gl_TextureMatrix[3] * gl_Vertex);\n"
453 " // transform unnormalized light direction into tangent space\n"
454 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
455 " // normalize it per pixel)\n"
456 " vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
457 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
458 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
459 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
462 "#ifdef MODE_LIGHTDIRECTION\n"
463 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
464 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
465 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
468 " // transform unnormalized eye direction into tangent space\n"
469 " vec3 eyeminusvertex = EyePosition - gl_Vertex.xyz;\n"
470 " EyeVector.x = dot(eyeminusvertex, gl_MultiTexCoord1.xyz);\n"
471 " EyeVector.y = dot(eyeminusvertex, gl_MultiTexCoord2.xyz);\n"
472 " EyeVector.z = dot(eyeminusvertex, gl_MultiTexCoord3.xyz);\n"
474 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
475 " VectorS = gl_MultiTexCoord1.xyz;\n"
476 " VectorT = gl_MultiTexCoord2.xyz;\n"
477 " VectorR = gl_MultiTexCoord3.xyz;\n"
480 " // transform vertex to camera space, using ftransform to match non-VS\n"
482 " gl_Position = ftransform();\n"
485 "#endif // VERTEX_SHADER\n"
490 "// fragment shader specific:\n"
491 "#ifdef FRAGMENT_SHADER\n"
493 "uniform sampler2D Texture_Normal;\n"
494 "uniform sampler2D Texture_Color;\n"
495 "uniform sampler2D Texture_Gloss;\n"
496 "uniform samplerCube Texture_Cube;\n"
497 "uniform sampler2D Texture_FogMask;\n"
498 "uniform sampler2D Texture_Pants;\n"
499 "uniform sampler2D Texture_Shirt;\n"
500 "uniform sampler2D Texture_Lightmap;\n"
501 "uniform sampler2D Texture_Deluxemap;\n"
502 "uniform sampler2D Texture_Glow;\n"
504 "uniform vec3 LightColor;\n"
505 "uniform vec3 AmbientColor;\n"
506 "uniform vec3 DiffuseColor;\n"
507 "uniform vec3 SpecularColor;\n"
508 "uniform vec3 Color_Pants;\n"
509 "uniform vec3 Color_Shirt;\n"
510 "uniform vec3 FogColor;\n"
512 "uniform float OffsetMapping_Scale;\n"
513 "uniform float OffsetMapping_Bias;\n"
514 "uniform float FogRangeRecip;\n"
516 "uniform float AmbientScale;\n"
517 "uniform float DiffuseScale;\n"
518 "uniform float SpecularScale;\n"
519 "uniform float SpecularPower;\n"
523 " // apply offsetmapping\n"
524 "#ifdef USEOFFSETMAPPING\n"
525 " vec2 TexCoordOffset = TexCoord;\n"
526 "#define TexCoord TexCoordOffset\n"
528 " vec3 eyedir = vec3(normalize(EyeVector));\n"
529 " float depthbias = 1.0 - eyedir.z; // should this be a -?\n"
530 " depthbias = 1.0 - depthbias * depthbias;\n"
532 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
533 " // 14 sample relief mapping: linear search and then binary search\n"
534 " vec3 OffsetVector = vec3(EyeVector.xy * (1.0 / EyeVector.z) * depthbias * OffsetMapping_Scale * vec2(-0.1, 0.1), -0.1);\n"
535 " vec3 RT = vec3(TexCoord - OffsetVector.xy * 10.0, 1.0) + OffsetVector;\n"
536 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += 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;OffsetVector *= 0.5;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 " TexCoord = RT.xy;\n"
552 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
553 " vec2 OffsetVector = vec2((EyeVector.xy * (1.0 / EyeVector.z) * depthbias) * OffsetMapping_Scale * vec2(-0.333, 0.333));\n"
554 " //TexCoord += OffsetVector * 3.0;\n"
555 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
556 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
557 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
561 " // combine the diffuse textures (base, pants, shirt)\n"
562 " vec4 color = vec4(texture2D(Texture_Color, TexCoord));\n"
563 "#ifdef USECOLORMAPPING\n"
564 " color.rgb += vec3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + vec3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
570 "#ifdef MODE_LIGHTSOURCE\n"
573 " // get the surface normal and light normal\n"
574 " vec3 surfacenormal = normalize(vec3(texture2D(Texture_Normal, TexCoord)) - 0.5);\n"
575 " vec3 diffusenormal = vec3(normalize(LightVector));\n"
577 " // calculate directional shading\n"
578 " color.rgb *= (AmbientScale + DiffuseScale * max(dot(surfacenormal, diffusenormal), 0.0));\n"
579 "#ifdef USESPECULAR\n"
580 " vec3 specularnormal = vec3(normalize(diffusenormal + vec3(normalize(EyeVector))));\n"
581 " color.rgb += vec3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(max(dot(surfacenormal, specularnormal), 0.0), SpecularPower);\n"
584 "#ifdef USECUBEFILTER\n"
585 " // apply light cubemap filter\n"
586 " //color.rgb *= normalize(CubeVector) * 0.5 + 0.5;//vec3(textureCube(Texture_Cube, CubeVector));\n"
587 " color.rgb *= vec3(textureCube(Texture_Cube, CubeVector));\n"
590 " // apply light color\n"
591 " color.rgb *= LightColor;\n"
593 " // apply attenuation\n"
595 " // the attenuation is (1-(x*x+y*y+z*z)) which gives a large bright\n"
596 " // center and sharp falloff at the edge, this is about the most efficient\n"
597 " // we can get away with as far as providing illumination.\n"
599 " // pow(1-(x*x+y*y+z*z), 4) is far more realistic but needs large lights to\n"
600 " // provide significant illumination, large = slow = pain.\n"
601 " color.rgb *= max(1.0 - dot(CubeVector, CubeVector), 0.0);\n"
606 "#elif defined(MODE_LIGHTDIRECTION)\n"
607 " // directional model lighting\n"
609 " // get the surface normal and light normal\n"
610 " vec3 surfacenormal = normalize(vec3(texture2D(Texture_Normal, TexCoord)) - 0.5);\n"
611 " vec3 diffusenormal = vec3(normalize(LightVector));\n"
613 " // calculate directional shading\n"
614 " color.rgb *= AmbientColor + DiffuseColor * max(dot(surfacenormal, diffusenormal), 0.0);\n"
615 "#ifdef USESPECULAR\n"
616 " vec3 specularnormal = vec3(normalize(diffusenormal + vec3(normalize(EyeVector))));\n"
617 " color.rgb += vec3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(max(dot(surfacenormal, specularnormal), 0.0), SpecularPower);\n"
623 "#elif defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE)\n"
624 " // deluxemap lightmapping using light vectors in modelspace (evil q3map2)\n"
626 " // get the surface normal and light normal\n"
627 " vec3 surfacenormal = normalize(vec3(texture2D(Texture_Normal, TexCoord)) - 0.5);\n"
628 " vec3 diffusenormal_modelspace = vec3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - 0.5;\n"
629 " vec3 diffusenormal = normalize(vec3(dot(diffusenormal_modelspace, VectorS), dot(diffusenormal_modelspace, VectorT), dot(diffusenormal_modelspace, VectorR)));\n"
631 " // calculate directional shading\n"
632 " vec3 tempcolor = color.rgb * (DiffuseScale * max(dot(surfacenormal, diffusenormal), 0.0));\n"
633 "#ifdef USESPECULAR\n"
634 " vec3 specularnormal = vec3(normalize(diffusenormal + vec3(normalize(EyeVector))));\n"
635 " tempcolor += vec3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(max(dot(surfacenormal, specularnormal), 0.0), SpecularPower);\n"
638 " // apply lightmap color\n"
639 " color.rgb = tempcolor * vec3(texture2D(Texture_Lightmap, TexCoordLightmap)) + color.rgb * vec3(AmbientScale);\n"
644 "#elif defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
645 " // deluxemap lightmapping using light vectors in tangentspace\n"
647 " // get the surface normal and light normal\n"
648 " vec3 surfacenormal = normalize(vec3(texture2D(Texture_Normal, TexCoord)) - 0.5);\n"
649 " vec3 diffusenormal = normalize(vec3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - 0.5);\n"
651 " // calculate directional shading\n"
652 " vec3 tempcolor = color.rgb * (DiffuseScale * max(dot(surfacenormal, diffusenormal), 0.0));\n"
653 "#ifdef USESPECULAR\n"
654 " vec3 specularnormal = vec3(normalize(diffusenormal + vec3(normalize(EyeVector))));\n"
655 " tempcolor += vec3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(max(dot(surfacenormal, specularnormal), 0.0), SpecularPower);\n"
658 " // apply lightmap color\n"
659 " color.rgb = tempcolor * vec3(texture2D(Texture_Lightmap, TexCoordLightmap)) + color.rgb * vec3(AmbientScale);\n"
664 "#else // MODE none (lightmap)\n"
665 " // apply lightmap color\n"
666 " color.rgb *= vec3(texture2D(Texture_Lightmap, TexCoordLightmap)) * DiffuseScale + vec3(AmbientScale);\n"
670 " color.rgb += vec3(texture2D(Texture_Glow, TexCoord));\n"
675 " float fog = texture2D(Texture_FogMask, vec2(length(EyeVector)*FogRangeRecip, 0.0)).x;\n"
676 " color.rgb = color.rgb * fog + FogColor * (1.0 - fog);\n"
679 " gl_FragColor = color * gl_Color;\n"
682 "#endif // FRAGMENT_SHADER\n"
685 void R_GLSL_CompilePermutation(int permutation)
687 r_glsl_permutation_t *p = r_glsl_permutations + permutation;
688 int vertstrings_count;
689 int fragstrings_count;
691 const char *vertstrings_list[SHADERPERMUTATION_COUNT+1];
692 const char *fragstrings_list[SHADERPERMUTATION_COUNT+1];
693 char permutationname[256];
697 vertstrings_list[0] = "#define VERTEX_SHADER\n";
698 fragstrings_list[0] = "#define FRAGMENT_SHADER\n";
699 vertstrings_count = 1;
700 fragstrings_count = 1;
701 permutationname[0] = 0;
702 if (permutation & SHADERPERMUTATION_MODE_LIGHTSOURCE)
704 vertstrings_list[vertstrings_count++] = "#define MODE_LIGHTSOURCE\n";
705 fragstrings_list[fragstrings_count++] = "#define MODE_LIGHTSOURCE\n";
706 strlcat(permutationname, " lightsource", sizeof(permutationname));
708 if (permutation & SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_MODELSPACE)
710 vertstrings_list[vertstrings_count++] = "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n";
711 fragstrings_list[fragstrings_count++] = "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n";
712 strlcat(permutationname, " lightdirectionmap_modelspace", sizeof(permutationname));
714 if (permutation & SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)
716 vertstrings_list[vertstrings_count++] = "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n";
717 fragstrings_list[fragstrings_count++] = "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n";
718 strlcat(permutationname, " lightdirectionmap_tangentspace", sizeof(permutationname));
720 if (permutation & SHADERPERMUTATION_MODE_LIGHTDIRECTION)
722 vertstrings_list[vertstrings_count++] = "#define MODE_LIGHTDIRECTION\n";
723 fragstrings_list[fragstrings_count++] = "#define MODE_LIGHTDIRECTION\n";
724 strlcat(permutationname, " lightdirection", sizeof(permutationname));
726 if (permutation & SHADERPERMUTATION_GLOW)
728 vertstrings_list[vertstrings_count++] = "#define USEGLOW\n";
729 fragstrings_list[fragstrings_count++] = "#define USEGLOW\n";
730 strlcat(permutationname, " glow", sizeof(permutationname));
732 if (permutation & SHADERPERMUTATION_COLORMAPPING)
734 vertstrings_list[vertstrings_count++] = "#define USECOLORMAPPING\n";
735 fragstrings_list[fragstrings_count++] = "#define USECOLORMAPPING\n";
736 strlcat(permutationname, " colormapping", sizeof(permutationname));
738 if (permutation & SHADERPERMUTATION_SPECULAR)
740 vertstrings_list[vertstrings_count++] = "#define USESPECULAR\n";
741 fragstrings_list[fragstrings_count++] = "#define USESPECULAR\n";
742 strlcat(permutationname, " specular", sizeof(permutationname));
744 if (permutation & SHADERPERMUTATION_FOG)
746 vertstrings_list[vertstrings_count++] = "#define USEFOG\n";
747 fragstrings_list[fragstrings_count++] = "#define USEFOG\n";
748 strlcat(permutationname, " fog", sizeof(permutationname));
750 if (permutation & SHADERPERMUTATION_CUBEFILTER)
752 vertstrings_list[vertstrings_count++] = "#define USECUBEFILTER\n";
753 fragstrings_list[fragstrings_count++] = "#define USECUBEFILTER\n";
754 strlcat(permutationname, " cubefilter", sizeof(permutationname));
756 if (permutation & SHADERPERMUTATION_OFFSETMAPPING)
758 vertstrings_list[vertstrings_count++] = "#define USEOFFSETMAPPING\n";
759 fragstrings_list[fragstrings_count++] = "#define USEOFFSETMAPPING\n";
760 strlcat(permutationname, " offsetmapping", sizeof(permutationname));
762 if (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING)
764 vertstrings_list[vertstrings_count++] = "#define USEOFFSETMAPPING_RELIEFMAPPING\n";
765 fragstrings_list[fragstrings_count++] = "#define USEOFFSETMAPPING_RELIEFMAPPING\n";
766 strlcat(permutationname, " OFFSETMAPPING_RELIEFMAPPING", sizeof(permutationname));
768 shaderstring = (char *)FS_LoadFile("glsl/default.glsl", r_main_mempool, false, NULL);
771 Con_DPrintf("GLSL shader text loaded from disk\n");
772 vertstrings_list[vertstrings_count++] = shaderstring;
773 fragstrings_list[fragstrings_count++] = shaderstring;
777 vertstrings_list[vertstrings_count++] = builtinshaderstring;
778 fragstrings_list[fragstrings_count++] = builtinshaderstring;
780 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, fragstrings_count, fragstrings_list);
784 qglUseProgramObjectARB(p->program);
785 p->loc_Texture_Normal = qglGetUniformLocationARB(p->program, "Texture_Normal");
786 p->loc_Texture_Color = qglGetUniformLocationARB(p->program, "Texture_Color");
787 p->loc_Texture_Gloss = qglGetUniformLocationARB(p->program, "Texture_Gloss");
788 p->loc_Texture_Cube = qglGetUniformLocationARB(p->program, "Texture_Cube");
789 p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
790 p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
791 p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
792 p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
793 p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
794 p->loc_Texture_Glow = qglGetUniformLocationARB(p->program, "Texture_Glow");
795 p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
796 p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
797 p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
798 p->loc_LightColor = qglGetUniformLocationARB(p->program, "LightColor");
799 p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants");
800 p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt");
801 p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip");
802 p->loc_AmbientScale = qglGetUniformLocationARB(p->program, "AmbientScale");
803 p->loc_DiffuseScale = qglGetUniformLocationARB(p->program, "DiffuseScale");
804 p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
805 p->loc_SpecularScale = qglGetUniformLocationARB(p->program, "SpecularScale");
806 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
807 p->loc_AmbientColor = qglGetUniformLocationARB(p->program, "AmbientColor");
808 p->loc_DiffuseColor = qglGetUniformLocationARB(p->program, "DiffuseColor");
809 p->loc_SpecularColor = qglGetUniformLocationARB(p->program, "SpecularColor");
810 p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
811 if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal, 0);
812 if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color, 1);
813 if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss, 2);
814 if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube, 3);
815 if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask, 4);
816 if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants, 5);
817 if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt, 6);
818 if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap, 7);
819 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap, 8);
820 if (p->loc_Texture_Glow >= 0) qglUniform1iARB(p->loc_Texture_Glow, 9);
821 qglUseProgramObjectARB(0);
825 Con_Printf("permutation%s failed for shader %s, some features may not work properly!\n", permutationname, "glsl/default.glsl");
827 Mem_Free(shaderstring);
830 void R_GLSL_Restart_f(void)
833 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
834 if (r_glsl_permutations[i].program)
835 GL_Backend_FreeProgram(r_glsl_permutations[i].program);
836 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
839 void R_SetupSurfaceShader(const entity_render_t *ent, const texture_t *texture, const vec3_t modelorg, const vec3_t lightcolorbase, qboolean modellighting)
841 // select a permutation of the lighting shader appropriate to this
842 // combination of texture, entity, light source, and fogging, only use the
843 // minimum features necessary to avoid wasting rendering time in the
844 // fragment shader on features that are not being used
846 float specularscale = texture->specularscale;
847 r_glsl_permutation = NULL;
848 if (r_shadow_rtlight)
850 permutation |= SHADERPERMUTATION_MODE_LIGHTSOURCE;
851 specularscale *= r_shadow_rtlight->specularscale;
852 if (r_shadow_rtlight->currentcubemap != r_texture_whitecube)
853 permutation |= SHADERPERMUTATION_CUBEFILTER;
858 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTION;
859 else if (r_glsl_deluxemapping.integer >= 1 && r_refdef.worldmodel && r_refdef.worldmodel->brushq3.deluxemapping)
861 if (r_refdef.worldmodel->brushq3.deluxemapping_modelspace)
862 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_MODELSPACE;
864 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
866 else if (r_glsl_deluxemapping.integer >= 2) // fake mode
867 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
868 if (texture->skin.glow)
869 permutation |= SHADERPERMUTATION_GLOW;
871 if (specularscale > 0)
872 permutation |= SHADERPERMUTATION_SPECULAR;
874 permutation |= SHADERPERMUTATION_FOG;
875 if (texture->colormapping)
876 permutation |= SHADERPERMUTATION_COLORMAPPING;
877 if (r_glsl_offsetmapping.integer)
879 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
880 if (r_glsl_offsetmapping_reliefmapping.integer)
881 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
883 if (!r_glsl_permutations[permutation].program)
885 if (!r_glsl_permutations[permutation].compiled)
886 R_GLSL_CompilePermutation(permutation);
887 if (!r_glsl_permutations[permutation].program)
889 // remove features until we find a valid permutation
891 for (i = SHADERPERMUTATION_COUNT-1;;i>>=1)
893 // reduce i more quickly whenever it would not remove any bits
897 if (!r_glsl_permutations[permutation].compiled)
898 R_GLSL_CompilePermutation(permutation);
899 if (r_glsl_permutations[permutation].program)
902 return; // utterly failed
906 r_glsl_permutation = r_glsl_permutations + permutation;
908 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
909 R_Mesh_TexMatrix(0, &texture->currenttexmatrix);
910 if (permutation & SHADERPERMUTATION_MODE_LIGHTSOURCE)
912 R_Mesh_TexMatrix(3, &r_shadow_entitytolight);
913 //if (r_glsl_permutation->loc_Texture_Cube >= 0) R_Mesh_TexBindCubeMap(3, R_GetTexture(r_shadow_rtlight->currentcubemap));
914 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]);
915 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
916 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_shadow_rtlight->ambientscale);
917 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_shadow_rtlight->diffusescale);
918 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, specularscale);
920 else if (permutation & SHADERPERMUTATION_MODE_LIGHTDIRECTION)
922 if (texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
924 if (r_glsl_permutation->loc_AmbientColor >= 0)
925 qglUniform3fARB(r_glsl_permutation->loc_AmbientColor, 1, 1, 1);
926 if (r_glsl_permutation->loc_DiffuseColor >= 0)
927 qglUniform3fARB(r_glsl_permutation->loc_DiffuseColor, 0, 0, 0);
928 if (r_glsl_permutation->loc_SpecularColor >= 0)
929 qglUniform3fARB(r_glsl_permutation->loc_SpecularColor, 0, 0, 0);
930 if (r_glsl_permutation->loc_LightDir >= 0)
931 qglUniform3fARB(r_glsl_permutation->loc_LightDir, 0, 0, -1);
935 if (r_glsl_permutation->loc_AmbientColor >= 0)
936 qglUniform3fARB(r_glsl_permutation->loc_AmbientColor, ent->modellight_ambient[0], ent->modellight_ambient[1], ent->modellight_ambient[2]);
937 if (r_glsl_permutation->loc_DiffuseColor >= 0)
938 qglUniform3fARB(r_glsl_permutation->loc_DiffuseColor, ent->modellight_diffuse[0], ent->modellight_diffuse[1], ent->modellight_diffuse[2]);
939 if (r_glsl_permutation->loc_SpecularColor >= 0)
940 qglUniform3fARB(r_glsl_permutation->loc_SpecularColor, ent->modellight_diffuse[0] * texture->specularscale, ent->modellight_diffuse[1] * texture->specularscale, ent->modellight_diffuse[2] * texture->specularscale);
941 if (r_glsl_permutation->loc_LightDir >= 0)
942 qglUniform3fARB(r_glsl_permutation->loc_LightDir, ent->modellight_lightdir[0], ent->modellight_lightdir[1], ent->modellight_lightdir[2]);
947 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_ambient.value * 2.0f / 128.0f);
948 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_lightmapintensity * 2.0f);
949 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, r_lightmapintensity * specularscale * 2.0f);
951 if (r_glsl_permutation->loc_Texture_Normal >= 0) R_Mesh_TexBind(0, R_GetTexture(texture->skin.nmap));
952 if (r_glsl_permutation->loc_Texture_Color >= 0) R_Mesh_TexBind(1, R_GetTexture(texture->basetexture));
953 if (r_glsl_permutation->loc_Texture_Gloss >= 0) R_Mesh_TexBind(2, R_GetTexture(texture->glosstexture));
954 if (r_glsl_permutation->loc_Texture_FogMask >= 0) R_Mesh_TexBind(4, R_GetTexture(r_texture_fogattenuation));
955 if (r_glsl_permutation->loc_Texture_Pants >= 0) R_Mesh_TexBind(5, R_GetTexture(texture->skin.pants));
956 if (r_glsl_permutation->loc_Texture_Shirt >= 0) R_Mesh_TexBind(6, R_GetTexture(texture->skin.shirt));
957 if (r_glsl_permutation->loc_Texture_Glow >= 0) R_Mesh_TexBind(9, R_GetTexture(texture->skin.glow));
958 if (r_glsl_permutation->loc_FogColor >= 0)
960 // additive passes are only darkened by fog, not tinted
961 if (r_shadow_rtlight || (texture->currentmaterialflags & MATERIALFLAG_ADD))
962 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
964 qglUniform3fARB(r_glsl_permutation->loc_FogColor, fogcolor[0], fogcolor[1], fogcolor[2]);
966 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, modelorg[0], modelorg[1], modelorg[2]);
967 if (r_glsl_permutation->loc_Color_Pants >= 0)
969 if (texture->skin.pants)
970 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, ent->colormap_pantscolor[0], ent->colormap_pantscolor[1], ent->colormap_pantscolor[2]);
972 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
974 if (r_glsl_permutation->loc_Color_Shirt >= 0)
976 if (texture->skin.shirt)
977 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, ent->colormap_shirtcolor[0], ent->colormap_shirtcolor[1], ent->colormap_shirtcolor[2]);
979 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
981 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, fograngerecip);
982 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, texture->specularpower);
983 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
987 void gl_main_start(void)
989 r_main_texturepool = R_AllocTexturePool();
990 r_bloom_texture_screen = NULL;
991 r_bloom_texture_bloom = NULL;
992 R_BuildBlankTextures();
994 if (gl_texturecubemap)
997 R_BuildNormalizationCube();
1000 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
1003 void gl_main_shutdown(void)
1005 R_FreeTexturePool(&r_main_texturepool);
1006 r_bloom_texture_screen = NULL;
1007 r_bloom_texture_bloom = NULL;
1008 r_texture_blanknormalmap = NULL;
1009 r_texture_white = NULL;
1010 r_texture_black = NULL;
1011 r_texture_whitecube = NULL;
1012 r_texture_normalizationcube = NULL;
1016 extern void CL_ParseEntityLump(char *entitystring);
1017 void gl_main_newmap(void)
1019 // FIXME: move this code to client
1021 char *entities, entname[MAX_QPATH];
1025 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
1026 l = (int)strlen(entname) - 4;
1027 if (l >= 0 && !strcmp(entname + l, ".bsp"))
1029 strcpy(entname + l, ".ent");
1030 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
1032 CL_ParseEntityLump(entities);
1037 if (cl.worldmodel->brush.entities)
1038 CL_ParseEntityLump(cl.worldmodel->brush.entities);
1042 void GL_Main_Init(void)
1044 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
1046 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed\n");
1047 FOG_registercvars(); // FIXME: move this fog stuff to client?
1048 Cvar_RegisterVariable(&r_nearclip);
1049 Cvar_RegisterVariable(&r_showsurfaces);
1050 Cvar_RegisterVariable(&r_showtris);
1051 Cvar_RegisterVariable(&r_shownormals);
1052 Cvar_RegisterVariable(&r_showlighting);
1053 Cvar_RegisterVariable(&r_showshadowvolumes);
1054 Cvar_RegisterVariable(&r_showcollisionbrushes);
1055 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
1056 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
1057 Cvar_RegisterVariable(&r_showdisabledepthtest);
1058 Cvar_RegisterVariable(&r_drawentities);
1059 Cvar_RegisterVariable(&r_drawviewmodel);
1060 Cvar_RegisterVariable(&r_speeds);
1061 Cvar_RegisterVariable(&r_fullbrights);
1062 Cvar_RegisterVariable(&r_wateralpha);
1063 Cvar_RegisterVariable(&r_dynamic);
1064 Cvar_RegisterVariable(&r_fullbright);
1065 Cvar_RegisterVariable(&r_textureunits);
1066 Cvar_RegisterVariable(&r_glsl);
1067 Cvar_RegisterVariable(&r_glsl_offsetmapping);
1068 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
1069 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
1070 Cvar_RegisterVariable(&r_glsl_deluxemapping);
1071 Cvar_RegisterVariable(&r_lerpsprites);
1072 Cvar_RegisterVariable(&r_lerpmodels);
1073 Cvar_RegisterVariable(&r_waterscroll);
1074 Cvar_RegisterVariable(&r_bloom);
1075 Cvar_RegisterVariable(&r_bloom_intensity);
1076 Cvar_RegisterVariable(&r_bloom_blur);
1077 Cvar_RegisterVariable(&r_bloom_resolution);
1078 Cvar_RegisterVariable(&r_bloom_power);
1079 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
1080 Cvar_RegisterVariable(&developer_texturelogging);
1081 Cvar_RegisterVariable(&gl_lightmaps);
1082 Cvar_RegisterVariable(&r_test);
1083 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
1084 Cvar_SetValue("r_fullbrights", 0);
1085 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
1088 static vec3_t r_farclip_origin;
1089 static vec3_t r_farclip_direction;
1090 static vec_t r_farclip_directiondist;
1091 static vec_t r_farclip_meshfarclip;
1092 static int r_farclip_directionbit0;
1093 static int r_farclip_directionbit1;
1094 static int r_farclip_directionbit2;
1096 // enlarge farclip to accomodate box
1097 static void R_FarClip_Box(vec3_t mins, vec3_t maxs)
1100 d = (r_farclip_directionbit0 ? mins[0] : maxs[0]) * r_farclip_direction[0]
1101 + (r_farclip_directionbit1 ? mins[1] : maxs[1]) * r_farclip_direction[1]
1102 + (r_farclip_directionbit2 ? mins[2] : maxs[2]) * r_farclip_direction[2];
1103 if (r_farclip_meshfarclip < d)
1104 r_farclip_meshfarclip = d;
1107 // return farclip value
1108 static float R_FarClip(vec3_t origin, vec3_t direction, vec_t startfarclip)
1112 VectorCopy(origin, r_farclip_origin);
1113 VectorCopy(direction, r_farclip_direction);
1114 r_farclip_directiondist = DotProduct(r_farclip_origin, r_farclip_direction);
1115 r_farclip_directionbit0 = r_farclip_direction[0] < 0;
1116 r_farclip_directionbit1 = r_farclip_direction[1] < 0;
1117 r_farclip_directionbit2 = r_farclip_direction[2] < 0;
1118 r_farclip_meshfarclip = r_farclip_directiondist + startfarclip;
1120 if (r_refdef.worldmodel)
1121 R_FarClip_Box(r_refdef.worldmodel->normalmins, r_refdef.worldmodel->normalmaxs);
1122 for (i = 0;i < r_refdef.numentities;i++)
1123 R_FarClip_Box(r_refdef.entities[i]->mins, r_refdef.entities[i]->maxs);
1125 return r_farclip_meshfarclip - r_farclip_directiondist;
1128 extern void R_Textures_Init(void);
1129 extern void GL_Draw_Init(void);
1130 extern void GL_Main_Init(void);
1131 extern void R_Shadow_Init(void);
1132 extern void R_Sky_Init(void);
1133 extern void GL_Surf_Init(void);
1134 extern void R_Crosshairs_Init(void);
1135 extern void R_Light_Init(void);
1136 extern void R_Particles_Init(void);
1137 extern void R_Explosion_Init(void);
1138 extern void gl_backend_init(void);
1139 extern void Sbar_Init(void);
1140 extern void R_LightningBeams_Init(void);
1141 extern void Mod_RenderInit(void);
1143 void Render_Init(void)
1153 R_Crosshairs_Init();
1158 R_LightningBeams_Init();
1167 extern char *ENGINE_EXTENSIONS;
1170 VID_CheckExtensions();
1172 // LordHavoc: report supported extensions
1173 Con_DPrintf("\nengine extensions: %s\n", vm_sv_extensions );
1175 // clear to black (loading plaque will be seen over this)
1176 qglClearColor(0,0,0,1);
1177 qglClear(GL_COLOR_BUFFER_BIT);
1180 int R_CullBox(const vec3_t mins, const vec3_t maxs)
1184 for (i = 0;i < 4;i++)
1191 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1195 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1199 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1203 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1207 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1211 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1215 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1219 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1227 //==================================================================================
1229 static void R_UpdateEntityLighting(entity_render_t *ent)
1231 vec3_t tempdiffusenormal;
1232 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));
1233 VectorClear(ent->modellight_diffuse);
1234 VectorClear(ent->modellight_lightdir);
1235 if ((ent->flags & RENDER_LIGHT) && r_refdef.worldmodel && r_refdef.worldmodel->brush.LightPoint)
1236 r_refdef.worldmodel->brush.LightPoint(r_refdef.worldmodel, ent->origin, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
1238 VectorSet(ent->modellight_ambient, 1, 1, 1);
1239 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
1240 VectorNormalize(ent->modellight_lightdir);
1241 ent->modellight_ambient[0] *= ent->colormod[0] * r_lightmapintensity;
1242 ent->modellight_ambient[1] *= ent->colormod[1] * r_lightmapintensity;
1243 ent->modellight_ambient[2] *= ent->colormod[2] * r_lightmapintensity;
1244 ent->modellight_diffuse[0] *= ent->colormod[0] * r_lightmapintensity;
1245 ent->modellight_diffuse[1] *= ent->colormod[1] * r_lightmapintensity;
1246 ent->modellight_diffuse[2] *= ent->colormod[2] * r_lightmapintensity;
1249 static void R_MarkEntities (void)
1252 entity_render_t *ent;
1254 if (!r_drawentities.integer)
1257 r_refdef.worldentity->visframe = r_framecount;
1258 renderimask = envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : (chase_active.integer ? 0 : RENDER_EXTERIORMODEL);
1259 if (r_refdef.worldmodel && r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs)
1261 // worldmodel can check visibility
1262 for (i = 0;i < r_refdef.numentities;i++)
1264 ent = r_refdef.entities[i];
1265 // some of the renderer still relies on origin...
1266 Matrix4x4_OriginFromMatrix(&ent->matrix, ent->origin);
1267 // some of the renderer still relies on scale...
1268 ent->scale = Matrix4x4_ScaleFromMatrix(&ent->matrix);
1269 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)))
1271 ent->visframe = r_framecount;
1272 R_UpdateEntityLighting(ent);
1278 // no worldmodel or it can't check visibility
1279 for (i = 0;i < r_refdef.numentities;i++)
1281 ent = r_refdef.entities[i];
1282 // some of the renderer still relies on origin...
1283 Matrix4x4_OriginFromMatrix(&ent->matrix, ent->origin);
1284 // some of the renderer still relies on scale...
1285 ent->scale = Matrix4x4_ScaleFromMatrix(&ent->matrix);
1286 if (!(ent->flags & renderimask) && !R_CullBox(ent->mins, ent->maxs) && (ent->effects & EF_NODEPTHTEST))
1288 ent->visframe = r_framecount;
1289 R_UpdateEntityLighting(ent);
1295 // only used if skyrendermasked, and normally returns false
1296 int R_DrawBrushModelsSky (void)
1299 entity_render_t *ent;
1301 if (!r_drawentities.integer)
1305 for (i = 0;i < r_refdef.numentities;i++)
1307 ent = r_refdef.entities[i];
1308 if (ent->visframe == r_framecount && ent->model && ent->model->DrawSky)
1310 ent->model->DrawSky(ent);
1317 void R_DrawNoModel(entity_render_t *ent);
1318 void R_DrawModels(void)
1321 entity_render_t *ent;
1323 if (!r_drawentities.integer)
1326 for (i = 0;i < r_refdef.numentities;i++)
1328 ent = r_refdef.entities[i];
1329 if (ent->visframe == r_framecount)
1331 renderstats.entities++;
1332 if (ent->model && ent->model->Draw != NULL)
1333 ent->model->Draw(ent);
1340 static void R_SetFrustum(void)
1342 // break apart the view matrix into vectors for various purposes
1343 Matrix4x4_ToVectors(&r_view_matrix, r_viewforward, r_viewleft, r_viewup, r_vieworigin);
1344 VectorNegate(r_viewleft, r_viewright);
1347 frustum[0].normal[0] = 0 - 1.0 / r_refdef.frustum_x;
1348 frustum[0].normal[1] = 0 - 0;
1349 frustum[0].normal[2] = -1 - 0;
1350 frustum[1].normal[0] = 0 + 1.0 / r_refdef.frustum_x;
1351 frustum[1].normal[1] = 0 + 0;
1352 frustum[1].normal[2] = -1 + 0;
1353 frustum[2].normal[0] = 0 - 0;
1354 frustum[2].normal[1] = 0 - 1.0 / r_refdef.frustum_y;
1355 frustum[2].normal[2] = -1 - 0;
1356 frustum[3].normal[0] = 0 + 0;
1357 frustum[3].normal[1] = 0 + 1.0 / r_refdef.frustum_y;
1358 frustum[3].normal[2] = -1 + 0;
1362 zNear = r_nearclip.value;
1363 nudge = 1.0 - 1.0 / (1<<23);
1364 frustum[4].normal[0] = 0 - 0;
1365 frustum[4].normal[1] = 0 - 0;
1366 frustum[4].normal[2] = -1 - -nudge;
1367 frustum[4].dist = 0 - -2 * zNear * nudge;
1368 frustum[5].normal[0] = 0 + 0;
1369 frustum[5].normal[1] = 0 + 0;
1370 frustum[5].normal[2] = -1 + -nudge;
1371 frustum[5].dist = 0 + -2 * zNear * nudge;
1377 frustum[0].normal[0] = m[3] - m[0];
1378 frustum[0].normal[1] = m[7] - m[4];
1379 frustum[0].normal[2] = m[11] - m[8];
1380 frustum[0].dist = m[15] - m[12];
1382 frustum[1].normal[0] = m[3] + m[0];
1383 frustum[1].normal[1] = m[7] + m[4];
1384 frustum[1].normal[2] = m[11] + m[8];
1385 frustum[1].dist = m[15] + m[12];
1387 frustum[2].normal[0] = m[3] - m[1];
1388 frustum[2].normal[1] = m[7] - m[5];
1389 frustum[2].normal[2] = m[11] - m[9];
1390 frustum[2].dist = m[15] - m[13];
1392 frustum[3].normal[0] = m[3] + m[1];
1393 frustum[3].normal[1] = m[7] + m[5];
1394 frustum[3].normal[2] = m[11] + m[9];
1395 frustum[3].dist = m[15] + m[13];
1397 frustum[4].normal[0] = m[3] - m[2];
1398 frustum[4].normal[1] = m[7] - m[6];
1399 frustum[4].normal[2] = m[11] - m[10];
1400 frustum[4].dist = m[15] - m[14];
1402 frustum[5].normal[0] = m[3] + m[2];
1403 frustum[5].normal[1] = m[7] + m[6];
1404 frustum[5].normal[2] = m[11] + m[10];
1405 frustum[5].dist = m[15] + m[14];
1410 VectorMAM(1, r_viewforward, 1.0 / -r_refdef.frustum_x, r_viewleft, frustum[0].normal);
1411 VectorMAM(1, r_viewforward, 1.0 / r_refdef.frustum_x, r_viewleft, frustum[1].normal);
1412 VectorMAM(1, r_viewforward, 1.0 / -r_refdef.frustum_y, r_viewup, frustum[2].normal);
1413 VectorMAM(1, r_viewforward, 1.0 / r_refdef.frustum_y, r_viewup, frustum[3].normal);
1414 VectorCopy(r_viewforward, frustum[4].normal);
1415 VectorNormalize(frustum[0].normal);
1416 VectorNormalize(frustum[1].normal);
1417 VectorNormalize(frustum[2].normal);
1418 VectorNormalize(frustum[3].normal);
1419 frustum[0].dist = DotProduct (r_vieworigin, frustum[0].normal);
1420 frustum[1].dist = DotProduct (r_vieworigin, frustum[1].normal);
1421 frustum[2].dist = DotProduct (r_vieworigin, frustum[2].normal);
1422 frustum[3].dist = DotProduct (r_vieworigin, frustum[3].normal);
1423 frustum[4].dist = DotProduct (r_vieworigin, frustum[4].normal) + r_nearclip.value;
1424 PlaneClassify(&frustum[0]);
1425 PlaneClassify(&frustum[1]);
1426 PlaneClassify(&frustum[2]);
1427 PlaneClassify(&frustum[3]);
1428 PlaneClassify(&frustum[4]);
1430 // LordHavoc: note to all quake engine coders, Quake had a special case
1431 // for 90 degrees which assumed a square view (wrong), so I removed it,
1432 // Quake2 has it disabled as well.
1434 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
1435 //RotatePointAroundVector( frustum[0].normal, r_viewup, r_viewforward, -(90 - r_refdef.fov_x / 2));
1436 //frustum[0].dist = DotProduct (r_vieworigin, frustum[0].normal);
1437 //PlaneClassify(&frustum[0]);
1439 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
1440 //RotatePointAroundVector( frustum[1].normal, r_viewup, r_viewforward, (90 - r_refdef.fov_x / 2));
1441 //frustum[1].dist = DotProduct (r_vieworigin, frustum[1].normal);
1442 //PlaneClassify(&frustum[1]);
1444 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
1445 //RotatePointAroundVector( frustum[2].normal, r_viewleft, r_viewforward, -(90 - r_refdef.fov_y / 2));
1446 //frustum[2].dist = DotProduct (r_vieworigin, frustum[2].normal);
1447 //PlaneClassify(&frustum[2]);
1449 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
1450 //RotatePointAroundVector( frustum[3].normal, r_viewleft, r_viewforward, (90 - r_refdef.fov_y / 2));
1451 //frustum[3].dist = DotProduct (r_vieworigin, frustum[3].normal);
1452 //PlaneClassify(&frustum[3]);
1455 //VectorCopy(r_viewforward, frustum[4].normal);
1456 //frustum[4].dist = DotProduct (r_vieworigin, frustum[4].normal) + r_nearclip.value;
1457 //PlaneClassify(&frustum[4]);
1460 static void R_BlendView(void)
1462 int screenwidth, screenheight;
1467 float texcoord2f[3][8];
1469 // set the (poorly named) screenwidth and screenheight variables to
1470 // a power of 2 at least as large as the screen, these will define the
1471 // size of the texture to allocate
1472 for (screenwidth = 1;screenwidth < vid.width;screenwidth *= 2);
1473 for (screenheight = 1;screenheight < vid.height;screenheight *= 2);
1475 doblend = r_refdef.viewblend[3] >= 0.01f;
1476 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;
1478 if (!dobloom && !doblend)
1481 GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
1483 GL_DepthTest(false);
1484 R_Mesh_Matrix(&identitymatrix);
1485 // vertex coordinates for a quad that covers the screen exactly
1486 vertex3f[0] = 0;vertex3f[1] = 0;vertex3f[2] = 0;
1487 vertex3f[3] = 1;vertex3f[4] = 0;vertex3f[5] = 0;
1488 vertex3f[6] = 1;vertex3f[7] = 1;vertex3f[8] = 0;
1489 vertex3f[9] = 0;vertex3f[10] = 1;vertex3f[11] = 0;
1492 int bloomwidth, bloomheight, x, dobloomblend, range;
1493 float xoffset, yoffset, r;
1494 renderstats.bloom++;
1495 // allocate textures as needed
1496 if (!r_bloom_texture_screen)
1497 r_bloom_texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", screenwidth, screenheight, NULL, TEXTYPE_RGBA, TEXF_FORCENEAREST | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
1498 if (!r_bloom_texture_bloom)
1499 r_bloom_texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", screenwidth, screenheight, NULL, TEXTYPE_RGBA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
1500 // set bloomwidth and bloomheight to the bloom resolution that will be
1501 // used (often less than the screen resolution for faster rendering)
1502 bloomwidth = min(r_view_width, r_bloom_resolution.integer);
1503 bloomheight = min(r_view_height, bloomwidth * r_view_height / r_view_width);
1504 // set up a texcoord array for the full resolution screen image
1505 // (we have to keep this around to copy back during final render)
1506 texcoord2f[0][0] = 0;
1507 texcoord2f[0][1] = (float)r_view_height / (float)screenheight;
1508 texcoord2f[0][2] = (float)r_view_width / (float)screenwidth;
1509 texcoord2f[0][3] = (float)r_view_height / (float)screenheight;
1510 texcoord2f[0][4] = (float)r_view_width / (float)screenwidth;
1511 texcoord2f[0][5] = 0;
1512 texcoord2f[0][6] = 0;
1513 texcoord2f[0][7] = 0;
1514 // set up a texcoord array for the reduced resolution bloom image
1515 // (which will be additive blended over the screen image)
1516 texcoord2f[1][0] = 0;
1517 texcoord2f[1][1] = (float)bloomheight / (float)screenheight;
1518 texcoord2f[1][2] = (float)bloomwidth / (float)screenwidth;
1519 texcoord2f[1][3] = (float)bloomheight / (float)screenheight;
1520 texcoord2f[1][4] = (float)bloomwidth / (float)screenwidth;
1521 texcoord2f[1][5] = 0;
1522 texcoord2f[1][6] = 0;
1523 texcoord2f[1][7] = 0;
1524 memset(&m, 0, sizeof(m));
1525 m.pointer_vertex = vertex3f;
1526 m.pointer_texcoord[0] = texcoord2f[0];
1527 m.tex[0] = R_GetTexture(r_bloom_texture_screen);
1529 // copy view into the full resolution screen image texture
1530 GL_ActiveTexture(0);
1531 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
1532 renderstats.bloom_copypixels += r_view_width * r_view_height;
1533 // now scale it down to the bloom size and raise to a power of itself
1534 // to darken it (this leaves the really bright stuff bright, and
1535 // everything else becomes very dark)
1536 // TODO: optimize with multitexture or GLSL
1537 qglViewport(r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
1538 GL_BlendFunc(GL_ONE, GL_ZERO);
1539 GL_Color(1, 1, 1, 1);
1540 R_Mesh_Draw(0, 4, 2, polygonelements);
1541 renderstats.bloom_drawpixels += bloomwidth * bloomheight;
1542 // render multiple times with a multiply blendfunc to raise to a power
1543 GL_BlendFunc(GL_DST_COLOR, GL_ZERO);
1544 for (x = 1;x < r_bloom_power.integer;x++)
1546 R_Mesh_Draw(0, 4, 2, polygonelements);
1547 renderstats.bloom_drawpixels += bloomwidth * bloomheight;
1549 // we now have a darkened bloom image in the framebuffer, copy it into
1550 // the bloom image texture for more processing
1551 memset(&m, 0, sizeof(m));
1552 m.pointer_vertex = vertex3f;
1553 m.tex[0] = R_GetTexture(r_bloom_texture_bloom);
1554 m.pointer_texcoord[0] = texcoord2f[2];
1556 GL_ActiveTexture(0);
1557 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
1558 renderstats.bloom_copypixels += bloomwidth * bloomheight;
1559 // blend on at multiple vertical offsets to achieve a vertical blur
1560 // TODO: do offset blends using GLSL
1561 range = r_bloom_blur.integer * bloomwidth / 320;
1562 GL_BlendFunc(GL_ONE, GL_ZERO);
1563 for (x = -range;x <= range;x++)
1565 xoffset = 0 / (float)bloomwidth * (float)bloomwidth / (float)screenwidth;
1566 yoffset = x / (float)bloomheight * (float)bloomheight / (float)screenheight;
1567 // compute a texcoord array with the specified x and y offset
1568 texcoord2f[2][0] = xoffset+0;
1569 texcoord2f[2][1] = yoffset+(float)bloomheight / (float)screenheight;
1570 texcoord2f[2][2] = xoffset+(float)bloomwidth / (float)screenwidth;
1571 texcoord2f[2][3] = yoffset+(float)bloomheight / (float)screenheight;
1572 texcoord2f[2][4] = xoffset+(float)bloomwidth / (float)screenwidth;
1573 texcoord2f[2][5] = yoffset+0;
1574 texcoord2f[2][6] = xoffset+0;
1575 texcoord2f[2][7] = yoffset+0;
1576 // this r value looks like a 'dot' particle, fading sharply to
1577 // black at the edges
1578 // (probably not realistic but looks good enough)
1579 r = r_bloom_intensity.value/(range*2+1)*(1 - x*x/(float)(range*range));
1582 GL_Color(r, r, r, 1);
1583 R_Mesh_Draw(0, 4, 2, polygonelements);
1584 renderstats.bloom_drawpixels += bloomwidth * bloomheight;
1585 GL_BlendFunc(GL_ONE, GL_ONE);
1587 // copy the vertically blurred bloom view to a texture
1588 GL_ActiveTexture(0);
1589 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
1590 renderstats.bloom_copypixels += bloomwidth * bloomheight;
1591 // blend the vertically blurred image at multiple offsets horizontally
1592 // to finish the blur effect
1593 // TODO: do offset blends using GLSL
1594 range = r_bloom_blur.integer * bloomwidth / 320;
1595 GL_BlendFunc(GL_ONE, GL_ZERO);
1596 for (x = -range;x <= range;x++)
1598 xoffset = x / (float)bloomwidth * (float)bloomwidth / (float)screenwidth;
1599 yoffset = 0 / (float)bloomheight * (float)bloomheight / (float)screenheight;
1600 // compute a texcoord array with the specified x and y offset
1601 texcoord2f[2][0] = xoffset+0;
1602 texcoord2f[2][1] = yoffset+(float)bloomheight / (float)screenheight;
1603 texcoord2f[2][2] = xoffset+(float)bloomwidth / (float)screenwidth;
1604 texcoord2f[2][3] = yoffset+(float)bloomheight / (float)screenheight;
1605 texcoord2f[2][4] = xoffset+(float)bloomwidth / (float)screenwidth;
1606 texcoord2f[2][5] = yoffset+0;
1607 texcoord2f[2][6] = xoffset+0;
1608 texcoord2f[2][7] = yoffset+0;
1609 // this r value looks like a 'dot' particle, fading sharply to
1610 // black at the edges
1611 // (probably not realistic but looks good enough)
1612 r = r_bloom_intensity.value/(range*2+1)*(1 - x*x/(float)(range*range));
1615 GL_Color(r, r, r, 1);
1616 R_Mesh_Draw(0, 4, 2, polygonelements);
1617 renderstats.bloom_drawpixels += bloomwidth * bloomheight;
1618 GL_BlendFunc(GL_ONE, GL_ONE);
1620 // copy the blurred bloom view to a texture
1621 GL_ActiveTexture(0);
1622 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
1623 renderstats.bloom_copypixels += bloomwidth * bloomheight;
1624 // go back to full view area
1625 qglViewport(r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
1626 // put the original screen image back in place and blend the bloom
1628 memset(&m, 0, sizeof(m));
1629 m.pointer_vertex = vertex3f;
1630 m.tex[0] = R_GetTexture(r_bloom_texture_screen);
1631 m.pointer_texcoord[0] = texcoord2f[0];
1633 dobloomblend = false;
1635 // do both in one pass if possible
1636 if (r_textureunits.integer >= 2 && gl_combine.integer)
1638 dobloomblend = false;
1639 m.texcombinergb[1] = GL_ADD;
1640 m.tex[1] = R_GetTexture(r_bloom_texture_bloom);
1641 m.pointer_texcoord[1] = texcoord2f[1];
1644 dobloomblend = true;
1647 GL_BlendFunc(GL_ONE, GL_ZERO);
1649 R_Mesh_Draw(0, 4, 2, polygonelements);
1650 renderstats.bloom_drawpixels += r_view_width * r_view_height;
1651 // now blend on the bloom texture if multipass
1654 memset(&m, 0, sizeof(m));
1655 m.pointer_vertex = vertex3f;
1656 m.tex[0] = R_GetTexture(r_bloom_texture_bloom);
1657 m.pointer_texcoord[0] = texcoord2f[1];
1659 GL_BlendFunc(GL_ONE, GL_ONE);
1661 R_Mesh_Draw(0, 4, 2, polygonelements);
1662 renderstats.bloom_drawpixels += r_view_width * r_view_height;
1667 // apply a color tint to the whole view
1668 memset(&m, 0, sizeof(m));
1669 m.pointer_vertex = vertex3f;
1671 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1672 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
1673 R_Mesh_Draw(0, 4, 2, polygonelements);
1677 void R_RenderScene(void);
1679 matrix4x4_t r_waterscrollmatrix;
1686 void R_RenderView(void)
1688 if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
1689 return; //Host_Error ("R_RenderView: NULL worldmodel");
1691 r_view_width = bound(0, r_refdef.width, vid.width);
1692 r_view_height = bound(0, r_refdef.height, vid.height);
1694 r_view_x = bound(0, r_refdef.x, vid.width - r_refdef.width);
1695 r_view_y = bound(0, r_refdef.y, vid.height - r_refdef.height);
1697 r_view_matrix = r_refdef.viewentitymatrix;
1698 GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
1699 r_rtworld = r_shadow_realtime_world.integer;
1700 r_rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
1701 r_rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer;
1702 r_rtdlightshadows = r_rtdlight && (r_rtworld ? r_shadow_realtime_world_dlightshadows.integer : r_shadow_realtime_dlight_shadows.integer) && gl_stencil;
1703 r_lightmapintensity = r_rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
1704 r_polygonfactor = 0;
1705 r_polygonoffset = 0;
1706 r_shadowpolygonfactor = r_polygonfactor + r_shadow_shadow_polygonfactor.value;
1707 r_shadowpolygonoffset = r_polygonoffset + r_shadow_shadow_polygonoffset.value;
1708 if (r_showsurfaces.integer)
1711 r_rtworldshadows = false;
1713 r_rtdlightshadows = false;
1714 r_lightmapintensity = 0;
1717 // GL is weird because it's bottom to top, r_view_y is top to bottom
1718 qglViewport(r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
1719 GL_Scissor(r_view_x, r_view_y, r_view_width, r_view_height);
1720 GL_ScissorTest(true);
1725 if (r_timereport_active)
1726 R_TimeReport("setup");
1728 qglDepthFunc(GL_LEQUAL);
1729 qglPolygonOffset(r_polygonfactor, r_polygonoffset);
1730 qglEnable(GL_POLYGON_OFFSET_FILL);
1734 qglPolygonOffset(r_polygonfactor, r_polygonoffset);
1735 qglDisable(GL_POLYGON_OFFSET_FILL);
1738 if (r_timereport_active)
1739 R_TimeReport("blendview");
1741 GL_Scissor(0, 0, vid.width, vid.height);
1742 GL_ScissorTest(false);
1746 void CSQC_R_ClearScreen (void)
1748 if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
1749 return; //Host_Error ("R_RenderView: NULL worldmodel");
1751 r_view_width = bound(0, r_refdef.width, vid.width);
1752 r_view_height = bound(0, r_refdef.height, vid.height);
1754 r_view_x = bound(0, r_refdef.x, vid.width - r_refdef.width);
1755 r_view_y = bound(0, r_refdef.y, vid.height - r_refdef.height);
1757 r_view_matrix = r_refdef.viewentitymatrix;
1758 GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
1759 r_rtworld = r_shadow_realtime_world.integer;
1760 r_rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
1761 r_rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer;
1762 r_rtdlightshadows = r_rtdlight && (r_rtworld ? r_shadow_realtime_world_dlightshadows.integer : r_shadow_realtime_dlight_shadows.integer) && gl_stencil;
1763 r_lightmapintensity = r_rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
1764 r_polygonfactor = 0;
1765 r_polygonoffset = 0;
1766 r_shadowpolygonfactor = r_polygonfactor + r_shadow_shadow_polygonfactor.value;
1767 r_shadowpolygonoffset = r_polygonoffset + r_shadow_shadow_polygonoffset.value;
1768 if (r_showsurfaces.integer)
1771 r_rtworldshadows = false;
1773 r_rtdlightshadows = false;
1774 r_lightmapintensity = 0;
1777 // GL is weird because it's bottom to top, r_view_y is top to bottom
1778 qglViewport(r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
1779 GL_Scissor(r_view_x, r_view_y, r_view_width, r_view_height);
1780 GL_ScissorTest(true);
1785 if (r_timereport_active)
1786 R_TimeReport("setup");
1790 void CSQC_R_RenderScene (void)
1792 qglDepthFunc(GL_LEQUAL);
1793 qglPolygonOffset(r_polygonfactor, r_polygonoffset);
1794 qglEnable(GL_POLYGON_OFFSET_FILL);
1798 qglPolygonOffset(r_polygonfactor, r_polygonoffset);
1799 qglDisable(GL_POLYGON_OFFSET_FILL);
1802 if (r_timereport_active)
1803 R_TimeReport("blendview");
1805 GL_Scissor(0, 0, vid.width, vid.height);
1806 GL_ScissorTest(false);
1809 extern void R_DrawLightningBeams (void);
1810 extern void VM_AddPolygonsToMeshQueue (void);
1811 void R_RenderScene(void)
1815 // don't let sound skip if going slow
1816 if (r_refdef.extraupdate)
1821 if (gl_support_fragment_shader)
1822 qglUseProgramObjectARB(0);
1824 R_MeshQueue_BeginScene();
1828 r_farclip = R_FarClip(r_vieworigin, r_viewforward, 768.0f) + 256.0f;
1829 nearclip = bound (0.001f, r_nearclip.value, r_farclip - 1.0f);
1831 if (r_rtworldshadows || r_rtdlightshadows)
1832 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_refdef.frustum_x, r_refdef.frustum_y, nearclip);
1834 GL_SetupView_Mode_Perspective(r_refdef.frustum_x, r_refdef.frustum_y, nearclip, r_farclip);
1836 GL_SetupView_Orientation_FromEntity(&r_view_matrix);
1838 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);
1842 R_WorldVisibility();
1843 if (r_timereport_active)
1844 R_TimeReport("worldvis");
1847 if (r_timereport_active)
1848 R_TimeReport("markentity");
1850 R_Shadow_UpdateWorldLightSelection();
1852 if (cl.csqc_vidvars.drawworld)
1854 // don't let sound skip if going slow
1855 if (r_refdef.extraupdate)
1858 if (r_refdef.worldmodel && r_refdef.worldmodel->DrawSky)
1860 r_refdef.worldmodel->DrawSky(r_refdef.worldentity);
1861 if (r_timereport_active)
1862 R_TimeReport("worldsky");
1865 if (R_DrawBrushModelsSky() && r_timereport_active)
1866 R_TimeReport("bmodelsky");
1868 if (r_refdef.worldmodel && r_refdef.worldmodel->Draw)
1870 r_refdef.worldmodel->Draw(r_refdef.worldentity);
1871 if (r_timereport_active)
1872 R_TimeReport("world");
1876 // don't let sound skip if going slow
1877 if (r_refdef.extraupdate)
1881 if (r_timereport_active)
1882 R_TimeReport("models");
1884 // don't let sound skip if going slow
1885 if (r_refdef.extraupdate)
1888 R_ShadowVolumeLighting(false);
1889 if (r_timereport_active)
1890 R_TimeReport("rtlights");
1892 // don't let sound skip if going slow
1893 if (r_refdef.extraupdate)
1896 if (cl.csqc_vidvars.drawworld)
1898 R_DrawLightningBeams();
1899 if (r_timereport_active)
1900 R_TimeReport("lightning");
1903 if (r_timereport_active)
1904 R_TimeReport("particles");
1907 if (r_timereport_active)
1908 R_TimeReport("explosions");
1911 R_MeshQueue_RenderTransparent();
1912 if (r_timereport_active)
1913 R_TimeReport("drawtrans");
1915 if (cl.csqc_vidvars.drawworld)
1918 if (r_timereport_active)
1919 R_TimeReport("coronas");
1921 if(cl.csqc_vidvars.drawcrosshair)
1923 R_DrawWorldCrosshair();
1924 if (r_timereport_active)
1925 R_TimeReport("crosshair");
1928 VM_AddPolygonsToMeshQueue();
1930 R_MeshQueue_Render();
1932 R_MeshQueue_EndScene();
1934 // don't let sound skip if going slow
1935 if (r_refdef.extraupdate)
1938 if (gl_support_fragment_shader)
1939 qglUseProgramObjectARB(0);
1943 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
1946 float *v, *c, f1, f2, diff[3], vertex3f[8*3], color4f[8*4];
1948 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1949 GL_DepthMask(false);
1951 R_Mesh_Matrix(&identitymatrix);
1953 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2];
1954 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
1955 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
1956 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
1957 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
1958 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
1959 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
1960 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
1961 R_FillColors(color, 8, cr, cg, cb, ca);
1964 for (i = 0, v = vertex, c = color;i < 8;i++, v += 4, c += 4)
1966 f2 = VERTEXFOGTABLE(VectorDistance(v, r_vieworigin));
1968 c[0] = c[0] * f1 + fogcolor[0] * f2;
1969 c[1] = c[1] * f1 + fogcolor[1] * f2;
1970 c[2] = c[2] * f1 + fogcolor[2] * f2;
1973 memset(&m, 0, sizeof(m));
1974 m.pointer_vertex = vertex3f;
1975 m.pointer_color = color;
1981 int nomodelelements[24] =
1993 float nomodelvertex3f[6*3] =
2003 float nomodelcolor4f[6*4] =
2005 0.0f, 0.0f, 0.5f, 1.0f,
2006 0.0f, 0.0f, 0.5f, 1.0f,
2007 0.0f, 0.5f, 0.0f, 1.0f,
2008 0.0f, 0.5f, 0.0f, 1.0f,
2009 0.5f, 0.0f, 0.0f, 1.0f,
2010 0.5f, 0.0f, 0.0f, 1.0f
2013 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight)
2019 R_Mesh_Matrix(&ent->matrix);
2021 memset(&m, 0, sizeof(m));
2022 m.pointer_vertex = nomodelvertex3f;
2024 if (ent->flags & EF_ADDITIVE)
2026 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2027 GL_DepthMask(false);
2029 else if (ent->alpha < 1)
2031 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2032 GL_DepthMask(false);
2036 GL_BlendFunc(GL_ONE, GL_ZERO);
2039 GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
2042 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
2043 m.pointer_color = color4f;
2044 f2 = VERTEXFOGTABLE(VectorDistance(ent->origin, r_vieworigin));
2046 for (i = 0, c = color4f;i < 6;i++, c += 4)
2048 c[0] = (c[0] * f1 + fogcolor[0] * f2);
2049 c[1] = (c[1] * f1 + fogcolor[1] * f2);
2050 c[2] = (c[2] * f1 + fogcolor[2] * f2);
2054 else if (ent->alpha != 1)
2056 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
2057 m.pointer_color = color4f;
2058 for (i = 0, c = color4f;i < 6;i++, c += 4)
2062 m.pointer_color = nomodelcolor4f;
2064 R_Mesh_Draw(0, 6, 8, nomodelelements);
2067 void R_DrawNoModel(entity_render_t *ent)
2069 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
2070 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_vieworigin : ent->origin, R_DrawNoModel_TransparentCallback, ent, 0, r_shadow_rtlight);
2072 // R_DrawNoModelCallback(ent, 0);
2075 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
2077 vec3_t right1, right2, diff, normal;
2079 VectorSubtract (org2, org1, normal);
2081 // calculate 'right' vector for start
2082 VectorSubtract (r_vieworigin, org1, diff);
2083 CrossProduct (normal, diff, right1);
2084 VectorNormalize (right1);
2086 // calculate 'right' vector for end
2087 VectorSubtract (r_vieworigin, org2, diff);
2088 CrossProduct (normal, diff, right2);
2089 VectorNormalize (right2);
2091 vert[ 0] = org1[0] + width * right1[0];
2092 vert[ 1] = org1[1] + width * right1[1];
2093 vert[ 2] = org1[2] + width * right1[2];
2094 vert[ 3] = org1[0] - width * right1[0];
2095 vert[ 4] = org1[1] - width * right1[1];
2096 vert[ 5] = org1[2] - width * right1[2];
2097 vert[ 6] = org2[0] - width * right2[0];
2098 vert[ 7] = org2[1] - width * right2[1];
2099 vert[ 8] = org2[2] - width * right2[2];
2100 vert[ 9] = org2[0] + width * right2[0];
2101 vert[10] = org2[1] + width * right2[1];
2102 vert[11] = org2[2] + width * right2[2];
2105 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
2107 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)
2109 float fog = 0.0f, ifog;
2114 fog = VERTEXFOGTABLE(VectorDistance(origin, r_vieworigin));
2117 R_Mesh_Matrix(&identitymatrix);
2118 GL_BlendFunc(blendfunc1, blendfunc2);
2119 GL_DepthMask(false);
2120 GL_DepthTest(!depthdisable);
2122 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
2123 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
2124 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
2125 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
2126 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
2127 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
2128 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
2129 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
2130 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
2131 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
2132 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
2133 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
2135 memset(&m, 0, sizeof(m));
2136 m.tex[0] = R_GetTexture(texture);
2137 m.pointer_texcoord[0] = spritetexcoord2f;
2138 m.pointer_vertex = vertex3f;
2140 GL_Color(cr * ifog, cg * ifog, cb * ifog, ca);
2141 R_Mesh_Draw(0, 4, 2, polygonelements);
2143 if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
2145 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
2146 GL_BlendFunc(blendfunc1, GL_ONE);
2147 GL_Color(fogcolor[0] * fog, fogcolor[1] * fog, fogcolor[2] * fog, ca);
2148 R_Mesh_Draw(0, 4, 2, polygonelements);
2152 int R_Mesh_AddVertex3f(rmesh_t *mesh, const float *v)
2156 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
2157 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
2159 if (i == mesh->numvertices)
2161 if (mesh->numvertices < mesh->maxvertices)
2163 VectorCopy(v, vertex3f);
2164 mesh->numvertices++;
2166 return mesh->numvertices;
2172 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
2176 element[0] = R_Mesh_AddVertex3f(mesh, vertex3f);vertex3f += 3;
2177 element[1] = R_Mesh_AddVertex3f(mesh, vertex3f);vertex3f += 3;
2178 e = mesh->element3i + mesh->numtriangles * 3;
2179 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
2181 element[2] = R_Mesh_AddVertex3f(mesh, vertex3f);
2182 if (mesh->numtriangles < mesh->maxtriangles)
2187 mesh->numtriangles++;
2189 element[1] = element[2];
2193 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
2195 int planenum, planenum2;
2198 mplane_t *plane, *plane2;
2199 float temppoints[2][256*3];
2200 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
2204 PolygonF_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->normal[3], 1024.0*1024.0*1024.0);
2205 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
2207 if (planenum2 == planenum)
2209 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);
2212 if (tempnumpoints < 3)
2214 // generate elements forming a triangle fan for this polygon
2215 R_Mesh_AddPolygon3f(mesh, tempnumpoints, temppoints[w]);
2219 static void R_DrawCollisionBrush(colbrushf_t *brush)
2223 memset(&m, 0, sizeof(m));
2224 m.pointer_vertex = brush->points->v;
2226 i = (int)(((size_t)brush) / sizeof(colbrushf_t));
2227 GL_Color((i & 31) * (1.0f / 32.0f), ((i >> 5) & 31) * (1.0f / 32.0f), ((i >> 10) & 31) * (1.0f / 32.0f), 0.2f);
2228 GL_LockArrays(0, brush->numpoints);
2229 R_Mesh_Draw(0, brush->numpoints, brush->numtriangles, brush->elements);
2230 GL_LockArrays(0, 0);
2233 static void R_DrawCollisionSurface(entity_render_t *ent, msurface_t *surface)
2237 if (!surface->num_collisiontriangles)
2239 memset(&m, 0, sizeof(m));
2240 m.pointer_vertex = surface->data_collisionvertex3f;
2242 i = (int)(((size_t)surface) / sizeof(msurface_t));
2243 GL_Color((i & 31) * (1.0f / 32.0f), ((i >> 5) & 31) * (1.0f / 32.0f), ((i >> 10) & 31) * (1.0f / 32.0f), 0.2f);
2244 GL_LockArrays(0, surface->num_collisionvertices);
2245 R_Mesh_Draw(0, surface->num_collisionvertices, surface->num_collisiontriangles, surface->data_collisionelement3i);
2246 GL_LockArrays(0, 0);
2249 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)
2251 texturelayer_t *layer;
2252 layer = t->currentlayers + t->currentnumlayers++;
2254 layer->depthmask = depthmask;
2255 layer->blendfunc1 = blendfunc1;
2256 layer->blendfunc2 = blendfunc2;
2257 layer->texture = texture;
2258 layer->texmatrix = *matrix;
2259 layer->color[0] = r;
2260 layer->color[1] = g;
2261 layer->color[2] = b;
2262 layer->color[3] = a;
2265 void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
2267 // FIXME: identify models using a better check than ent->model->brush.shadowmesh
2268 //int lightmode = ((ent->effects & EF_FULLBRIGHT) || ent->model->brush.shadowmesh) ? 0 : 2;
2271 texture_t *texture = t;
2272 model_t *model = ent->model;
2273 int s = ent->skinnum;
2274 if ((unsigned int)s >= (unsigned int)model->numskins)
2276 if (model->skinscenes)
2278 if (model->skinscenes[s].framecount > 1)
2279 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
2281 s = model->skinscenes[s].firstframe;
2284 t = t + s * model->num_surfaces;
2286 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];
2287 texture->currentframe = t;
2290 t->currentmaterialflags = t->basematerialflags;
2291 t->currentalpha = ent->alpha;
2292 if (t->basematerialflags & MATERIALFLAG_WATERALPHA)
2293 t->currentalpha *= r_wateralpha.value;
2294 if (!(ent->flags & RENDER_LIGHT))
2295 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
2296 if (ent->effects & EF_ADDITIVE)
2297 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_TRANSPARENT;
2298 else if (t->currentalpha < 1)
2299 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_TRANSPARENT;
2300 if (ent->effects & EF_NODEPTHTEST)
2301 t->currentmaterialflags |= MATERIALFLAG_NODEPTHTEST;
2302 if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
2303 t->currenttexmatrix = r_waterscrollmatrix;
2305 t->currenttexmatrix = identitymatrix;
2307 t->colormapping = VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f);
2308 t->basetexture = (!t->colormapping && t->skin.merged) ? t->skin.merged : t->skin.base;
2309 t->glosstexture = r_texture_white;
2310 t->specularpower = 8;
2311 t->specularscale = 0;
2312 if (r_shadow_gloss.integer > 0)
2316 if (r_shadow_glossintensity.value > 0)
2318 t->glosstexture = t->skin.gloss;
2319 t->specularscale = r_shadow_glossintensity.value;
2322 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
2323 t->specularscale = r_shadow_gloss2intensity.value;
2326 t->currentnumlayers = 0;
2327 if (!(t->currentmaterialflags & MATERIALFLAG_NODRAW))
2329 if (gl_lightmaps.integer)
2330 R_Texture_AddLayer(t, true, GL_ONE, GL_ZERO, TEXTURELAYERTYPE_LITTEXTURE_MULTIPASS, r_texture_white, &identitymatrix, 1, 1, 1, 1);
2331 else if (!(t->currentmaterialflags & MATERIALFLAG_SKY))
2333 int blendfunc1, blendfunc2, depthmask;
2334 if (t->currentmaterialflags & MATERIALFLAG_ADD)
2336 blendfunc1 = GL_SRC_ALPHA;
2337 blendfunc2 = GL_ONE;
2340 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
2342 blendfunc1 = GL_SRC_ALPHA;
2343 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
2348 blendfunc1 = GL_ONE;
2349 blendfunc2 = GL_ZERO;
2352 if (t->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL))
2354 rtexture_t *currentbasetexture;
2356 if (fogenabled && (t->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
2357 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
2358 currentbasetexture = (VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) < (1.0f / 1048576.0f) && t->skin.merged) ? t->skin.merged : t->skin.base;
2359 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2361 // fullbright is not affected by r_lightmapintensity
2362 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
2363 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->skin.pants)
2364 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);
2365 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->skin.shirt)
2366 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);
2372 // q3bsp has no lightmap updates, so the lightstylevalue that
2373 // would normally be baked into the lightmaptexture must be
2374 // applied to the color
2375 if (ent->model->type == mod_brushq3)
2376 colorscale *= r_refdef.lightstylevalue[0] * (1.0f / 256.0f);
2377 colorscale *= r_lightmapintensity;
2378 if (r_textureunits.integer >= 2 && gl_combine.integer)
2379 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);
2380 else if ((t->currentmaterialflags & MATERIALFLAG_TRANSPARENT) == 0)
2381 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);
2383 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);
2384 if (r_ambient.value >= (1.0f/64.0f))
2385 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);
2386 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->skin.pants)
2388 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);
2389 if (r_ambient.value >= (1.0f/64.0f))
2390 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);
2392 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->skin.shirt)
2394 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);
2395 if (r_ambient.value >= (1.0f/64.0f))
2396 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);
2399 if (t->skin.glow != NULL)
2400 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.glow, &t->currenttexmatrix, 1, 1, 1, t->currentalpha);
2401 if (fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
2403 // if this is opaque use alpha blend which will darken the earlier
2406 // if this is an alpha blended material, all the earlier passes
2407 // were darkened by fog already, so we only need to add the fog
2408 // color ontop through the fog mask texture
2410 // if this is an additive blended material, all the earlier passes
2411 // were darkened by fog already, and we should not add fog color
2412 // (because the background was not darkened, there is no fog color
2413 // that was lost behind it).
2414 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);
2421 void R_UpdateAllTextureInfo(entity_render_t *ent)
2425 for (i = 0;i < ent->model->num_textures;i++)
2426 R_UpdateTextureInfo(ent, ent->model->data_textures + i);
2429 int rsurface_array_size = 0;
2430 float *rsurface_array_vertex3f = NULL;
2431 float *rsurface_array_svector3f = NULL;
2432 float *rsurface_array_tvector3f = NULL;
2433 float *rsurface_array_normal3f = NULL;
2434 float *rsurface_array_color4f = NULL;
2435 float *rsurface_array_texcoord3f = NULL;
2437 void R_Mesh_ResizeArrays(int newvertices)
2439 if (rsurface_array_size >= newvertices)
2441 if (rsurface_array_vertex3f)
2442 Mem_Free(rsurface_array_vertex3f);
2443 rsurface_array_size = (newvertices + 1023) & ~1023;
2444 rsurface_array_vertex3f = Mem_Alloc(r_main_mempool, rsurface_array_size * sizeof(float[19]));
2445 rsurface_array_svector3f = rsurface_array_vertex3f + rsurface_array_size * 3;
2446 rsurface_array_tvector3f = rsurface_array_vertex3f + rsurface_array_size * 6;
2447 rsurface_array_normal3f = rsurface_array_vertex3f + rsurface_array_size * 9;
2448 rsurface_array_color4f = rsurface_array_vertex3f + rsurface_array_size * 12;
2449 rsurface_array_texcoord3f = rsurface_array_vertex3f + rsurface_array_size * 16;
2452 float *rsurface_vertex3f;
2453 float *rsurface_svector3f;
2454 float *rsurface_tvector3f;
2455 float *rsurface_normal3f;
2456 float *rsurface_lightmapcolor4f;
2457 qboolean rsurface_generatevertex;
2458 qboolean rsurface_generatetangents;
2459 qboolean rsurface_generatenormals;
2460 qboolean rsurface_deformvertex;
2461 qboolean rsurface_dynamicvertex;
2462 vec3_t rsurface_modelorg;
2463 const entity_render_t *rsurface_entity;
2464 const model_t *rsurface_model;
2465 const texture_t *rsurface_texture;
2467 void RSurf_PrepareForBatch(const entity_render_t *ent, const texture_t *texture, const vec3_t modelorg)
2469 VectorCopy(modelorg, rsurface_modelorg);
2470 rsurface_entity = ent;
2471 rsurface_model = ent->model;
2472 rsurface_texture = texture;
2475 void RSurf_SetPointersForPass(qboolean generatenormals, qboolean generatetangents)
2477 if (rsurface_array_size < rsurface_model->surfmesh.num_vertices)
2478 R_Mesh_ResizeArrays(rsurface_model->surfmesh.num_vertices);
2479 if ((rsurface_entity->frameblend[0].lerp != 1 || rsurface_entity->frameblend[0].frame != 0) && (rsurface_model->surfmesh.data_morphvertex3f || rsurface_model->surfmesh.data_vertexboneweights))
2481 rsurface_generatevertex = true;
2482 rsurface_generatetangents = false;
2483 rsurface_generatenormals = false;
2484 rsurface_vertex3f = rsurface_array_vertex3f;
2485 if (generatetangents || (rsurface_texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2)))
2487 rsurface_generatetangents = true;
2488 rsurface_svector3f = rsurface_array_svector3f;
2489 rsurface_tvector3f = rsurface_array_tvector3f;
2490 rsurface_normal3f = rsurface_array_normal3f;
2494 rsurface_svector3f = NULL;
2495 rsurface_tvector3f = NULL;
2496 if (generatenormals)
2498 rsurface_generatenormals = true;
2499 rsurface_normal3f = rsurface_array_normal3f;
2502 rsurface_normal3f = NULL;
2507 rsurface_generatevertex = false;
2508 rsurface_generatetangents = false;
2509 rsurface_generatenormals = false;
2510 rsurface_vertex3f = rsurface_model->surfmesh.data_vertex3f;
2511 rsurface_svector3f = rsurface_model->surfmesh.data_svector3f;
2512 rsurface_tvector3f = rsurface_model->surfmesh.data_tvector3f;
2513 rsurface_normal3f = rsurface_model->surfmesh.data_normal3f;
2515 if (rsurface_texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
2517 rsurface_deformvertex = true;
2518 rsurface_vertex3f = rsurface_array_vertex3f;
2519 rsurface_svector3f = rsurface_array_svector3f;
2520 rsurface_tvector3f = rsurface_array_tvector3f;
2521 rsurface_normal3f = rsurface_array_normal3f;
2524 rsurface_deformvertex = false;
2525 R_Mesh_VertexPointer(rsurface_vertex3f);
2526 rsurface_dynamicvertex = rsurface_generatevertex || rsurface_deformvertex;
2529 void RSurf_PrepareDynamicSurfaceVertices(const msurface_t *surface)
2531 float *vertex3f, *svector3f, *tvector3f, *normal3f;
2532 model_t *model = rsurface_entity->model;
2533 if (!rsurface_dynamicvertex)
2535 if (rsurface_generatevertex)
2537 Mod_Alias_GetMesh_Vertex3f(model, rsurface_entity->frameblend, rsurface_array_vertex3f);
2538 if (rsurface_generatetangents)
2539 Mod_BuildTextureVectorsAndNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface_vertex3f, model->surfmesh.data_texcoordtexture2f, model->surfmesh.data_element3i + surface->num_firsttriangle * 3, rsurface_array_svector3f, rsurface_array_tvector3f, rsurface_array_normal3f, r_smoothnormals_areaweighting.integer);
2540 else if (rsurface_generatenormals)
2541 Mod_BuildNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface_array_vertex3f, model->surfmesh.data_element3i + 3 * surface->num_firsttriangle, rsurface_array_normal3f, r_smoothnormals_areaweighting.integer);
2543 if (rsurface_deformvertex)
2546 float center[3], forward[3], right[3], up[3], v[4][3];
2547 matrix4x4_t matrix1, imatrix1;
2548 if (rsurface_generatevertex)
2550 vertex3f = rsurface_array_vertex3f;
2551 svector3f = rsurface_array_svector3f;
2552 tvector3f = rsurface_array_tvector3f;
2553 normal3f = rsurface_array_normal3f;
2557 vertex3f = rsurface_vertex3f;
2558 svector3f = rsurface_svector3f;
2559 tvector3f = rsurface_tvector3f;
2560 normal3f = rsurface_normal3f;
2562 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_viewforward, forward);
2563 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_viewright, right);
2564 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_viewup, up);
2565 // a single autosprite surface can contain multiple sprites...
2566 for (j = 0;j < surface->num_vertices - 3;j += 4)
2568 VectorClear(center);
2569 for (i = 0;i < 4;i++)
2570 VectorAdd(center, (vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
2571 VectorScale(center, 0.25f, center);
2572 // FIXME: calculate vectors from triangle edges instead of using texture vectors as an easy way out?
2573 Matrix4x4_FromVectors(&matrix1, (normal3f + 3 * surface->num_firstvertex) + j*3, (svector3f + 3 * surface->num_firstvertex) + j*3, (tvector3f + 3 * surface->num_firstvertex) + j*3, center);
2574 Matrix4x4_Invert_Simple(&imatrix1, &matrix1);
2575 for (i = 0;i < 4;i++)
2576 Matrix4x4_Transform(&imatrix1, (vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, v[i]);
2577 if (rsurface_texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE2)
2579 forward[0] = rsurface_modelorg[0] - center[0];
2580 forward[1] = rsurface_modelorg[1] - center[1];
2582 VectorNormalize(forward);
2583 right[0] = forward[1];
2584 right[1] = -forward[0];
2586 VectorSet(up, 0, 0, 1);
2588 for (i = 0;i < 4;i++)
2589 VectorMAMAMAM(1, center, v[i][0], forward, v[i][1], right, v[i][2], up, rsurface_array_vertex3f + (surface->num_firstvertex+i+j) * 3);
2591 Mod_BuildTextureVectorsAndNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface_array_vertex3f, model->surfmesh.data_texcoordtexture2f, model->surfmesh.data_element3i + surface->num_firsttriangle * 3, rsurface_array_svector3f, rsurface_array_tvector3f, rsurface_array_normal3f, r_smoothnormals_areaweighting.integer);
2595 static void RSurf_Draw(const msurface_t *surface)
2597 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2598 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
2599 GL_LockArrays(0, 0);
2602 static void RSurf_DrawLightmap(const msurface_t *surface, float r, float g, float b, float a, int lightmode, qboolean applycolor, qboolean applyfog)
2610 vec3_t ambientcolor;
2611 vec3_t diffusecolor;
2613 VectorCopy(rsurface_entity->modellight_lightdir, lightdir);
2614 ambientcolor[0] = rsurface_entity->modellight_ambient[0] * r * 0.5f;
2615 ambientcolor[1] = rsurface_entity->modellight_ambient[1] * g * 0.5f;
2616 ambientcolor[2] = rsurface_entity->modellight_ambient[2] * b * 0.5f;
2617 diffusecolor[0] = rsurface_entity->modellight_diffuse[0] * r * 0.5f;
2618 diffusecolor[1] = rsurface_entity->modellight_diffuse[1] * g * 0.5f;
2619 diffusecolor[2] = rsurface_entity->modellight_diffuse[2] * b * 0.5f;
2620 if (VectorLength2(diffusecolor) > 0)
2622 int numverts = surface->num_vertices;
2623 v = rsurface_vertex3f + 3 * surface->num_firstvertex;
2624 c2 = rsurface_normal3f + 3 * surface->num_firstvertex;
2625 c = rsurface_array_color4f + 4 * surface->num_firstvertex;
2626 // q3-style directional shading
2627 for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
2629 if ((f = DotProduct(c2, lightdir)) > 0)
2630 VectorMA(ambientcolor, f, diffusecolor, c);
2632 VectorCopy(ambientcolor, c);
2640 rsurface_lightmapcolor4f = rsurface_array_color4f;
2644 r = ambientcolor[0];
2645 g = ambientcolor[1];
2646 b = ambientcolor[2];
2647 rsurface_lightmapcolor4f = NULL;
2650 else if (lightmode >= 1)
2652 if (surface->lightmapinfo && surface->lightmapinfo->stainsamples)
2654 for (i = 0, c = rsurface_array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
2656 if (surface->lightmapinfo->samples)
2658 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface_model->surfmesh.data_lightmapoffsets + surface->num_firstvertex)[i];
2659 float scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
2660 VectorScale(lm, scale, c);
2661 if (surface->lightmapinfo->styles[1] != 255)
2663 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
2665 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
2666 VectorMA(c, scale, lm, c);
2667 if (surface->lightmapinfo->styles[2] != 255)
2670 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
2671 VectorMA(c, scale, lm, c);
2672 if (surface->lightmapinfo->styles[3] != 255)
2675 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
2676 VectorMA(c, scale, lm, c);
2684 rsurface_lightmapcolor4f = rsurface_array_color4f;
2687 rsurface_lightmapcolor4f = rsurface_model->surfmesh.data_lightmapcolor4f;
2690 rsurface_lightmapcolor4f = NULL;
2693 if (rsurface_lightmapcolor4f)
2695 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)
2697 f = 1 - VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
2706 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)
2708 f = 1 - VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
2715 rsurface_lightmapcolor4f = rsurface_array_color4f;
2717 if (applycolor && rsurface_lightmapcolor4f)
2719 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)
2726 rsurface_lightmapcolor4f = rsurface_array_color4f;
2728 R_Mesh_ColorPointer(rsurface_lightmapcolor4f);
2729 GL_Color(r, g, b, a);
2730 RSurf_Draw(surface);
2733 static void R_DrawTextureSurfaceList(const entity_render_t *ent, texture_t *texture, int texturenumsurfaces, const msurface_t **texturesurfacelist, const vec3_t modelorg)
2735 int texturesurfaceindex;
2737 const msurface_t *surface;
2738 model_t *model = ent->model;
2739 qboolean applycolor;
2742 if (texture->currentmaterialflags & MATERIALFLAG_NODRAW)
2744 r_shadow_rtlight = NULL;
2745 renderstats.entities_surfaces += texturenumsurfaces;
2746 // FIXME: identify models using a better check than model->brush.shadowmesh
2747 lightmode = ((ent->effects & EF_FULLBRIGHT) || model->brush.shadowmesh) ? 0 : 2;
2748 GL_DepthTest(!(texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
2749 if ((texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (ent->flags & RENDER_NOCULLFACE))
2750 qglDisable(GL_CULL_FACE);
2751 RSurf_PrepareForBatch(ent, texture, modelorg);
2752 if (texture->currentmaterialflags & MATERIALFLAG_SKY)
2754 // transparent sky would be ridiculous
2755 if (!(texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
2759 skyrendernow = false;
2761 // restore entity matrix
2762 R_Mesh_Matrix(&ent->matrix);
2765 // LordHavoc: HalfLife maps have freaky skypolys...
2766 // LordHavoc: Quake3 never did sky masking (unlike software Quake
2767 // and Quake2), so disable the sky masking in Quake3 maps as it
2768 // causes problems with q3map2 sky tricks
2769 if (!model->brush.ishlbsp && model->type != mod_brushq3)
2771 GL_Color(fogcolor[0], fogcolor[1], fogcolor[2], 1);
2772 memset(&m, 0, sizeof(m));
2774 if (skyrendermasked)
2776 // depth-only (masking)
2777 GL_ColorMask(0,0,0,0);
2778 // just to make sure that braindead drivers don't draw
2779 // anything despite that colormask...
2780 GL_BlendFunc(GL_ZERO, GL_ONE);
2785 GL_BlendFunc(GL_ONE, GL_ZERO);
2787 RSurf_SetPointersForPass(false, false);
2788 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2790 surface = texturesurfacelist[texturesurfaceindex];
2791 if (rsurface_dynamicvertex)
2792 RSurf_PrepareDynamicSurfaceVertices(surface);
2793 RSurf_Draw(surface);
2795 if (skyrendermasked)
2796 GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
2800 else if (r_glsl.integer && gl_support_fragment_shader)
2802 if (texture->currentmaterialflags & MATERIALFLAG_ADD)
2804 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2805 GL_DepthMask(false);
2807 else if (texture->currentmaterialflags & MATERIALFLAG_ALPHA)
2809 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2810 GL_DepthMask(false);
2814 GL_BlendFunc(GL_ONE, GL_ZERO);
2818 memset(&m, 0, sizeof(m));
2820 GL_Color(ent->colormod[0], ent->colormod[1], ent->colormod[2], texture->currentalpha);
2821 R_SetupSurfaceShader(ent, texture, modelorg, vec3_origin, lightmode == 2);
2822 if (!r_glsl_permutation)
2824 RSurf_SetPointersForPass(false, true);
2827 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2829 surface = texturesurfacelist[texturesurfaceindex];
2830 if (rsurface_dynamicvertex)
2831 RSurf_PrepareDynamicSurfaceVertices(surface);
2832 R_Mesh_TexCoordPointer(0, 2, model->surfmesh.data_texcoordtexture2f);
2833 R_Mesh_TexCoordPointer(1, 3, rsurface_svector3f);
2834 R_Mesh_TexCoordPointer(2, 3, rsurface_tvector3f);
2835 R_Mesh_TexCoordPointer(3, 3, rsurface_normal3f);
2836 RSurf_Draw(surface);
2841 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2843 surface = texturesurfacelist[texturesurfaceindex];
2844 if (rsurface_dynamicvertex)
2845 RSurf_PrepareDynamicSurfaceVertices(surface);
2846 R_Mesh_TexCoordPointer(0, 2, model->surfmesh.data_texcoordtexture2f);
2847 R_Mesh_TexCoordPointer(1, 3, rsurface_svector3f);
2848 R_Mesh_TexCoordPointer(2, 3, rsurface_tvector3f);
2849 R_Mesh_TexCoordPointer(3, 3, rsurface_normal3f);
2850 R_Mesh_TexCoordPointer(4, 2, model->surfmesh.data_texcoordlightmap2f);
2851 if (surface->lightmaptexture)
2853 R_Mesh_TexBind(7, R_GetTexture(surface->lightmaptexture));
2854 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
2855 R_Mesh_TexBind(8, R_GetTexture(surface->deluxemaptexture));
2856 R_Mesh_ColorPointer(NULL);
2860 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
2861 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
2862 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
2863 R_Mesh_ColorPointer(model->surfmesh.data_lightmapcolor4f);
2865 RSurf_Draw(surface);
2868 qglUseProgramObjectARB(0);
2870 else if (texture->currentnumlayers)
2873 texturelayer_t *layer;
2874 for (layerindex = 0, layer = texture->currentlayers;layerindex < texture->currentnumlayers;layerindex++, layer++)
2877 int layertexrgbscale;
2878 GL_DepthMask(layer->depthmask);
2879 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
2880 if ((layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2) && (gl_combine.integer || layer->depthmask))
2882 layertexrgbscale = 4;
2883 VectorScale(layer->color, 0.25f, layercolor);
2885 else if ((layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1) && (gl_combine.integer || layer->depthmask))
2887 layertexrgbscale = 2;
2888 VectorScale(layer->color, 0.5f, layercolor);
2892 layertexrgbscale = 1;
2893 VectorScale(layer->color, 1.0f, layercolor);
2895 layercolor[3] = layer->color[3];
2896 GL_Color(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
2897 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
2898 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
2899 switch (layer->type)
2901 case TEXTURELAYERTYPE_LITTEXTURE_COMBINE:
2902 memset(&m, 0, sizeof(m));
2903 m.tex[1] = R_GetTexture(layer->texture);
2904 m.texmatrix[1] = layer->texmatrix;
2905 m.texrgbscale[1] = layertexrgbscale;
2906 m.pointer_color = rsurface_array_color4f;
2908 RSurf_SetPointersForPass(lightmode == 2, false);
2911 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2913 surface = texturesurfacelist[texturesurfaceindex];
2914 R_Mesh_TexCoordPointer(0, 2, model->surfmesh.data_texcoordlightmap2f);
2915 R_Mesh_TexCoordPointer(1, 2, model->surfmesh.data_texcoordtexture2f);
2916 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2917 if (rsurface_dynamicvertex)
2918 RSurf_PrepareDynamicSurfaceVertices(surface);
2919 RSurf_DrawLightmap(surface, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 2, applycolor, applyfog);
2924 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2926 surface = texturesurfacelist[texturesurfaceindex];
2927 R_Mesh_TexCoordPointer(0, 2, model->surfmesh.data_texcoordlightmap2f);
2928 R_Mesh_TexCoordPointer(1, 2, model->surfmesh.data_texcoordtexture2f);
2929 if (rsurface_dynamicvertex)
2930 RSurf_PrepareDynamicSurfaceVertices(surface);
2931 if (surface->lightmaptexture)
2933 R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
2934 RSurf_DrawLightmap(surface, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, applyfog);
2938 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2939 RSurf_DrawLightmap(surface, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 1, applycolor, applyfog);
2944 case TEXTURELAYERTYPE_LITTEXTURE_MULTIPASS:
2945 memset(&m, 0, sizeof(m));
2946 m.tex[0] = R_GetTexture(layer->texture);
2947 m.texmatrix[0] = layer->texmatrix;
2948 m.pointer_color = rsurface_array_color4f;
2949 m.texrgbscale[0] = layertexrgbscale;
2951 RSurf_SetPointersForPass(lightmode == 2, false);
2954 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2956 surface = texturesurfacelist[texturesurfaceindex];
2957 R_Mesh_TexCoordPointer(0, 2, model->surfmesh.data_texcoordlightmap2f);
2958 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2959 if (rsurface_dynamicvertex)
2960 RSurf_PrepareDynamicSurfaceVertices(surface);
2961 RSurf_DrawLightmap(surface, 1, 1, 1, 1, 2, false, false);
2966 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2968 surface = texturesurfacelist[texturesurfaceindex];
2969 R_Mesh_TexCoordPointer(0, 2, model->surfmesh.data_texcoordlightmap2f);
2970 if (rsurface_dynamicvertex)
2971 RSurf_PrepareDynamicSurfaceVertices(surface);
2972 if (surface->lightmaptexture)
2974 R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
2975 RSurf_DrawLightmap(surface, 1, 1, 1, 1, 0, false, false);
2979 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2980 RSurf_DrawLightmap(surface, 1, 1, 1, 1, 1, false, false);
2984 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
2985 memset(&m, 0, sizeof(m));
2986 m.tex[0] = R_GetTexture(layer->texture);
2987 m.texmatrix[0] = layer->texmatrix;
2988 m.pointer_color = rsurface_array_color4f;
2989 m.texrgbscale[0] = layertexrgbscale;
2991 RSurf_SetPointersForPass(false, false);
2992 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2994 surface = texturesurfacelist[texturesurfaceindex];
2995 R_Mesh_TexCoordPointer(0, 2, model->surfmesh.data_texcoordtexture2f);
2996 if (rsurface_dynamicvertex)
2997 RSurf_PrepareDynamicSurfaceVertices(surface);
2998 RSurf_DrawLightmap(surface, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, false);
3001 case TEXTURELAYERTYPE_LITTEXTURE_VERTEX:
3002 memset(&m, 0, sizeof(m));
3003 m.tex[0] = R_GetTexture(layer->texture);
3004 m.texmatrix[0] = layer->texmatrix;
3005 m.texrgbscale[0] = layertexrgbscale;
3006 m.pointer_color = rsurface_array_color4f;
3008 RSurf_SetPointersForPass(lightmode == 2, false);
3011 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3013 surface = texturesurfacelist[texturesurfaceindex];
3014 R_Mesh_TexCoordPointer(0, 2, model->surfmesh.data_texcoordtexture2f);
3015 if (rsurface_dynamicvertex)
3016 RSurf_PrepareDynamicSurfaceVertices(surface);
3017 RSurf_DrawLightmap(surface, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 2, applycolor, applyfog);
3022 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3024 surface = texturesurfacelist[texturesurfaceindex];
3025 R_Mesh_TexCoordPointer(0, 2, model->surfmesh.data_texcoordtexture2f);
3026 if (rsurface_dynamicvertex)
3027 RSurf_PrepareDynamicSurfaceVertices(surface);
3028 RSurf_DrawLightmap(surface, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 1, applycolor, applyfog);
3032 case TEXTURELAYERTYPE_TEXTURE:
3033 memset(&m, 0, sizeof(m));
3034 m.tex[0] = R_GetTexture(layer->texture);
3035 m.texmatrix[0] = layer->texmatrix;
3036 m.pointer_color = rsurface_array_color4f;
3037 m.texrgbscale[0] = layertexrgbscale;
3039 RSurf_SetPointersForPass(false, false);
3040 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3042 surface = texturesurfacelist[texturesurfaceindex];
3043 R_Mesh_TexCoordPointer(0, 2, model->surfmesh.data_texcoordtexture2f);
3044 if (rsurface_dynamicvertex)
3045 RSurf_PrepareDynamicSurfaceVertices(surface);
3046 RSurf_DrawLightmap(surface, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, applyfog);
3049 case TEXTURELAYERTYPE_FOG:
3050 memset(&m, 0, sizeof(m));
3053 m.tex[0] = R_GetTexture(layer->texture);
3054 m.texmatrix[0] = layer->texmatrix;
3057 RSurf_SetPointersForPass(false, false);
3058 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3062 surface = texturesurfacelist[texturesurfaceindex];
3064 R_Mesh_TexCoordPointer(0, 2, model->surfmesh.data_texcoordtexture2f);
3065 R_Mesh_ColorPointer(rsurface_array_color4f);
3066 if (rsurface_dynamicvertex)
3067 RSurf_PrepareDynamicSurfaceVertices(surface);
3068 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)
3070 f = VERTEXFOGTABLE(VectorDistance(v, modelorg));
3071 c[0] = layercolor[0];
3072 c[1] = layercolor[1];
3073 c[2] = layercolor[2];
3074 c[3] = f * layercolor[3];
3076 RSurf_Draw(surface);
3080 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
3082 // if trying to do overbright on first pass of an opaque surface
3083 // when combine is not supported, brighten as a post process
3084 if (layertexrgbscale > 1 && !gl_combine.integer && layer->depthmask)
3087 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
3088 GL_Color(1, 1, 1, 1);
3089 memset(&m, 0, sizeof(m));
3091 RSurf_SetPointersForPass(false, false);
3092 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3094 surface = texturesurfacelist[texturesurfaceindex];
3095 if (rsurface_dynamicvertex)
3096 RSurf_PrepareDynamicSurfaceVertices(surface);
3097 for (scale = 1;scale < layertexrgbscale;scale <<= 1)
3098 RSurf_Draw(surface);
3103 if ((texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (ent->flags & RENDER_NOCULLFACE))
3104 qglEnable(GL_CULL_FACE);
3107 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight)
3109 const msurface_t *surface = ent->model->data_surfaces + surfacenumber;
3113 texture = surface->texture;
3114 if (texture->basematerialflags & MATERIALFLAG_SKY)
3115 return; // transparent sky is too difficult
3116 R_UpdateTextureInfo(ent, texture);
3118 R_Mesh_Matrix(&ent->matrix);
3119 Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
3120 R_DrawTextureSurfaceList(ent, texture->currentframe, 1, &surface, modelorg);
3123 void R_QueueTextureSurfaceList(entity_render_t *ent, texture_t *texture, int texturenumsurfaces, const msurface_t **texturesurfacelist, const vec3_t modelorg)
3125 int texturesurfaceindex;
3126 const msurface_t *surface;
3127 vec3_t tempcenter, center;
3128 if (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT)
3130 // drawing sky transparently would be too difficult
3131 if (!(texture->currentmaterialflags & MATERIALFLAG_SKY))
3133 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3135 surface = texturesurfacelist[texturesurfaceindex];
3136 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
3137 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
3138 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
3139 Matrix4x4_Transform(&ent->matrix, tempcenter, center);
3140 R_MeshQueue_AddTransparent(texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_vieworigin : center, R_DrawSurface_TransparentCallback, ent, surface - ent->model->data_surfaces, r_shadow_rtlight);
3145 R_DrawTextureSurfaceList(ent, texture, texturenumsurfaces, texturesurfacelist, modelorg);
3148 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
3149 void R_DrawSurfaces(entity_render_t *ent, qboolean skysurfaces)
3151 int i, j, f, flagsmask;
3152 int counttriangles = 0;
3153 msurface_t *surface, **surfacechain;
3154 texture_t *t, *texture;
3155 model_t *model = ent->model;
3157 const int maxsurfacelist = 1024;
3158 int numsurfacelist = 0;
3159 const msurface_t *surfacelist[1024];
3162 R_Mesh_Matrix(&ent->matrix);
3163 Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
3165 // update light styles
3166 if (!skysurfaces && model->brushq1.light_styleupdatechains)
3168 for (i = 0;i < model->brushq1.light_styles;i++)
3170 if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
3172 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
3173 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
3174 for (;(surface = *surfacechain);surfacechain++)
3175 surface->cached_dlight = true;
3180 R_UpdateAllTextureInfo(ent);
3181 flagsmask = skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL);
3186 if (r_showsurfaces.integer)
3191 GL_BlendFunc(GL_ONE, GL_ZERO);
3192 memset(&m, 0, sizeof(m));
3195 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
3197 if (ent == r_refdef.worldentity && !r_worldsurfacevisible[j])
3199 if (t != surface->texture)
3201 t = surface->texture;
3202 texture = t->currentframe;
3203 RSurf_PrepareForBatch(ent, texture, modelorg);
3204 RSurf_SetPointersForPass(false, false);
3206 if ((texture->currentmaterialflags & flagsmask) && surface->num_triangles)
3208 int k = (int)(((size_t)surface) / sizeof(msurface_t));
3209 GL_Color((k & 15) * (1.0f / 16.0f), ((k >> 4) & 15) * (1.0f / 16.0f), ((k >> 8) & 15) * (1.0f / 16.0f), 0.2f);
3210 if (rsurface_dynamicvertex)
3211 RSurf_PrepareDynamicSurfaceVertices(surface);
3212 RSurf_Draw(surface);
3213 renderstats.entities_triangles += surface->num_triangles;
3215 renderstats.entities_surfaces++;
3218 else if (ent == r_refdef.worldentity)
3220 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
3222 if (!r_worldsurfacevisible[j])
3224 if (t != surface->texture)
3228 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
3231 t = surface->texture;
3232 texture = t->currentframe;
3233 f = texture->currentmaterialflags & flagsmask;
3235 if (f && surface->num_triangles)
3237 // if lightmap parameters changed, rebuild lightmap texture
3238 if (surface->cached_dlight)
3239 R_BuildLightMap(ent, surface);
3240 // add face to draw list
3241 surfacelist[numsurfacelist++] = surface;
3242 counttriangles += surface->num_triangles;
3243 if (numsurfacelist >= maxsurfacelist)
3245 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
3253 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
3255 if (t != surface->texture)
3259 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
3262 t = surface->texture;
3263 texture = t->currentframe;
3264 f = texture->currentmaterialflags & flagsmask;
3266 if (f && surface->num_triangles)
3268 // if lightmap parameters changed, rebuild lightmap texture
3269 if (surface->cached_dlight)
3270 R_BuildLightMap(ent, surface);
3271 // add face to draw list
3272 surfacelist[numsurfacelist++] = surface;
3273 counttriangles += surface->num_triangles;
3274 if (numsurfacelist >= maxsurfacelist)
3276 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
3283 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
3284 renderstats.entities_triangles += counttriangles;
3285 if (gl_support_fragment_shader)
3286 qglUseProgramObjectARB(0);
3288 if (r_showcollisionbrushes.integer && model->brush.num_brushes && !skysurfaces)
3291 msurface_t *surface;
3293 R_Mesh_Matrix(&ent->matrix);
3294 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
3295 GL_DepthMask(false);
3296 GL_DepthTest(!r_showdisabledepthtest.integer);
3297 qglPolygonOffset(r_polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_polygonoffset + r_showcollisionbrushes_polygonoffset.value);
3298 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
3299 if (brush->colbrushf && brush->colbrushf->numtriangles)
3300 R_DrawCollisionBrush(brush->colbrushf);
3301 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
3302 if (surface->num_collisiontriangles)
3303 R_DrawCollisionSurface(ent, surface);
3304 qglPolygonOffset(r_polygonfactor, r_polygonoffset);
3307 if (r_showtris.integer || r_shownormals.integer)
3310 const int *elements;
3315 if (r_showdisabledepthtest.integer)
3316 qglDepthFunc(GL_ALWAYS);
3317 GL_BlendFunc(GL_ONE, GL_ZERO);
3318 memset(&m, 0, sizeof(m));
3320 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
3322 if (ent == r_refdef.worldentity && !r_worldsurfacevisible[j])
3324 texture = surface->texture->currentframe;
3325 if ((texture->currentmaterialflags & flagsmask) && surface->num_triangles)
3327 RSurf_PrepareForBatch(ent, texture, modelorg);
3328 RSurf_SetPointersForPass(false, r_shownormals.integer != 0);
3329 if (rsurface_dynamicvertex)
3330 RSurf_PrepareDynamicSurfaceVertices(surface);
3331 if (r_showtris.integer)
3333 if (!texture->currentlayers->depthmask)
3334 GL_Color(r_showtris.value, 0, 0, 1);
3335 else if (ent == r_refdef.worldentity)
3336 GL_Color(r_showtris.value, r_showtris.value, r_showtris.value, 1);
3338 GL_Color(0, r_showtris.value, 0, 1);
3339 elements = (ent->model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
3341 for (k = 0;k < surface->num_triangles;k++, elements += 3)
3343 qglArrayElement(elements[0]);qglArrayElement(elements[1]);
3344 qglArrayElement(elements[1]);qglArrayElement(elements[2]);
3345 qglArrayElement(elements[2]);qglArrayElement(elements[0]);
3349 if (r_shownormals.integer)
3351 GL_Color(r_shownormals.value, 0, 0, 1);
3353 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
3355 VectorCopy(rsurface_vertex3f + l * 3, v);
3356 qglVertex3f(v[0], v[1], v[2]);
3357 VectorMA(v, 8, rsurface_svector3f + l * 3, v);
3358 qglVertex3f(v[0], v[1], v[2]);
3361 GL_Color(0, 0, r_shownormals.value, 1);
3363 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
3365 VectorCopy(rsurface_vertex3f + l * 3, v);
3366 qglVertex3f(v[0], v[1], v[2]);
3367 VectorMA(v, 8, rsurface_tvector3f + l * 3, v);
3368 qglVertex3f(v[0], v[1], v[2]);
3371 GL_Color(0, r_shownormals.value, 0, 1);
3373 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
3375 VectorCopy(rsurface_vertex3f + l * 3, v);
3376 qglVertex3f(v[0], v[1], v[2]);
3377 VectorMA(v, 8, rsurface_normal3f + l * 3, v);
3378 qglVertex3f(v[0], v[1], v[2]);
3384 if (r_showdisabledepthtest.integer)
3385 qglDepthFunc(GL_LEQUAL);