2 Copyright (C) 1996-1997 Id Software, Inc.
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26 mempool_t *r_main_mempool;
27 rtexturepool_t *r_main_texturepool;
29 // used for dlight push checking and other things
34 renderstats_t renderstats;
36 // true during envmap command capture
39 // maximum visible distance (recalculated from world box each frame)
41 // brightness of world lightmaps and related lighting
42 // (often reduced when world rtlights are enabled)
43 float r_lightmapintensity;
44 // whether to draw world lights realtime, dlights realtime, and their shadows
46 qboolean r_rtworldshadows;
48 qboolean r_rtdlightshadows;
63 matrix4x4_t r_view_matrix;
64 float r_polygonfactor;
65 float r_polygonoffset;
66 float r_shadowpolygonfactor;
67 float r_shadowpolygonoffset;
73 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
74 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "shows surfaces as different colors"};
75 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
76 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
77 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
78 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
79 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
80 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
81 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
82 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing\n"};
83 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
84 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
85 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
86 cvar_t r_fullbright = {0, "r_fullbright","0", "make everything bright cheat (not allowed in multiplayer)"};
87 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
88 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
89 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
90 cvar_t r_q1bsp_skymasking = {0, "r_qb1sp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
92 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
93 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
94 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
95 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
96 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
97 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
98 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
100 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of hardware texture units reported by driver (note: setting this to 1 turns off gl_combine)"};
102 cvar_t r_glsl = {0, "r_glsl", "1", "enables use of OpenGL 2.0 pixel shaders for lighting"};
103 cvar_t r_glsl_offsetmapping = {0, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
104 cvar_t r_glsl_offsetmapping_reliefmapping = {0, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
105 cvar_t r_glsl_offsetmapping_scale = {0, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
106 cvar_t r_glsl_deluxemapping = {0, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"};
108 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1", "enables animation smoothing on sprites (requires r_lerpmodels 1)"};
109 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
110 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
112 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
113 cvar_t r_bloom_intensity = {CVAR_SAVE, "r_bloom_intensity", "1.5", "how bright the glow is"};
114 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
115 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
116 cvar_t r_bloom_power = {CVAR_SAVE, "r_bloom_power", "2", "how much to darken the image before blurring to make the bloom effect"};
118 cvar_t r_smoothnormals_areaweighting = {0, "r_smoothnormals_areaweighting", "1", "uses significantly faster (and supposedly higher quality) area-weighted vertex normals and tangent vectors rather than summing normalized triangle normals and tangents"};
120 cvar_t developer_texturelogging = {0, "developer_texturelogging", "0", "produces a textures.log file containing names of skins and map textures the engine tried to load"};
122 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
124 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"}; // used for testing renderer code changes, otherwise does nothing
126 rtexture_t *r_bloom_texture_screen;
127 rtexture_t *r_bloom_texture_bloom;
128 rtexture_t *r_texture_blanknormalmap;
129 rtexture_t *r_texture_white;
130 rtexture_t *r_texture_black;
131 rtexture_t *r_texture_notexture;
132 rtexture_t *r_texture_whitecube;
133 rtexture_t *r_texture_normalizationcube;
134 rtexture_t *r_texture_fogattenuation;
135 //rtexture_t *r_texture_fogintensity;
137 // information about each possible shader permutation
138 r_glsl_permutation_t r_glsl_permutations[SHADERPERMUTATION_COUNT];
139 // currently selected permutation
140 r_glsl_permutation_t *r_glsl_permutation;
142 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
145 for (i = 0;i < verts;i++)
156 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
159 for (i = 0;i < verts;i++)
174 vec_t fogtabledistmultiplier;
175 float fogtable[FOGTABLEWIDTH];
176 float fog_density, fog_red, fog_green, fog_blue;
178 qboolean oldgl_fogenable;
179 void R_UpdateFog(void)
181 if (gamemode == GAME_NEHAHRA)
183 if (gl_fogenable.integer)
185 oldgl_fogenable = true;
186 fog_density = gl_fogdensity.value;
187 fog_red = gl_fogred.value;
188 fog_green = gl_foggreen.value;
189 fog_blue = gl_fogblue.value;
191 else if (oldgl_fogenable)
193 oldgl_fogenable = false;
202 fogcolor[0] = fog_red = bound(0.0f, fog_red , 1.0f);
203 fogcolor[1] = fog_green = bound(0.0f, fog_green, 1.0f);
204 fogcolor[2] = fog_blue = bound(0.0f, fog_blue , 1.0f);
209 fogdensity = -4000.0f / (fog_density * fog_density);
210 // this is the point where the fog reaches 0.9986 alpha, which we
211 // consider a good enough cutoff point for the texture
212 // (0.9986 * 256 == 255.6)
213 fogrange = 400 / fog_density;
214 fograngerecip = 1.0f / fogrange;
215 fogtabledistmultiplier = FOGTABLEWIDTH * fograngerecip;
216 // fog color was already set
222 // FIXME: move this to client?
225 if (gamemode == GAME_NEHAHRA)
227 Cvar_Set("gl_fogenable", "0");
228 Cvar_Set("gl_fogdensity", "0.2");
229 Cvar_Set("gl_fogred", "0.3");
230 Cvar_Set("gl_foggreen", "0.3");
231 Cvar_Set("gl_fogblue", "0.3");
233 fog_density = fog_red = fog_green = fog_blue = 0.0f;
236 // FIXME: move this to client?
237 void FOG_registercvars(void)
242 if (gamemode == GAME_NEHAHRA)
244 Cvar_RegisterVariable (&gl_fogenable);
245 Cvar_RegisterVariable (&gl_fogdensity);
246 Cvar_RegisterVariable (&gl_fogred);
247 Cvar_RegisterVariable (&gl_foggreen);
248 Cvar_RegisterVariable (&gl_fogblue);
249 Cvar_RegisterVariable (&gl_fogstart);
250 Cvar_RegisterVariable (&gl_fogend);
253 r = (-1.0/256.0) * (FOGTABLEWIDTH * FOGTABLEWIDTH);
254 for (x = 0;x < FOGTABLEWIDTH;x++)
256 alpha = exp(r / ((double)x*(double)x));
257 if (x == FOGTABLEWIDTH - 1)
259 fogtable[x] = bound(0, alpha, 1);
263 static void R_BuildBlankTextures(void)
265 unsigned char data[4];
266 data[0] = 128; // normal X
267 data[1] = 128; // normal Y
268 data[2] = 255; // normal Z
269 data[3] = 128; // height
270 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
275 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
280 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
283 static void R_BuildNoTexture(void)
286 unsigned char pix[16][16][4];
287 // this makes a light grey/dark grey checkerboard texture
288 for (y = 0;y < 16;y++)
290 for (x = 0;x < 16;x++)
292 if ((y < 8) ^ (x < 8))
308 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_RGBA, TEXF_MIPMAP, NULL);
311 static void R_BuildWhiteCube(void)
313 unsigned char data[6*1*1*4];
314 data[ 0] = 255;data[ 1] = 255;data[ 2] = 255;data[ 3] = 255;
315 data[ 4] = 255;data[ 5] = 255;data[ 6] = 255;data[ 7] = 255;
316 data[ 8] = 255;data[ 9] = 255;data[10] = 255;data[11] = 255;
317 data[12] = 255;data[13] = 255;data[14] = 255;data[15] = 255;
318 data[16] = 255;data[17] = 255;data[18] = 255;data[19] = 255;
319 data[20] = 255;data[21] = 255;data[22] = 255;data[23] = 255;
320 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
323 static void R_BuildNormalizationCube(void)
327 vec_t s, t, intensity;
329 unsigned char data[6][NORMSIZE][NORMSIZE][4];
330 for (side = 0;side < 6;side++)
332 for (y = 0;y < NORMSIZE;y++)
334 for (x = 0;x < NORMSIZE;x++)
336 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
337 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
372 intensity = 127.0f / sqrt(DotProduct(v, v));
373 data[side][y][x][0] = (unsigned char)(128.0f + intensity * v[0]);
374 data[side][y][x][1] = (unsigned char)(128.0f + intensity * v[1]);
375 data[side][y][x][2] = (unsigned char)(128.0f + intensity * v[2]);
376 data[side][y][x][3] = 255;
380 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, &data[0][0][0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
383 static void R_BuildFogTexture(void)
388 unsigned char data1[FOGWIDTH][4];
389 //unsigned char data2[FOGWIDTH][4];
390 r = (-1.0/256.0) * (FOGWIDTH * FOGWIDTH);
391 for (x = 0;x < FOGWIDTH;x++)
393 alpha = exp(r / ((double)x*(double)x));
394 if (x == FOGWIDTH - 1)
396 b = (int)(256.0 * alpha);
397 b = bound(0, b, 255);
398 data1[x][0] = 255 - b;
399 data1[x][1] = 255 - b;
400 data1[x][2] = 255 - b;
407 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
408 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
411 static const char *builtinshaderstring =
412 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
413 "// written by Forest 'LordHavoc' Hale\n"
415 "// common definitions between vertex shader and fragment shader:\n"
417 "varying vec2 TexCoord;\n"
418 "varying vec2 TexCoordLightmap;\n"
420 "varying vec3 CubeVector;\n"
421 "varying vec3 LightVector;\n"
422 "varying vec3 EyeVector;\n"
424 "varying vec3 EyeVectorModelSpace;\n"
427 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
428 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
429 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
434 "// vertex shader specific:\n"
435 "#ifdef VERTEX_SHADER\n"
437 "uniform vec3 LightPosition;\n"
438 "uniform vec3 EyePosition;\n"
439 "uniform vec3 LightDir;\n"
441 "// TODO: get rid of tangentt (texcoord2) and use a crossproduct to regenerate it from tangents (texcoord1) and normal (texcoord3)\n"
445 " gl_FrontColor = gl_Color;\n"
446 " // copy the surface texcoord\n"
447 " TexCoord = vec2(gl_TextureMatrix[0] * gl_MultiTexCoord0);\n"
448 "#if !defined(MODE_LIGHTSOURCE) && !defined(MODE_LIGHTDIRECTION)\n"
449 " TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
452 "#ifdef MODE_LIGHTSOURCE\n"
453 " // transform vertex position into light attenuation/cubemap space\n"
454 " // (-1 to +1 across the light box)\n"
455 " CubeVector = vec3(gl_TextureMatrix[3] * gl_Vertex);\n"
457 " // transform unnormalized light direction into tangent space\n"
458 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
459 " // normalize it per pixel)\n"
460 " vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
461 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
462 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
463 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
466 "#ifdef MODE_LIGHTDIRECTION\n"
467 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
468 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
469 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
472 " // transform unnormalized eye direction into tangent space\n"
474 " vec3 EyeVectorModelSpace;\n"
476 " EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
477 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
478 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
479 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
481 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
482 " VectorS = gl_MultiTexCoord1.xyz;\n"
483 " VectorT = gl_MultiTexCoord2.xyz;\n"
484 " VectorR = gl_MultiTexCoord3.xyz;\n"
487 " // transform vertex to camera space, using ftransform to match non-VS\n"
489 " gl_Position = ftransform();\n"
492 "#endif // VERTEX_SHADER\n"
497 "// fragment shader specific:\n"
498 "#ifdef FRAGMENT_SHADER\n"
500 "uniform sampler2D Texture_Normal;\n"
501 "uniform sampler2D Texture_Color;\n"
502 "uniform sampler2D Texture_Gloss;\n"
503 "uniform samplerCube Texture_Cube;\n"
504 "uniform sampler2D Texture_FogMask;\n"
505 "uniform sampler2D Texture_Pants;\n"
506 "uniform sampler2D Texture_Shirt;\n"
507 "uniform sampler2D Texture_Lightmap;\n"
508 "uniform sampler2D Texture_Deluxemap;\n"
509 "uniform sampler2D Texture_Glow;\n"
511 "uniform vec3 LightColor;\n"
512 "uniform vec3 AmbientColor;\n"
513 "uniform vec3 DiffuseColor;\n"
514 "uniform vec3 SpecularColor;\n"
515 "uniform vec3 Color_Pants;\n"
516 "uniform vec3 Color_Shirt;\n"
517 "uniform vec3 FogColor;\n"
519 "uniform float OffsetMapping_Scale;\n"
520 "uniform float OffsetMapping_Bias;\n"
521 "uniform float FogRangeRecip;\n"
523 "uniform float AmbientScale;\n"
524 "uniform float DiffuseScale;\n"
525 "uniform float SpecularScale;\n"
526 "uniform float SpecularPower;\n"
530 " // apply offsetmapping\n"
531 "#ifdef USEOFFSETMAPPING\n"
532 " vec2 TexCoordOffset = TexCoord;\n"
533 "#define TexCoord TexCoordOffset\n"
535 " vec3 eyedir = vec3(normalize(EyeVector));\n"
536 " float depthbias = 1.0 - eyedir.z; // should this be a -?\n"
537 " depthbias = 1.0 - depthbias * depthbias;\n"
539 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
540 " // 14 sample relief mapping: linear search and then binary search\n"
541 " vec3 OffsetVector = vec3(EyeVector.xy * (1.0 / EyeVector.z) * depthbias * OffsetMapping_Scale * vec2(-0.1, 0.1), -0.1);\n"
542 " vec3 RT = vec3(TexCoord - OffsetVector.xy * 10.0, 1.0) + OffsetVector;\n"
543 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
544 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
545 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
546 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
547 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
548 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
549 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
550 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
551 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;OffsetVector *= 0.5;RT -= OffsetVector;\n"
552 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;OffsetVector *= 0.5;RT -= OffsetVector;\n"
553 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;OffsetVector *= 0.5;RT -= OffsetVector;\n"
554 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;OffsetVector *= 0.5;RT -= OffsetVector;\n"
555 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;OffsetVector *= 0.5;RT -= OffsetVector;\n"
556 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;OffsetVector *= 0.5;RT -= OffsetVector;\n"
557 " TexCoord = RT.xy;\n"
559 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
560 " vec2 OffsetVector = vec2((EyeVector.xy * (1.0 / EyeVector.z) * depthbias) * OffsetMapping_Scale * vec2(-0.333, 0.333));\n"
561 " //TexCoord += OffsetVector * 3.0;\n"
562 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
563 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
564 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
568 " // combine the diffuse textures (base, pants, shirt)\n"
569 " vec4 color = vec4(texture2D(Texture_Color, TexCoord));\n"
570 "#ifdef USECOLORMAPPING\n"
571 " color.rgb += vec3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + vec3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
577 "#ifdef MODE_LIGHTSOURCE\n"
580 " // get the surface normal and light normal\n"
581 " vec3 surfacenormal = normalize(vec3(texture2D(Texture_Normal, TexCoord)) - 0.5);\n"
582 " vec3 diffusenormal = vec3(normalize(LightVector));\n"
584 " // calculate directional shading\n"
585 " color.rgb *= (AmbientScale + DiffuseScale * max(dot(surfacenormal, diffusenormal), 0.0));\n"
586 "#ifdef USESPECULAR\n"
587 " vec3 specularnormal = vec3(normalize(diffusenormal + vec3(normalize(EyeVector))));\n"
588 " color.rgb += vec3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(max(dot(surfacenormal, specularnormal), 0.0), SpecularPower);\n"
591 "#ifdef USECUBEFILTER\n"
592 " // apply light cubemap filter\n"
593 " //color.rgb *= normalize(CubeVector) * 0.5 + 0.5;//vec3(textureCube(Texture_Cube, CubeVector));\n"
594 " color.rgb *= vec3(textureCube(Texture_Cube, CubeVector));\n"
597 " // apply light color\n"
598 " color.rgb *= LightColor;\n"
600 " // apply attenuation\n"
602 " // the attenuation is (1-(x*x+y*y+z*z)) which gives a large bright\n"
603 " // center and sharp falloff at the edge, this is about the most efficient\n"
604 " // we can get away with as far as providing illumination.\n"
606 " // pow(1-(x*x+y*y+z*z), 4) is far more realistic but needs large lights to\n"
607 " // provide significant illumination, large = slow = pain.\n"
608 " color.rgb *= max(1.0 - dot(CubeVector, CubeVector), 0.0);\n"
613 "#elif defined(MODE_LIGHTDIRECTION)\n"
614 " // directional model lighting\n"
616 " // get the surface normal and light normal\n"
617 " vec3 surfacenormal = normalize(vec3(texture2D(Texture_Normal, TexCoord)) - 0.5);\n"
618 " vec3 diffusenormal = vec3(normalize(LightVector));\n"
620 " // calculate directional shading\n"
621 " color.rgb *= AmbientColor + DiffuseColor * max(dot(surfacenormal, diffusenormal), 0.0);\n"
622 "#ifdef USESPECULAR\n"
623 " vec3 specularnormal = vec3(normalize(diffusenormal + vec3(normalize(EyeVector))));\n"
624 " color.rgb += vec3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(max(dot(surfacenormal, specularnormal), 0.0), SpecularPower);\n"
630 "#elif defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE)\n"
631 " // deluxemap lightmapping using light vectors in modelspace (evil q3map2)\n"
633 " // get the surface normal and light normal\n"
634 " vec3 surfacenormal = normalize(vec3(texture2D(Texture_Normal, TexCoord)) - 0.5);\n"
635 " vec3 diffusenormal_modelspace = vec3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - 0.5;\n"
636 " vec3 diffusenormal = normalize(vec3(dot(diffusenormal_modelspace, VectorS), dot(diffusenormal_modelspace, VectorT), dot(diffusenormal_modelspace, VectorR)));\n"
638 " // calculate directional shading\n"
639 " vec3 tempcolor = color.rgb * (DiffuseScale * max(dot(surfacenormal, diffusenormal), 0.0));\n"
640 "#ifdef USESPECULAR\n"
641 " vec3 specularnormal = vec3(normalize(diffusenormal + vec3(normalize(EyeVector))));\n"
642 " tempcolor += vec3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(max(dot(surfacenormal, specularnormal), 0.0), SpecularPower);\n"
645 " // apply lightmap color\n"
646 " color.rgb = tempcolor * vec3(texture2D(Texture_Lightmap, TexCoordLightmap)) + color.rgb * vec3(AmbientScale);\n"
651 "#elif defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
652 " // deluxemap lightmapping using light vectors in tangentspace\n"
654 " // get the surface normal and light normal\n"
655 " vec3 surfacenormal = normalize(vec3(texture2D(Texture_Normal, TexCoord)) - 0.5);\n"
656 " vec3 diffusenormal = normalize(vec3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - 0.5);\n"
658 " // calculate directional shading\n"
659 " vec3 tempcolor = color.rgb * (DiffuseScale * max(dot(surfacenormal, diffusenormal), 0.0));\n"
660 "#ifdef USESPECULAR\n"
661 " vec3 specularnormal = vec3(normalize(diffusenormal + vec3(normalize(EyeVector))));\n"
662 " tempcolor += vec3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(max(dot(surfacenormal, specularnormal), 0.0), SpecularPower);\n"
665 " // apply lightmap color\n"
666 " color.rgb = tempcolor * vec3(texture2D(Texture_Lightmap, TexCoordLightmap)) + color.rgb * vec3(AmbientScale);\n"
671 "#else // MODE none (lightmap)\n"
672 " // apply lightmap color\n"
673 " color.rgb *= vec3(texture2D(Texture_Lightmap, TexCoordLightmap)) * DiffuseScale + vec3(AmbientScale);\n"
676 " color *= gl_Color;\n"
679 " color.rgb += vec3(texture2D(Texture_Glow, TexCoord));\n"
684 " float fog = texture2D(Texture_FogMask, vec2(length(EyeVectorModelSpace)*FogRangeRecip, 0.0)).x;\n"
685 " color.rgb = color.rgb * fog + FogColor * (1.0 - fog);\n"
688 " gl_FragColor = color;\n"
691 "#endif // FRAGMENT_SHADER\n"
694 void R_GLSL_CompilePermutation(int permutation)
696 r_glsl_permutation_t *p = r_glsl_permutations + permutation;
697 int vertstrings_count;
698 int fragstrings_count;
700 const char *vertstrings_list[SHADERPERMUTATION_COUNT+1];
701 const char *fragstrings_list[SHADERPERMUTATION_COUNT+1];
702 char permutationname[256];
706 vertstrings_list[0] = "#define VERTEX_SHADER\n";
707 fragstrings_list[0] = "#define FRAGMENT_SHADER\n";
708 vertstrings_count = 1;
709 fragstrings_count = 1;
710 permutationname[0] = 0;
711 if (permutation & SHADERPERMUTATION_MODE_LIGHTSOURCE)
713 vertstrings_list[vertstrings_count++] = "#define MODE_LIGHTSOURCE\n";
714 fragstrings_list[fragstrings_count++] = "#define MODE_LIGHTSOURCE\n";
715 strlcat(permutationname, " lightsource", sizeof(permutationname));
717 if (permutation & SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_MODELSPACE)
719 vertstrings_list[vertstrings_count++] = "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n";
720 fragstrings_list[fragstrings_count++] = "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n";
721 strlcat(permutationname, " lightdirectionmap_modelspace", sizeof(permutationname));
723 if (permutation & SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)
725 vertstrings_list[vertstrings_count++] = "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n";
726 fragstrings_list[fragstrings_count++] = "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n";
727 strlcat(permutationname, " lightdirectionmap_tangentspace", sizeof(permutationname));
729 if (permutation & SHADERPERMUTATION_MODE_LIGHTDIRECTION)
731 vertstrings_list[vertstrings_count++] = "#define MODE_LIGHTDIRECTION\n";
732 fragstrings_list[fragstrings_count++] = "#define MODE_LIGHTDIRECTION\n";
733 strlcat(permutationname, " lightdirection", sizeof(permutationname));
735 if (permutation & SHADERPERMUTATION_GLOW)
737 vertstrings_list[vertstrings_count++] = "#define USEGLOW\n";
738 fragstrings_list[fragstrings_count++] = "#define USEGLOW\n";
739 strlcat(permutationname, " glow", sizeof(permutationname));
741 if (permutation & SHADERPERMUTATION_COLORMAPPING)
743 vertstrings_list[vertstrings_count++] = "#define USECOLORMAPPING\n";
744 fragstrings_list[fragstrings_count++] = "#define USECOLORMAPPING\n";
745 strlcat(permutationname, " colormapping", sizeof(permutationname));
747 if (permutation & SHADERPERMUTATION_SPECULAR)
749 vertstrings_list[vertstrings_count++] = "#define USESPECULAR\n";
750 fragstrings_list[fragstrings_count++] = "#define USESPECULAR\n";
751 strlcat(permutationname, " specular", sizeof(permutationname));
753 if (permutation & SHADERPERMUTATION_FOG)
755 vertstrings_list[vertstrings_count++] = "#define USEFOG\n";
756 fragstrings_list[fragstrings_count++] = "#define USEFOG\n";
757 strlcat(permutationname, " fog", sizeof(permutationname));
759 if (permutation & SHADERPERMUTATION_CUBEFILTER)
761 vertstrings_list[vertstrings_count++] = "#define USECUBEFILTER\n";
762 fragstrings_list[fragstrings_count++] = "#define USECUBEFILTER\n";
763 strlcat(permutationname, " cubefilter", sizeof(permutationname));
765 if (permutation & SHADERPERMUTATION_OFFSETMAPPING)
767 vertstrings_list[vertstrings_count++] = "#define USEOFFSETMAPPING\n";
768 fragstrings_list[fragstrings_count++] = "#define USEOFFSETMAPPING\n";
769 strlcat(permutationname, " offsetmapping", sizeof(permutationname));
771 if (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING)
773 vertstrings_list[vertstrings_count++] = "#define USEOFFSETMAPPING_RELIEFMAPPING\n";
774 fragstrings_list[fragstrings_count++] = "#define USEOFFSETMAPPING_RELIEFMAPPING\n";
775 strlcat(permutationname, " OFFSETMAPPING_RELIEFMAPPING", sizeof(permutationname));
777 shaderstring = (char *)FS_LoadFile("glsl/default.glsl", r_main_mempool, false, NULL);
780 Con_DPrintf("GLSL shader text loaded from disk\n");
781 vertstrings_list[vertstrings_count++] = shaderstring;
782 fragstrings_list[fragstrings_count++] = shaderstring;
786 vertstrings_list[vertstrings_count++] = builtinshaderstring;
787 fragstrings_list[fragstrings_count++] = builtinshaderstring;
789 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, fragstrings_count, fragstrings_list);
793 qglUseProgramObjectARB(p->program);
794 p->loc_Texture_Normal = qglGetUniformLocationARB(p->program, "Texture_Normal");
795 p->loc_Texture_Color = qglGetUniformLocationARB(p->program, "Texture_Color");
796 p->loc_Texture_Gloss = qglGetUniformLocationARB(p->program, "Texture_Gloss");
797 p->loc_Texture_Cube = qglGetUniformLocationARB(p->program, "Texture_Cube");
798 p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
799 p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
800 p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
801 p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
802 p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
803 p->loc_Texture_Glow = qglGetUniformLocationARB(p->program, "Texture_Glow");
804 p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
805 p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
806 p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
807 p->loc_LightColor = qglGetUniformLocationARB(p->program, "LightColor");
808 p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants");
809 p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt");
810 p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip");
811 p->loc_AmbientScale = qglGetUniformLocationARB(p->program, "AmbientScale");
812 p->loc_DiffuseScale = qglGetUniformLocationARB(p->program, "DiffuseScale");
813 p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
814 p->loc_SpecularScale = qglGetUniformLocationARB(p->program, "SpecularScale");
815 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
816 p->loc_AmbientColor = qglGetUniformLocationARB(p->program, "AmbientColor");
817 p->loc_DiffuseColor = qglGetUniformLocationARB(p->program, "DiffuseColor");
818 p->loc_SpecularColor = qglGetUniformLocationARB(p->program, "SpecularColor");
819 p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
820 if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal, 0);
821 if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color, 1);
822 if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss, 2);
823 if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube, 3);
824 if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask, 4);
825 if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants, 5);
826 if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt, 6);
827 if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap, 7);
828 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap, 8);
829 if (p->loc_Texture_Glow >= 0) qglUniform1iARB(p->loc_Texture_Glow, 9);
830 qglUseProgramObjectARB(0);
834 Con_Printf("permutation%s failed for shader %s, some features may not work properly!\n", permutationname, "glsl/default.glsl");
836 Mem_Free(shaderstring);
839 void R_GLSL_Restart_f(void)
842 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
843 if (r_glsl_permutations[i].program)
844 GL_Backend_FreeProgram(r_glsl_permutations[i].program);
845 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
848 void R_SetupSurfaceShader(const entity_render_t *ent, const texture_t *texture, rtexture_t *lightmaptexture, const vec3_t modelorg, const vec3_t lightcolorbase, qboolean modellighting)
850 // select a permutation of the lighting shader appropriate to this
851 // combination of texture, entity, light source, and fogging, only use the
852 // minimum features necessary to avoid wasting rendering time in the
853 // fragment shader on features that are not being used
855 float specularscale = texture->specularscale;
856 r_glsl_permutation = NULL;
857 if (r_shadow_rtlight)
859 permutation |= SHADERPERMUTATION_MODE_LIGHTSOURCE;
860 specularscale *= r_shadow_rtlight->specularscale;
861 if (r_shadow_rtlight->currentcubemap != r_texture_whitecube)
862 permutation |= SHADERPERMUTATION_CUBEFILTER;
866 if (!(texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
869 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTION;
870 else if (r_glsl_deluxemapping.integer >= 1 && r_refdef.worldmodel && r_refdef.worldmodel->brushq3.deluxemapping && lightmaptexture)
872 if (r_refdef.worldmodel->brushq3.deluxemapping_modelspace)
873 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_MODELSPACE;
875 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
877 else if (r_glsl_deluxemapping.integer >= 2) // fake mode
878 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
880 if (texture->skin.glow)
881 permutation |= SHADERPERMUTATION_GLOW;
883 if (specularscale > 0)
884 permutation |= SHADERPERMUTATION_SPECULAR;
886 permutation |= SHADERPERMUTATION_FOG;
887 if (texture->colormapping)
888 permutation |= SHADERPERMUTATION_COLORMAPPING;
889 if (r_glsl_offsetmapping.integer)
891 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
892 if (r_glsl_offsetmapping_reliefmapping.integer)
893 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
895 if (!r_glsl_permutations[permutation].program)
897 if (!r_glsl_permutations[permutation].compiled)
898 R_GLSL_CompilePermutation(permutation);
899 if (!r_glsl_permutations[permutation].program)
901 // remove features until we find a valid permutation
903 for (i = SHADERPERMUTATION_COUNT-1;;i>>=1)
905 // reduce i more quickly whenever it would not remove any bits
909 if (!r_glsl_permutations[permutation].compiled)
910 R_GLSL_CompilePermutation(permutation);
911 if (r_glsl_permutations[permutation].program)
914 return; // utterly failed
918 r_glsl_permutation = r_glsl_permutations + permutation;
920 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
921 R_Mesh_TexMatrix(0, &texture->currenttexmatrix);
922 if (permutation & SHADERPERMUTATION_MODE_LIGHTSOURCE)
924 R_Mesh_TexMatrix(3, &r_shadow_entitytolight);
925 //if (r_glsl_permutation->loc_Texture_Cube >= 0) R_Mesh_TexBindCubeMap(3, R_GetTexture(r_shadow_rtlight->currentcubemap));
926 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]);
927 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
928 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_shadow_rtlight->ambientscale);
929 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_shadow_rtlight->diffusescale);
930 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, specularscale);
932 else if (permutation & SHADERPERMUTATION_MODE_LIGHTDIRECTION)
934 if (texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
936 if (r_glsl_permutation->loc_AmbientColor >= 0)
937 qglUniform3fARB(r_glsl_permutation->loc_AmbientColor, 1, 1, 1);
938 if (r_glsl_permutation->loc_DiffuseColor >= 0)
939 qglUniform3fARB(r_glsl_permutation->loc_DiffuseColor, 0, 0, 0);
940 if (r_glsl_permutation->loc_SpecularColor >= 0)
941 qglUniform3fARB(r_glsl_permutation->loc_SpecularColor, 0, 0, 0);
942 if (r_glsl_permutation->loc_LightDir >= 0)
943 qglUniform3fARB(r_glsl_permutation->loc_LightDir, 0, 0, -1);
947 if (r_glsl_permutation->loc_AmbientColor >= 0)
948 qglUniform3fARB(r_glsl_permutation->loc_AmbientColor, ent->modellight_ambient[0], ent->modellight_ambient[1], ent->modellight_ambient[2]);
949 if (r_glsl_permutation->loc_DiffuseColor >= 0)
950 qglUniform3fARB(r_glsl_permutation->loc_DiffuseColor, ent->modellight_diffuse[0], ent->modellight_diffuse[1], ent->modellight_diffuse[2]);
951 if (r_glsl_permutation->loc_SpecularColor >= 0)
952 qglUniform3fARB(r_glsl_permutation->loc_SpecularColor, ent->modellight_diffuse[0] * texture->specularscale, ent->modellight_diffuse[1] * texture->specularscale, ent->modellight_diffuse[2] * texture->specularscale);
953 if (r_glsl_permutation->loc_LightDir >= 0)
954 qglUniform3fARB(r_glsl_permutation->loc_LightDir, ent->modellight_lightdir[0], ent->modellight_lightdir[1], ent->modellight_lightdir[2]);
959 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_ambient.value * 2.0f / 128.0f);
960 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_lightmapintensity * 2.0f);
961 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, r_lightmapintensity * specularscale * 2.0f);
963 if (r_glsl_permutation->loc_Texture_Normal >= 0) R_Mesh_TexBind(0, R_GetTexture(texture->skin.nmap));
964 if (r_glsl_permutation->loc_Texture_Color >= 0) R_Mesh_TexBind(1, R_GetTexture(texture->basetexture));
965 if (r_glsl_permutation->loc_Texture_Gloss >= 0) R_Mesh_TexBind(2, R_GetTexture(texture->glosstexture));
966 //if (r_glsl_permutation->loc_Texture_Cube >= 0 && permutation & SHADERPERMUTATION_MODE_LIGHTSOURCE) R_Mesh_TexBindCubeMap(3, R_GetTexture(r_shadow_rtlight->currentcubemap));
967 if (r_glsl_permutation->loc_Texture_FogMask >= 0) R_Mesh_TexBind(4, R_GetTexture(r_texture_fogattenuation));
968 if (r_glsl_permutation->loc_Texture_Pants >= 0) R_Mesh_TexBind(5, R_GetTexture(texture->skin.pants));
969 if (r_glsl_permutation->loc_Texture_Shirt >= 0) R_Mesh_TexBind(6, R_GetTexture(texture->skin.shirt));
970 if (r_glsl_permutation->loc_Texture_Lightmap >= 0) R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
971 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
972 if (r_glsl_permutation->loc_Texture_Glow >= 0) R_Mesh_TexBind(9, R_GetTexture(texture->skin.glow));
973 if (r_glsl_permutation->loc_FogColor >= 0)
975 // additive passes are only darkened by fog, not tinted
976 if (r_shadow_rtlight || (texture->currentmaterialflags & MATERIALFLAG_ADD))
977 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
979 qglUniform3fARB(r_glsl_permutation->loc_FogColor, fogcolor[0], fogcolor[1], fogcolor[2]);
981 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, modelorg[0], modelorg[1], modelorg[2]);
982 if (r_glsl_permutation->loc_Color_Pants >= 0)
984 if (texture->skin.pants)
985 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, ent->colormap_pantscolor[0], ent->colormap_pantscolor[1], ent->colormap_pantscolor[2]);
987 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
989 if (r_glsl_permutation->loc_Color_Shirt >= 0)
991 if (texture->skin.shirt)
992 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, ent->colormap_shirtcolor[0], ent->colormap_shirtcolor[1], ent->colormap_shirtcolor[2]);
994 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
996 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, fograngerecip);
997 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, texture->specularpower);
998 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
1002 void gl_main_start(void)
1004 r_main_texturepool = R_AllocTexturePool();
1005 r_bloom_texture_screen = NULL;
1006 r_bloom_texture_bloom = NULL;
1007 R_BuildBlankTextures();
1009 if (gl_texturecubemap)
1012 R_BuildNormalizationCube();
1014 R_BuildFogTexture();
1015 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
1018 void gl_main_shutdown(void)
1020 R_FreeTexturePool(&r_main_texturepool);
1021 r_bloom_texture_screen = NULL;
1022 r_bloom_texture_bloom = NULL;
1023 r_texture_blanknormalmap = NULL;
1024 r_texture_white = NULL;
1025 r_texture_black = NULL;
1026 r_texture_whitecube = NULL;
1027 r_texture_normalizationcube = NULL;
1031 extern void CL_ParseEntityLump(char *entitystring);
1032 void gl_main_newmap(void)
1034 // FIXME: move this code to client
1036 char *entities, entname[MAX_QPATH];
1040 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
1041 l = (int)strlen(entname) - 4;
1042 if (l >= 0 && !strcmp(entname + l, ".bsp"))
1044 strcpy(entname + l, ".ent");
1045 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
1047 CL_ParseEntityLump(entities);
1052 if (cl.worldmodel->brush.entities)
1053 CL_ParseEntityLump(cl.worldmodel->brush.entities);
1057 void GL_Main_Init(void)
1059 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
1061 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed\n");
1062 FOG_registercvars(); // FIXME: move this fog stuff to client?
1063 Cvar_RegisterVariable(&r_nearclip);
1064 Cvar_RegisterVariable(&r_showsurfaces);
1065 Cvar_RegisterVariable(&r_showtris);
1066 Cvar_RegisterVariable(&r_shownormals);
1067 Cvar_RegisterVariable(&r_showlighting);
1068 Cvar_RegisterVariable(&r_showshadowvolumes);
1069 Cvar_RegisterVariable(&r_showcollisionbrushes);
1070 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
1071 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
1072 Cvar_RegisterVariable(&r_showdisabledepthtest);
1073 Cvar_RegisterVariable(&r_drawentities);
1074 Cvar_RegisterVariable(&r_drawviewmodel);
1075 Cvar_RegisterVariable(&r_speeds);
1076 Cvar_RegisterVariable(&r_fullbrights);
1077 Cvar_RegisterVariable(&r_wateralpha);
1078 Cvar_RegisterVariable(&r_dynamic);
1079 Cvar_RegisterVariable(&r_fullbright);
1080 Cvar_RegisterVariable(&r_q1bsp_skymasking);
1081 Cvar_RegisterVariable(&r_textureunits);
1082 Cvar_RegisterVariable(&r_glsl);
1083 Cvar_RegisterVariable(&r_glsl_offsetmapping);
1084 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
1085 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
1086 Cvar_RegisterVariable(&r_glsl_deluxemapping);
1087 Cvar_RegisterVariable(&r_lerpsprites);
1088 Cvar_RegisterVariable(&r_lerpmodels);
1089 Cvar_RegisterVariable(&r_waterscroll);
1090 Cvar_RegisterVariable(&r_bloom);
1091 Cvar_RegisterVariable(&r_bloom_intensity);
1092 Cvar_RegisterVariable(&r_bloom_blur);
1093 Cvar_RegisterVariable(&r_bloom_resolution);
1094 Cvar_RegisterVariable(&r_bloom_power);
1095 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
1096 Cvar_RegisterVariable(&developer_texturelogging);
1097 Cvar_RegisterVariable(&gl_lightmaps);
1098 Cvar_RegisterVariable(&r_test);
1099 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
1100 Cvar_SetValue("r_fullbrights", 0);
1101 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
1104 static vec3_t r_farclip_origin;
1105 static vec3_t r_farclip_direction;
1106 static vec_t r_farclip_directiondist;
1107 static vec_t r_farclip_meshfarclip;
1108 static int r_farclip_directionbit0;
1109 static int r_farclip_directionbit1;
1110 static int r_farclip_directionbit2;
1112 // enlarge farclip to accomodate box
1113 static void R_FarClip_Box(vec3_t mins, vec3_t maxs)
1116 d = (r_farclip_directionbit0 ? mins[0] : maxs[0]) * r_farclip_direction[0]
1117 + (r_farclip_directionbit1 ? mins[1] : maxs[1]) * r_farclip_direction[1]
1118 + (r_farclip_directionbit2 ? mins[2] : maxs[2]) * r_farclip_direction[2];
1119 if (r_farclip_meshfarclip < d)
1120 r_farclip_meshfarclip = d;
1123 // return farclip value
1124 static float R_FarClip(vec3_t origin, vec3_t direction, vec_t startfarclip)
1128 VectorCopy(origin, r_farclip_origin);
1129 VectorCopy(direction, r_farclip_direction);
1130 r_farclip_directiondist = DotProduct(r_farclip_origin, r_farclip_direction);
1131 r_farclip_directionbit0 = r_farclip_direction[0] < 0;
1132 r_farclip_directionbit1 = r_farclip_direction[1] < 0;
1133 r_farclip_directionbit2 = r_farclip_direction[2] < 0;
1134 r_farclip_meshfarclip = r_farclip_directiondist + startfarclip;
1136 if (r_refdef.worldmodel)
1137 R_FarClip_Box(r_refdef.worldmodel->normalmins, r_refdef.worldmodel->normalmaxs);
1138 for (i = 0;i < r_refdef.numentities;i++)
1139 R_FarClip_Box(r_refdef.entities[i]->mins, r_refdef.entities[i]->maxs);
1141 return r_farclip_meshfarclip - r_farclip_directiondist;
1144 extern void R_Textures_Init(void);
1145 extern void GL_Draw_Init(void);
1146 extern void GL_Main_Init(void);
1147 extern void R_Shadow_Init(void);
1148 extern void R_Sky_Init(void);
1149 extern void GL_Surf_Init(void);
1150 extern void R_Crosshairs_Init(void);
1151 extern void R_Light_Init(void);
1152 extern void R_Particles_Init(void);
1153 extern void R_Explosion_Init(void);
1154 extern void gl_backend_init(void);
1155 extern void Sbar_Init(void);
1156 extern void R_LightningBeams_Init(void);
1157 extern void Mod_RenderInit(void);
1159 void Render_Init(void)
1169 R_Crosshairs_Init();
1174 R_LightningBeams_Init();
1183 extern char *ENGINE_EXTENSIONS;
1186 VID_CheckExtensions();
1188 // LordHavoc: report supported extensions
1189 Con_DPrintf("\nengine extensions: %s\n", vm_sv_extensions );
1191 // clear to black (loading plaque will be seen over this)
1192 qglClearColor(0,0,0,1);
1193 qglClear(GL_COLOR_BUFFER_BIT);
1196 int R_CullBox(const vec3_t mins, const vec3_t maxs)
1200 for (i = 0;i < 4;i++)
1207 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1211 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1215 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1219 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1223 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1227 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1231 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1235 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1243 //==================================================================================
1245 static void R_UpdateEntityLighting(entity_render_t *ent)
1247 vec3_t tempdiffusenormal;
1248 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));
1249 VectorClear(ent->modellight_diffuse);
1250 VectorClear(ent->modellight_lightdir);
1251 if ((ent->flags & RENDER_LIGHT) && r_refdef.worldmodel && r_refdef.worldmodel->brush.LightPoint)
1252 r_refdef.worldmodel->brush.LightPoint(r_refdef.worldmodel, ent->origin, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
1254 VectorSet(ent->modellight_ambient, 1, 1, 1);
1255 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
1256 VectorNormalize(ent->modellight_lightdir);
1257 ent->modellight_ambient[0] *= ent->colormod[0] * r_lightmapintensity;
1258 ent->modellight_ambient[1] *= ent->colormod[1] * r_lightmapintensity;
1259 ent->modellight_ambient[2] *= ent->colormod[2] * r_lightmapintensity;
1260 ent->modellight_diffuse[0] *= ent->colormod[0] * r_lightmapintensity;
1261 ent->modellight_diffuse[1] *= ent->colormod[1] * r_lightmapintensity;
1262 ent->modellight_diffuse[2] *= ent->colormod[2] * r_lightmapintensity;
1265 static void R_MarkEntities (void)
1268 entity_render_t *ent;
1270 if (!r_drawentities.integer)
1273 r_refdef.worldentity->visframe = r_framecount;
1274 renderimask = envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : (chase_active.integer ? 0 : RENDER_EXTERIORMODEL);
1275 if (r_refdef.worldmodel && r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs)
1277 // worldmodel can check visibility
1278 for (i = 0;i < r_refdef.numentities;i++)
1280 ent = r_refdef.entities[i];
1281 // some of the renderer still relies on origin...
1282 Matrix4x4_OriginFromMatrix(&ent->matrix, ent->origin);
1283 // some of the renderer still relies on scale...
1284 ent->scale = Matrix4x4_ScaleFromMatrix(&ent->matrix);
1285 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)))
1287 ent->visframe = r_framecount;
1288 R_UpdateEntityLighting(ent);
1294 // no worldmodel or it can't check visibility
1295 for (i = 0;i < r_refdef.numentities;i++)
1297 ent = r_refdef.entities[i];
1298 // some of the renderer still relies on origin...
1299 Matrix4x4_OriginFromMatrix(&ent->matrix, ent->origin);
1300 // some of the renderer still relies on scale...
1301 ent->scale = Matrix4x4_ScaleFromMatrix(&ent->matrix);
1302 if (!(ent->flags & renderimask) && !R_CullBox(ent->mins, ent->maxs) && (ent->effects & EF_NODEPTHTEST))
1304 ent->visframe = r_framecount;
1305 R_UpdateEntityLighting(ent);
1311 // only used if skyrendermasked, and normally returns false
1312 int R_DrawBrushModelsSky (void)
1315 entity_render_t *ent;
1317 if (!r_drawentities.integer)
1321 for (i = 0;i < r_refdef.numentities;i++)
1323 ent = r_refdef.entities[i];
1324 if (ent->visframe == r_framecount && ent->model && ent->model->DrawSky)
1326 ent->model->DrawSky(ent);
1333 void R_DrawNoModel(entity_render_t *ent);
1334 void R_DrawModels(void)
1337 entity_render_t *ent;
1339 if (!r_drawentities.integer)
1342 for (i = 0;i < r_refdef.numentities;i++)
1344 ent = r_refdef.entities[i];
1345 if (ent->visframe == r_framecount)
1347 renderstats.entities++;
1348 if (ent->model && ent->model->Draw != NULL)
1349 ent->model->Draw(ent);
1356 static void R_SetFrustum(void)
1358 // break apart the view matrix into vectors for various purposes
1359 Matrix4x4_ToVectors(&r_view_matrix, r_viewforward, r_viewleft, r_viewup, r_vieworigin);
1360 VectorNegate(r_viewleft, r_viewright);
1363 frustum[0].normal[0] = 0 - 1.0 / r_refdef.frustum_x;
1364 frustum[0].normal[1] = 0 - 0;
1365 frustum[0].normal[2] = -1 - 0;
1366 frustum[1].normal[0] = 0 + 1.0 / r_refdef.frustum_x;
1367 frustum[1].normal[1] = 0 + 0;
1368 frustum[1].normal[2] = -1 + 0;
1369 frustum[2].normal[0] = 0 - 0;
1370 frustum[2].normal[1] = 0 - 1.0 / r_refdef.frustum_y;
1371 frustum[2].normal[2] = -1 - 0;
1372 frustum[3].normal[0] = 0 + 0;
1373 frustum[3].normal[1] = 0 + 1.0 / r_refdef.frustum_y;
1374 frustum[3].normal[2] = -1 + 0;
1378 zNear = r_nearclip.value;
1379 nudge = 1.0 - 1.0 / (1<<23);
1380 frustum[4].normal[0] = 0 - 0;
1381 frustum[4].normal[1] = 0 - 0;
1382 frustum[4].normal[2] = -1 - -nudge;
1383 frustum[4].dist = 0 - -2 * zNear * nudge;
1384 frustum[5].normal[0] = 0 + 0;
1385 frustum[5].normal[1] = 0 + 0;
1386 frustum[5].normal[2] = -1 + -nudge;
1387 frustum[5].dist = 0 + -2 * zNear * nudge;
1393 frustum[0].normal[0] = m[3] - m[0];
1394 frustum[0].normal[1] = m[7] - m[4];
1395 frustum[0].normal[2] = m[11] - m[8];
1396 frustum[0].dist = m[15] - m[12];
1398 frustum[1].normal[0] = m[3] + m[0];
1399 frustum[1].normal[1] = m[7] + m[4];
1400 frustum[1].normal[2] = m[11] + m[8];
1401 frustum[1].dist = m[15] + m[12];
1403 frustum[2].normal[0] = m[3] - m[1];
1404 frustum[2].normal[1] = m[7] - m[5];
1405 frustum[2].normal[2] = m[11] - m[9];
1406 frustum[2].dist = m[15] - m[13];
1408 frustum[3].normal[0] = m[3] + m[1];
1409 frustum[3].normal[1] = m[7] + m[5];
1410 frustum[3].normal[2] = m[11] + m[9];
1411 frustum[3].dist = m[15] + m[13];
1413 frustum[4].normal[0] = m[3] - m[2];
1414 frustum[4].normal[1] = m[7] - m[6];
1415 frustum[4].normal[2] = m[11] - m[10];
1416 frustum[4].dist = m[15] - m[14];
1418 frustum[5].normal[0] = m[3] + m[2];
1419 frustum[5].normal[1] = m[7] + m[6];
1420 frustum[5].normal[2] = m[11] + m[10];
1421 frustum[5].dist = m[15] + m[14];
1426 VectorMAM(1, r_viewforward, 1.0 / -r_refdef.frustum_x, r_viewleft, frustum[0].normal);
1427 VectorMAM(1, r_viewforward, 1.0 / r_refdef.frustum_x, r_viewleft, frustum[1].normal);
1428 VectorMAM(1, r_viewforward, 1.0 / -r_refdef.frustum_y, r_viewup, frustum[2].normal);
1429 VectorMAM(1, r_viewforward, 1.0 / r_refdef.frustum_y, r_viewup, frustum[3].normal);
1430 VectorCopy(r_viewforward, frustum[4].normal);
1431 VectorNormalize(frustum[0].normal);
1432 VectorNormalize(frustum[1].normal);
1433 VectorNormalize(frustum[2].normal);
1434 VectorNormalize(frustum[3].normal);
1435 frustum[0].dist = DotProduct (r_vieworigin, frustum[0].normal);
1436 frustum[1].dist = DotProduct (r_vieworigin, frustum[1].normal);
1437 frustum[2].dist = DotProduct (r_vieworigin, frustum[2].normal);
1438 frustum[3].dist = DotProduct (r_vieworigin, frustum[3].normal);
1439 frustum[4].dist = DotProduct (r_vieworigin, frustum[4].normal) + r_nearclip.value;
1440 PlaneClassify(&frustum[0]);
1441 PlaneClassify(&frustum[1]);
1442 PlaneClassify(&frustum[2]);
1443 PlaneClassify(&frustum[3]);
1444 PlaneClassify(&frustum[4]);
1446 // LordHavoc: note to all quake engine coders, Quake had a special case
1447 // for 90 degrees which assumed a square view (wrong), so I removed it,
1448 // Quake2 has it disabled as well.
1450 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
1451 //RotatePointAroundVector( frustum[0].normal, r_viewup, r_viewforward, -(90 - r_refdef.fov_x / 2));
1452 //frustum[0].dist = DotProduct (r_vieworigin, frustum[0].normal);
1453 //PlaneClassify(&frustum[0]);
1455 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
1456 //RotatePointAroundVector( frustum[1].normal, r_viewup, r_viewforward, (90 - r_refdef.fov_x / 2));
1457 //frustum[1].dist = DotProduct (r_vieworigin, frustum[1].normal);
1458 //PlaneClassify(&frustum[1]);
1460 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
1461 //RotatePointAroundVector( frustum[2].normal, r_viewleft, r_viewforward, -(90 - r_refdef.fov_y / 2));
1462 //frustum[2].dist = DotProduct (r_vieworigin, frustum[2].normal);
1463 //PlaneClassify(&frustum[2]);
1465 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
1466 //RotatePointAroundVector( frustum[3].normal, r_viewleft, r_viewforward, (90 - r_refdef.fov_y / 2));
1467 //frustum[3].dist = DotProduct (r_vieworigin, frustum[3].normal);
1468 //PlaneClassify(&frustum[3]);
1471 //VectorCopy(r_viewforward, frustum[4].normal);
1472 //frustum[4].dist = DotProduct (r_vieworigin, frustum[4].normal) + r_nearclip.value;
1473 //PlaneClassify(&frustum[4]);
1476 static void R_BlendView(void)
1478 int screenwidth, screenheight;
1482 float texcoord2f[3][8];
1484 // set the (poorly named) screenwidth and screenheight variables to
1485 // a power of 2 at least as large as the screen, these will define the
1486 // size of the texture to allocate
1487 for (screenwidth = 1;screenwidth < vid.width;screenwidth *= 2);
1488 for (screenheight = 1;screenheight < vid.height;screenheight *= 2);
1490 doblend = r_refdef.viewblend[3] >= 0.01f;
1491 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;
1493 if (!dobloom && !doblend)
1496 GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
1498 GL_DepthTest(false);
1499 R_Mesh_Matrix(&identitymatrix);
1500 // vertex coordinates for a quad that covers the screen exactly
1501 vertex3f[0] = 0;vertex3f[1] = 0;vertex3f[2] = 0;
1502 vertex3f[3] = 1;vertex3f[4] = 0;vertex3f[5] = 0;
1503 vertex3f[6] = 1;vertex3f[7] = 1;vertex3f[8] = 0;
1504 vertex3f[9] = 0;vertex3f[10] = 1;vertex3f[11] = 0;
1505 R_Mesh_VertexPointer(vertex3f);
1506 R_Mesh_ColorPointer(NULL);
1507 R_Mesh_ResetTextureState();
1510 int bloomwidth, bloomheight, x, range;
1511 float xoffset, yoffset, r;
1512 renderstats.bloom++;
1513 // allocate textures as needed
1514 if (!r_bloom_texture_screen)
1515 r_bloom_texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", screenwidth, screenheight, NULL, TEXTYPE_RGBA, TEXF_FORCENEAREST | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
1516 if (!r_bloom_texture_bloom)
1517 r_bloom_texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", screenwidth, screenheight, NULL, TEXTYPE_RGBA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
1518 // set bloomwidth and bloomheight to the bloom resolution that will be
1519 // used (often less than the screen resolution for faster rendering)
1520 bloomwidth = min(r_view_width, r_bloom_resolution.integer);
1521 bloomheight = min(r_view_height, bloomwidth * r_view_height / r_view_width);
1522 // set up a texcoord array for the full resolution screen image
1523 // (we have to keep this around to copy back during final render)
1524 texcoord2f[0][0] = 0;
1525 texcoord2f[0][1] = (float)r_view_height / (float)screenheight;
1526 texcoord2f[0][2] = (float)r_view_width / (float)screenwidth;
1527 texcoord2f[0][3] = (float)r_view_height / (float)screenheight;
1528 texcoord2f[0][4] = (float)r_view_width / (float)screenwidth;
1529 texcoord2f[0][5] = 0;
1530 texcoord2f[0][6] = 0;
1531 texcoord2f[0][7] = 0;
1532 // set up a texcoord array for the reduced resolution bloom image
1533 // (which will be additive blended over the screen image)
1534 texcoord2f[1][0] = 0;
1535 texcoord2f[1][1] = (float)bloomheight / (float)screenheight;
1536 texcoord2f[1][2] = (float)bloomwidth / (float)screenwidth;
1537 texcoord2f[1][3] = (float)bloomheight / (float)screenheight;
1538 texcoord2f[1][4] = (float)bloomwidth / (float)screenwidth;
1539 texcoord2f[1][5] = 0;
1540 texcoord2f[1][6] = 0;
1541 texcoord2f[1][7] = 0;
1542 R_Mesh_TexCoordPointer(0, 2, texcoord2f[0]);
1543 R_Mesh_TexBind(0, R_GetTexture(r_bloom_texture_screen));
1544 // copy view into the full resolution screen image texture
1545 GL_ActiveTexture(0);
1546 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
1547 renderstats.bloom_copypixels += r_view_width * r_view_height;
1548 // now scale it down to the bloom size and raise to a power of itself
1549 // to darken it (this leaves the really bright stuff bright, and
1550 // everything else becomes very dark)
1551 // TODO: optimize with multitexture or GLSL
1552 qglViewport(r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
1553 GL_BlendFunc(GL_ONE, GL_ZERO);
1554 GL_Color(1, 1, 1, 1);
1555 R_Mesh_Draw(0, 4, 2, polygonelements);
1556 renderstats.bloom_drawpixels += bloomwidth * bloomheight;
1557 // render multiple times with a multiply blendfunc to raise to a power
1558 GL_BlendFunc(GL_DST_COLOR, GL_ZERO);
1559 for (x = 1;x < r_bloom_power.integer;x++)
1561 R_Mesh_Draw(0, 4, 2, polygonelements);
1562 renderstats.bloom_drawpixels += bloomwidth * bloomheight;
1564 // we now have a darkened bloom image in the framebuffer, copy it into
1565 // the bloom image texture for more processing
1566 R_Mesh_TexBind(0, R_GetTexture(r_bloom_texture_bloom));
1567 R_Mesh_TexCoordPointer(0, 2, texcoord2f[2]);
1568 GL_ActiveTexture(0);
1569 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
1570 renderstats.bloom_copypixels += bloomwidth * bloomheight;
1571 // blend on at multiple vertical offsets to achieve a vertical blur
1572 // TODO: do offset blends using GLSL
1573 range = r_bloom_blur.integer * bloomwidth / 320;
1574 GL_BlendFunc(GL_ONE, GL_ZERO);
1575 for (x = -range;x <= range;x++)
1577 xoffset = 0 / (float)bloomwidth * (float)bloomwidth / (float)screenwidth;
1578 yoffset = x / (float)bloomheight * (float)bloomheight / (float)screenheight;
1579 // compute a texcoord array with the specified x and y offset
1580 texcoord2f[2][0] = xoffset+0;
1581 texcoord2f[2][1] = yoffset+(float)bloomheight / (float)screenheight;
1582 texcoord2f[2][2] = xoffset+(float)bloomwidth / (float)screenwidth;
1583 texcoord2f[2][3] = yoffset+(float)bloomheight / (float)screenheight;
1584 texcoord2f[2][4] = xoffset+(float)bloomwidth / (float)screenwidth;
1585 texcoord2f[2][5] = yoffset+0;
1586 texcoord2f[2][6] = xoffset+0;
1587 texcoord2f[2][7] = yoffset+0;
1588 // this r value looks like a 'dot' particle, fading sharply to
1589 // black at the edges
1590 // (probably not realistic but looks good enough)
1591 r = r_bloom_intensity.value/(range*2+1)*(1 - x*x/(float)(range*range));
1594 GL_Color(r, r, r, 1);
1595 R_Mesh_Draw(0, 4, 2, polygonelements);
1596 renderstats.bloom_drawpixels += bloomwidth * bloomheight;
1597 GL_BlendFunc(GL_ONE, GL_ONE);
1599 // copy the vertically blurred bloom view to a texture
1600 GL_ActiveTexture(0);
1601 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
1602 renderstats.bloom_copypixels += bloomwidth * bloomheight;
1603 // blend the vertically blurred image at multiple offsets horizontally
1604 // to finish the blur effect
1605 // TODO: do offset blends using GLSL
1606 range = r_bloom_blur.integer * bloomwidth / 320;
1607 GL_BlendFunc(GL_ONE, GL_ZERO);
1608 for (x = -range;x <= range;x++)
1610 xoffset = x / (float)bloomwidth * (float)bloomwidth / (float)screenwidth;
1611 yoffset = 0 / (float)bloomheight * (float)bloomheight / (float)screenheight;
1612 // compute a texcoord array with the specified x and y offset
1613 texcoord2f[2][0] = xoffset+0;
1614 texcoord2f[2][1] = yoffset+(float)bloomheight / (float)screenheight;
1615 texcoord2f[2][2] = xoffset+(float)bloomwidth / (float)screenwidth;
1616 texcoord2f[2][3] = yoffset+(float)bloomheight / (float)screenheight;
1617 texcoord2f[2][4] = xoffset+(float)bloomwidth / (float)screenwidth;
1618 texcoord2f[2][5] = yoffset+0;
1619 texcoord2f[2][6] = xoffset+0;
1620 texcoord2f[2][7] = yoffset+0;
1621 // this r value looks like a 'dot' particle, fading sharply to
1622 // black at the edges
1623 // (probably not realistic but looks good enough)
1624 r = r_bloom_intensity.value/(range*2+1)*(1 - x*x/(float)(range*range));
1627 GL_Color(r, r, r, 1);
1628 R_Mesh_Draw(0, 4, 2, polygonelements);
1629 renderstats.bloom_drawpixels += bloomwidth * bloomheight;
1630 GL_BlendFunc(GL_ONE, GL_ONE);
1632 // copy the blurred bloom view to a texture
1633 GL_ActiveTexture(0);
1634 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
1635 renderstats.bloom_copypixels += bloomwidth * bloomheight;
1636 // go back to full view area
1637 qglViewport(r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
1638 // put the original screen image back in place and blend the bloom
1641 GL_BlendFunc(GL_ONE, GL_ZERO);
1642 // do both in one pass if possible
1643 R_Mesh_TexBind(0, R_GetTexture(r_bloom_texture_screen));
1644 R_Mesh_TexCoordPointer(0, 2, texcoord2f[0]);
1645 if (r_textureunits.integer >= 2 && gl_combine.integer)
1647 R_Mesh_TexCombine(1, GL_ADD, GL_ADD, 1, 1);
1648 R_Mesh_TexBind(1, R_GetTexture(r_bloom_texture_bloom));
1649 R_Mesh_TexCoordPointer(1, 2, texcoord2f[1]);
1653 R_Mesh_Draw(0, 4, 2, polygonelements);
1654 renderstats.bloom_drawpixels += r_view_width * r_view_height;
1655 // now blend on the bloom texture
1656 GL_BlendFunc(GL_ONE, GL_ONE);
1657 R_Mesh_TexBind(0, R_GetTexture(r_bloom_texture_bloom));
1658 R_Mesh_TexCoordPointer(0, 2, texcoord2f[1]);
1660 R_Mesh_Draw(0, 4, 2, polygonelements);
1661 renderstats.bloom_drawpixels += r_view_width * r_view_height;
1665 // apply a color tint to the whole view
1666 R_Mesh_ResetTextureState();
1667 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1668 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
1669 R_Mesh_Draw(0, 4, 2, polygonelements);
1673 void R_RenderScene(void);
1675 matrix4x4_t r_waterscrollmatrix;
1682 void R_RenderView(void)
1684 if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
1685 return; //Host_Error ("R_RenderView: NULL worldmodel");
1687 r_view_width = bound(0, r_refdef.width, vid.width);
1688 r_view_height = bound(0, r_refdef.height, vid.height);
1690 r_view_x = bound(0, r_refdef.x, vid.width - r_refdef.width);
1691 r_view_y = bound(0, r_refdef.y, vid.height - r_refdef.height);
1693 r_view_matrix = r_refdef.viewentitymatrix;
1694 GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
1695 r_rtworld = r_shadow_realtime_world.integer;
1696 r_rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
1697 r_rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer;
1698 r_rtdlightshadows = r_rtdlight && (r_rtworld ? r_shadow_realtime_world_dlightshadows.integer : r_shadow_realtime_dlight_shadows.integer) && gl_stencil;
1699 r_lightmapintensity = r_rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
1700 r_polygonfactor = 0;
1701 r_polygonoffset = 0;
1702 r_shadowpolygonfactor = r_polygonfactor + r_shadow_shadow_polygonfactor.value;
1703 r_shadowpolygonoffset = r_polygonoffset + r_shadow_shadow_polygonoffset.value;
1704 if (r_showsurfaces.integer)
1707 r_rtworldshadows = false;
1709 r_rtdlightshadows = false;
1710 r_lightmapintensity = 0;
1713 // GL is weird because it's bottom to top, r_view_y is top to bottom
1714 qglViewport(r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
1715 GL_Scissor(r_view_x, r_view_y, r_view_width, r_view_height);
1716 GL_ScissorTest(true);
1721 if (r_timereport_active)
1722 R_TimeReport("setup");
1724 qglDepthFunc(GL_LEQUAL);
1725 qglPolygonOffset(r_polygonfactor, r_polygonoffset);
1726 qglEnable(GL_POLYGON_OFFSET_FILL);
1730 qglPolygonOffset(r_polygonfactor, r_polygonoffset);
1731 qglDisable(GL_POLYGON_OFFSET_FILL);
1734 if (r_timereport_active)
1735 R_TimeReport("blendview");
1737 GL_Scissor(0, 0, vid.width, vid.height);
1738 GL_ScissorTest(false);
1742 void CSQC_R_ClearScreen (void)
1744 if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
1745 return; //Host_Error ("R_RenderView: NULL worldmodel");
1747 r_view_width = bound(0, r_refdef.width, vid.width);
1748 r_view_height = bound(0, r_refdef.height, vid.height);
1750 r_view_x = bound(0, r_refdef.x, vid.width - r_refdef.width);
1751 r_view_y = bound(0, r_refdef.y, vid.height - r_refdef.height);
1753 r_view_matrix = r_refdef.viewentitymatrix;
1754 GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
1755 r_rtworld = r_shadow_realtime_world.integer;
1756 r_rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
1757 r_rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer;
1758 r_rtdlightshadows = r_rtdlight && (r_rtworld ? r_shadow_realtime_world_dlightshadows.integer : r_shadow_realtime_dlight_shadows.integer) && gl_stencil;
1759 r_lightmapintensity = r_rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
1760 r_polygonfactor = 0;
1761 r_polygonoffset = 0;
1762 r_shadowpolygonfactor = r_polygonfactor + r_shadow_shadow_polygonfactor.value;
1763 r_shadowpolygonoffset = r_polygonoffset + r_shadow_shadow_polygonoffset.value;
1764 if (r_showsurfaces.integer)
1767 r_rtworldshadows = false;
1769 r_rtdlightshadows = false;
1770 r_lightmapintensity = 0;
1773 // GL is weird because it's bottom to top, r_view_y is top to bottom
1774 qglViewport(r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
1775 GL_Scissor(r_view_x, r_view_y, r_view_width, r_view_height);
1776 GL_ScissorTest(true);
1781 if (r_timereport_active)
1782 R_TimeReport("setup");
1786 void CSQC_R_RenderScene (void)
1788 qglDepthFunc(GL_LEQUAL);
1789 qglPolygonOffset(r_polygonfactor, r_polygonoffset);
1790 qglEnable(GL_POLYGON_OFFSET_FILL);
1794 qglPolygonOffset(r_polygonfactor, r_polygonoffset);
1795 qglDisable(GL_POLYGON_OFFSET_FILL);
1798 if (r_timereport_active)
1799 R_TimeReport("blendview");
1801 GL_Scissor(0, 0, vid.width, vid.height);
1802 GL_ScissorTest(false);
1805 extern void R_DrawLightningBeams (void);
1806 extern void VM_AddPolygonsToMeshQueue (void);
1807 void R_RenderScene(void)
1811 // don't let sound skip if going slow
1812 if (r_refdef.extraupdate)
1817 if (gl_support_fragment_shader)
1818 qglUseProgramObjectARB(0);
1820 R_MeshQueue_BeginScene();
1824 r_farclip = R_FarClip(r_vieworigin, r_viewforward, 768.0f) + 256.0f;
1825 nearclip = bound (0.001f, r_nearclip.value, r_farclip - 1.0f);
1827 if (r_rtworldshadows || r_rtdlightshadows)
1828 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_refdef.frustum_x, r_refdef.frustum_y, nearclip);
1830 GL_SetupView_Mode_Perspective(r_refdef.frustum_x, r_refdef.frustum_y, nearclip, r_farclip);
1832 GL_SetupView_Orientation_FromEntity(&r_view_matrix);
1834 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);
1838 R_WorldVisibility();
1839 if (r_timereport_active)
1840 R_TimeReport("worldvis");
1843 if (r_timereport_active)
1844 R_TimeReport("markentity");
1846 R_Shadow_UpdateWorldLightSelection();
1848 if (cl.csqc_vidvars.drawworld)
1850 // don't let sound skip if going slow
1851 if (r_refdef.extraupdate)
1854 if (r_refdef.worldmodel && r_refdef.worldmodel->DrawSky)
1856 r_refdef.worldmodel->DrawSky(r_refdef.worldentity);
1857 if (r_timereport_active)
1858 R_TimeReport("worldsky");
1861 if (R_DrawBrushModelsSky() && r_timereport_active)
1862 R_TimeReport("bmodelsky");
1864 if (r_refdef.worldmodel && r_refdef.worldmodel->Draw)
1866 r_refdef.worldmodel->Draw(r_refdef.worldentity);
1867 if (r_timereport_active)
1868 R_TimeReport("world");
1872 // don't let sound skip if going slow
1873 if (r_refdef.extraupdate)
1877 if (r_timereport_active)
1878 R_TimeReport("models");
1880 // don't let sound skip if going slow
1881 if (r_refdef.extraupdate)
1884 R_ShadowVolumeLighting(false);
1885 if (r_timereport_active)
1886 R_TimeReport("rtlights");
1888 // don't let sound skip if going slow
1889 if (r_refdef.extraupdate)
1892 if (cl.csqc_vidvars.drawworld)
1894 R_DrawLightningBeams();
1895 if (r_timereport_active)
1896 R_TimeReport("lightning");
1899 if (r_timereport_active)
1900 R_TimeReport("particles");
1903 if (r_timereport_active)
1904 R_TimeReport("explosions");
1907 R_MeshQueue_RenderTransparent();
1908 if (r_timereport_active)
1909 R_TimeReport("drawtrans");
1911 if (cl.csqc_vidvars.drawworld)
1914 if (r_timereport_active)
1915 R_TimeReport("coronas");
1917 if(cl.csqc_vidvars.drawcrosshair)
1919 R_DrawWorldCrosshair();
1920 if (r_timereport_active)
1921 R_TimeReport("crosshair");
1924 VM_AddPolygonsToMeshQueue();
1926 R_MeshQueue_Render();
1928 R_MeshQueue_EndScene();
1930 // don't let sound skip if going slow
1931 if (r_refdef.extraupdate)
1934 if (gl_support_fragment_shader)
1935 qglUseProgramObjectARB(0);
1939 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
1942 float *v, *c, f1, f2, diff[3], vertex3f[8*3], color4f[8*4];
1943 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1944 GL_DepthMask(false);
1946 R_Mesh_Matrix(&identitymatrix);
1948 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2];
1949 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
1950 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
1951 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
1952 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
1953 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
1954 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
1955 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
1956 R_FillColors(color, 8, cr, cg, cb, ca);
1959 for (i = 0, v = vertex, c = color;i < 8;i++, v += 4, c += 4)
1961 f2 = VERTEXFOGTABLE(VectorDistance(v, r_vieworigin));
1963 c[0] = c[0] * f1 + fogcolor[0] * f2;
1964 c[1] = c[1] * f1 + fogcolor[1] * f2;
1965 c[2] = c[2] * f1 + fogcolor[2] * f2;
1968 R_Mesh_VertexPointer(vertex3f);
1969 R_Mesh_ColorPointer(color);
1970 R_Mesh_ResetTextureState();
1975 int nomodelelements[24] =
1987 float nomodelvertex3f[6*3] =
1997 float nomodelcolor4f[6*4] =
1999 0.0f, 0.0f, 0.5f, 1.0f,
2000 0.0f, 0.0f, 0.5f, 1.0f,
2001 0.0f, 0.5f, 0.0f, 1.0f,
2002 0.0f, 0.5f, 0.0f, 1.0f,
2003 0.5f, 0.0f, 0.0f, 1.0f,
2004 0.5f, 0.0f, 0.0f, 1.0f
2007 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight)
2012 R_Mesh_Matrix(&ent->matrix);
2014 if (ent->flags & EF_ADDITIVE)
2016 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2017 GL_DepthMask(false);
2019 else if (ent->alpha < 1)
2021 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2022 GL_DepthMask(false);
2026 GL_BlendFunc(GL_ONE, GL_ZERO);
2029 GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
2030 R_Mesh_VertexPointer(nomodelvertex3f);
2033 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
2034 R_Mesh_ColorPointer(color4f);
2035 f2 = VERTEXFOGTABLE(VectorDistance(ent->origin, r_vieworigin));
2037 for (i = 0, c = color4f;i < 6;i++, c += 4)
2039 c[0] = (c[0] * f1 + fogcolor[0] * f2);
2040 c[1] = (c[1] * f1 + fogcolor[1] * f2);
2041 c[2] = (c[2] * f1 + fogcolor[2] * f2);
2045 else if (ent->alpha != 1)
2047 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
2048 R_Mesh_ColorPointer(color4f);
2049 for (i = 0, c = color4f;i < 6;i++, c += 4)
2053 R_Mesh_ColorPointer(nomodelcolor4f);
2054 R_Mesh_ResetTextureState();
2055 R_Mesh_Draw(0, 6, 8, nomodelelements);
2058 void R_DrawNoModel(entity_render_t *ent)
2060 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
2061 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_vieworigin : ent->origin, R_DrawNoModel_TransparentCallback, ent, 0, r_shadow_rtlight);
2063 // R_DrawNoModelCallback(ent, 0);
2066 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
2068 vec3_t right1, right2, diff, normal;
2070 VectorSubtract (org2, org1, normal);
2072 // calculate 'right' vector for start
2073 VectorSubtract (r_vieworigin, org1, diff);
2074 CrossProduct (normal, diff, right1);
2075 VectorNormalize (right1);
2077 // calculate 'right' vector for end
2078 VectorSubtract (r_vieworigin, org2, diff);
2079 CrossProduct (normal, diff, right2);
2080 VectorNormalize (right2);
2082 vert[ 0] = org1[0] + width * right1[0];
2083 vert[ 1] = org1[1] + width * right1[1];
2084 vert[ 2] = org1[2] + width * right1[2];
2085 vert[ 3] = org1[0] - width * right1[0];
2086 vert[ 4] = org1[1] - width * right1[1];
2087 vert[ 5] = org1[2] - width * right1[2];
2088 vert[ 6] = org2[0] - width * right2[0];
2089 vert[ 7] = org2[1] - width * right2[1];
2090 vert[ 8] = org2[2] - width * right2[2];
2091 vert[ 9] = org2[0] + width * right2[0];
2092 vert[10] = org2[1] + width * right2[1];
2093 vert[11] = org2[2] + width * right2[2];
2096 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
2098 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)
2100 float fog = 0.0f, ifog;
2104 fog = VERTEXFOGTABLE(VectorDistance(origin, r_vieworigin));
2107 R_Mesh_Matrix(&identitymatrix);
2108 GL_BlendFunc(blendfunc1, blendfunc2);
2109 GL_DepthMask(false);
2110 GL_DepthTest(!depthdisable);
2112 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
2113 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
2114 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
2115 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
2116 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
2117 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
2118 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
2119 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
2120 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
2121 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
2122 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
2123 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
2125 R_Mesh_VertexPointer(vertex3f);
2126 R_Mesh_ColorPointer(NULL);
2127 R_Mesh_ResetTextureState();
2128 R_Mesh_TexBind(0, R_GetTexture(texture));
2129 R_Mesh_TexCoordPointer(0, 2, spritetexcoord2f);
2130 GL_Color(cr * ifog, cg * ifog, cb * ifog, ca);
2131 R_Mesh_Draw(0, 4, 2, polygonelements);
2133 if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
2135 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
2136 GL_BlendFunc(blendfunc1, GL_ONE);
2137 GL_Color(fogcolor[0] * fog, fogcolor[1] * fog, fogcolor[2] * fog, ca);
2138 R_Mesh_Draw(0, 4, 2, polygonelements);
2142 int R_Mesh_AddVertex3f(rmesh_t *mesh, const float *v)
2146 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
2147 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
2149 if (i == mesh->numvertices)
2151 if (mesh->numvertices < mesh->maxvertices)
2153 VectorCopy(v, vertex3f);
2154 mesh->numvertices++;
2156 return mesh->numvertices;
2162 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
2166 element[0] = R_Mesh_AddVertex3f(mesh, vertex3f);vertex3f += 3;
2167 element[1] = R_Mesh_AddVertex3f(mesh, vertex3f);vertex3f += 3;
2168 e = mesh->element3i + mesh->numtriangles * 3;
2169 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
2171 element[2] = R_Mesh_AddVertex3f(mesh, vertex3f);
2172 if (mesh->numtriangles < mesh->maxtriangles)
2177 mesh->numtriangles++;
2179 element[1] = element[2];
2183 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
2185 int planenum, planenum2;
2188 mplane_t *plane, *plane2;
2189 float temppoints[2][256*3];
2190 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
2194 PolygonF_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->normal[3], 1024.0*1024.0*1024.0);
2195 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
2197 if (planenum2 == planenum)
2199 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);
2202 if (tempnumpoints < 3)
2204 // generate elements forming a triangle fan for this polygon
2205 R_Mesh_AddPolygon3f(mesh, tempnumpoints, temppoints[w]);
2209 static void R_DrawCollisionBrush(const colbrushf_t *brush)
2212 R_Mesh_VertexPointer(brush->points->v);
2213 i = (int)(((size_t)brush) / sizeof(colbrushf_t));
2214 GL_Color((i & 31) * (1.0f / 32.0f), ((i >> 5) & 31) * (1.0f / 32.0f), ((i >> 10) & 31) * (1.0f / 32.0f), 0.2f);
2215 GL_LockArrays(0, brush->numpoints);
2216 R_Mesh_Draw(0, brush->numpoints, brush->numtriangles, brush->elements);
2217 GL_LockArrays(0, 0);
2220 static void R_DrawCollisionSurface(const entity_render_t *ent, const msurface_t *surface)
2223 if (!surface->num_collisiontriangles)
2225 R_Mesh_VertexPointer(surface->data_collisionvertex3f);
2226 i = (int)(((size_t)surface) / sizeof(msurface_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, surface->num_collisionvertices);
2229 R_Mesh_Draw(0, surface->num_collisionvertices, surface->num_collisiontriangles, surface->data_collisionelement3i);
2230 GL_LockArrays(0, 0);
2233 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)
2235 texturelayer_t *layer;
2236 layer = t->currentlayers + t->currentnumlayers++;
2238 layer->depthmask = depthmask;
2239 layer->blendfunc1 = blendfunc1;
2240 layer->blendfunc2 = blendfunc2;
2241 layer->texture = texture;
2242 layer->texmatrix = *matrix;
2243 layer->color[0] = r;
2244 layer->color[1] = g;
2245 layer->color[2] = b;
2246 layer->color[3] = a;
2249 void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
2251 // FIXME: identify models using a better check than ent->model->brush.shadowmesh
2252 //int lightmode = ((ent->effects & EF_FULLBRIGHT) || ent->model->brush.shadowmesh) ? 0 : 2;
2255 texture_t *texture = t;
2256 model_t *model = ent->model;
2257 int s = ent->skinnum;
2258 if ((unsigned int)s >= (unsigned int)model->numskins)
2260 if (model->skinscenes)
2262 if (model->skinscenes[s].framecount > 1)
2263 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
2265 s = model->skinscenes[s].firstframe;
2268 t = t + s * model->num_surfaces;
2270 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];
2271 texture->currentframe = t;
2274 t->currentmaterialflags = t->basematerialflags;
2275 t->currentalpha = ent->alpha;
2276 if (t->basematerialflags & MATERIALFLAG_WATERALPHA)
2277 t->currentalpha *= r_wateralpha.value;
2278 if (!(ent->flags & RENDER_LIGHT))
2279 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
2280 if (ent->effects & EF_ADDITIVE)
2281 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_TRANSPARENT;
2282 else if (t->currentalpha < 1)
2283 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_TRANSPARENT;
2284 if (ent->effects & EF_NODEPTHTEST)
2285 t->currentmaterialflags |= MATERIALFLAG_NODEPTHTEST;
2286 if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
2287 t->currenttexmatrix = r_waterscrollmatrix;
2289 t->currenttexmatrix = identitymatrix;
2291 t->colormapping = VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f);
2292 t->basetexture = (!t->colormapping && t->skin.merged) ? t->skin.merged : t->skin.base;
2293 t->glosstexture = r_texture_white;
2294 t->specularpower = 8;
2295 t->specularscale = 0;
2296 if (r_shadow_gloss.integer > 0)
2300 if (r_shadow_glossintensity.value > 0)
2302 t->glosstexture = t->skin.gloss;
2303 t->specularscale = r_shadow_glossintensity.value;
2306 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
2307 t->specularscale = r_shadow_gloss2intensity.value;
2310 t->currentnumlayers = 0;
2311 if (!(t->currentmaterialflags & MATERIALFLAG_NODRAW))
2313 if (gl_lightmaps.integer)
2314 R_Texture_AddLayer(t, true, GL_ONE, GL_ZERO, TEXTURELAYERTYPE_LITTEXTURE_MULTIPASS, r_texture_white, &identitymatrix, 1, 1, 1, 1);
2315 else if (!(t->currentmaterialflags & MATERIALFLAG_SKY))
2317 int blendfunc1, blendfunc2, depthmask;
2318 if (t->currentmaterialflags & MATERIALFLAG_ADD)
2320 blendfunc1 = GL_SRC_ALPHA;
2321 blendfunc2 = GL_ONE;
2324 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
2326 blendfunc1 = GL_SRC_ALPHA;
2327 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
2332 blendfunc1 = GL_ONE;
2333 blendfunc2 = GL_ZERO;
2336 if (t->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL))
2338 rtexture_t *currentbasetexture;
2340 if (fogenabled && (t->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
2341 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
2342 currentbasetexture = (VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) < (1.0f / 1048576.0f) && t->skin.merged) ? t->skin.merged : t->skin.base;
2343 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2345 // fullbright is not affected by r_lightmapintensity
2346 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
2347 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->skin.pants)
2348 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);
2349 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->skin.shirt)
2350 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);
2356 // q3bsp has no lightmap updates, so the lightstylevalue that
2357 // would normally be baked into the lightmaptexture must be
2358 // applied to the color
2359 if (ent->model->type == mod_brushq3)
2360 colorscale *= r_refdef.lightstylevalue[0] * (1.0f / 256.0f);
2361 colorscale *= r_lightmapintensity;
2362 if (r_textureunits.integer >= 2 && gl_combine.integer)
2363 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);
2364 else if ((t->currentmaterialflags & MATERIALFLAG_TRANSPARENT) == 0)
2365 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);
2367 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);
2368 if (r_ambient.value >= (1.0f/64.0f))
2369 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);
2370 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->skin.pants)
2372 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);
2373 if (r_ambient.value >= (1.0f/64.0f))
2374 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);
2376 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->skin.shirt)
2378 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);
2379 if (r_ambient.value >= (1.0f/64.0f))
2380 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);
2383 if (t->skin.glow != NULL)
2384 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.glow, &t->currenttexmatrix, 1, 1, 1, t->currentalpha);
2385 if (fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
2387 // if this is opaque use alpha blend which will darken the earlier
2390 // if this is an alpha blended material, all the earlier passes
2391 // were darkened by fog already, so we only need to add the fog
2392 // color ontop through the fog mask texture
2394 // if this is an additive blended material, all the earlier passes
2395 // were darkened by fog already, and we should not add fog color
2396 // (because the background was not darkened, there is no fog color
2397 // that was lost behind it).
2398 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);
2405 void R_UpdateAllTextureInfo(entity_render_t *ent)
2409 for (i = 0;i < ent->model->num_textures;i++)
2410 R_UpdateTextureInfo(ent, ent->model->data_textures + i);
2413 int rsurface_array_size = 0;
2414 float *rsurface_array_vertex3f = NULL;
2415 float *rsurface_array_svector3f = NULL;
2416 float *rsurface_array_tvector3f = NULL;
2417 float *rsurface_array_normal3f = NULL;
2418 float *rsurface_array_color4f = NULL;
2419 float *rsurface_array_texcoord3f = NULL;
2421 void R_Mesh_ResizeArrays(int newvertices)
2423 if (rsurface_array_size >= newvertices)
2425 if (rsurface_array_vertex3f)
2426 Mem_Free(rsurface_array_vertex3f);
2427 rsurface_array_size = (newvertices + 1023) & ~1023;
2428 rsurface_array_vertex3f = (float *)Mem_Alloc(r_main_mempool, rsurface_array_size * sizeof(float[19]));
2429 rsurface_array_svector3f = rsurface_array_vertex3f + rsurface_array_size * 3;
2430 rsurface_array_tvector3f = rsurface_array_vertex3f + rsurface_array_size * 6;
2431 rsurface_array_normal3f = rsurface_array_vertex3f + rsurface_array_size * 9;
2432 rsurface_array_color4f = rsurface_array_vertex3f + rsurface_array_size * 12;
2433 rsurface_array_texcoord3f = rsurface_array_vertex3f + rsurface_array_size * 16;
2436 float *rsurface_vertex3f;
2437 float *rsurface_svector3f;
2438 float *rsurface_tvector3f;
2439 float *rsurface_normal3f;
2440 float *rsurface_lightmapcolor4f;
2441 vec3_t rsurface_modelorg;
2442 const entity_render_t *rsurface_entity;
2443 const model_t *rsurface_model;
2444 const texture_t *rsurface_texture;
2446 void RSurf_PrepareVerticesForBatch(const entity_render_t *ent, const texture_t *texture, const vec3_t modelorg, qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, msurface_t **texturesurfacelist)
2448 VectorCopy(modelorg, rsurface_modelorg);
2449 rsurface_entity = ent;
2450 rsurface_model = ent->model;
2451 rsurface_texture = texture;
2452 if (rsurface_array_size < rsurface_model->surfmesh.num_vertices)
2453 R_Mesh_ResizeArrays(rsurface_model->surfmesh.num_vertices);
2454 if ((rsurface_entity->frameblend[0].lerp != 1 || rsurface_entity->frameblend[0].frame != 0) && (rsurface_model->surfmesh.data_morphvertex3f || rsurface_model->surfmesh.data_vertexboneweights))
2456 rsurface_vertex3f = rsurface_array_vertex3f;
2457 rsurface_svector3f = NULL;
2458 rsurface_tvector3f = NULL;
2459 rsurface_normal3f = NULL;
2460 Mod_Alias_GetMesh_Vertex3f(rsurface_model, rsurface_entity->frameblend, rsurface_array_vertex3f);
2461 if (rsurface_texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
2462 generatetangents = true;
2463 if (generatetangents)
2464 generatenormals = true;
2465 if (generatenormals && !rsurface_normal3f)
2467 rsurface_normal3f = rsurface_array_normal3f;
2468 Mod_BuildNormals(0, rsurface_model->surfmesh.num_vertices, rsurface_model->surfmesh.num_triangles, rsurface_array_vertex3f, rsurface_model->surfmesh.data_element3i, rsurface_array_normal3f, r_smoothnormals_areaweighting.integer);
2470 if (generatetangents && !rsurface_svector3f)
2472 Mod_BuildTextureVectorsFromNormals(0, rsurface_model->surfmesh.num_vertices, rsurface_model->surfmesh.num_triangles, rsurface_array_vertex3f, rsurface_model->surfmesh.data_texcoordtexture2f, rsurface_normal3f, rsurface_model->surfmesh.data_element3i, rsurface_array_svector3f, rsurface_array_tvector3f, r_smoothnormals_areaweighting.integer);
2473 rsurface_svector3f = rsurface_array_svector3f;
2474 rsurface_tvector3f = rsurface_array_tvector3f;
2479 rsurface_vertex3f = rsurface_model->surfmesh.data_vertex3f;
2480 rsurface_svector3f = rsurface_model->surfmesh.data_svector3f;
2481 rsurface_tvector3f = rsurface_model->surfmesh.data_tvector3f;
2482 rsurface_normal3f = rsurface_model->surfmesh.data_normal3f;
2484 if (rsurface_texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
2486 int texturesurfaceindex;
2487 float center[3], forward[3], right[3], up[3], v[4][3];
2488 matrix4x4_t matrix1, imatrix1;
2489 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_viewforward, forward);
2490 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_viewright, right);
2491 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_viewup, up);
2492 if (rsurface_texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE2)
2494 forward[0] = rsurface_modelorg[0] - center[0];
2495 forward[1] = rsurface_modelorg[1] - center[1];
2497 VectorNormalize(forward);
2498 right[0] = forward[1];
2499 right[1] = -forward[0];
2501 VectorSet(up, 0, 0, 1);
2503 // make deformed versions of only the vertices used by the specified surfaces
2504 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2507 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2508 // a single autosprite surface can contain multiple sprites...
2509 for (j = 0;j < surface->num_vertices - 3;j += 4)
2511 VectorClear(center);
2512 for (i = 0;i < 4;i++)
2513 VectorAdd(center, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
2514 VectorScale(center, 0.25f, center);
2515 // FIXME: calculate vectors from triangle edges instead of using texture vectors as an easy way out?
2516 Matrix4x4_FromVectors(&matrix1, (rsurface_normal3f + 3 * surface->num_firstvertex) + j*3, (rsurface_svector3f + 3 * surface->num_firstvertex) + j*3, (rsurface_tvector3f + 3 * surface->num_firstvertex) + j*3, center);
2517 Matrix4x4_Invert_Simple(&imatrix1, &matrix1);
2518 for (i = 0;i < 4;i++)
2519 Matrix4x4_Transform(&imatrix1, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, v[i]);
2520 for (i = 0;i < 4;i++)
2521 VectorMAMAMAM(1, center, v[i][0], forward, v[i][1], right, v[i][2], up, rsurface_array_vertex3f + (surface->num_firstvertex+i+j) * 3);
2523 Mod_BuildNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface_array_vertex3f, rsurface_model->surfmesh.data_element3i + surface->num_firsttriangle * 3, rsurface_array_normal3f, r_smoothnormals_areaweighting.integer);
2524 Mod_BuildTextureVectorsFromNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface_array_vertex3f, rsurface_model->surfmesh.data_texcoordtexture2f, rsurface_array_normal3f, rsurface_model->surfmesh.data_element3i + surface->num_firsttriangle * 3, rsurface_array_svector3f, rsurface_array_tvector3f, r_smoothnormals_areaweighting.integer);
2526 rsurface_vertex3f = rsurface_array_vertex3f;
2527 rsurface_svector3f = rsurface_array_svector3f;
2528 rsurface_tvector3f = rsurface_array_tvector3f;
2529 rsurface_normal3f = rsurface_array_normal3f;
2531 R_Mesh_VertexPointer(rsurface_vertex3f);
2534 static void RSurf_Draw(const msurface_t *surface)
2536 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2537 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
2540 static void RSurf_DrawLightmap(const msurface_t *surface, float r, float g, float b, float a, int lightmode, qboolean applycolor, qboolean applyfog)
2548 vec3_t ambientcolor;
2549 vec3_t diffusecolor;
2551 VectorCopy(rsurface_entity->modellight_lightdir, lightdir);
2552 ambientcolor[0] = rsurface_entity->modellight_ambient[0] * r * 0.5f;
2553 ambientcolor[1] = rsurface_entity->modellight_ambient[1] * g * 0.5f;
2554 ambientcolor[2] = rsurface_entity->modellight_ambient[2] * b * 0.5f;
2555 diffusecolor[0] = rsurface_entity->modellight_diffuse[0] * r * 0.5f;
2556 diffusecolor[1] = rsurface_entity->modellight_diffuse[1] * g * 0.5f;
2557 diffusecolor[2] = rsurface_entity->modellight_diffuse[2] * b * 0.5f;
2558 if (VectorLength2(diffusecolor) > 0)
2560 int numverts = surface->num_vertices;
2561 v = rsurface_vertex3f + 3 * surface->num_firstvertex;
2562 c2 = rsurface_normal3f + 3 * surface->num_firstvertex;
2563 c = rsurface_array_color4f + 4 * surface->num_firstvertex;
2564 // q3-style directional shading
2565 for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
2567 if ((f = DotProduct(c2, lightdir)) > 0)
2568 VectorMA(ambientcolor, f, diffusecolor, c);
2570 VectorCopy(ambientcolor, c);
2578 rsurface_lightmapcolor4f = rsurface_array_color4f;
2582 r = ambientcolor[0];
2583 g = ambientcolor[1];
2584 b = ambientcolor[2];
2585 rsurface_lightmapcolor4f = NULL;
2588 else if (lightmode >= 1)
2590 if (surface->lightmapinfo && surface->lightmapinfo->stainsamples)
2592 for (i = 0, c = rsurface_array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
2594 if (surface->lightmapinfo->samples)
2596 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface_model->surfmesh.data_lightmapoffsets + surface->num_firstvertex)[i];
2597 float scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
2598 VectorScale(lm, scale, c);
2599 if (surface->lightmapinfo->styles[1] != 255)
2601 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
2603 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
2604 VectorMA(c, scale, lm, c);
2605 if (surface->lightmapinfo->styles[2] != 255)
2608 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
2609 VectorMA(c, scale, lm, c);
2610 if (surface->lightmapinfo->styles[3] != 255)
2613 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
2614 VectorMA(c, scale, lm, c);
2622 rsurface_lightmapcolor4f = rsurface_array_color4f;
2625 rsurface_lightmapcolor4f = rsurface_model->surfmesh.data_lightmapcolor4f;
2628 rsurface_lightmapcolor4f = NULL;
2631 if (rsurface_lightmapcolor4f)
2633 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)
2635 f = 1 - VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
2644 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)
2646 f = 1 - VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
2653 rsurface_lightmapcolor4f = rsurface_array_color4f;
2655 if (applycolor && rsurface_lightmapcolor4f)
2657 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)
2664 rsurface_lightmapcolor4f = rsurface_array_color4f;
2666 R_Mesh_ColorPointer(rsurface_lightmapcolor4f);
2667 GL_Color(r, g, b, a);
2668 RSurf_Draw(surface);
2671 static void R_DrawTextureSurfaceList(const entity_render_t *ent, texture_t *texture, rtexture_t *lightmaptexture, int texturenumsurfaces, msurface_t **texturesurfacelist, const vec3_t modelorg)
2673 int texturesurfaceindex;
2675 model_t *model = ent->model;
2676 qboolean applycolor;
2679 if (texture->currentmaterialflags & MATERIALFLAG_NODRAW)
2681 r_shadow_rtlight = NULL;
2682 renderstats.entities_surfaces += texturenumsurfaces;
2683 // FIXME: identify models using a better check than model->brush.shadowmesh
2684 lightmode = ((ent->effects & EF_FULLBRIGHT) || model->brush.shadowmesh) ? 0 : 2;
2685 GL_DepthTest(!(texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
2686 if ((texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (ent->flags & RENDER_NOCULLFACE))
2687 qglDisable(GL_CULL_FACE);
2688 if (r_showsurfaces.integer)
2691 GL_BlendFunc(GL_ONE, GL_ZERO);
2692 R_Mesh_ColorPointer(NULL);
2693 R_Mesh_ResetTextureState();
2694 RSurf_PrepareVerticesForBatch(ent, texture, modelorg, false, false, texturenumsurfaces, texturesurfacelist);
2695 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2697 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2698 int k = (int)(((size_t)surface) / sizeof(msurface_t));
2699 GL_Color((k & 15) * (1.0f / 16.0f), ((k >> 4) & 15) * (1.0f / 16.0f), ((k >> 8) & 15) * (1.0f / 16.0f), 0.2f);
2700 RSurf_Draw(surface);
2703 else if (texture->currentmaterialflags & MATERIALFLAG_SKY)
2705 // transparent sky would be ridiculous
2706 if (!(texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
2710 skyrendernow = false;
2712 // restore entity matrix
2713 R_Mesh_Matrix(&ent->matrix);
2716 // LordHavoc: HalfLife maps have freaky skypolys so don't use
2717 // skymasking on them, and Quake3 never did sky masking (unlike
2718 // software Quake and software Quake2), so disable the sky masking
2719 // in Quake3 maps as it causes problems with q3map2 sky tricks,
2720 // and skymasking also looks very bad when noclipping outside the
2721 // level, so don't use it then either.
2722 if (model->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_worldnovis)
2724 GL_Color(fogcolor[0], fogcolor[1], fogcolor[2], 1);
2725 R_Mesh_ColorPointer(NULL);
2726 R_Mesh_ResetTextureState();
2727 if (skyrendermasked)
2729 // depth-only (masking)
2730 GL_ColorMask(0,0,0,0);
2731 // just to make sure that braindead drivers don't draw
2732 // anything despite that colormask...
2733 GL_BlendFunc(GL_ZERO, GL_ONE);
2738 GL_BlendFunc(GL_ONE, GL_ZERO);
2740 RSurf_PrepareVerticesForBatch(ent, texture, modelorg, false, false, texturenumsurfaces, texturesurfacelist);
2741 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2743 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2744 RSurf_Draw(surface);
2746 if (skyrendermasked)
2747 GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
2751 else if (r_glsl.integer && gl_support_fragment_shader)
2753 if (texture->currentmaterialflags & MATERIALFLAG_ADD)
2755 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2756 GL_DepthMask(false);
2758 else if (texture->currentmaterialflags & MATERIALFLAG_ALPHA)
2760 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2761 GL_DepthMask(false);
2765 GL_BlendFunc(GL_ONE, GL_ZERO);
2769 R_Mesh_ColorPointer(NULL);
2770 R_Mesh_ResetTextureState();
2771 GL_Color(ent->colormod[0], ent->colormod[1], ent->colormod[2], texture->currentalpha);
2772 R_SetupSurfaceShader(ent, texture, lightmaptexture, modelorg, vec3_origin, lightmode == 2);
2773 if (!r_glsl_permutation)
2775 RSurf_PrepareVerticesForBatch(ent, texture, modelorg, true, true, texturenumsurfaces, texturesurfacelist);
2776 R_Mesh_TexCoordPointer(0, 2, model->surfmesh.data_texcoordtexture2f);
2777 R_Mesh_TexCoordPointer(1, 3, rsurface_svector3f);
2778 R_Mesh_TexCoordPointer(2, 3, rsurface_tvector3f);
2779 R_Mesh_TexCoordPointer(3, 3, rsurface_normal3f);
2782 R_Mesh_TexCoordPointer(4, 2, model->surfmesh.data_texcoordlightmap2f);
2783 if (lightmaptexture)
2785 R_Mesh_TexBind(7, R_GetTexture(lightmaptexture));
2786 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
2787 R_Mesh_TexBind(8, R_GetTexture(texturesurfacelist[0]->deluxemaptexture));
2788 R_Mesh_ColorPointer(NULL);
2792 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
2793 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
2794 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
2795 R_Mesh_ColorPointer(model->surfmesh.data_lightmapcolor4f);
2798 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2800 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2801 RSurf_Draw(surface);
2803 qglUseProgramObjectARB(0);
2805 else if (texture->currentnumlayers)
2808 texturelayer_t *layer;
2809 RSurf_PrepareVerticesForBatch(ent, texture, modelorg, true, false, texturenumsurfaces, texturesurfacelist);
2810 for (layerindex = 0, layer = texture->currentlayers;layerindex < texture->currentnumlayers;layerindex++, layer++)
2813 int layertexrgbscale;
2814 GL_DepthMask(layer->depthmask);
2815 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
2816 if ((layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2) && (gl_combine.integer || layer->depthmask))
2818 layertexrgbscale = 4;
2819 VectorScale(layer->color, 0.25f, layercolor);
2821 else if ((layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1) && (gl_combine.integer || layer->depthmask))
2823 layertexrgbscale = 2;
2824 VectorScale(layer->color, 0.5f, layercolor);
2828 layertexrgbscale = 1;
2829 VectorScale(layer->color, 1.0f, layercolor);
2831 layercolor[3] = layer->color[3];
2832 R_Mesh_ColorPointer(NULL);
2833 GL_Color(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
2834 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
2835 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
2836 switch (layer->type)
2838 case TEXTURELAYERTYPE_LITTEXTURE_COMBINE:
2839 memset(&m, 0, sizeof(m));
2840 m.pointer_texcoord[0] = model->surfmesh.data_texcoordlightmap2f;
2841 m.tex[1] = R_GetTexture(layer->texture);
2842 m.texmatrix[1] = layer->texmatrix;
2843 m.texrgbscale[1] = layertexrgbscale;
2844 m.pointer_texcoord[1] = model->surfmesh.data_texcoordtexture2f;
2845 R_Mesh_TextureState(&m);
2848 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2850 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2851 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2852 RSurf_DrawLightmap(surface, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 2, applycolor, applyfog);
2855 else if (lightmaptexture)
2857 R_Mesh_TexBind(0, R_GetTexture(lightmaptexture));
2858 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2860 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2861 RSurf_DrawLightmap(surface, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, applyfog);
2866 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2867 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2869 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2870 RSurf_DrawLightmap(surface, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 1, applycolor, applyfog);
2874 case TEXTURELAYERTYPE_LITTEXTURE_MULTIPASS:
2875 memset(&m, 0, sizeof(m));
2876 m.tex[0] = R_GetTexture(layer->texture);
2877 m.texmatrix[0] = layer->texmatrix;
2878 m.texrgbscale[0] = layertexrgbscale;
2879 m.pointer_texcoord[0] = model->surfmesh.data_texcoordlightmap2f;
2880 R_Mesh_TextureState(&m);
2883 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2885 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2886 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2887 RSurf_DrawLightmap(surface, 1, 1, 1, 1, 2, false, false);
2890 else if (lightmaptexture)
2892 R_Mesh_TexBind(0, R_GetTexture(lightmaptexture));
2893 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2895 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2896 RSurf_DrawLightmap(surface, 1, 1, 1, 1, 0, false, false);
2901 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2902 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2904 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2905 RSurf_DrawLightmap(surface, 1, 1, 1, 1, 1, false, false);
2908 GL_LockArrays(0, 0);
2909 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
2910 memset(&m, 0, sizeof(m));
2911 m.tex[0] = R_GetTexture(layer->texture);
2912 m.texmatrix[0] = layer->texmatrix;
2913 m.texrgbscale[0] = layertexrgbscale;
2914 m.pointer_texcoord[0] = model->surfmesh.data_texcoordtexture2f;
2915 R_Mesh_TextureState(&m);
2916 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2918 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2919 RSurf_DrawLightmap(surface, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, false);
2922 case TEXTURELAYERTYPE_LITTEXTURE_VERTEX:
2923 memset(&m, 0, sizeof(m));
2924 m.tex[0] = R_GetTexture(layer->texture);
2925 m.texmatrix[0] = layer->texmatrix;
2926 m.texrgbscale[0] = layertexrgbscale;
2927 m.pointer_texcoord[0] = model->surfmesh.data_texcoordtexture2f;
2928 R_Mesh_TextureState(&m);
2931 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2933 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2934 RSurf_DrawLightmap(surface, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 2, applycolor, applyfog);
2939 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2941 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2942 RSurf_DrawLightmap(surface, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 1, applycolor, applyfog);
2946 case TEXTURELAYERTYPE_TEXTURE:
2947 memset(&m, 0, sizeof(m));
2948 m.tex[0] = R_GetTexture(layer->texture);
2949 m.texmatrix[0] = layer->texmatrix;
2950 m.texrgbscale[0] = layertexrgbscale;
2951 m.pointer_texcoord[0] = model->surfmesh.data_texcoordtexture2f;
2952 R_Mesh_TextureState(&m);
2953 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2955 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2956 RSurf_DrawLightmap(surface, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, applyfog);
2959 case TEXTURELAYERTYPE_FOG:
2960 R_Mesh_ColorPointer(rsurface_array_color4f);
2963 memset(&m, 0, sizeof(m));
2964 m.tex[0] = R_GetTexture(layer->texture);
2965 m.texmatrix[0] = layer->texmatrix;
2966 m.pointer_texcoord[0] = model->surfmesh.data_texcoordtexture2f;
2967 R_Mesh_TextureState(&m);
2970 R_Mesh_ResetTextureState();
2971 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2975 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2976 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)
2978 f = VERTEXFOGTABLE(VectorDistance(v, modelorg));
2979 c[0] = layercolor[0];
2980 c[1] = layercolor[1];
2981 c[2] = layercolor[2];
2982 c[3] = f * layercolor[3];
2984 RSurf_Draw(surface);
2988 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
2990 GL_LockArrays(0, 0);
2991 // if trying to do overbright on first pass of an opaque surface
2992 // when combine is not supported, brighten as a post process
2993 if (layertexrgbscale > 1 && !gl_combine.integer && layer->depthmask)
2996 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
2997 R_Mesh_ColorPointer(NULL);
2998 GL_Color(1, 1, 1, 1);
2999 R_Mesh_ResetTextureState();
3000 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3002 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3003 for (scale = 1;scale < layertexrgbscale;scale <<= 1)
3004 RSurf_Draw(surface);
3006 GL_LockArrays(0, 0);
3010 GL_LockArrays(0, 0);
3011 if ((texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (ent->flags & RENDER_NOCULLFACE))
3012 qglEnable(GL_CULL_FACE);
3015 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight)
3017 msurface_t *surface = ent->model->data_surfaces + surfacenumber;
3021 texture = surface->texture;
3022 if (texture->basematerialflags & MATERIALFLAG_SKY)
3023 return; // transparent sky is too difficult
3024 R_UpdateTextureInfo(ent, texture);
3026 R_Mesh_Matrix(&ent->matrix);
3027 Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
3028 R_DrawTextureSurfaceList(ent, texture->currentframe, surface->lightmaptexture, 1, &surface, modelorg);
3031 void R_QueueTextureSurfaceList(entity_render_t *ent, texture_t *texture, rtexture_t *lightmaptexture, int texturenumsurfaces, msurface_t **texturesurfacelist, const vec3_t modelorg)
3033 int texturesurfaceindex;
3034 vec3_t tempcenter, center;
3035 if (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT)
3037 // drawing sky transparently would be too difficult
3038 if (!(texture->currentmaterialflags & MATERIALFLAG_SKY))
3040 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3042 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3043 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
3044 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
3045 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
3046 Matrix4x4_Transform(&ent->matrix, tempcenter, center);
3047 R_MeshQueue_AddTransparent(texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_vieworigin : center, R_DrawSurface_TransparentCallback, ent, surface - ent->model->data_surfaces, r_shadow_rtlight);
3052 R_DrawTextureSurfaceList(ent, texture, lightmaptexture, texturenumsurfaces, texturesurfacelist, modelorg);
3055 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
3056 void R_DrawSurfaces(entity_render_t *ent, qboolean skysurfaces)
3058 int i, j, f, flagsmask;
3059 int counttriangles = 0;
3060 texture_t *t, *texture;
3062 model_t *model = ent->model;
3064 const int maxsurfacelist = 1024;
3065 int numsurfacelist = 0;
3066 msurface_t *surfacelist[1024];
3069 R_Mesh_Matrix(&ent->matrix);
3070 Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
3072 // update light styles
3073 if (!skysurfaces && model->brushq1.light_styleupdatechains)
3075 msurface_t *surface, **surfacechain;
3076 for (i = 0;i < model->brushq1.light_styles;i++)
3078 if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
3080 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
3081 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
3082 for (;(surface = *surfacechain);surfacechain++)
3083 surface->cached_dlight = true;
3088 R_UpdateAllTextureInfo(ent);
3089 flagsmask = skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL);
3095 if (ent == r_refdef.worldentity)
3097 msurface_t *surface;
3098 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
3100 if (!r_worldsurfacevisible[j])
3102 if (t != surface->texture || lmap != surface->lightmaptexture)
3106 R_QueueTextureSurfaceList(ent, texture, lmap, numsurfacelist, surfacelist, modelorg);
3109 t = surface->texture;
3110 lmap = surface->lightmaptexture;
3111 texture = t->currentframe;
3112 f = texture->currentmaterialflags & flagsmask;
3114 if (f && surface->num_triangles)
3116 // if lightmap parameters changed, rebuild lightmap texture
3117 if (surface->cached_dlight)
3118 R_BuildLightMap(ent, surface);
3119 // add face to draw list
3120 surfacelist[numsurfacelist++] = surface;
3121 counttriangles += surface->num_triangles;
3122 if (numsurfacelist >= maxsurfacelist)
3124 R_QueueTextureSurfaceList(ent, texture, lmap, numsurfacelist, surfacelist, modelorg);
3132 msurface_t *surface;
3133 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
3135 if (t != surface->texture || lmap != surface->lightmaptexture)
3139 R_QueueTextureSurfaceList(ent, texture, lmap, numsurfacelist, surfacelist, modelorg);
3142 t = surface->texture;
3143 lmap = surface->lightmaptexture;
3144 texture = t->currentframe;
3145 f = texture->currentmaterialflags & flagsmask;
3147 if (f && surface->num_triangles)
3149 // if lightmap parameters changed, rebuild lightmap texture
3150 if (surface->cached_dlight)
3151 R_BuildLightMap(ent, surface);
3152 // add face to draw list
3153 surfacelist[numsurfacelist++] = surface;
3154 counttriangles += surface->num_triangles;
3155 if (numsurfacelist >= maxsurfacelist)
3157 R_QueueTextureSurfaceList(ent, texture, lmap, numsurfacelist, surfacelist, modelorg);
3164 R_QueueTextureSurfaceList(ent, texture, lmap, numsurfacelist, surfacelist, modelorg);
3165 renderstats.entities_triangles += counttriangles;
3166 if (gl_support_fragment_shader)
3167 qglUseProgramObjectARB(0);
3169 if (r_showcollisionbrushes.integer && model->brush.num_brushes && !skysurfaces)
3172 const msurface_t *surface;
3174 R_Mesh_Matrix(&ent->matrix);
3175 R_Mesh_ColorPointer(NULL);
3176 R_Mesh_ResetTextureState();
3177 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
3178 GL_DepthMask(false);
3179 GL_DepthTest(!r_showdisabledepthtest.integer);
3180 qglPolygonOffset(r_polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_polygonoffset + r_showcollisionbrushes_polygonoffset.value);
3181 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
3182 if (brush->colbrushf && brush->colbrushf->numtriangles)
3183 R_DrawCollisionBrush(brush->colbrushf);
3184 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
3185 if (surface->num_collisiontriangles)
3186 R_DrawCollisionSurface(ent, surface);
3187 qglPolygonOffset(r_polygonfactor, r_polygonoffset);
3190 if (r_showtris.integer || r_shownormals.integer)
3193 msurface_t *surface;
3194 const int *elements;
3198 if (r_showdisabledepthtest.integer)
3199 qglDepthFunc(GL_ALWAYS);
3200 GL_BlendFunc(GL_ONE, GL_ZERO);
3201 R_Mesh_ColorPointer(NULL);
3202 R_Mesh_ResetTextureState();
3203 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
3205 if (ent == r_refdef.worldentity && !r_worldsurfacevisible[j])
3207 texture = surface->texture->currentframe;
3208 if ((texture->currentmaterialflags & flagsmask) && surface->num_triangles)
3210 RSurf_PrepareVerticesForBatch(ent, texture, modelorg, false, r_shownormals.integer != 0, 1, &surface);
3211 if (r_showtris.integer)
3213 if (!texture->currentlayers->depthmask)
3214 GL_Color(r_showtris.value, 0, 0, 1);
3215 else if (ent == r_refdef.worldentity)
3216 GL_Color(r_showtris.value, r_showtris.value, r_showtris.value, 1);
3218 GL_Color(0, r_showtris.value, 0, 1);
3219 elements = (ent->model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
3221 for (k = 0;k < surface->num_triangles;k++, elements += 3)
3223 qglArrayElement(elements[0]);qglArrayElement(elements[1]);
3224 qglArrayElement(elements[1]);qglArrayElement(elements[2]);
3225 qglArrayElement(elements[2]);qglArrayElement(elements[0]);
3229 if (r_shownormals.integer)
3231 GL_Color(r_shownormals.value, 0, 0, 1);
3233 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
3235 VectorCopy(rsurface_vertex3f + l * 3, v);
3236 qglVertex3f(v[0], v[1], v[2]);
3237 VectorMA(v, 8, rsurface_svector3f + l * 3, v);
3238 qglVertex3f(v[0], v[1], v[2]);
3241 GL_Color(0, 0, r_shownormals.value, 1);
3243 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
3245 VectorCopy(rsurface_vertex3f + l * 3, v);
3246 qglVertex3f(v[0], v[1], v[2]);
3247 VectorMA(v, 8, rsurface_tvector3f + l * 3, v);
3248 qglVertex3f(v[0], v[1], v[2]);
3251 GL_Color(0, r_shownormals.value, 0, 1);
3253 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
3255 VectorCopy(rsurface_vertex3f + l * 3, v);
3256 qglVertex3f(v[0], v[1], v[2]);
3257 VectorMA(v, 8, rsurface_normal3f + l * 3, v);
3258 qglVertex3f(v[0], v[1], v[2]);
3264 if (r_showdisabledepthtest.integer)
3265 qglDepthFunc(GL_LEQUAL);