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, 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;
867 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTION;
868 else if (r_glsl_deluxemapping.integer >= 1 && r_refdef.worldmodel && r_refdef.worldmodel->brushq3.deluxemapping)
870 if (r_refdef.worldmodel->brushq3.deluxemapping_modelspace)
871 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_MODELSPACE;
873 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
875 else if (r_glsl_deluxemapping.integer >= 2) // fake mode
876 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
877 if (texture->skin.glow)
878 permutation |= SHADERPERMUTATION_GLOW;
880 if (specularscale > 0)
881 permutation |= SHADERPERMUTATION_SPECULAR;
883 permutation |= SHADERPERMUTATION_FOG;
884 if (texture->colormapping)
885 permutation |= SHADERPERMUTATION_COLORMAPPING;
886 if (r_glsl_offsetmapping.integer)
888 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
889 if (r_glsl_offsetmapping_reliefmapping.integer)
890 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
892 if (!r_glsl_permutations[permutation].program)
894 if (!r_glsl_permutations[permutation].compiled)
895 R_GLSL_CompilePermutation(permutation);
896 if (!r_glsl_permutations[permutation].program)
898 // remove features until we find a valid permutation
900 for (i = SHADERPERMUTATION_COUNT-1;;i>>=1)
902 // reduce i more quickly whenever it would not remove any bits
906 if (!r_glsl_permutations[permutation].compiled)
907 R_GLSL_CompilePermutation(permutation);
908 if (r_glsl_permutations[permutation].program)
911 return; // utterly failed
915 r_glsl_permutation = r_glsl_permutations + permutation;
917 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
918 R_Mesh_TexMatrix(0, &texture->currenttexmatrix);
919 if (permutation & SHADERPERMUTATION_MODE_LIGHTSOURCE)
921 R_Mesh_TexMatrix(3, &r_shadow_entitytolight);
922 //if (r_glsl_permutation->loc_Texture_Cube >= 0) R_Mesh_TexBindCubeMap(3, R_GetTexture(r_shadow_rtlight->currentcubemap));
923 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]);
924 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
925 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_shadow_rtlight->ambientscale);
926 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_shadow_rtlight->diffusescale);
927 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, specularscale);
929 else if (permutation & SHADERPERMUTATION_MODE_LIGHTDIRECTION)
931 if (texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
933 if (r_glsl_permutation->loc_AmbientColor >= 0)
934 qglUniform3fARB(r_glsl_permutation->loc_AmbientColor, 1, 1, 1);
935 if (r_glsl_permutation->loc_DiffuseColor >= 0)
936 qglUniform3fARB(r_glsl_permutation->loc_DiffuseColor, 0, 0, 0);
937 if (r_glsl_permutation->loc_SpecularColor >= 0)
938 qglUniform3fARB(r_glsl_permutation->loc_SpecularColor, 0, 0, 0);
939 if (r_glsl_permutation->loc_LightDir >= 0)
940 qglUniform3fARB(r_glsl_permutation->loc_LightDir, 0, 0, -1);
944 if (r_glsl_permutation->loc_AmbientColor >= 0)
945 qglUniform3fARB(r_glsl_permutation->loc_AmbientColor, ent->modellight_ambient[0], ent->modellight_ambient[1], ent->modellight_ambient[2]);
946 if (r_glsl_permutation->loc_DiffuseColor >= 0)
947 qglUniform3fARB(r_glsl_permutation->loc_DiffuseColor, ent->modellight_diffuse[0], ent->modellight_diffuse[1], ent->modellight_diffuse[2]);
948 if (r_glsl_permutation->loc_SpecularColor >= 0)
949 qglUniform3fARB(r_glsl_permutation->loc_SpecularColor, ent->modellight_diffuse[0] * texture->specularscale, ent->modellight_diffuse[1] * texture->specularscale, ent->modellight_diffuse[2] * texture->specularscale);
950 if (r_glsl_permutation->loc_LightDir >= 0)
951 qglUniform3fARB(r_glsl_permutation->loc_LightDir, ent->modellight_lightdir[0], ent->modellight_lightdir[1], ent->modellight_lightdir[2]);
956 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_ambient.value * 2.0f / 128.0f);
957 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_lightmapintensity * 2.0f);
958 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, r_lightmapintensity * specularscale * 2.0f);
960 if (r_glsl_permutation->loc_Texture_Normal >= 0) R_Mesh_TexBind(0, R_GetTexture(texture->skin.nmap));
961 if (r_glsl_permutation->loc_Texture_Color >= 0) R_Mesh_TexBind(1, R_GetTexture(texture->basetexture));
962 if (r_glsl_permutation->loc_Texture_Gloss >= 0) R_Mesh_TexBind(2, R_GetTexture(texture->glosstexture));
963 //if (r_glsl_permutation->loc_Texture_Cube >= 0 && permutation & SHADERPERMUTATION_MODE_LIGHTSOURCE) R_Mesh_TexBindCubeMap(3, R_GetTexture(r_shadow_rtlight->currentcubemap));
964 if (r_glsl_permutation->loc_Texture_FogMask >= 0) R_Mesh_TexBind(4, R_GetTexture(r_texture_fogattenuation));
965 if (r_glsl_permutation->loc_Texture_Pants >= 0) R_Mesh_TexBind(5, R_GetTexture(texture->skin.pants));
966 if (r_glsl_permutation->loc_Texture_Shirt >= 0) R_Mesh_TexBind(6, R_GetTexture(texture->skin.shirt));
967 if (r_glsl_permutation->loc_Texture_Lightmap >= 0) R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
968 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
969 if (r_glsl_permutation->loc_Texture_Glow >= 0) R_Mesh_TexBind(9, R_GetTexture(texture->skin.glow));
970 if (r_glsl_permutation->loc_FogColor >= 0)
972 // additive passes are only darkened by fog, not tinted
973 if (r_shadow_rtlight || (texture->currentmaterialflags & MATERIALFLAG_ADD))
974 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
976 qglUniform3fARB(r_glsl_permutation->loc_FogColor, fogcolor[0], fogcolor[1], fogcolor[2]);
978 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, modelorg[0], modelorg[1], modelorg[2]);
979 if (r_glsl_permutation->loc_Color_Pants >= 0)
981 if (texture->skin.pants)
982 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, ent->colormap_pantscolor[0], ent->colormap_pantscolor[1], ent->colormap_pantscolor[2]);
984 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
986 if (r_glsl_permutation->loc_Color_Shirt >= 0)
988 if (texture->skin.shirt)
989 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, ent->colormap_shirtcolor[0], ent->colormap_shirtcolor[1], ent->colormap_shirtcolor[2]);
991 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
993 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, fograngerecip);
994 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, texture->specularpower);
995 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
999 void gl_main_start(void)
1001 r_main_texturepool = R_AllocTexturePool();
1002 r_bloom_texture_screen = NULL;
1003 r_bloom_texture_bloom = NULL;
1004 R_BuildBlankTextures();
1006 if (gl_texturecubemap)
1009 R_BuildNormalizationCube();
1011 R_BuildFogTexture();
1012 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
1015 void gl_main_shutdown(void)
1017 R_FreeTexturePool(&r_main_texturepool);
1018 r_bloom_texture_screen = NULL;
1019 r_bloom_texture_bloom = NULL;
1020 r_texture_blanknormalmap = NULL;
1021 r_texture_white = NULL;
1022 r_texture_black = NULL;
1023 r_texture_whitecube = NULL;
1024 r_texture_normalizationcube = NULL;
1028 extern void CL_ParseEntityLump(char *entitystring);
1029 void gl_main_newmap(void)
1031 // FIXME: move this code to client
1033 char *entities, entname[MAX_QPATH];
1037 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
1038 l = (int)strlen(entname) - 4;
1039 if (l >= 0 && !strcmp(entname + l, ".bsp"))
1041 strcpy(entname + l, ".ent");
1042 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
1044 CL_ParseEntityLump(entities);
1049 if (cl.worldmodel->brush.entities)
1050 CL_ParseEntityLump(cl.worldmodel->brush.entities);
1054 void GL_Main_Init(void)
1056 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
1058 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed\n");
1059 FOG_registercvars(); // FIXME: move this fog stuff to client?
1060 Cvar_RegisterVariable(&r_nearclip);
1061 Cvar_RegisterVariable(&r_showsurfaces);
1062 Cvar_RegisterVariable(&r_showtris);
1063 Cvar_RegisterVariable(&r_shownormals);
1064 Cvar_RegisterVariable(&r_showlighting);
1065 Cvar_RegisterVariable(&r_showshadowvolumes);
1066 Cvar_RegisterVariable(&r_showcollisionbrushes);
1067 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
1068 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
1069 Cvar_RegisterVariable(&r_showdisabledepthtest);
1070 Cvar_RegisterVariable(&r_drawentities);
1071 Cvar_RegisterVariable(&r_drawviewmodel);
1072 Cvar_RegisterVariable(&r_speeds);
1073 Cvar_RegisterVariable(&r_fullbrights);
1074 Cvar_RegisterVariable(&r_wateralpha);
1075 Cvar_RegisterVariable(&r_dynamic);
1076 Cvar_RegisterVariable(&r_fullbright);
1077 Cvar_RegisterVariable(&r_q1bsp_skymasking);
1078 Cvar_RegisterVariable(&r_textureunits);
1079 Cvar_RegisterVariable(&r_glsl);
1080 Cvar_RegisterVariable(&r_glsl_offsetmapping);
1081 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
1082 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
1083 Cvar_RegisterVariable(&r_glsl_deluxemapping);
1084 Cvar_RegisterVariable(&r_lerpsprites);
1085 Cvar_RegisterVariable(&r_lerpmodels);
1086 Cvar_RegisterVariable(&r_waterscroll);
1087 Cvar_RegisterVariable(&r_bloom);
1088 Cvar_RegisterVariable(&r_bloom_intensity);
1089 Cvar_RegisterVariable(&r_bloom_blur);
1090 Cvar_RegisterVariable(&r_bloom_resolution);
1091 Cvar_RegisterVariable(&r_bloom_power);
1092 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
1093 Cvar_RegisterVariable(&developer_texturelogging);
1094 Cvar_RegisterVariable(&gl_lightmaps);
1095 Cvar_RegisterVariable(&r_test);
1096 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
1097 Cvar_SetValue("r_fullbrights", 0);
1098 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
1101 static vec3_t r_farclip_origin;
1102 static vec3_t r_farclip_direction;
1103 static vec_t r_farclip_directiondist;
1104 static vec_t r_farclip_meshfarclip;
1105 static int r_farclip_directionbit0;
1106 static int r_farclip_directionbit1;
1107 static int r_farclip_directionbit2;
1109 // enlarge farclip to accomodate box
1110 static void R_FarClip_Box(vec3_t mins, vec3_t maxs)
1113 d = (r_farclip_directionbit0 ? mins[0] : maxs[0]) * r_farclip_direction[0]
1114 + (r_farclip_directionbit1 ? mins[1] : maxs[1]) * r_farclip_direction[1]
1115 + (r_farclip_directionbit2 ? mins[2] : maxs[2]) * r_farclip_direction[2];
1116 if (r_farclip_meshfarclip < d)
1117 r_farclip_meshfarclip = d;
1120 // return farclip value
1121 static float R_FarClip(vec3_t origin, vec3_t direction, vec_t startfarclip)
1125 VectorCopy(origin, r_farclip_origin);
1126 VectorCopy(direction, r_farclip_direction);
1127 r_farclip_directiondist = DotProduct(r_farclip_origin, r_farclip_direction);
1128 r_farclip_directionbit0 = r_farclip_direction[0] < 0;
1129 r_farclip_directionbit1 = r_farclip_direction[1] < 0;
1130 r_farclip_directionbit2 = r_farclip_direction[2] < 0;
1131 r_farclip_meshfarclip = r_farclip_directiondist + startfarclip;
1133 if (r_refdef.worldmodel)
1134 R_FarClip_Box(r_refdef.worldmodel->normalmins, r_refdef.worldmodel->normalmaxs);
1135 for (i = 0;i < r_refdef.numentities;i++)
1136 R_FarClip_Box(r_refdef.entities[i]->mins, r_refdef.entities[i]->maxs);
1138 return r_farclip_meshfarclip - r_farclip_directiondist;
1141 extern void R_Textures_Init(void);
1142 extern void GL_Draw_Init(void);
1143 extern void GL_Main_Init(void);
1144 extern void R_Shadow_Init(void);
1145 extern void R_Sky_Init(void);
1146 extern void GL_Surf_Init(void);
1147 extern void R_Crosshairs_Init(void);
1148 extern void R_Light_Init(void);
1149 extern void R_Particles_Init(void);
1150 extern void R_Explosion_Init(void);
1151 extern void gl_backend_init(void);
1152 extern void Sbar_Init(void);
1153 extern void R_LightningBeams_Init(void);
1154 extern void Mod_RenderInit(void);
1156 void Render_Init(void)
1166 R_Crosshairs_Init();
1171 R_LightningBeams_Init();
1180 extern char *ENGINE_EXTENSIONS;
1183 VID_CheckExtensions();
1185 // LordHavoc: report supported extensions
1186 Con_DPrintf("\nengine extensions: %s\n", vm_sv_extensions );
1188 // clear to black (loading plaque will be seen over this)
1189 qglClearColor(0,0,0,1);
1190 qglClear(GL_COLOR_BUFFER_BIT);
1193 int R_CullBox(const vec3_t mins, const vec3_t maxs)
1197 for (i = 0;i < 4;i++)
1204 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1208 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1212 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1216 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1220 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1224 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1228 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1232 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1240 //==================================================================================
1242 static void R_UpdateEntityLighting(entity_render_t *ent)
1244 vec3_t tempdiffusenormal;
1245 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));
1246 VectorClear(ent->modellight_diffuse);
1247 VectorClear(ent->modellight_lightdir);
1248 if ((ent->flags & RENDER_LIGHT) && r_refdef.worldmodel && r_refdef.worldmodel->brush.LightPoint)
1249 r_refdef.worldmodel->brush.LightPoint(r_refdef.worldmodel, ent->origin, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
1251 VectorSet(ent->modellight_ambient, 1, 1, 1);
1252 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
1253 VectorNormalize(ent->modellight_lightdir);
1254 ent->modellight_ambient[0] *= ent->colormod[0] * r_lightmapintensity;
1255 ent->modellight_ambient[1] *= ent->colormod[1] * r_lightmapintensity;
1256 ent->modellight_ambient[2] *= ent->colormod[2] * r_lightmapintensity;
1257 ent->modellight_diffuse[0] *= ent->colormod[0] * r_lightmapintensity;
1258 ent->modellight_diffuse[1] *= ent->colormod[1] * r_lightmapintensity;
1259 ent->modellight_diffuse[2] *= ent->colormod[2] * r_lightmapintensity;
1262 static void R_MarkEntities (void)
1265 entity_render_t *ent;
1267 if (!r_drawentities.integer)
1270 r_refdef.worldentity->visframe = r_framecount;
1271 renderimask = envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : (chase_active.integer ? 0 : RENDER_EXTERIORMODEL);
1272 if (r_refdef.worldmodel && r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs)
1274 // worldmodel can check visibility
1275 for (i = 0;i < r_refdef.numentities;i++)
1277 ent = r_refdef.entities[i];
1278 // some of the renderer still relies on origin...
1279 Matrix4x4_OriginFromMatrix(&ent->matrix, ent->origin);
1280 // some of the renderer still relies on scale...
1281 ent->scale = Matrix4x4_ScaleFromMatrix(&ent->matrix);
1282 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)))
1284 ent->visframe = r_framecount;
1285 R_UpdateEntityLighting(ent);
1291 // no worldmodel or it can't check visibility
1292 for (i = 0;i < r_refdef.numentities;i++)
1294 ent = r_refdef.entities[i];
1295 // some of the renderer still relies on origin...
1296 Matrix4x4_OriginFromMatrix(&ent->matrix, ent->origin);
1297 // some of the renderer still relies on scale...
1298 ent->scale = Matrix4x4_ScaleFromMatrix(&ent->matrix);
1299 if (!(ent->flags & renderimask) && !R_CullBox(ent->mins, ent->maxs) && (ent->effects & EF_NODEPTHTEST))
1301 ent->visframe = r_framecount;
1302 R_UpdateEntityLighting(ent);
1308 // only used if skyrendermasked, and normally returns false
1309 int R_DrawBrushModelsSky (void)
1312 entity_render_t *ent;
1314 if (!r_drawentities.integer)
1318 for (i = 0;i < r_refdef.numentities;i++)
1320 ent = r_refdef.entities[i];
1321 if (ent->visframe == r_framecount && ent->model && ent->model->DrawSky)
1323 ent->model->DrawSky(ent);
1330 void R_DrawNoModel(entity_render_t *ent);
1331 void R_DrawModels(void)
1334 entity_render_t *ent;
1336 if (!r_drawentities.integer)
1339 for (i = 0;i < r_refdef.numentities;i++)
1341 ent = r_refdef.entities[i];
1342 if (ent->visframe == r_framecount)
1344 renderstats.entities++;
1345 if (ent->model && ent->model->Draw != NULL)
1346 ent->model->Draw(ent);
1353 static void R_SetFrustum(void)
1355 // break apart the view matrix into vectors for various purposes
1356 Matrix4x4_ToVectors(&r_view_matrix, r_viewforward, r_viewleft, r_viewup, r_vieworigin);
1357 VectorNegate(r_viewleft, r_viewright);
1360 frustum[0].normal[0] = 0 - 1.0 / r_refdef.frustum_x;
1361 frustum[0].normal[1] = 0 - 0;
1362 frustum[0].normal[2] = -1 - 0;
1363 frustum[1].normal[0] = 0 + 1.0 / r_refdef.frustum_x;
1364 frustum[1].normal[1] = 0 + 0;
1365 frustum[1].normal[2] = -1 + 0;
1366 frustum[2].normal[0] = 0 - 0;
1367 frustum[2].normal[1] = 0 - 1.0 / r_refdef.frustum_y;
1368 frustum[2].normal[2] = -1 - 0;
1369 frustum[3].normal[0] = 0 + 0;
1370 frustum[3].normal[1] = 0 + 1.0 / r_refdef.frustum_y;
1371 frustum[3].normal[2] = -1 + 0;
1375 zNear = r_nearclip.value;
1376 nudge = 1.0 - 1.0 / (1<<23);
1377 frustum[4].normal[0] = 0 - 0;
1378 frustum[4].normal[1] = 0 - 0;
1379 frustum[4].normal[2] = -1 - -nudge;
1380 frustum[4].dist = 0 - -2 * zNear * nudge;
1381 frustum[5].normal[0] = 0 + 0;
1382 frustum[5].normal[1] = 0 + 0;
1383 frustum[5].normal[2] = -1 + -nudge;
1384 frustum[5].dist = 0 + -2 * zNear * nudge;
1390 frustum[0].normal[0] = m[3] - m[0];
1391 frustum[0].normal[1] = m[7] - m[4];
1392 frustum[0].normal[2] = m[11] - m[8];
1393 frustum[0].dist = m[15] - m[12];
1395 frustum[1].normal[0] = m[3] + m[0];
1396 frustum[1].normal[1] = m[7] + m[4];
1397 frustum[1].normal[2] = m[11] + m[8];
1398 frustum[1].dist = m[15] + m[12];
1400 frustum[2].normal[0] = m[3] - m[1];
1401 frustum[2].normal[1] = m[7] - m[5];
1402 frustum[2].normal[2] = m[11] - m[9];
1403 frustum[2].dist = m[15] - m[13];
1405 frustum[3].normal[0] = m[3] + m[1];
1406 frustum[3].normal[1] = m[7] + m[5];
1407 frustum[3].normal[2] = m[11] + m[9];
1408 frustum[3].dist = m[15] + m[13];
1410 frustum[4].normal[0] = m[3] - m[2];
1411 frustum[4].normal[1] = m[7] - m[6];
1412 frustum[4].normal[2] = m[11] - m[10];
1413 frustum[4].dist = m[15] - m[14];
1415 frustum[5].normal[0] = m[3] + m[2];
1416 frustum[5].normal[1] = m[7] + m[6];
1417 frustum[5].normal[2] = m[11] + m[10];
1418 frustum[5].dist = m[15] + m[14];
1423 VectorMAM(1, r_viewforward, 1.0 / -r_refdef.frustum_x, r_viewleft, frustum[0].normal);
1424 VectorMAM(1, r_viewforward, 1.0 / r_refdef.frustum_x, r_viewleft, frustum[1].normal);
1425 VectorMAM(1, r_viewforward, 1.0 / -r_refdef.frustum_y, r_viewup, frustum[2].normal);
1426 VectorMAM(1, r_viewforward, 1.0 / r_refdef.frustum_y, r_viewup, frustum[3].normal);
1427 VectorCopy(r_viewforward, frustum[4].normal);
1428 VectorNormalize(frustum[0].normal);
1429 VectorNormalize(frustum[1].normal);
1430 VectorNormalize(frustum[2].normal);
1431 VectorNormalize(frustum[3].normal);
1432 frustum[0].dist = DotProduct (r_vieworigin, frustum[0].normal);
1433 frustum[1].dist = DotProduct (r_vieworigin, frustum[1].normal);
1434 frustum[2].dist = DotProduct (r_vieworigin, frustum[2].normal);
1435 frustum[3].dist = DotProduct (r_vieworigin, frustum[3].normal);
1436 frustum[4].dist = DotProduct (r_vieworigin, frustum[4].normal) + r_nearclip.value;
1437 PlaneClassify(&frustum[0]);
1438 PlaneClassify(&frustum[1]);
1439 PlaneClassify(&frustum[2]);
1440 PlaneClassify(&frustum[3]);
1441 PlaneClassify(&frustum[4]);
1443 // LordHavoc: note to all quake engine coders, Quake had a special case
1444 // for 90 degrees which assumed a square view (wrong), so I removed it,
1445 // Quake2 has it disabled as well.
1447 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
1448 //RotatePointAroundVector( frustum[0].normal, r_viewup, r_viewforward, -(90 - r_refdef.fov_x / 2));
1449 //frustum[0].dist = DotProduct (r_vieworigin, frustum[0].normal);
1450 //PlaneClassify(&frustum[0]);
1452 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
1453 //RotatePointAroundVector( frustum[1].normal, r_viewup, r_viewforward, (90 - r_refdef.fov_x / 2));
1454 //frustum[1].dist = DotProduct (r_vieworigin, frustum[1].normal);
1455 //PlaneClassify(&frustum[1]);
1457 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
1458 //RotatePointAroundVector( frustum[2].normal, r_viewleft, r_viewforward, -(90 - r_refdef.fov_y / 2));
1459 //frustum[2].dist = DotProduct (r_vieworigin, frustum[2].normal);
1460 //PlaneClassify(&frustum[2]);
1462 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
1463 //RotatePointAroundVector( frustum[3].normal, r_viewleft, r_viewforward, (90 - r_refdef.fov_y / 2));
1464 //frustum[3].dist = DotProduct (r_vieworigin, frustum[3].normal);
1465 //PlaneClassify(&frustum[3]);
1468 //VectorCopy(r_viewforward, frustum[4].normal);
1469 //frustum[4].dist = DotProduct (r_vieworigin, frustum[4].normal) + r_nearclip.value;
1470 //PlaneClassify(&frustum[4]);
1473 static void R_BlendView(void)
1475 int screenwidth, screenheight;
1479 float texcoord2f[3][8];
1481 // set the (poorly named) screenwidth and screenheight variables to
1482 // a power of 2 at least as large as the screen, these will define the
1483 // size of the texture to allocate
1484 for (screenwidth = 1;screenwidth < vid.width;screenwidth *= 2);
1485 for (screenheight = 1;screenheight < vid.height;screenheight *= 2);
1487 doblend = r_refdef.viewblend[3] >= 0.01f;
1488 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;
1490 if (!dobloom && !doblend)
1493 GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
1495 GL_DepthTest(false);
1496 R_Mesh_Matrix(&identitymatrix);
1497 // vertex coordinates for a quad that covers the screen exactly
1498 vertex3f[0] = 0;vertex3f[1] = 0;vertex3f[2] = 0;
1499 vertex3f[3] = 1;vertex3f[4] = 0;vertex3f[5] = 0;
1500 vertex3f[6] = 1;vertex3f[7] = 1;vertex3f[8] = 0;
1501 vertex3f[9] = 0;vertex3f[10] = 1;vertex3f[11] = 0;
1502 R_Mesh_VertexPointer(vertex3f);
1503 R_Mesh_ColorPointer(NULL);
1504 R_Mesh_ResetTextureState();
1507 int bloomwidth, bloomheight, x, range;
1508 float xoffset, yoffset, r;
1509 renderstats.bloom++;
1510 // allocate textures as needed
1511 if (!r_bloom_texture_screen)
1512 r_bloom_texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", screenwidth, screenheight, NULL, TEXTYPE_RGBA, TEXF_FORCENEAREST | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
1513 if (!r_bloom_texture_bloom)
1514 r_bloom_texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", screenwidth, screenheight, NULL, TEXTYPE_RGBA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
1515 // set bloomwidth and bloomheight to the bloom resolution that will be
1516 // used (often less than the screen resolution for faster rendering)
1517 bloomwidth = min(r_view_width, r_bloom_resolution.integer);
1518 bloomheight = min(r_view_height, bloomwidth * r_view_height / r_view_width);
1519 // set up a texcoord array for the full resolution screen image
1520 // (we have to keep this around to copy back during final render)
1521 texcoord2f[0][0] = 0;
1522 texcoord2f[0][1] = (float)r_view_height / (float)screenheight;
1523 texcoord2f[0][2] = (float)r_view_width / (float)screenwidth;
1524 texcoord2f[0][3] = (float)r_view_height / (float)screenheight;
1525 texcoord2f[0][4] = (float)r_view_width / (float)screenwidth;
1526 texcoord2f[0][5] = 0;
1527 texcoord2f[0][6] = 0;
1528 texcoord2f[0][7] = 0;
1529 // set up a texcoord array for the reduced resolution bloom image
1530 // (which will be additive blended over the screen image)
1531 texcoord2f[1][0] = 0;
1532 texcoord2f[1][1] = (float)bloomheight / (float)screenheight;
1533 texcoord2f[1][2] = (float)bloomwidth / (float)screenwidth;
1534 texcoord2f[1][3] = (float)bloomheight / (float)screenheight;
1535 texcoord2f[1][4] = (float)bloomwidth / (float)screenwidth;
1536 texcoord2f[1][5] = 0;
1537 texcoord2f[1][6] = 0;
1538 texcoord2f[1][7] = 0;
1539 R_Mesh_TexCoordPointer(0, 2, texcoord2f[0]);
1540 R_Mesh_TexBind(0, R_GetTexture(r_bloom_texture_screen));
1541 // copy view into the full resolution screen image texture
1542 GL_ActiveTexture(0);
1543 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
1544 renderstats.bloom_copypixels += r_view_width * r_view_height;
1545 // now scale it down to the bloom size and raise to a power of itself
1546 // to darken it (this leaves the really bright stuff bright, and
1547 // everything else becomes very dark)
1548 // TODO: optimize with multitexture or GLSL
1549 qglViewport(r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
1550 GL_BlendFunc(GL_ONE, GL_ZERO);
1551 GL_Color(1, 1, 1, 1);
1552 R_Mesh_Draw(0, 4, 2, polygonelements);
1553 renderstats.bloom_drawpixels += bloomwidth * bloomheight;
1554 // render multiple times with a multiply blendfunc to raise to a power
1555 GL_BlendFunc(GL_DST_COLOR, GL_ZERO);
1556 for (x = 1;x < r_bloom_power.integer;x++)
1558 R_Mesh_Draw(0, 4, 2, polygonelements);
1559 renderstats.bloom_drawpixels += bloomwidth * bloomheight;
1561 // we now have a darkened bloom image in the framebuffer, copy it into
1562 // the bloom image texture for more processing
1563 R_Mesh_TexBind(0, R_GetTexture(r_bloom_texture_bloom));
1564 R_Mesh_TexCoordPointer(0, 2, texcoord2f[2]);
1565 GL_ActiveTexture(0);
1566 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
1567 renderstats.bloom_copypixels += bloomwidth * bloomheight;
1568 // blend on at multiple vertical offsets to achieve a vertical blur
1569 // TODO: do offset blends using GLSL
1570 range = r_bloom_blur.integer * bloomwidth / 320;
1571 GL_BlendFunc(GL_ONE, GL_ZERO);
1572 for (x = -range;x <= range;x++)
1574 xoffset = 0 / (float)bloomwidth * (float)bloomwidth / (float)screenwidth;
1575 yoffset = x / (float)bloomheight * (float)bloomheight / (float)screenheight;
1576 // compute a texcoord array with the specified x and y offset
1577 texcoord2f[2][0] = xoffset+0;
1578 texcoord2f[2][1] = yoffset+(float)bloomheight / (float)screenheight;
1579 texcoord2f[2][2] = xoffset+(float)bloomwidth / (float)screenwidth;
1580 texcoord2f[2][3] = yoffset+(float)bloomheight / (float)screenheight;
1581 texcoord2f[2][4] = xoffset+(float)bloomwidth / (float)screenwidth;
1582 texcoord2f[2][5] = yoffset+0;
1583 texcoord2f[2][6] = xoffset+0;
1584 texcoord2f[2][7] = yoffset+0;
1585 // this r value looks like a 'dot' particle, fading sharply to
1586 // black at the edges
1587 // (probably not realistic but looks good enough)
1588 r = r_bloom_intensity.value/(range*2+1)*(1 - x*x/(float)(range*range));
1591 GL_Color(r, r, r, 1);
1592 R_Mesh_Draw(0, 4, 2, polygonelements);
1593 renderstats.bloom_drawpixels += bloomwidth * bloomheight;
1594 GL_BlendFunc(GL_ONE, GL_ONE);
1596 // copy the vertically blurred bloom view to a texture
1597 GL_ActiveTexture(0);
1598 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
1599 renderstats.bloom_copypixels += bloomwidth * bloomheight;
1600 // blend the vertically blurred image at multiple offsets horizontally
1601 // to finish the blur effect
1602 // TODO: do offset blends using GLSL
1603 range = r_bloom_blur.integer * bloomwidth / 320;
1604 GL_BlendFunc(GL_ONE, GL_ZERO);
1605 for (x = -range;x <= range;x++)
1607 xoffset = x / (float)bloomwidth * (float)bloomwidth / (float)screenwidth;
1608 yoffset = 0 / (float)bloomheight * (float)bloomheight / (float)screenheight;
1609 // compute a texcoord array with the specified x and y offset
1610 texcoord2f[2][0] = xoffset+0;
1611 texcoord2f[2][1] = yoffset+(float)bloomheight / (float)screenheight;
1612 texcoord2f[2][2] = xoffset+(float)bloomwidth / (float)screenwidth;
1613 texcoord2f[2][3] = yoffset+(float)bloomheight / (float)screenheight;
1614 texcoord2f[2][4] = xoffset+(float)bloomwidth / (float)screenwidth;
1615 texcoord2f[2][5] = yoffset+0;
1616 texcoord2f[2][6] = xoffset+0;
1617 texcoord2f[2][7] = yoffset+0;
1618 // this r value looks like a 'dot' particle, fading sharply to
1619 // black at the edges
1620 // (probably not realistic but looks good enough)
1621 r = r_bloom_intensity.value/(range*2+1)*(1 - x*x/(float)(range*range));
1624 GL_Color(r, r, r, 1);
1625 R_Mesh_Draw(0, 4, 2, polygonelements);
1626 renderstats.bloom_drawpixels += bloomwidth * bloomheight;
1627 GL_BlendFunc(GL_ONE, GL_ONE);
1629 // copy the blurred bloom view to a texture
1630 GL_ActiveTexture(0);
1631 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
1632 renderstats.bloom_copypixels += bloomwidth * bloomheight;
1633 // go back to full view area
1634 qglViewport(r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
1635 // put the original screen image back in place and blend the bloom
1638 GL_BlendFunc(GL_ONE, GL_ZERO);
1639 // do both in one pass if possible
1640 R_Mesh_TexBind(0, R_GetTexture(r_bloom_texture_screen));
1641 R_Mesh_TexCoordPointer(0, 2, texcoord2f[0]);
1642 if (r_textureunits.integer >= 2 && gl_combine.integer)
1644 R_Mesh_TexCombine(1, GL_ADD, GL_ADD, 1, 1);
1645 R_Mesh_TexBind(1, R_GetTexture(r_bloom_texture_bloom));
1646 R_Mesh_TexCoordPointer(1, 2, texcoord2f[1]);
1650 R_Mesh_Draw(0, 4, 2, polygonelements);
1651 renderstats.bloom_drawpixels += r_view_width * r_view_height;
1652 // now blend on the bloom texture
1653 GL_BlendFunc(GL_ONE, GL_ONE);
1654 R_Mesh_TexBind(0, R_GetTexture(r_bloom_texture_bloom));
1655 R_Mesh_TexCoordPointer(0, 2, texcoord2f[1]);
1657 R_Mesh_Draw(0, 4, 2, polygonelements);
1658 renderstats.bloom_drawpixels += r_view_width * r_view_height;
1662 // apply a color tint to the whole view
1663 R_Mesh_ResetTextureState();
1664 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1665 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
1666 R_Mesh_Draw(0, 4, 2, polygonelements);
1670 void R_RenderScene(void);
1672 matrix4x4_t r_waterscrollmatrix;
1679 void R_RenderView(void)
1681 if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
1682 return; //Host_Error ("R_RenderView: NULL worldmodel");
1684 r_view_width = bound(0, r_refdef.width, vid.width);
1685 r_view_height = bound(0, r_refdef.height, vid.height);
1687 r_view_x = bound(0, r_refdef.x, vid.width - r_refdef.width);
1688 r_view_y = bound(0, r_refdef.y, vid.height - r_refdef.height);
1690 r_view_matrix = r_refdef.viewentitymatrix;
1691 GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
1692 r_rtworld = r_shadow_realtime_world.integer;
1693 r_rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
1694 r_rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer;
1695 r_rtdlightshadows = r_rtdlight && (r_rtworld ? r_shadow_realtime_world_dlightshadows.integer : r_shadow_realtime_dlight_shadows.integer) && gl_stencil;
1696 r_lightmapintensity = r_rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
1697 r_polygonfactor = 0;
1698 r_polygonoffset = 0;
1699 r_shadowpolygonfactor = r_polygonfactor + r_shadow_shadow_polygonfactor.value;
1700 r_shadowpolygonoffset = r_polygonoffset + r_shadow_shadow_polygonoffset.value;
1701 if (r_showsurfaces.integer)
1704 r_rtworldshadows = false;
1706 r_rtdlightshadows = false;
1707 r_lightmapintensity = 0;
1710 // GL is weird because it's bottom to top, r_view_y is top to bottom
1711 qglViewport(r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
1712 GL_Scissor(r_view_x, r_view_y, r_view_width, r_view_height);
1713 GL_ScissorTest(true);
1718 if (r_timereport_active)
1719 R_TimeReport("setup");
1721 qglDepthFunc(GL_LEQUAL);
1722 qglPolygonOffset(r_polygonfactor, r_polygonoffset);
1723 qglEnable(GL_POLYGON_OFFSET_FILL);
1727 qglPolygonOffset(r_polygonfactor, r_polygonoffset);
1728 qglDisable(GL_POLYGON_OFFSET_FILL);
1731 if (r_timereport_active)
1732 R_TimeReport("blendview");
1734 GL_Scissor(0, 0, vid.width, vid.height);
1735 GL_ScissorTest(false);
1739 void CSQC_R_ClearScreen (void)
1741 if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
1742 return; //Host_Error ("R_RenderView: NULL worldmodel");
1744 r_view_width = bound(0, r_refdef.width, vid.width);
1745 r_view_height = bound(0, r_refdef.height, vid.height);
1747 r_view_x = bound(0, r_refdef.x, vid.width - r_refdef.width);
1748 r_view_y = bound(0, r_refdef.y, vid.height - r_refdef.height);
1750 r_view_matrix = r_refdef.viewentitymatrix;
1751 GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
1752 r_rtworld = r_shadow_realtime_world.integer;
1753 r_rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
1754 r_rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer;
1755 r_rtdlightshadows = r_rtdlight && (r_rtworld ? r_shadow_realtime_world_dlightshadows.integer : r_shadow_realtime_dlight_shadows.integer) && gl_stencil;
1756 r_lightmapintensity = r_rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
1757 r_polygonfactor = 0;
1758 r_polygonoffset = 0;
1759 r_shadowpolygonfactor = r_polygonfactor + r_shadow_shadow_polygonfactor.value;
1760 r_shadowpolygonoffset = r_polygonoffset + r_shadow_shadow_polygonoffset.value;
1761 if (r_showsurfaces.integer)
1764 r_rtworldshadows = false;
1766 r_rtdlightshadows = false;
1767 r_lightmapintensity = 0;
1770 // GL is weird because it's bottom to top, r_view_y is top to bottom
1771 qglViewport(r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
1772 GL_Scissor(r_view_x, r_view_y, r_view_width, r_view_height);
1773 GL_ScissorTest(true);
1778 if (r_timereport_active)
1779 R_TimeReport("setup");
1783 void CSQC_R_RenderScene (void)
1785 qglDepthFunc(GL_LEQUAL);
1786 qglPolygonOffset(r_polygonfactor, r_polygonoffset);
1787 qglEnable(GL_POLYGON_OFFSET_FILL);
1791 qglPolygonOffset(r_polygonfactor, r_polygonoffset);
1792 qglDisable(GL_POLYGON_OFFSET_FILL);
1795 if (r_timereport_active)
1796 R_TimeReport("blendview");
1798 GL_Scissor(0, 0, vid.width, vid.height);
1799 GL_ScissorTest(false);
1802 extern void R_DrawLightningBeams (void);
1803 extern void VM_AddPolygonsToMeshQueue (void);
1804 void R_RenderScene(void)
1808 // don't let sound skip if going slow
1809 if (r_refdef.extraupdate)
1814 if (gl_support_fragment_shader)
1815 qglUseProgramObjectARB(0);
1817 R_MeshQueue_BeginScene();
1821 r_farclip = R_FarClip(r_vieworigin, r_viewforward, 768.0f) + 256.0f;
1822 nearclip = bound (0.001f, r_nearclip.value, r_farclip - 1.0f);
1824 if (r_rtworldshadows || r_rtdlightshadows)
1825 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_refdef.frustum_x, r_refdef.frustum_y, nearclip);
1827 GL_SetupView_Mode_Perspective(r_refdef.frustum_x, r_refdef.frustum_y, nearclip, r_farclip);
1829 GL_SetupView_Orientation_FromEntity(&r_view_matrix);
1831 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);
1835 R_WorldVisibility();
1836 if (r_timereport_active)
1837 R_TimeReport("worldvis");
1840 if (r_timereport_active)
1841 R_TimeReport("markentity");
1843 R_Shadow_UpdateWorldLightSelection();
1845 if (cl.csqc_vidvars.drawworld)
1847 // don't let sound skip if going slow
1848 if (r_refdef.extraupdate)
1851 if (r_refdef.worldmodel && r_refdef.worldmodel->DrawSky)
1853 r_refdef.worldmodel->DrawSky(r_refdef.worldentity);
1854 if (r_timereport_active)
1855 R_TimeReport("worldsky");
1858 if (R_DrawBrushModelsSky() && r_timereport_active)
1859 R_TimeReport("bmodelsky");
1861 if (r_refdef.worldmodel && r_refdef.worldmodel->Draw)
1863 r_refdef.worldmodel->Draw(r_refdef.worldentity);
1864 if (r_timereport_active)
1865 R_TimeReport("world");
1869 // don't let sound skip if going slow
1870 if (r_refdef.extraupdate)
1874 if (r_timereport_active)
1875 R_TimeReport("models");
1877 // don't let sound skip if going slow
1878 if (r_refdef.extraupdate)
1881 R_ShadowVolumeLighting(false);
1882 if (r_timereport_active)
1883 R_TimeReport("rtlights");
1885 // don't let sound skip if going slow
1886 if (r_refdef.extraupdate)
1889 if (cl.csqc_vidvars.drawworld)
1891 R_DrawLightningBeams();
1892 if (r_timereport_active)
1893 R_TimeReport("lightning");
1896 if (r_timereport_active)
1897 R_TimeReport("particles");
1900 if (r_timereport_active)
1901 R_TimeReport("explosions");
1904 R_MeshQueue_RenderTransparent();
1905 if (r_timereport_active)
1906 R_TimeReport("drawtrans");
1908 if (cl.csqc_vidvars.drawworld)
1911 if (r_timereport_active)
1912 R_TimeReport("coronas");
1914 if(cl.csqc_vidvars.drawcrosshair)
1916 R_DrawWorldCrosshair();
1917 if (r_timereport_active)
1918 R_TimeReport("crosshair");
1921 VM_AddPolygonsToMeshQueue();
1923 R_MeshQueue_Render();
1925 R_MeshQueue_EndScene();
1927 // don't let sound skip if going slow
1928 if (r_refdef.extraupdate)
1931 if (gl_support_fragment_shader)
1932 qglUseProgramObjectARB(0);
1936 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
1939 float *v, *c, f1, f2, diff[3], vertex3f[8*3], color4f[8*4];
1940 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1941 GL_DepthMask(false);
1943 R_Mesh_Matrix(&identitymatrix);
1945 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2];
1946 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
1947 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
1948 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
1949 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
1950 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
1951 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
1952 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
1953 R_FillColors(color, 8, cr, cg, cb, ca);
1956 for (i = 0, v = vertex, c = color;i < 8;i++, v += 4, c += 4)
1958 f2 = VERTEXFOGTABLE(VectorDistance(v, r_vieworigin));
1960 c[0] = c[0] * f1 + fogcolor[0] * f2;
1961 c[1] = c[1] * f1 + fogcolor[1] * f2;
1962 c[2] = c[2] * f1 + fogcolor[2] * f2;
1965 R_Mesh_VertexPointer(vertex3f);
1966 R_Mesh_ColorPointer(color);
1967 R_Mesh_ResetTextureState();
1972 int nomodelelements[24] =
1984 float nomodelvertex3f[6*3] =
1994 float nomodelcolor4f[6*4] =
1996 0.0f, 0.0f, 0.5f, 1.0f,
1997 0.0f, 0.0f, 0.5f, 1.0f,
1998 0.0f, 0.5f, 0.0f, 1.0f,
1999 0.0f, 0.5f, 0.0f, 1.0f,
2000 0.5f, 0.0f, 0.0f, 1.0f,
2001 0.5f, 0.0f, 0.0f, 1.0f
2004 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight)
2009 R_Mesh_Matrix(&ent->matrix);
2011 if (ent->flags & EF_ADDITIVE)
2013 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2014 GL_DepthMask(false);
2016 else if (ent->alpha < 1)
2018 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2019 GL_DepthMask(false);
2023 GL_BlendFunc(GL_ONE, GL_ZERO);
2026 GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
2027 R_Mesh_VertexPointer(nomodelvertex3f);
2030 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
2031 R_Mesh_ColorPointer(color4f);
2032 f2 = VERTEXFOGTABLE(VectorDistance(ent->origin, r_vieworigin));
2034 for (i = 0, c = color4f;i < 6;i++, c += 4)
2036 c[0] = (c[0] * f1 + fogcolor[0] * f2);
2037 c[1] = (c[1] * f1 + fogcolor[1] * f2);
2038 c[2] = (c[2] * f1 + fogcolor[2] * f2);
2042 else if (ent->alpha != 1)
2044 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
2045 R_Mesh_ColorPointer(color4f);
2046 for (i = 0, c = color4f;i < 6;i++, c += 4)
2050 R_Mesh_ColorPointer(nomodelcolor4f);
2051 R_Mesh_ResetTextureState();
2052 R_Mesh_Draw(0, 6, 8, nomodelelements);
2055 void R_DrawNoModel(entity_render_t *ent)
2057 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
2058 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_vieworigin : ent->origin, R_DrawNoModel_TransparentCallback, ent, 0, r_shadow_rtlight);
2060 // R_DrawNoModelCallback(ent, 0);
2063 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
2065 vec3_t right1, right2, diff, normal;
2067 VectorSubtract (org2, org1, normal);
2069 // calculate 'right' vector for start
2070 VectorSubtract (r_vieworigin, org1, diff);
2071 CrossProduct (normal, diff, right1);
2072 VectorNormalize (right1);
2074 // calculate 'right' vector for end
2075 VectorSubtract (r_vieworigin, org2, diff);
2076 CrossProduct (normal, diff, right2);
2077 VectorNormalize (right2);
2079 vert[ 0] = org1[0] + width * right1[0];
2080 vert[ 1] = org1[1] + width * right1[1];
2081 vert[ 2] = org1[2] + width * right1[2];
2082 vert[ 3] = org1[0] - width * right1[0];
2083 vert[ 4] = org1[1] - width * right1[1];
2084 vert[ 5] = org1[2] - width * right1[2];
2085 vert[ 6] = org2[0] - width * right2[0];
2086 vert[ 7] = org2[1] - width * right2[1];
2087 vert[ 8] = org2[2] - width * right2[2];
2088 vert[ 9] = org2[0] + width * right2[0];
2089 vert[10] = org2[1] + width * right2[1];
2090 vert[11] = org2[2] + width * right2[2];
2093 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
2095 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)
2097 float fog = 0.0f, ifog;
2101 fog = VERTEXFOGTABLE(VectorDistance(origin, r_vieworigin));
2104 R_Mesh_Matrix(&identitymatrix);
2105 GL_BlendFunc(blendfunc1, blendfunc2);
2106 GL_DepthMask(false);
2107 GL_DepthTest(!depthdisable);
2109 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
2110 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
2111 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
2112 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
2113 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
2114 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
2115 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
2116 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
2117 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
2118 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
2119 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
2120 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
2122 R_Mesh_VertexPointer(vertex3f);
2123 R_Mesh_ColorPointer(NULL);
2124 R_Mesh_ResetTextureState();
2125 R_Mesh_TexBind(0, R_GetTexture(texture));
2126 R_Mesh_TexCoordPointer(0, 2, spritetexcoord2f);
2127 GL_Color(cr * ifog, cg * ifog, cb * ifog, ca);
2128 R_Mesh_Draw(0, 4, 2, polygonelements);
2130 if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
2132 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
2133 GL_BlendFunc(blendfunc1, GL_ONE);
2134 GL_Color(fogcolor[0] * fog, fogcolor[1] * fog, fogcolor[2] * fog, ca);
2135 R_Mesh_Draw(0, 4, 2, polygonelements);
2139 int R_Mesh_AddVertex3f(rmesh_t *mesh, const float *v)
2143 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
2144 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
2146 if (i == mesh->numvertices)
2148 if (mesh->numvertices < mesh->maxvertices)
2150 VectorCopy(v, vertex3f);
2151 mesh->numvertices++;
2153 return mesh->numvertices;
2159 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
2163 element[0] = R_Mesh_AddVertex3f(mesh, vertex3f);vertex3f += 3;
2164 element[1] = R_Mesh_AddVertex3f(mesh, vertex3f);vertex3f += 3;
2165 e = mesh->element3i + mesh->numtriangles * 3;
2166 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
2168 element[2] = R_Mesh_AddVertex3f(mesh, vertex3f);
2169 if (mesh->numtriangles < mesh->maxtriangles)
2174 mesh->numtriangles++;
2176 element[1] = element[2];
2180 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
2182 int planenum, planenum2;
2185 mplane_t *plane, *plane2;
2186 float temppoints[2][256*3];
2187 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
2191 PolygonF_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->normal[3], 1024.0*1024.0*1024.0);
2192 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
2194 if (planenum2 == planenum)
2196 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);
2199 if (tempnumpoints < 3)
2201 // generate elements forming a triangle fan for this polygon
2202 R_Mesh_AddPolygon3f(mesh, tempnumpoints, temppoints[w]);
2206 static void R_DrawCollisionBrush(colbrushf_t *brush)
2209 R_Mesh_VertexPointer(brush->points->v);
2210 i = (int)(((size_t)brush) / sizeof(colbrushf_t));
2211 GL_Color((i & 31) * (1.0f / 32.0f), ((i >> 5) & 31) * (1.0f / 32.0f), ((i >> 10) & 31) * (1.0f / 32.0f), 0.2f);
2212 GL_LockArrays(0, brush->numpoints);
2213 R_Mesh_Draw(0, brush->numpoints, brush->numtriangles, brush->elements);
2214 GL_LockArrays(0, 0);
2217 static void R_DrawCollisionSurface(entity_render_t *ent, msurface_t *surface)
2220 if (!surface->num_collisiontriangles)
2222 R_Mesh_VertexPointer(surface->data_collisionvertex3f);
2223 i = (int)(((size_t)surface) / sizeof(msurface_t));
2224 GL_Color((i & 31) * (1.0f / 32.0f), ((i >> 5) & 31) * (1.0f / 32.0f), ((i >> 10) & 31) * (1.0f / 32.0f), 0.2f);
2225 GL_LockArrays(0, surface->num_collisionvertices);
2226 R_Mesh_Draw(0, surface->num_collisionvertices, surface->num_collisiontriangles, surface->data_collisionelement3i);
2227 GL_LockArrays(0, 0);
2230 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)
2232 texturelayer_t *layer;
2233 layer = t->currentlayers + t->currentnumlayers++;
2235 layer->depthmask = depthmask;
2236 layer->blendfunc1 = blendfunc1;
2237 layer->blendfunc2 = blendfunc2;
2238 layer->texture = texture;
2239 layer->texmatrix = *matrix;
2240 layer->color[0] = r;
2241 layer->color[1] = g;
2242 layer->color[2] = b;
2243 layer->color[3] = a;
2246 void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
2248 // FIXME: identify models using a better check than ent->model->brush.shadowmesh
2249 //int lightmode = ((ent->effects & EF_FULLBRIGHT) || ent->model->brush.shadowmesh) ? 0 : 2;
2252 texture_t *texture = t;
2253 model_t *model = ent->model;
2254 int s = ent->skinnum;
2255 if ((unsigned int)s >= (unsigned int)model->numskins)
2257 if (model->skinscenes)
2259 if (model->skinscenes[s].framecount > 1)
2260 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
2262 s = model->skinscenes[s].firstframe;
2265 t = t + s * model->num_surfaces;
2267 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];
2268 texture->currentframe = t;
2271 t->currentmaterialflags = t->basematerialflags;
2272 t->currentalpha = ent->alpha;
2273 if (t->basematerialflags & MATERIALFLAG_WATERALPHA)
2274 t->currentalpha *= r_wateralpha.value;
2275 if (!(ent->flags & RENDER_LIGHT))
2276 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
2277 if (ent->effects & EF_ADDITIVE)
2278 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_TRANSPARENT;
2279 else if (t->currentalpha < 1)
2280 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_TRANSPARENT;
2281 if (ent->effects & EF_NODEPTHTEST)
2282 t->currentmaterialflags |= MATERIALFLAG_NODEPTHTEST;
2283 if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
2284 t->currenttexmatrix = r_waterscrollmatrix;
2286 t->currenttexmatrix = identitymatrix;
2288 t->colormapping = VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f);
2289 t->basetexture = (!t->colormapping && t->skin.merged) ? t->skin.merged : t->skin.base;
2290 t->glosstexture = r_texture_white;
2291 t->specularpower = 8;
2292 t->specularscale = 0;
2293 if (r_shadow_gloss.integer > 0)
2297 if (r_shadow_glossintensity.value > 0)
2299 t->glosstexture = t->skin.gloss;
2300 t->specularscale = r_shadow_glossintensity.value;
2303 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
2304 t->specularscale = r_shadow_gloss2intensity.value;
2307 t->currentnumlayers = 0;
2308 if (!(t->currentmaterialflags & MATERIALFLAG_NODRAW))
2310 if (gl_lightmaps.integer)
2311 R_Texture_AddLayer(t, true, GL_ONE, GL_ZERO, TEXTURELAYERTYPE_LITTEXTURE_MULTIPASS, r_texture_white, &identitymatrix, 1, 1, 1, 1);
2312 else if (!(t->currentmaterialflags & MATERIALFLAG_SKY))
2314 int blendfunc1, blendfunc2, depthmask;
2315 if (t->currentmaterialflags & MATERIALFLAG_ADD)
2317 blendfunc1 = GL_SRC_ALPHA;
2318 blendfunc2 = GL_ONE;
2321 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
2323 blendfunc1 = GL_SRC_ALPHA;
2324 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
2329 blendfunc1 = GL_ONE;
2330 blendfunc2 = GL_ZERO;
2333 if (t->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL))
2335 rtexture_t *currentbasetexture;
2337 if (fogenabled && (t->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
2338 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
2339 currentbasetexture = (VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) < (1.0f / 1048576.0f) && t->skin.merged) ? t->skin.merged : t->skin.base;
2340 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2342 // fullbright is not affected by r_lightmapintensity
2343 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
2344 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->skin.pants)
2345 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);
2346 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->skin.shirt)
2347 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);
2353 // q3bsp has no lightmap updates, so the lightstylevalue that
2354 // would normally be baked into the lightmaptexture must be
2355 // applied to the color
2356 if (ent->model->type == mod_brushq3)
2357 colorscale *= r_refdef.lightstylevalue[0] * (1.0f / 256.0f);
2358 colorscale *= r_lightmapintensity;
2359 if (r_textureunits.integer >= 2 && gl_combine.integer)
2360 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);
2361 else if ((t->currentmaterialflags & MATERIALFLAG_TRANSPARENT) == 0)
2362 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);
2364 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);
2365 if (r_ambient.value >= (1.0f/64.0f))
2366 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);
2367 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->skin.pants)
2369 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);
2370 if (r_ambient.value >= (1.0f/64.0f))
2371 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);
2373 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->skin.shirt)
2375 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);
2376 if (r_ambient.value >= (1.0f/64.0f))
2377 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);
2380 if (t->skin.glow != NULL)
2381 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.glow, &t->currenttexmatrix, 1, 1, 1, t->currentalpha);
2382 if (fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
2384 // if this is opaque use alpha blend which will darken the earlier
2387 // if this is an alpha blended material, all the earlier passes
2388 // were darkened by fog already, so we only need to add the fog
2389 // color ontop through the fog mask texture
2391 // if this is an additive blended material, all the earlier passes
2392 // were darkened by fog already, and we should not add fog color
2393 // (because the background was not darkened, there is no fog color
2394 // that was lost behind it).
2395 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);
2402 void R_UpdateAllTextureInfo(entity_render_t *ent)
2406 for (i = 0;i < ent->model->num_textures;i++)
2407 R_UpdateTextureInfo(ent, ent->model->data_textures + i);
2410 int rsurface_array_size = 0;
2411 float *rsurface_array_vertex3f = NULL;
2412 float *rsurface_array_svector3f = NULL;
2413 float *rsurface_array_tvector3f = NULL;
2414 float *rsurface_array_normal3f = NULL;
2415 float *rsurface_array_color4f = NULL;
2416 float *rsurface_array_texcoord3f = NULL;
2418 void R_Mesh_ResizeArrays(int newvertices)
2420 if (rsurface_array_size >= newvertices)
2422 if (rsurface_array_vertex3f)
2423 Mem_Free(rsurface_array_vertex3f);
2424 rsurface_array_size = (newvertices + 1023) & ~1023;
2425 rsurface_array_vertex3f = (float *)Mem_Alloc(r_main_mempool, rsurface_array_size * sizeof(float[19]));
2426 rsurface_array_svector3f = rsurface_array_vertex3f + rsurface_array_size * 3;
2427 rsurface_array_tvector3f = rsurface_array_vertex3f + rsurface_array_size * 6;
2428 rsurface_array_normal3f = rsurface_array_vertex3f + rsurface_array_size * 9;
2429 rsurface_array_color4f = rsurface_array_vertex3f + rsurface_array_size * 12;
2430 rsurface_array_texcoord3f = rsurface_array_vertex3f + rsurface_array_size * 16;
2433 float *rsurface_vertex3f;
2434 float *rsurface_svector3f;
2435 float *rsurface_tvector3f;
2436 float *rsurface_normal3f;
2437 float *rsurface_lightmapcolor4f;
2438 vec3_t rsurface_modelorg;
2439 const entity_render_t *rsurface_entity;
2440 const model_t *rsurface_model;
2441 const texture_t *rsurface_texture;
2443 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)
2445 VectorCopy(modelorg, rsurface_modelorg);
2446 rsurface_entity = ent;
2447 rsurface_model = ent->model;
2448 rsurface_texture = texture;
2449 if (rsurface_array_size < rsurface_model->surfmesh.num_vertices)
2450 R_Mesh_ResizeArrays(rsurface_model->surfmesh.num_vertices);
2451 if ((rsurface_entity->frameblend[0].lerp != 1 || rsurface_entity->frameblend[0].frame != 0) && (rsurface_model->surfmesh.data_morphvertex3f || rsurface_model->surfmesh.data_vertexboneweights))
2453 rsurface_vertex3f = rsurface_array_vertex3f;
2454 rsurface_svector3f = NULL;
2455 rsurface_tvector3f = NULL;
2456 rsurface_normal3f = NULL;
2457 Mod_Alias_GetMesh_Vertex3f(rsurface_model, rsurface_entity->frameblend, rsurface_array_vertex3f);
2458 if (rsurface_texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
2459 generatetangents = true;
2460 if (generatetangents)
2461 generatenormals = true;
2462 if (generatenormals && !rsurface_normal3f)
2464 rsurface_normal3f = rsurface_array_normal3f;
2465 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);
2467 if (generatetangents && !rsurface_svector3f)
2469 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);
2470 rsurface_svector3f = rsurface_array_svector3f;
2471 rsurface_tvector3f = rsurface_array_tvector3f;
2476 rsurface_vertex3f = rsurface_model->surfmesh.data_vertex3f;
2477 rsurface_svector3f = rsurface_model->surfmesh.data_svector3f;
2478 rsurface_tvector3f = rsurface_model->surfmesh.data_tvector3f;
2479 rsurface_normal3f = rsurface_model->surfmesh.data_normal3f;
2481 if (rsurface_texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
2483 int texturesurfaceindex;
2484 float center[3], forward[3], right[3], up[3], v[4][3];
2485 matrix4x4_t matrix1, imatrix1;
2486 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_viewforward, forward);
2487 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_viewright, right);
2488 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_viewup, up);
2489 if (rsurface_texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE2)
2491 forward[0] = rsurface_modelorg[0] - center[0];
2492 forward[1] = rsurface_modelorg[1] - center[1];
2494 VectorNormalize(forward);
2495 right[0] = forward[1];
2496 right[1] = -forward[0];
2498 VectorSet(up, 0, 0, 1);
2500 // make deformed versions of only the vertices used by the specified surfaces
2501 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2504 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2505 // a single autosprite surface can contain multiple sprites...
2506 for (j = 0;j < surface->num_vertices - 3;j += 4)
2508 VectorClear(center);
2509 for (i = 0;i < 4;i++)
2510 VectorAdd(center, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
2511 VectorScale(center, 0.25f, center);
2512 // FIXME: calculate vectors from triangle edges instead of using texture vectors as an easy way out?
2513 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);
2514 Matrix4x4_Invert_Simple(&imatrix1, &matrix1);
2515 for (i = 0;i < 4;i++)
2516 Matrix4x4_Transform(&imatrix1, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, v[i]);
2517 for (i = 0;i < 4;i++)
2518 VectorMAMAMAM(1, center, v[i][0], forward, v[i][1], right, v[i][2], up, rsurface_array_vertex3f + (surface->num_firstvertex+i+j) * 3);
2520 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);
2521 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);
2523 rsurface_vertex3f = rsurface_array_vertex3f;
2524 rsurface_svector3f = rsurface_array_svector3f;
2525 rsurface_tvector3f = rsurface_array_tvector3f;
2526 rsurface_normal3f = rsurface_array_normal3f;
2528 R_Mesh_VertexPointer(rsurface_vertex3f);
2531 static void RSurf_Draw(const msurface_t *surface)
2533 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2534 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
2537 static void RSurf_DrawLightmap(const msurface_t *surface, float r, float g, float b, float a, int lightmode, qboolean applycolor, qboolean applyfog)
2545 vec3_t ambientcolor;
2546 vec3_t diffusecolor;
2548 VectorCopy(rsurface_entity->modellight_lightdir, lightdir);
2549 ambientcolor[0] = rsurface_entity->modellight_ambient[0] * r * 0.5f;
2550 ambientcolor[1] = rsurface_entity->modellight_ambient[1] * g * 0.5f;
2551 ambientcolor[2] = rsurface_entity->modellight_ambient[2] * b * 0.5f;
2552 diffusecolor[0] = rsurface_entity->modellight_diffuse[0] * r * 0.5f;
2553 diffusecolor[1] = rsurface_entity->modellight_diffuse[1] * g * 0.5f;
2554 diffusecolor[2] = rsurface_entity->modellight_diffuse[2] * b * 0.5f;
2555 if (VectorLength2(diffusecolor) > 0)
2557 int numverts = surface->num_vertices;
2558 v = rsurface_vertex3f + 3 * surface->num_firstvertex;
2559 c2 = rsurface_normal3f + 3 * surface->num_firstvertex;
2560 c = rsurface_array_color4f + 4 * surface->num_firstvertex;
2561 // q3-style directional shading
2562 for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
2564 if ((f = DotProduct(c2, lightdir)) > 0)
2565 VectorMA(ambientcolor, f, diffusecolor, c);
2567 VectorCopy(ambientcolor, c);
2575 rsurface_lightmapcolor4f = rsurface_array_color4f;
2579 r = ambientcolor[0];
2580 g = ambientcolor[1];
2581 b = ambientcolor[2];
2582 rsurface_lightmapcolor4f = NULL;
2585 else if (lightmode >= 1)
2587 if (surface->lightmapinfo && surface->lightmapinfo->stainsamples)
2589 for (i = 0, c = rsurface_array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
2591 if (surface->lightmapinfo->samples)
2593 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface_model->surfmesh.data_lightmapoffsets + surface->num_firstvertex)[i];
2594 float scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
2595 VectorScale(lm, scale, c);
2596 if (surface->lightmapinfo->styles[1] != 255)
2598 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
2600 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
2601 VectorMA(c, scale, lm, c);
2602 if (surface->lightmapinfo->styles[2] != 255)
2605 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
2606 VectorMA(c, scale, lm, c);
2607 if (surface->lightmapinfo->styles[3] != 255)
2610 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
2611 VectorMA(c, scale, lm, c);
2619 rsurface_lightmapcolor4f = rsurface_array_color4f;
2622 rsurface_lightmapcolor4f = rsurface_model->surfmesh.data_lightmapcolor4f;
2625 rsurface_lightmapcolor4f = NULL;
2628 if (rsurface_lightmapcolor4f)
2630 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)
2632 f = 1 - VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
2641 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)
2643 f = 1 - VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
2650 rsurface_lightmapcolor4f = rsurface_array_color4f;
2652 if (applycolor && rsurface_lightmapcolor4f)
2654 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)
2661 rsurface_lightmapcolor4f = rsurface_array_color4f;
2663 R_Mesh_ColorPointer(rsurface_lightmapcolor4f);
2664 GL_Color(r, g, b, a);
2665 RSurf_Draw(surface);
2668 static void R_DrawTextureSurfaceList(const entity_render_t *ent, texture_t *texture, int texturenumsurfaces, msurface_t **texturesurfacelist, const vec3_t modelorg)
2670 int texturesurfaceindex;
2672 const msurface_t *surface;
2673 model_t *model = ent->model;
2674 qboolean applycolor;
2677 if (texture->currentmaterialflags & MATERIALFLAG_NODRAW)
2679 r_shadow_rtlight = NULL;
2680 renderstats.entities_surfaces += texturenumsurfaces;
2681 // FIXME: identify models using a better check than model->brush.shadowmesh
2682 lightmode = ((ent->effects & EF_FULLBRIGHT) || model->brush.shadowmesh) ? 0 : 2;
2683 GL_DepthTest(!(texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
2684 if ((texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (ent->flags & RENDER_NOCULLFACE))
2685 qglDisable(GL_CULL_FACE);
2686 if (r_showsurfaces.integer)
2689 GL_BlendFunc(GL_ONE, GL_ZERO);
2690 R_Mesh_ColorPointer(NULL);
2691 R_Mesh_ResetTextureState();
2692 RSurf_PrepareVerticesForBatch(ent, texture, modelorg, false, false, texturenumsurfaces, texturesurfacelist);
2693 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2695 int k = (int)(((size_t)surface) / sizeof(msurface_t));
2696 GL_Color((k & 15) * (1.0f / 16.0f), ((k >> 4) & 15) * (1.0f / 16.0f), ((k >> 8) & 15) * (1.0f / 16.0f), 0.2f);
2697 surface = texturesurfacelist[texturesurfaceindex];
2698 RSurf_Draw(surface);
2701 else if (texture->currentmaterialflags & MATERIALFLAG_SKY)
2703 // transparent sky would be ridiculous
2704 if (!(texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
2708 skyrendernow = false;
2710 // restore entity matrix
2711 R_Mesh_Matrix(&ent->matrix);
2714 // LordHavoc: HalfLife maps have freaky skypolys so don't use
2715 // skymasking on them, and Quake3 never did sky masking (unlike
2716 // software Quake and software Quake2), so disable the sky masking
2717 // in Quake3 maps as it causes problems with q3map2 sky tricks,
2718 // and skymasking also looks very bad when noclipping outside the
2719 // level, so don't use it then either.
2720 if (model->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_worldnovis)
2722 GL_Color(fogcolor[0], fogcolor[1], fogcolor[2], 1);
2723 R_Mesh_ColorPointer(NULL);
2724 R_Mesh_ResetTextureState();
2725 if (skyrendermasked)
2727 // depth-only (masking)
2728 GL_ColorMask(0,0,0,0);
2729 // just to make sure that braindead drivers don't draw
2730 // anything despite that colormask...
2731 GL_BlendFunc(GL_ZERO, GL_ONE);
2736 GL_BlendFunc(GL_ONE, GL_ZERO);
2738 RSurf_PrepareVerticesForBatch(ent, texture, modelorg, false, false, texturenumsurfaces, texturesurfacelist);
2739 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2741 surface = texturesurfacelist[texturesurfaceindex];
2742 RSurf_Draw(surface);
2744 if (skyrendermasked)
2745 GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
2749 else if (r_glsl.integer && gl_support_fragment_shader)
2751 if (texture->currentmaterialflags & MATERIALFLAG_ADD)
2753 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2754 GL_DepthMask(false);
2756 else if (texture->currentmaterialflags & MATERIALFLAG_ALPHA)
2758 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2759 GL_DepthMask(false);
2763 GL_BlendFunc(GL_ONE, GL_ZERO);
2767 R_Mesh_ColorPointer(NULL);
2768 R_Mesh_ResetTextureState();
2769 GL_Color(ent->colormod[0], ent->colormod[1], ent->colormod[2], texture->currentalpha);
2770 R_SetupSurfaceShader(ent, texture, modelorg, vec3_origin, lightmode == 2);
2771 if (!r_glsl_permutation)
2773 RSurf_PrepareVerticesForBatch(ent, texture, modelorg, true, true, texturenumsurfaces, texturesurfacelist);
2774 R_Mesh_TexCoordPointer(0, 2, model->surfmesh.data_texcoordtexture2f);
2775 R_Mesh_TexCoordPointer(1, 3, rsurface_svector3f);
2776 R_Mesh_TexCoordPointer(2, 3, rsurface_tvector3f);
2777 R_Mesh_TexCoordPointer(3, 3, rsurface_normal3f);
2780 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2782 surface = texturesurfacelist[texturesurfaceindex];
2783 RSurf_Draw(surface);
2788 R_Mesh_TexCoordPointer(4, 2, model->surfmesh.data_texcoordlightmap2f);
2789 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2791 surface = texturesurfacelist[texturesurfaceindex];
2792 if (surface->lightmaptexture)
2794 R_Mesh_TexBind(7, R_GetTexture(surface->lightmaptexture));
2795 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
2796 R_Mesh_TexBind(8, R_GetTexture(surface->deluxemaptexture));
2797 R_Mesh_ColorPointer(NULL);
2801 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
2802 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
2803 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
2804 R_Mesh_ColorPointer(model->surfmesh.data_lightmapcolor4f);
2806 RSurf_Draw(surface);
2809 qglUseProgramObjectARB(0);
2811 else if (texture->currentnumlayers)
2814 texturelayer_t *layer;
2815 RSurf_PrepareVerticesForBatch(ent, texture, modelorg, true, false, texturenumsurfaces, texturesurfacelist);
2816 for (layerindex = 0, layer = texture->currentlayers;layerindex < texture->currentnumlayers;layerindex++, layer++)
2819 int layertexrgbscale;
2820 GL_DepthMask(layer->depthmask);
2821 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
2822 if ((layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2) && (gl_combine.integer || layer->depthmask))
2824 layertexrgbscale = 4;
2825 VectorScale(layer->color, 0.25f, layercolor);
2827 else if ((layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1) && (gl_combine.integer || layer->depthmask))
2829 layertexrgbscale = 2;
2830 VectorScale(layer->color, 0.5f, layercolor);
2834 layertexrgbscale = 1;
2835 VectorScale(layer->color, 1.0f, layercolor);
2837 layercolor[3] = layer->color[3];
2838 R_Mesh_ColorPointer(NULL);
2839 GL_Color(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
2840 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
2841 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
2842 switch (layer->type)
2844 case TEXTURELAYERTYPE_LITTEXTURE_COMBINE:
2845 memset(&m, 0, sizeof(m));
2846 m.pointer_texcoord[0] = model->surfmesh.data_texcoordlightmap2f;
2847 m.tex[1] = R_GetTexture(layer->texture);
2848 m.texmatrix[1] = layer->texmatrix;
2849 m.texrgbscale[1] = layertexrgbscale;
2850 m.pointer_texcoord[1] = model->surfmesh.data_texcoordtexture2f;
2851 R_Mesh_TextureState(&m);
2854 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2856 surface = texturesurfacelist[texturesurfaceindex];
2857 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2858 RSurf_DrawLightmap(surface, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 2, applycolor, applyfog);
2863 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2865 surface = texturesurfacelist[texturesurfaceindex];
2866 if (surface->lightmaptexture)
2868 R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
2869 RSurf_DrawLightmap(surface, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, applyfog);
2873 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2874 RSurf_DrawLightmap(surface, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 1, applycolor, applyfog);
2879 case TEXTURELAYERTYPE_LITTEXTURE_MULTIPASS:
2880 memset(&m, 0, sizeof(m));
2881 m.tex[0] = R_GetTexture(layer->texture);
2882 m.texmatrix[0] = layer->texmatrix;
2883 m.texrgbscale[0] = layertexrgbscale;
2884 m.pointer_texcoord[0] = model->surfmesh.data_texcoordlightmap2f;
2885 R_Mesh_TextureState(&m);
2888 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2890 surface = texturesurfacelist[texturesurfaceindex];
2891 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2892 RSurf_DrawLightmap(surface, 1, 1, 1, 1, 2, false, false);
2897 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2899 surface = texturesurfacelist[texturesurfaceindex];
2900 if (surface->lightmaptexture)
2902 R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
2903 RSurf_DrawLightmap(surface, 1, 1, 1, 1, 0, false, false);
2907 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2908 RSurf_DrawLightmap(surface, 1, 1, 1, 1, 1, false, false);
2912 GL_LockArrays(0, 0);
2913 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
2914 memset(&m, 0, sizeof(m));
2915 m.tex[0] = R_GetTexture(layer->texture);
2916 m.texmatrix[0] = layer->texmatrix;
2917 m.texrgbscale[0] = layertexrgbscale;
2918 m.pointer_texcoord[0] = model->surfmesh.data_texcoordtexture2f;
2919 R_Mesh_TextureState(&m);
2920 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2922 surface = texturesurfacelist[texturesurfaceindex];
2923 RSurf_DrawLightmap(surface, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, false);
2926 case TEXTURELAYERTYPE_LITTEXTURE_VERTEX:
2927 memset(&m, 0, sizeof(m));
2928 m.tex[0] = R_GetTexture(layer->texture);
2929 m.texmatrix[0] = layer->texmatrix;
2930 m.texrgbscale[0] = layertexrgbscale;
2931 m.pointer_texcoord[0] = model->surfmesh.data_texcoordtexture2f;
2932 R_Mesh_TextureState(&m);
2935 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2937 surface = texturesurfacelist[texturesurfaceindex];
2938 RSurf_DrawLightmap(surface, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 2, applycolor, applyfog);
2943 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2945 surface = texturesurfacelist[texturesurfaceindex];
2946 RSurf_DrawLightmap(surface, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 1, applycolor, applyfog);
2950 case TEXTURELAYERTYPE_TEXTURE:
2951 memset(&m, 0, sizeof(m));
2952 m.tex[0] = R_GetTexture(layer->texture);
2953 m.texmatrix[0] = layer->texmatrix;
2954 m.texrgbscale[0] = layertexrgbscale;
2955 m.pointer_texcoord[0] = model->surfmesh.data_texcoordtexture2f;
2956 R_Mesh_TextureState(&m);
2957 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2959 surface = texturesurfacelist[texturesurfaceindex];
2960 RSurf_DrawLightmap(surface, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, applyfog);
2963 case TEXTURELAYERTYPE_FOG:
2964 R_Mesh_ColorPointer(rsurface_array_color4f);
2967 memset(&m, 0, sizeof(m));
2968 m.tex[0] = R_GetTexture(layer->texture);
2969 m.texmatrix[0] = layer->texmatrix;
2970 m.pointer_texcoord[0] = model->surfmesh.data_texcoordtexture2f;
2971 R_Mesh_TextureState(&m);
2974 R_Mesh_ResetTextureState();
2975 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2979 surface = texturesurfacelist[texturesurfaceindex];
2980 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)
2982 f = VERTEXFOGTABLE(VectorDistance(v, modelorg));
2983 c[0] = layercolor[0];
2984 c[1] = layercolor[1];
2985 c[2] = layercolor[2];
2986 c[3] = f * layercolor[3];
2988 RSurf_Draw(surface);
2992 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
2994 GL_LockArrays(0, 0);
2995 // if trying to do overbright on first pass of an opaque surface
2996 // when combine is not supported, brighten as a post process
2997 if (layertexrgbscale > 1 && !gl_combine.integer && layer->depthmask)
3000 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
3001 R_Mesh_ColorPointer(NULL);
3002 GL_Color(1, 1, 1, 1);
3003 R_Mesh_ResetTextureState();
3004 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3006 surface = texturesurfacelist[texturesurfaceindex];
3007 for (scale = 1;scale < layertexrgbscale;scale <<= 1)
3008 RSurf_Draw(surface);
3010 GL_LockArrays(0, 0);
3014 GL_LockArrays(0, 0);
3015 if ((texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (ent->flags & RENDER_NOCULLFACE))
3016 qglEnable(GL_CULL_FACE);
3019 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight)
3021 msurface_t *surface = ent->model->data_surfaces + surfacenumber;
3025 texture = surface->texture;
3026 if (texture->basematerialflags & MATERIALFLAG_SKY)
3027 return; // transparent sky is too difficult
3028 R_UpdateTextureInfo(ent, texture);
3030 R_Mesh_Matrix(&ent->matrix);
3031 Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
3032 R_DrawTextureSurfaceList(ent, texture->currentframe, 1, &surface, modelorg);
3035 void R_QueueTextureSurfaceList(entity_render_t *ent, texture_t *texture, int texturenumsurfaces, msurface_t **texturesurfacelist, const vec3_t modelorg)
3037 int texturesurfaceindex;
3038 const msurface_t *surface;
3039 vec3_t tempcenter, center;
3040 if (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT)
3042 // drawing sky transparently would be too difficult
3043 if (!(texture->currentmaterialflags & MATERIALFLAG_SKY))
3045 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3047 surface = texturesurfacelist[texturesurfaceindex];
3048 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
3049 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
3050 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
3051 Matrix4x4_Transform(&ent->matrix, tempcenter, center);
3052 R_MeshQueue_AddTransparent(texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_vieworigin : center, R_DrawSurface_TransparentCallback, ent, surface - ent->model->data_surfaces, r_shadow_rtlight);
3057 R_DrawTextureSurfaceList(ent, texture, texturenumsurfaces, texturesurfacelist, modelorg);
3060 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
3061 void R_DrawSurfaces(entity_render_t *ent, qboolean skysurfaces)
3063 int i, j, f, flagsmask;
3064 int counttriangles = 0;
3065 msurface_t *surface, **surfacechain;
3066 texture_t *t, *texture;
3067 model_t *model = ent->model;
3069 const int maxsurfacelist = 1024;
3070 int numsurfacelist = 0;
3071 msurface_t *surfacelist[1024];
3074 R_Mesh_Matrix(&ent->matrix);
3075 Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
3077 // update light styles
3078 if (!skysurfaces && model->brushq1.light_styleupdatechains)
3080 for (i = 0;i < model->brushq1.light_styles;i++)
3082 if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
3084 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
3085 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
3086 for (;(surface = *surfacechain);surfacechain++)
3087 surface->cached_dlight = true;
3092 R_UpdateAllTextureInfo(ent);
3093 flagsmask = skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL);
3098 if (ent == r_refdef.worldentity)
3100 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
3102 if (!r_worldsurfacevisible[j])
3104 if (t != surface->texture)
3108 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
3111 t = surface->texture;
3112 texture = t->currentframe;
3113 f = texture->currentmaterialflags & flagsmask;
3115 if (f && surface->num_triangles)
3117 // if lightmap parameters changed, rebuild lightmap texture
3118 if (surface->cached_dlight)
3119 R_BuildLightMap(ent, surface);
3120 // add face to draw list
3121 surfacelist[numsurfacelist++] = surface;
3122 counttriangles += surface->num_triangles;
3123 if (numsurfacelist >= maxsurfacelist)
3125 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
3133 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
3135 if (t != surface->texture)
3139 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
3142 t = surface->texture;
3143 texture = t->currentframe;
3144 f = texture->currentmaterialflags & flagsmask;
3146 if (f && surface->num_triangles)
3148 // if lightmap parameters changed, rebuild lightmap texture
3149 if (surface->cached_dlight)
3150 R_BuildLightMap(ent, surface);
3151 // add face to draw list
3152 surfacelist[numsurfacelist++] = surface;
3153 counttriangles += surface->num_triangles;
3154 if (numsurfacelist >= maxsurfacelist)
3156 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
3163 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
3164 renderstats.entities_triangles += counttriangles;
3165 if (gl_support_fragment_shader)
3166 qglUseProgramObjectARB(0);
3168 if (r_showcollisionbrushes.integer && model->brush.num_brushes && !skysurfaces)
3171 msurface_t *surface;
3173 R_Mesh_Matrix(&ent->matrix);
3174 R_Mesh_ColorPointer(NULL);
3175 R_Mesh_ResetTextureState();
3176 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
3177 GL_DepthMask(false);
3178 GL_DepthTest(!r_showdisabledepthtest.integer);
3179 qglPolygonOffset(r_polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_polygonoffset + r_showcollisionbrushes_polygonoffset.value);
3180 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
3181 if (brush->colbrushf && brush->colbrushf->numtriangles)
3182 R_DrawCollisionBrush(brush->colbrushf);
3183 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
3184 if (surface->num_collisiontriangles)
3185 R_DrawCollisionSurface(ent, surface);
3186 qglPolygonOffset(r_polygonfactor, r_polygonoffset);
3189 if (r_showtris.integer || r_shownormals.integer)
3192 const int *elements;
3196 if (r_showdisabledepthtest.integer)
3197 qglDepthFunc(GL_ALWAYS);
3198 GL_BlendFunc(GL_ONE, GL_ZERO);
3199 R_Mesh_ColorPointer(NULL);
3200 R_Mesh_ResetTextureState();
3201 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
3203 if (ent == r_refdef.worldentity && !r_worldsurfacevisible[j])
3205 texture = surface->texture->currentframe;
3206 if ((texture->currentmaterialflags & flagsmask) && surface->num_triangles)
3208 RSurf_PrepareVerticesForBatch(ent, texture, modelorg, false, r_shownormals.integer != 0, 1, &surface);
3209 if (r_showtris.integer)
3211 if (!texture->currentlayers->depthmask)
3212 GL_Color(r_showtris.value, 0, 0, 1);
3213 else if (ent == r_refdef.worldentity)
3214 GL_Color(r_showtris.value, r_showtris.value, r_showtris.value, 1);
3216 GL_Color(0, r_showtris.value, 0, 1);
3217 elements = (ent->model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
3219 for (k = 0;k < surface->num_triangles;k++, elements += 3)
3221 qglArrayElement(elements[0]);qglArrayElement(elements[1]);
3222 qglArrayElement(elements[1]);qglArrayElement(elements[2]);
3223 qglArrayElement(elements[2]);qglArrayElement(elements[0]);
3227 if (r_shownormals.integer)
3229 GL_Color(r_shownormals.value, 0, 0, 1);
3231 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
3233 VectorCopy(rsurface_vertex3f + l * 3, v);
3234 qglVertex3f(v[0], v[1], v[2]);
3235 VectorMA(v, 8, rsurface_svector3f + l * 3, v);
3236 qglVertex3f(v[0], v[1], v[2]);
3239 GL_Color(0, 0, r_shownormals.value, 1);
3241 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
3243 VectorCopy(rsurface_vertex3f + l * 3, v);
3244 qglVertex3f(v[0], v[1], v[2]);
3245 VectorMA(v, 8, rsurface_tvector3f + l * 3, v);
3246 qglVertex3f(v[0], v[1], v[2]);
3249 GL_Color(0, r_shownormals.value, 0, 1);
3251 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
3253 VectorCopy(rsurface_vertex3f + l * 3, v);
3254 qglVertex3f(v[0], v[1], v[2]);
3255 VectorMA(v, 8, rsurface_normal3f + l * 3, v);
3256 qglVertex3f(v[0], v[1], v[2]);
3262 if (r_showdisabledepthtest.integer)
3263 qglDepthFunc(GL_LEQUAL);