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);CHECKGLERROR
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);
831 qglUseProgramObjectARB(0);CHECKGLERROR
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 int R_SetupSurfaceShader(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 = rsurface_texture->specularscale;
856 r_glsl_permutation = NULL;
857 if (r_shadow_rtlight)
859 permutation |= SHADERPERMUTATION_MODE_LIGHTSOURCE;
860 specularscale *= r_shadow_rtlight->specularscale;
861 if (r_shadow_rtlight->currentcubemap != r_texture_whitecube)
862 permutation |= SHADERPERMUTATION_CUBEFILTER;
866 if (!(rsurface_texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
869 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTION;
872 if (r_glsl_deluxemapping.integer >= 1 && r_refdef.worldmodel && r_refdef.worldmodel->brushq3.deluxemapping && rsurface_lightmaptexture)
874 if (r_refdef.worldmodel->brushq3.deluxemapping_modelspace)
875 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_MODELSPACE;
877 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
879 else if (r_glsl_deluxemapping.integer >= 2) // fake mode
880 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
883 if (rsurface_texture->skin.glow)
884 permutation |= SHADERPERMUTATION_GLOW;
886 if (specularscale > 0)
887 permutation |= SHADERPERMUTATION_SPECULAR;
889 permutation |= SHADERPERMUTATION_FOG;
890 if (rsurface_texture->colormapping)
891 permutation |= SHADERPERMUTATION_COLORMAPPING;
892 if (r_glsl_offsetmapping.integer)
894 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
895 if (r_glsl_offsetmapping_reliefmapping.integer)
896 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
898 if (!r_glsl_permutations[permutation].program)
900 if (!r_glsl_permutations[permutation].compiled)
901 R_GLSL_CompilePermutation(permutation);
902 if (!r_glsl_permutations[permutation].program)
904 // remove features until we find a valid permutation
906 for (i = SHADERPERMUTATION_COUNT-1;;i>>=1)
908 // reduce i more quickly whenever it would not remove any bits
912 if (!r_glsl_permutations[permutation].compiled)
913 R_GLSL_CompilePermutation(permutation);
914 if (r_glsl_permutations[permutation].program)
917 return 0; // utterly failed
921 r_glsl_permutation = r_glsl_permutations + permutation;
923 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
924 R_Mesh_TexMatrix(0, &rsurface_texture->currenttexmatrix);
925 if (permutation & SHADERPERMUTATION_MODE_LIGHTSOURCE)
927 if (r_glsl_permutation->loc_Texture_Cube >= 0 && r_shadow_rtlight) R_Mesh_TexBindCubeMap(3, R_GetTexture(r_shadow_rtlight->currentcubemap));
928 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]);
929 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
930 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_shadow_rtlight->ambientscale);
931 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_shadow_rtlight->diffusescale);
932 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, specularscale);
934 else if (permutation & SHADERPERMUTATION_MODE_LIGHTDIRECTION)
936 if (r_glsl_permutation->loc_AmbientColor >= 0)
937 qglUniform3fARB(r_glsl_permutation->loc_AmbientColor, rsurface_entity->modellight_ambient[0], rsurface_entity->modellight_ambient[1], rsurface_entity->modellight_ambient[2]);
938 if (r_glsl_permutation->loc_DiffuseColor >= 0)
939 qglUniform3fARB(r_glsl_permutation->loc_DiffuseColor, rsurface_entity->modellight_diffuse[0], rsurface_entity->modellight_diffuse[1], rsurface_entity->modellight_diffuse[2]);
940 if (r_glsl_permutation->loc_SpecularColor >= 0)
941 qglUniform3fARB(r_glsl_permutation->loc_SpecularColor, rsurface_entity->modellight_diffuse[0] * rsurface_texture->specularscale, rsurface_entity->modellight_diffuse[1] * rsurface_texture->specularscale, rsurface_entity->modellight_diffuse[2] * rsurface_texture->specularscale);
942 if (r_glsl_permutation->loc_LightDir >= 0)
943 qglUniform3fARB(r_glsl_permutation->loc_LightDir, rsurface_entity->modellight_lightdir[0], rsurface_entity->modellight_lightdir[1], rsurface_entity->modellight_lightdir[2]);
947 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_ambient.value * 2.0f / 128.0f);
948 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_lightmapintensity * 2.0f);
949 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, r_lightmapintensity * specularscale * 2.0f);
951 if (r_glsl_permutation->loc_Texture_Normal >= 0) R_Mesh_TexBind(0, R_GetTexture(rsurface_texture->skin.nmap));
952 if (r_glsl_permutation->loc_Texture_Color >= 0) R_Mesh_TexBind(1, R_GetTexture(rsurface_texture->basetexture));
953 if (r_glsl_permutation->loc_Texture_Gloss >= 0) R_Mesh_TexBind(2, R_GetTexture(rsurface_texture->glosstexture));
954 //if (r_glsl_permutation->loc_Texture_Cube >= 0 && permutation & SHADERPERMUTATION_MODE_LIGHTSOURCE) R_Mesh_TexBindCubeMap(3, R_GetTexture(r_shadow_rtlight->currentcubemap));
955 if (r_glsl_permutation->loc_Texture_FogMask >= 0) R_Mesh_TexBind(4, R_GetTexture(r_texture_fogattenuation));
956 if (r_glsl_permutation->loc_Texture_Pants >= 0) R_Mesh_TexBind(5, R_GetTexture(rsurface_texture->skin.pants));
957 if (r_glsl_permutation->loc_Texture_Shirt >= 0) R_Mesh_TexBind(6, R_GetTexture(rsurface_texture->skin.shirt));
958 //if (r_glsl_permutation->loc_Texture_Lightmap >= 0) R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
959 //if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
960 if (r_glsl_permutation->loc_Texture_Glow >= 0) R_Mesh_TexBind(9, R_GetTexture(rsurface_texture->skin.glow));
961 if (r_glsl_permutation->loc_FogColor >= 0)
963 // additive passes are only darkened by fog, not tinted
964 if (r_shadow_rtlight || (rsurface_texture->currentmaterialflags & MATERIALFLAG_ADD))
965 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
967 qglUniform3fARB(r_glsl_permutation->loc_FogColor, fogcolor[0], fogcolor[1], fogcolor[2]);
969 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface_modelorg[0], rsurface_modelorg[1], rsurface_modelorg[2]);
970 if (r_glsl_permutation->loc_Color_Pants >= 0)
972 if (rsurface_texture->skin.pants)
973 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface_entity->colormap_pantscolor[0], rsurface_entity->colormap_pantscolor[1], rsurface_entity->colormap_pantscolor[2]);
975 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
977 if (r_glsl_permutation->loc_Color_Shirt >= 0)
979 if (rsurface_texture->skin.shirt)
980 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface_entity->colormap_shirtcolor[0], rsurface_entity->colormap_shirtcolor[1], rsurface_entity->colormap_shirtcolor[2]);
982 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
984 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, fograngerecip);
985 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface_texture->specularpower);
986 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
991 void R_SwitchSurfaceShader(int permutation)
993 if (r_glsl_permutation != r_glsl_permutations + permutation)
995 r_glsl_permutation = r_glsl_permutations + permutation;
997 qglUseProgramObjectARB(r_glsl_permutation->program);
1002 void gl_main_start(void)
1004 r_main_texturepool = R_AllocTexturePool();
1005 r_bloom_texture_screen = NULL;
1006 r_bloom_texture_bloom = NULL;
1007 R_BuildBlankTextures();
1009 if (gl_texturecubemap)
1012 R_BuildNormalizationCube();
1014 R_BuildFogTexture();
1015 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
1018 void gl_main_shutdown(void)
1020 R_FreeTexturePool(&r_main_texturepool);
1021 r_bloom_texture_screen = NULL;
1022 r_bloom_texture_bloom = NULL;
1023 r_texture_blanknormalmap = NULL;
1024 r_texture_white = NULL;
1025 r_texture_black = NULL;
1026 r_texture_whitecube = NULL;
1027 r_texture_normalizationcube = NULL;
1031 extern void CL_ParseEntityLump(char *entitystring);
1032 void gl_main_newmap(void)
1034 // FIXME: move this code to client
1036 char *entities, entname[MAX_QPATH];
1040 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
1041 l = (int)strlen(entname) - 4;
1042 if (l >= 0 && !strcmp(entname + l, ".bsp"))
1044 strcpy(entname + l, ".ent");
1045 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
1047 CL_ParseEntityLump(entities);
1052 if (cl.worldmodel->brush.entities)
1053 CL_ParseEntityLump(cl.worldmodel->brush.entities);
1057 void GL_Main_Init(void)
1059 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
1061 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed\n");
1062 FOG_registercvars(); // FIXME: move this fog stuff to client?
1063 Cvar_RegisterVariable(&r_nearclip);
1064 Cvar_RegisterVariable(&r_showsurfaces);
1065 Cvar_RegisterVariable(&r_showtris);
1066 Cvar_RegisterVariable(&r_shownormals);
1067 Cvar_RegisterVariable(&r_showlighting);
1068 Cvar_RegisterVariable(&r_showshadowvolumes);
1069 Cvar_RegisterVariable(&r_showcollisionbrushes);
1070 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
1071 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
1072 Cvar_RegisterVariable(&r_showdisabledepthtest);
1073 Cvar_RegisterVariable(&r_drawentities);
1074 Cvar_RegisterVariable(&r_drawviewmodel);
1075 Cvar_RegisterVariable(&r_speeds);
1076 Cvar_RegisterVariable(&r_fullbrights);
1077 Cvar_RegisterVariable(&r_wateralpha);
1078 Cvar_RegisterVariable(&r_dynamic);
1079 Cvar_RegisterVariable(&r_fullbright);
1080 Cvar_RegisterVariable(&r_q1bsp_skymasking);
1081 Cvar_RegisterVariable(&r_textureunits);
1082 Cvar_RegisterVariable(&r_glsl);
1083 Cvar_RegisterVariable(&r_glsl_offsetmapping);
1084 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
1085 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
1086 Cvar_RegisterVariable(&r_glsl_deluxemapping);
1087 Cvar_RegisterVariable(&r_lerpsprites);
1088 Cvar_RegisterVariable(&r_lerpmodels);
1089 Cvar_RegisterVariable(&r_waterscroll);
1090 Cvar_RegisterVariable(&r_bloom);
1091 Cvar_RegisterVariable(&r_bloom_intensity);
1092 Cvar_RegisterVariable(&r_bloom_blur);
1093 Cvar_RegisterVariable(&r_bloom_resolution);
1094 Cvar_RegisterVariable(&r_bloom_power);
1095 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
1096 Cvar_RegisterVariable(&developer_texturelogging);
1097 Cvar_RegisterVariable(&gl_lightmaps);
1098 Cvar_RegisterVariable(&r_test);
1099 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
1100 Cvar_SetValue("r_fullbrights", 0);
1101 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
1104 static vec3_t r_farclip_origin;
1105 static vec3_t r_farclip_direction;
1106 static vec_t r_farclip_directiondist;
1107 static vec_t r_farclip_meshfarclip;
1108 static int r_farclip_directionbit0;
1109 static int r_farclip_directionbit1;
1110 static int r_farclip_directionbit2;
1112 // enlarge farclip to accomodate box
1113 static void R_FarClip_Box(vec3_t mins, vec3_t maxs)
1116 d = (r_farclip_directionbit0 ? mins[0] : maxs[0]) * r_farclip_direction[0]
1117 + (r_farclip_directionbit1 ? mins[1] : maxs[1]) * r_farclip_direction[1]
1118 + (r_farclip_directionbit2 ? mins[2] : maxs[2]) * r_farclip_direction[2];
1119 if (r_farclip_meshfarclip < d)
1120 r_farclip_meshfarclip = d;
1123 // return farclip value
1124 static float R_FarClip(vec3_t origin, vec3_t direction, vec_t startfarclip)
1128 VectorCopy(origin, r_farclip_origin);
1129 VectorCopy(direction, r_farclip_direction);
1130 r_farclip_directiondist = DotProduct(r_farclip_origin, r_farclip_direction);
1131 r_farclip_directionbit0 = r_farclip_direction[0] < 0;
1132 r_farclip_directionbit1 = r_farclip_direction[1] < 0;
1133 r_farclip_directionbit2 = r_farclip_direction[2] < 0;
1134 r_farclip_meshfarclip = r_farclip_directiondist + startfarclip;
1136 if (r_refdef.worldmodel)
1137 R_FarClip_Box(r_refdef.worldmodel->normalmins, r_refdef.worldmodel->normalmaxs);
1138 for (i = 0;i < r_refdef.numentities;i++)
1139 R_FarClip_Box(r_refdef.entities[i]->mins, r_refdef.entities[i]->maxs);
1141 return r_farclip_meshfarclip - r_farclip_directiondist;
1144 extern void R_Textures_Init(void);
1145 extern void GL_Draw_Init(void);
1146 extern void GL_Main_Init(void);
1147 extern void R_Shadow_Init(void);
1148 extern void R_Sky_Init(void);
1149 extern void GL_Surf_Init(void);
1150 extern void R_Crosshairs_Init(void);
1151 extern void R_Light_Init(void);
1152 extern void R_Particles_Init(void);
1153 extern void R_Explosion_Init(void);
1154 extern void gl_backend_init(void);
1155 extern void Sbar_Init(void);
1156 extern void R_LightningBeams_Init(void);
1157 extern void Mod_RenderInit(void);
1159 void Render_Init(void)
1169 R_Crosshairs_Init();
1174 R_LightningBeams_Init();
1183 extern char *ENGINE_EXTENSIONS;
1186 VID_CheckExtensions();
1188 // LordHavoc: report supported extensions
1189 Con_DPrintf("\nengine extensions: %s\n", vm_sv_extensions );
1191 // clear to black (loading plaque will be seen over this)
1193 qglClearColor(0,0,0,1);CHECKGLERROR
1194 qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
1197 int R_CullBox(const vec3_t mins, const vec3_t maxs)
1201 for (i = 0;i < 4;i++)
1208 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1212 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1216 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1220 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1224 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1228 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1232 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1236 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1244 //==================================================================================
1246 static void R_UpdateEntityLighting(entity_render_t *ent)
1248 vec3_t tempdiffusenormal;
1249 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));
1250 VectorClear(ent->modellight_diffuse);
1251 VectorClear(ent->modellight_lightdir);
1252 if ((ent->flags & RENDER_LIGHT) && r_refdef.worldmodel && r_refdef.worldmodel->brush.LightPoint)
1253 r_refdef.worldmodel->brush.LightPoint(r_refdef.worldmodel, ent->origin, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
1255 VectorSet(ent->modellight_ambient, 1, 1, 1);
1256 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
1257 VectorNormalize(ent->modellight_lightdir);
1258 ent->modellight_ambient[0] *= ent->colormod[0] * r_lightmapintensity;
1259 ent->modellight_ambient[1] *= ent->colormod[1] * r_lightmapintensity;
1260 ent->modellight_ambient[2] *= ent->colormod[2] * r_lightmapintensity;
1261 ent->modellight_diffuse[0] *= ent->colormod[0] * r_lightmapintensity;
1262 ent->modellight_diffuse[1] *= ent->colormod[1] * r_lightmapintensity;
1263 ent->modellight_diffuse[2] *= ent->colormod[2] * r_lightmapintensity;
1266 static void R_MarkEntities (void)
1269 entity_render_t *ent;
1271 if (!r_drawentities.integer)
1274 r_refdef.worldentity->visframe = r_framecount;
1275 renderimask = envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : (chase_active.integer ? 0 : RENDER_EXTERIORMODEL);
1276 if (r_refdef.worldmodel && r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs)
1278 // worldmodel can check visibility
1279 for (i = 0;i < r_refdef.numentities;i++)
1281 ent = r_refdef.entities[i];
1282 // some of the renderer still relies on origin...
1283 Matrix4x4_OriginFromMatrix(&ent->matrix, ent->origin);
1284 // some of the renderer still relies on scale...
1285 ent->scale = Matrix4x4_ScaleFromMatrix(&ent->matrix);
1286 if (!(ent->flags & renderimask) && !R_CullBox(ent->mins, ent->maxs) && ((ent->effects & EF_NODEPTHTEST) || r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs(r_refdef.worldmodel, r_worldleafvisible, ent->mins, ent->maxs)))
1288 ent->visframe = r_framecount;
1289 R_UpdateEntityLighting(ent);
1295 // no worldmodel or it can't check visibility
1296 for (i = 0;i < r_refdef.numentities;i++)
1298 ent = r_refdef.entities[i];
1299 // some of the renderer still relies on origin...
1300 Matrix4x4_OriginFromMatrix(&ent->matrix, ent->origin);
1301 // some of the renderer still relies on scale...
1302 ent->scale = Matrix4x4_ScaleFromMatrix(&ent->matrix);
1303 if (!(ent->flags & renderimask) && !R_CullBox(ent->mins, ent->maxs) && (ent->effects & EF_NODEPTHTEST))
1305 ent->visframe = r_framecount;
1306 R_UpdateEntityLighting(ent);
1312 // only used if skyrendermasked, and normally returns false
1313 int R_DrawBrushModelsSky (void)
1316 entity_render_t *ent;
1318 if (!r_drawentities.integer)
1322 for (i = 0;i < r_refdef.numentities;i++)
1324 ent = r_refdef.entities[i];
1325 if (ent->visframe == r_framecount && ent->model && ent->model->DrawSky)
1327 ent->model->DrawSky(ent);
1334 void R_DrawNoModel(entity_render_t *ent);
1335 void R_DrawModels(void)
1338 entity_render_t *ent;
1340 if (!r_drawentities.integer)
1343 for (i = 0;i < r_refdef.numentities;i++)
1345 ent = r_refdef.entities[i];
1346 if (ent->visframe == r_framecount)
1348 renderstats.entities++;
1349 if (ent->model && ent->model->Draw != NULL)
1350 ent->model->Draw(ent);
1357 static void R_SetFrustum(void)
1359 // break apart the view matrix into vectors for various purposes
1360 Matrix4x4_ToVectors(&r_view_matrix, r_viewforward, r_viewleft, r_viewup, r_vieworigin);
1361 VectorNegate(r_viewleft, r_viewright);
1364 frustum[0].normal[0] = 0 - 1.0 / r_refdef.frustum_x;
1365 frustum[0].normal[1] = 0 - 0;
1366 frustum[0].normal[2] = -1 - 0;
1367 frustum[1].normal[0] = 0 + 1.0 / r_refdef.frustum_x;
1368 frustum[1].normal[1] = 0 + 0;
1369 frustum[1].normal[2] = -1 + 0;
1370 frustum[2].normal[0] = 0 - 0;
1371 frustum[2].normal[1] = 0 - 1.0 / r_refdef.frustum_y;
1372 frustum[2].normal[2] = -1 - 0;
1373 frustum[3].normal[0] = 0 + 0;
1374 frustum[3].normal[1] = 0 + 1.0 / r_refdef.frustum_y;
1375 frustum[3].normal[2] = -1 + 0;
1379 zNear = r_nearclip.value;
1380 nudge = 1.0 - 1.0 / (1<<23);
1381 frustum[4].normal[0] = 0 - 0;
1382 frustum[4].normal[1] = 0 - 0;
1383 frustum[4].normal[2] = -1 - -nudge;
1384 frustum[4].dist = 0 - -2 * zNear * nudge;
1385 frustum[5].normal[0] = 0 + 0;
1386 frustum[5].normal[1] = 0 + 0;
1387 frustum[5].normal[2] = -1 + -nudge;
1388 frustum[5].dist = 0 + -2 * zNear * nudge;
1394 frustum[0].normal[0] = m[3] - m[0];
1395 frustum[0].normal[1] = m[7] - m[4];
1396 frustum[0].normal[2] = m[11] - m[8];
1397 frustum[0].dist = m[15] - m[12];
1399 frustum[1].normal[0] = m[3] + m[0];
1400 frustum[1].normal[1] = m[7] + m[4];
1401 frustum[1].normal[2] = m[11] + m[8];
1402 frustum[1].dist = m[15] + m[12];
1404 frustum[2].normal[0] = m[3] - m[1];
1405 frustum[2].normal[1] = m[7] - m[5];
1406 frustum[2].normal[2] = m[11] - m[9];
1407 frustum[2].dist = m[15] - m[13];
1409 frustum[3].normal[0] = m[3] + m[1];
1410 frustum[3].normal[1] = m[7] + m[5];
1411 frustum[3].normal[2] = m[11] + m[9];
1412 frustum[3].dist = m[15] + m[13];
1414 frustum[4].normal[0] = m[3] - m[2];
1415 frustum[4].normal[1] = m[7] - m[6];
1416 frustum[4].normal[2] = m[11] - m[10];
1417 frustum[4].dist = m[15] - m[14];
1419 frustum[5].normal[0] = m[3] + m[2];
1420 frustum[5].normal[1] = m[7] + m[6];
1421 frustum[5].normal[2] = m[11] + m[10];
1422 frustum[5].dist = m[15] + m[14];
1427 VectorMAM(1, r_viewforward, 1.0 / -r_refdef.frustum_x, r_viewleft, frustum[0].normal);
1428 VectorMAM(1, r_viewforward, 1.0 / r_refdef.frustum_x, r_viewleft, frustum[1].normal);
1429 VectorMAM(1, r_viewforward, 1.0 / -r_refdef.frustum_y, r_viewup, frustum[2].normal);
1430 VectorMAM(1, r_viewforward, 1.0 / r_refdef.frustum_y, r_viewup, frustum[3].normal);
1431 VectorCopy(r_viewforward, frustum[4].normal);
1432 VectorNormalize(frustum[0].normal);
1433 VectorNormalize(frustum[1].normal);
1434 VectorNormalize(frustum[2].normal);
1435 VectorNormalize(frustum[3].normal);
1436 frustum[0].dist = DotProduct (r_vieworigin, frustum[0].normal);
1437 frustum[1].dist = DotProduct (r_vieworigin, frustum[1].normal);
1438 frustum[2].dist = DotProduct (r_vieworigin, frustum[2].normal);
1439 frustum[3].dist = DotProduct (r_vieworigin, frustum[3].normal);
1440 frustum[4].dist = DotProduct (r_vieworigin, frustum[4].normal) + r_nearclip.value;
1441 PlaneClassify(&frustum[0]);
1442 PlaneClassify(&frustum[1]);
1443 PlaneClassify(&frustum[2]);
1444 PlaneClassify(&frustum[3]);
1445 PlaneClassify(&frustum[4]);
1447 // LordHavoc: note to all quake engine coders, Quake had a special case
1448 // for 90 degrees which assumed a square view (wrong), so I removed it,
1449 // Quake2 has it disabled as well.
1451 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
1452 //RotatePointAroundVector( frustum[0].normal, r_viewup, r_viewforward, -(90 - r_refdef.fov_x / 2));
1453 //frustum[0].dist = DotProduct (r_vieworigin, frustum[0].normal);
1454 //PlaneClassify(&frustum[0]);
1456 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
1457 //RotatePointAroundVector( frustum[1].normal, r_viewup, r_viewforward, (90 - r_refdef.fov_x / 2));
1458 //frustum[1].dist = DotProduct (r_vieworigin, frustum[1].normal);
1459 //PlaneClassify(&frustum[1]);
1461 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
1462 //RotatePointAroundVector( frustum[2].normal, r_viewleft, r_viewforward, -(90 - r_refdef.fov_y / 2));
1463 //frustum[2].dist = DotProduct (r_vieworigin, frustum[2].normal);
1464 //PlaneClassify(&frustum[2]);
1466 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
1467 //RotatePointAroundVector( frustum[3].normal, r_viewleft, r_viewforward, (90 - r_refdef.fov_y / 2));
1468 //frustum[3].dist = DotProduct (r_vieworigin, frustum[3].normal);
1469 //PlaneClassify(&frustum[3]);
1472 //VectorCopy(r_viewforward, frustum[4].normal);
1473 //frustum[4].dist = DotProduct (r_vieworigin, frustum[4].normal) + r_nearclip.value;
1474 //PlaneClassify(&frustum[4]);
1477 static void R_BlendView(void)
1479 int screenwidth, screenheight;
1483 float texcoord2f[3][8];
1485 // set the (poorly named) screenwidth and screenheight variables to
1486 // a power of 2 at least as large as the screen, these will define the
1487 // size of the texture to allocate
1488 for (screenwidth = 1;screenwidth < vid.width;screenwidth *= 2);
1489 for (screenheight = 1;screenheight < vid.height;screenheight *= 2);
1491 doblend = r_refdef.viewblend[3] >= 0.01f;
1492 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;
1494 if (!dobloom && !doblend)
1497 GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
1499 GL_DepthTest(false);
1500 R_Mesh_Matrix(&identitymatrix);
1501 // vertex coordinates for a quad that covers the screen exactly
1502 vertex3f[0] = 0;vertex3f[1] = 0;vertex3f[2] = 0;
1503 vertex3f[3] = 1;vertex3f[4] = 0;vertex3f[5] = 0;
1504 vertex3f[6] = 1;vertex3f[7] = 1;vertex3f[8] = 0;
1505 vertex3f[9] = 0;vertex3f[10] = 1;vertex3f[11] = 0;
1506 R_Mesh_VertexPointer(vertex3f);
1507 R_Mesh_ColorPointer(NULL);
1508 R_Mesh_ResetTextureState();
1511 int bloomwidth, bloomheight, x, range;
1512 float xoffset, yoffset, r;
1513 renderstats.bloom++;
1514 // allocate textures as needed
1515 if (!r_bloom_texture_screen)
1516 r_bloom_texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", screenwidth, screenheight, NULL, TEXTYPE_RGBA, TEXF_FORCENEAREST | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
1517 if (!r_bloom_texture_bloom)
1518 r_bloom_texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", screenwidth, screenheight, NULL, TEXTYPE_RGBA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
1519 // set bloomwidth and bloomheight to the bloom resolution that will be
1520 // used (often less than the screen resolution for faster rendering)
1521 bloomwidth = min(r_view_width, r_bloom_resolution.integer);
1522 bloomheight = min(r_view_height, bloomwidth * r_view_height / r_view_width);
1523 // set up a texcoord array for the full resolution screen image
1524 // (we have to keep this around to copy back during final render)
1525 texcoord2f[0][0] = 0;
1526 texcoord2f[0][1] = (float)r_view_height / (float)screenheight;
1527 texcoord2f[0][2] = (float)r_view_width / (float)screenwidth;
1528 texcoord2f[0][3] = (float)r_view_height / (float)screenheight;
1529 texcoord2f[0][4] = (float)r_view_width / (float)screenwidth;
1530 texcoord2f[0][5] = 0;
1531 texcoord2f[0][6] = 0;
1532 texcoord2f[0][7] = 0;
1533 // set up a texcoord array for the reduced resolution bloom image
1534 // (which will be additive blended over the screen image)
1535 texcoord2f[1][0] = 0;
1536 texcoord2f[1][1] = (float)bloomheight / (float)screenheight;
1537 texcoord2f[1][2] = (float)bloomwidth / (float)screenwidth;
1538 texcoord2f[1][3] = (float)bloomheight / (float)screenheight;
1539 texcoord2f[1][4] = (float)bloomwidth / (float)screenwidth;
1540 texcoord2f[1][5] = 0;
1541 texcoord2f[1][6] = 0;
1542 texcoord2f[1][7] = 0;
1543 R_Mesh_TexCoordPointer(0, 2, texcoord2f[0]);
1544 R_Mesh_TexBind(0, R_GetTexture(r_bloom_texture_screen));
1545 // copy view into the full resolution screen image texture
1546 GL_ActiveTexture(0);
1548 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);CHECKGLERROR
1549 renderstats.bloom_copypixels += r_view_width * r_view_height;
1550 // now scale it down to the bloom size and raise to a power of itself
1551 // to darken it (this leaves the really bright stuff bright, and
1552 // everything else becomes very dark)
1553 // TODO: optimize with multitexture or GLSL
1555 qglViewport(r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);CHECKGLERROR
1556 GL_BlendFunc(GL_ONE, GL_ZERO);
1557 GL_Color(1, 1, 1, 1);
1558 R_Mesh_Draw(0, 4, 2, polygonelements);
1559 renderstats.bloom_drawpixels += bloomwidth * bloomheight;
1560 // render multiple times with a multiply blendfunc to raise to a power
1561 GL_BlendFunc(GL_DST_COLOR, GL_ZERO);
1562 for (x = 1;x < r_bloom_power.integer;x++)
1564 R_Mesh_Draw(0, 4, 2, polygonelements);
1565 renderstats.bloom_drawpixels += bloomwidth * bloomheight;
1567 // we now have a darkened bloom image in the framebuffer, copy it into
1568 // the bloom image texture for more processing
1569 R_Mesh_TexBind(0, R_GetTexture(r_bloom_texture_bloom));
1570 R_Mesh_TexCoordPointer(0, 2, texcoord2f[2]);
1571 GL_ActiveTexture(0);
1573 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);CHECKGLERROR
1574 renderstats.bloom_copypixels += bloomwidth * bloomheight;
1575 // blend on at multiple vertical offsets to achieve a vertical blur
1576 // TODO: do offset blends using GLSL
1577 range = r_bloom_blur.integer * bloomwidth / 320;
1578 GL_BlendFunc(GL_ONE, GL_ZERO);
1579 for (x = -range;x <= range;x++)
1581 xoffset = 0 / (float)bloomwidth * (float)bloomwidth / (float)screenwidth;
1582 yoffset = x / (float)bloomheight * (float)bloomheight / (float)screenheight;
1583 // compute a texcoord array with the specified x and y offset
1584 texcoord2f[2][0] = xoffset+0;
1585 texcoord2f[2][1] = yoffset+(float)bloomheight / (float)screenheight;
1586 texcoord2f[2][2] = xoffset+(float)bloomwidth / (float)screenwidth;
1587 texcoord2f[2][3] = yoffset+(float)bloomheight / (float)screenheight;
1588 texcoord2f[2][4] = xoffset+(float)bloomwidth / (float)screenwidth;
1589 texcoord2f[2][5] = yoffset+0;
1590 texcoord2f[2][6] = xoffset+0;
1591 texcoord2f[2][7] = yoffset+0;
1592 // this r value looks like a 'dot' particle, fading sharply to
1593 // black at the edges
1594 // (probably not realistic but looks good enough)
1595 r = r_bloom_intensity.value/(range*2+1)*(1 - x*x/(float)(range*range));
1598 GL_Color(r, r, r, 1);
1599 R_Mesh_Draw(0, 4, 2, polygonelements);
1600 renderstats.bloom_drawpixels += bloomwidth * bloomheight;
1601 GL_BlendFunc(GL_ONE, GL_ONE);
1603 // copy the vertically blurred bloom view to a texture
1604 GL_ActiveTexture(0);
1606 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);CHECKGLERROR
1607 renderstats.bloom_copypixels += bloomwidth * bloomheight;
1608 // blend the vertically blurred image at multiple offsets horizontally
1609 // to finish the blur effect
1610 // TODO: do offset blends using GLSL
1611 range = r_bloom_blur.integer * bloomwidth / 320;
1612 GL_BlendFunc(GL_ONE, GL_ZERO);
1613 for (x = -range;x <= range;x++)
1615 xoffset = x / (float)bloomwidth * (float)bloomwidth / (float)screenwidth;
1616 yoffset = 0 / (float)bloomheight * (float)bloomheight / (float)screenheight;
1617 // compute a texcoord array with the specified x and y offset
1618 texcoord2f[2][0] = xoffset+0;
1619 texcoord2f[2][1] = yoffset+(float)bloomheight / (float)screenheight;
1620 texcoord2f[2][2] = xoffset+(float)bloomwidth / (float)screenwidth;
1621 texcoord2f[2][3] = yoffset+(float)bloomheight / (float)screenheight;
1622 texcoord2f[2][4] = xoffset+(float)bloomwidth / (float)screenwidth;
1623 texcoord2f[2][5] = yoffset+0;
1624 texcoord2f[2][6] = xoffset+0;
1625 texcoord2f[2][7] = yoffset+0;
1626 // this r value looks like a 'dot' particle, fading sharply to
1627 // black at the edges
1628 // (probably not realistic but looks good enough)
1629 r = r_bloom_intensity.value/(range*2+1)*(1 - x*x/(float)(range*range));
1632 GL_Color(r, r, r, 1);
1633 R_Mesh_Draw(0, 4, 2, polygonelements);
1634 renderstats.bloom_drawpixels += bloomwidth * bloomheight;
1635 GL_BlendFunc(GL_ONE, GL_ONE);
1637 // copy the blurred bloom view to a texture
1638 GL_ActiveTexture(0);
1640 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);CHECKGLERROR
1641 renderstats.bloom_copypixels += bloomwidth * bloomheight;
1642 // go back to full view area
1643 qglViewport(r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);CHECKGLERROR
1644 // put the original screen image back in place and blend the bloom
1647 GL_BlendFunc(GL_ONE, GL_ZERO);
1648 // do both in one pass if possible
1649 R_Mesh_TexBind(0, R_GetTexture(r_bloom_texture_screen));
1650 R_Mesh_TexCoordPointer(0, 2, texcoord2f[0]);
1651 if (r_textureunits.integer >= 2 && gl_combine.integer)
1653 R_Mesh_TexCombine(1, GL_ADD, GL_ADD, 1, 1);
1654 R_Mesh_TexBind(1, R_GetTexture(r_bloom_texture_bloom));
1655 R_Mesh_TexCoordPointer(1, 2, texcoord2f[1]);
1659 R_Mesh_Draw(0, 4, 2, polygonelements);
1660 renderstats.bloom_drawpixels += r_view_width * r_view_height;
1661 // now blend on the bloom texture
1662 GL_BlendFunc(GL_ONE, GL_ONE);
1663 R_Mesh_TexBind(0, R_GetTexture(r_bloom_texture_bloom));
1664 R_Mesh_TexCoordPointer(0, 2, texcoord2f[1]);
1666 R_Mesh_Draw(0, 4, 2, polygonelements);
1667 renderstats.bloom_drawpixels += r_view_width * r_view_height;
1671 // apply a color tint to the whole view
1672 R_Mesh_ResetTextureState();
1673 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1674 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
1675 R_Mesh_Draw(0, 4, 2, polygonelements);
1679 void R_RenderScene(void);
1681 matrix4x4_t r_waterscrollmatrix;
1688 void R_RenderView(void)
1690 if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
1691 return; //Host_Error ("R_RenderView: NULL worldmodel");
1693 r_view_width = bound(0, r_refdef.width, vid.width);
1694 r_view_height = bound(0, r_refdef.height, vid.height);
1696 r_view_x = bound(0, r_refdef.x, vid.width - r_refdef.width);
1697 r_view_y = bound(0, r_refdef.y, vid.height - r_refdef.height);
1699 r_view_matrix = r_refdef.viewentitymatrix;
1700 GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
1701 r_rtworld = r_shadow_realtime_world.integer;
1702 r_rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
1703 r_rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer;
1704 r_rtdlightshadows = r_rtdlight && (r_rtworld ? r_shadow_realtime_world_dlightshadows.integer : r_shadow_realtime_dlight_shadows.integer) && gl_stencil;
1705 r_lightmapintensity = r_rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
1706 r_polygonfactor = 0;
1707 r_polygonoffset = 0;
1708 r_shadowpolygonfactor = r_polygonfactor + r_shadow_shadow_polygonfactor.value;
1709 r_shadowpolygonoffset = r_polygonoffset + r_shadow_shadow_polygonoffset.value;
1710 if (r_showsurfaces.integer)
1713 r_rtworldshadows = false;
1715 r_rtdlightshadows = false;
1716 r_lightmapintensity = 0;
1719 // GL is weird because it's bottom to top, r_view_y is top to bottom
1721 qglViewport(r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);CHECKGLERROR
1722 GL_Scissor(r_view_x, r_view_y, r_view_width, r_view_height);
1723 GL_ScissorTest(true);
1728 if (r_timereport_active)
1729 R_TimeReport("setup");
1732 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
1733 qglPolygonOffset(r_polygonfactor, r_polygonoffset);CHECKGLERROR
1734 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
1739 qglPolygonOffset(r_polygonfactor, r_polygonoffset);CHECKGLERROR
1740 qglDisable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
1743 if (r_timereport_active)
1744 R_TimeReport("blendview");
1746 GL_Scissor(0, 0, vid.width, vid.height);
1747 GL_ScissorTest(false);
1752 void CSQC_R_ClearScreen (void)
1754 if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
1755 return; //Host_Error ("R_RenderView: NULL worldmodel");
1757 r_view_width = bound(0, r_refdef.width, vid.width);
1758 r_view_height = bound(0, r_refdef.height, vid.height);
1760 r_view_x = bound(0, r_refdef.x, vid.width - r_refdef.width);
1761 r_view_y = bound(0, r_refdef.y, vid.height - r_refdef.height);
1763 r_view_matrix = r_refdef.viewentitymatrix;
1764 GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
1765 r_rtworld = r_shadow_realtime_world.integer;
1766 r_rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
1767 r_rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer;
1768 r_rtdlightshadows = r_rtdlight && (r_rtworld ? r_shadow_realtime_world_dlightshadows.integer : r_shadow_realtime_dlight_shadows.integer) && gl_stencil;
1769 r_lightmapintensity = r_rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
1770 r_polygonfactor = 0;
1771 r_polygonoffset = 0;
1772 r_shadowpolygonfactor = r_polygonfactor + r_shadow_shadow_polygonfactor.value;
1773 r_shadowpolygonoffset = r_polygonoffset + r_shadow_shadow_polygonoffset.value;
1774 if (r_showsurfaces.integer)
1777 r_rtworldshadows = false;
1779 r_rtdlightshadows = false;
1780 r_lightmapintensity = 0;
1783 // GL is weird because it's bottom to top, r_view_y is top to bottom
1785 qglViewport(r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);CHECKGLERROR
1786 GL_Scissor(r_view_x, r_view_y, r_view_width, r_view_height);
1787 GL_ScissorTest(true);
1792 if (r_timereport_active)
1793 R_TimeReport("setup");
1798 void CSQC_R_RenderScene (void)
1801 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
1802 qglPolygonOffset(r_polygonfactor, r_polygonoffset);CHECKGLERROR
1803 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
1808 qglPolygonOffset(r_polygonfactor, r_polygonoffset);CHECKGLERROR
1809 qglDisable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
1812 if (r_timereport_active)
1813 R_TimeReport("blendview");
1815 GL_Scissor(0, 0, vid.width, vid.height);
1816 GL_ScissorTest(false);
1820 extern void R_DrawLightningBeams (void);
1821 extern void VM_AddPolygonsToMeshQueue (void);
1822 void R_RenderScene(void)
1826 // don't let sound skip if going slow
1827 if (r_refdef.extraupdate)
1833 if (gl_support_fragment_shader)
1835 qglUseProgramObjectARB(0);CHECKGLERROR
1838 R_MeshQueue_BeginScene();
1842 r_farclip = R_FarClip(r_vieworigin, r_viewforward, 768.0f) + 256.0f;
1843 nearclip = bound (0.001f, r_nearclip.value, r_farclip - 1.0f);
1845 if (r_rtworldshadows || r_rtdlightshadows)
1846 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_refdef.frustum_x, r_refdef.frustum_y, nearclip);
1848 GL_SetupView_Mode_Perspective(r_refdef.frustum_x, r_refdef.frustum_y, nearclip, r_farclip);
1850 GL_SetupView_Orientation_FromEntity(&r_view_matrix);
1852 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);
1856 R_WorldVisibility();
1857 if (r_timereport_active)
1858 R_TimeReport("worldvis");
1861 if (r_timereport_active)
1862 R_TimeReport("markentity");
1864 R_Shadow_UpdateWorldLightSelection();
1866 if (cl.csqc_vidvars.drawworld)
1868 // don't let sound skip if going slow
1869 if (r_refdef.extraupdate)
1872 if (r_refdef.worldmodel && r_refdef.worldmodel->DrawSky)
1874 r_refdef.worldmodel->DrawSky(r_refdef.worldentity);
1875 if (r_timereport_active)
1876 R_TimeReport("worldsky");
1879 if (R_DrawBrushModelsSky() && r_timereport_active)
1880 R_TimeReport("bmodelsky");
1882 if (r_refdef.worldmodel && r_refdef.worldmodel->Draw)
1884 r_refdef.worldmodel->Draw(r_refdef.worldentity);
1885 if (r_timereport_active)
1886 R_TimeReport("world");
1890 // don't let sound skip if going slow
1891 if (r_refdef.extraupdate)
1895 if (r_timereport_active)
1896 R_TimeReport("models");
1898 // don't let sound skip if going slow
1899 if (r_refdef.extraupdate)
1902 R_ShadowVolumeLighting(false);
1903 if (r_timereport_active)
1904 R_TimeReport("rtlights");
1906 // don't let sound skip if going slow
1907 if (r_refdef.extraupdate)
1910 if (cl.csqc_vidvars.drawworld)
1912 R_DrawLightningBeams();
1913 if (r_timereport_active)
1914 R_TimeReport("lightning");
1917 if (r_timereport_active)
1918 R_TimeReport("particles");
1921 if (r_timereport_active)
1922 R_TimeReport("explosions");
1925 R_MeshQueue_RenderTransparent();
1926 if (r_timereport_active)
1927 R_TimeReport("drawtrans");
1929 if (cl.csqc_vidvars.drawworld)
1932 if (r_timereport_active)
1933 R_TimeReport("coronas");
1935 if(cl.csqc_vidvars.drawcrosshair)
1937 R_DrawWorldCrosshair();
1938 if (r_timereport_active)
1939 R_TimeReport("crosshair");
1942 VM_AddPolygonsToMeshQueue();
1944 R_MeshQueue_Render();
1946 R_MeshQueue_EndScene();
1948 // don't let sound skip if going slow
1949 if (r_refdef.extraupdate)
1953 if (gl_support_fragment_shader)
1955 qglUseProgramObjectARB(0);CHECKGLERROR
1960 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
1963 float *v, *c, f1, f2, diff[3], vertex3f[8*3], color4f[8*4];
1964 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1965 GL_DepthMask(false);
1967 R_Mesh_Matrix(&identitymatrix);
1969 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2];
1970 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
1971 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
1972 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
1973 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
1974 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
1975 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
1976 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
1977 R_FillColors(color, 8, cr, cg, cb, ca);
1980 for (i = 0, v = vertex, c = color;i < 8;i++, v += 4, c += 4)
1982 f2 = VERTEXFOGTABLE(VectorDistance(v, r_vieworigin));
1984 c[0] = c[0] * f1 + fogcolor[0] * f2;
1985 c[1] = c[1] * f1 + fogcolor[1] * f2;
1986 c[2] = c[2] * f1 + fogcolor[2] * f2;
1989 R_Mesh_VertexPointer(vertex3f);
1990 R_Mesh_ColorPointer(color);
1991 R_Mesh_ResetTextureState();
1996 int nomodelelements[24] =
2008 float nomodelvertex3f[6*3] =
2018 float nomodelcolor4f[6*4] =
2020 0.0f, 0.0f, 0.5f, 1.0f,
2021 0.0f, 0.0f, 0.5f, 1.0f,
2022 0.0f, 0.5f, 0.0f, 1.0f,
2023 0.0f, 0.5f, 0.0f, 1.0f,
2024 0.5f, 0.0f, 0.0f, 1.0f,
2025 0.5f, 0.0f, 0.0f, 1.0f
2028 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
2033 // this is only called once per entity so numsurfaces is always 1, and
2034 // surfacelist is always {0}, so this code does not handle batches
2035 R_Mesh_Matrix(&ent->matrix);
2037 if (ent->flags & EF_ADDITIVE)
2039 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2040 GL_DepthMask(false);
2042 else if (ent->alpha < 1)
2044 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2045 GL_DepthMask(false);
2049 GL_BlendFunc(GL_ONE, GL_ZERO);
2052 GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
2053 R_Mesh_VertexPointer(nomodelvertex3f);
2056 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
2057 R_Mesh_ColorPointer(color4f);
2058 f2 = VERTEXFOGTABLE(VectorDistance(ent->origin, r_vieworigin));
2060 for (i = 0, c = color4f;i < 6;i++, c += 4)
2062 c[0] = (c[0] * f1 + fogcolor[0] * f2);
2063 c[1] = (c[1] * f1 + fogcolor[1] * f2);
2064 c[2] = (c[2] * f1 + fogcolor[2] * f2);
2068 else if (ent->alpha != 1)
2070 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
2071 R_Mesh_ColorPointer(color4f);
2072 for (i = 0, c = color4f;i < 6;i++, c += 4)
2076 R_Mesh_ColorPointer(nomodelcolor4f);
2077 R_Mesh_ResetTextureState();
2078 R_Mesh_Draw(0, 6, 8, nomodelelements);
2081 void R_DrawNoModel(entity_render_t *ent)
2083 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
2084 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_vieworigin : ent->origin, R_DrawNoModel_TransparentCallback, ent, 0, r_shadow_rtlight);
2086 // R_DrawNoModelCallback(ent, 0);
2089 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
2091 vec3_t right1, right2, diff, normal;
2093 VectorSubtract (org2, org1, normal);
2095 // calculate 'right' vector for start
2096 VectorSubtract (r_vieworigin, org1, diff);
2097 CrossProduct (normal, diff, right1);
2098 VectorNormalize (right1);
2100 // calculate 'right' vector for end
2101 VectorSubtract (r_vieworigin, org2, diff);
2102 CrossProduct (normal, diff, right2);
2103 VectorNormalize (right2);
2105 vert[ 0] = org1[0] + width * right1[0];
2106 vert[ 1] = org1[1] + width * right1[1];
2107 vert[ 2] = org1[2] + width * right1[2];
2108 vert[ 3] = org1[0] - width * right1[0];
2109 vert[ 4] = org1[1] - width * right1[1];
2110 vert[ 5] = org1[2] - width * right1[2];
2111 vert[ 6] = org2[0] - width * right2[0];
2112 vert[ 7] = org2[1] - width * right2[1];
2113 vert[ 8] = org2[2] - width * right2[2];
2114 vert[ 9] = org2[0] + width * right2[0];
2115 vert[10] = org2[1] + width * right2[1];
2116 vert[11] = org2[2] + width * right2[2];
2119 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
2121 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)
2123 float fog = 0.0f, ifog;
2127 fog = VERTEXFOGTABLE(VectorDistance(origin, r_vieworigin));
2130 R_Mesh_Matrix(&identitymatrix);
2131 GL_BlendFunc(blendfunc1, blendfunc2);
2132 GL_DepthMask(false);
2133 GL_DepthTest(!depthdisable);
2135 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
2136 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
2137 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
2138 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
2139 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
2140 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
2141 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
2142 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
2143 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
2144 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
2145 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
2146 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
2148 R_Mesh_VertexPointer(vertex3f);
2149 R_Mesh_ColorPointer(NULL);
2150 R_Mesh_ResetTextureState();
2151 R_Mesh_TexBind(0, R_GetTexture(texture));
2152 R_Mesh_TexCoordPointer(0, 2, spritetexcoord2f);
2153 GL_Color(cr * ifog, cg * ifog, cb * ifog, ca);
2154 R_Mesh_Draw(0, 4, 2, polygonelements);
2156 if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
2158 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
2159 GL_BlendFunc(blendfunc1, GL_ONE);
2160 GL_Color(fogcolor[0] * fog, fogcolor[1] * fog, fogcolor[2] * fog, ca);
2161 R_Mesh_Draw(0, 4, 2, polygonelements);
2165 int R_Mesh_AddVertex3f(rmesh_t *mesh, const float *v)
2169 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
2170 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
2172 if (i == mesh->numvertices)
2174 if (mesh->numvertices < mesh->maxvertices)
2176 VectorCopy(v, vertex3f);
2177 mesh->numvertices++;
2179 return mesh->numvertices;
2185 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
2189 element[0] = R_Mesh_AddVertex3f(mesh, vertex3f);vertex3f += 3;
2190 element[1] = R_Mesh_AddVertex3f(mesh, vertex3f);vertex3f += 3;
2191 e = mesh->element3i + mesh->numtriangles * 3;
2192 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
2194 element[2] = R_Mesh_AddVertex3f(mesh, vertex3f);
2195 if (mesh->numtriangles < mesh->maxtriangles)
2200 mesh->numtriangles++;
2202 element[1] = element[2];
2206 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
2208 int planenum, planenum2;
2211 mplane_t *plane, *plane2;
2212 float temppoints[2][256*3];
2213 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
2217 PolygonF_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->normal[3], 1024.0*1024.0*1024.0);
2218 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
2220 if (planenum2 == planenum)
2222 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);
2225 if (tempnumpoints < 3)
2227 // generate elements forming a triangle fan for this polygon
2228 R_Mesh_AddPolygon3f(mesh, tempnumpoints, temppoints[w]);
2232 static void R_DrawCollisionBrush(const colbrushf_t *brush)
2235 R_Mesh_VertexPointer(brush->points->v);
2236 i = (int)(((size_t)brush) / sizeof(colbrushf_t));
2237 GL_Color((i & 31) * (1.0f / 32.0f), ((i >> 5) & 31) * (1.0f / 32.0f), ((i >> 10) & 31) * (1.0f / 32.0f), 0.2f);
2238 GL_LockArrays(0, brush->numpoints);
2239 R_Mesh_Draw(0, brush->numpoints, brush->numtriangles, brush->elements);
2240 GL_LockArrays(0, 0);
2243 static void R_DrawCollisionSurface(const entity_render_t *ent, const msurface_t *surface)
2246 if (!surface->num_collisiontriangles)
2248 R_Mesh_VertexPointer(surface->data_collisionvertex3f);
2249 i = (int)(((size_t)surface) / sizeof(msurface_t));
2250 GL_Color((i & 31) * (1.0f / 32.0f), ((i >> 5) & 31) * (1.0f / 32.0f), ((i >> 10) & 31) * (1.0f / 32.0f), 0.2f);
2251 GL_LockArrays(0, surface->num_collisionvertices);
2252 R_Mesh_Draw(0, surface->num_collisionvertices, surface->num_collisiontriangles, surface->data_collisionelement3i);
2253 GL_LockArrays(0, 0);
2256 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)
2258 texturelayer_t *layer;
2259 layer = t->currentlayers + t->currentnumlayers++;
2261 layer->depthmask = depthmask;
2262 layer->blendfunc1 = blendfunc1;
2263 layer->blendfunc2 = blendfunc2;
2264 layer->texture = texture;
2265 layer->texmatrix = *matrix;
2266 layer->color[0] = r;
2267 layer->color[1] = g;
2268 layer->color[2] = b;
2269 layer->color[3] = a;
2272 void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
2274 // FIXME: identify models using a better check than ent->model->brush.shadowmesh
2275 //int lightmode = ((ent->effects & EF_FULLBRIGHT) || ent->model->brush.shadowmesh) ? 0 : 2;
2278 texture_t *texture = t;
2279 model_t *model = ent->model;
2280 int s = ent->skinnum;
2281 if ((unsigned int)s >= (unsigned int)model->numskins)
2283 if (model->skinscenes)
2285 if (model->skinscenes[s].framecount > 1)
2286 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
2288 s = model->skinscenes[s].firstframe;
2291 t = t + s * model->num_surfaces;
2293 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];
2294 texture->currentframe = t;
2297 t->currentmaterialflags = t->basematerialflags;
2298 t->currentalpha = ent->alpha;
2299 if (t->basematerialflags & MATERIALFLAG_WATERALPHA)
2300 t->currentalpha *= r_wateralpha.value;
2301 if (!(ent->flags & RENDER_LIGHT))
2302 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
2303 if (ent->effects & EF_ADDITIVE)
2304 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_TRANSPARENT;
2305 else if (t->currentalpha < 1)
2306 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_TRANSPARENT;
2307 if (ent->effects & EF_NODEPTHTEST)
2308 t->currentmaterialflags |= MATERIALFLAG_NODEPTHTEST;
2309 if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
2310 t->currenttexmatrix = r_waterscrollmatrix;
2312 t->currenttexmatrix = identitymatrix;
2314 t->colormapping = VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f);
2315 t->basetexture = (!t->colormapping && t->skin.merged) ? t->skin.merged : t->skin.base;
2316 t->glosstexture = r_texture_white;
2317 t->specularpower = 8;
2318 t->specularscale = 0;
2319 if (r_shadow_gloss.integer > 0)
2323 if (r_shadow_glossintensity.value > 0)
2325 t->glosstexture = t->skin.gloss;
2326 t->specularscale = r_shadow_glossintensity.value;
2329 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
2330 t->specularscale = r_shadow_gloss2intensity.value;
2333 t->currentnumlayers = 0;
2334 if (!(t->currentmaterialflags & MATERIALFLAG_NODRAW))
2336 if (gl_lightmaps.integer)
2337 R_Texture_AddLayer(t, true, GL_ONE, GL_ZERO, TEXTURELAYERTYPE_LITTEXTURE_MULTIPASS, r_texture_white, &identitymatrix, 1, 1, 1, 1);
2338 else if (!(t->currentmaterialflags & MATERIALFLAG_SKY))
2340 int blendfunc1, blendfunc2, depthmask;
2341 if (t->currentmaterialflags & MATERIALFLAG_ADD)
2343 blendfunc1 = GL_SRC_ALPHA;
2344 blendfunc2 = GL_ONE;
2346 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
2348 blendfunc1 = GL_SRC_ALPHA;
2349 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
2351 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
2353 blendfunc1 = t->customblendfunc[0];
2354 blendfunc2 = t->customblendfunc[1];
2358 blendfunc1 = GL_ONE;
2359 blendfunc2 = GL_ZERO;
2361 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
2362 if (t->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL))
2364 rtexture_t *currentbasetexture;
2366 if (fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED))
2367 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
2368 currentbasetexture = (VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) < (1.0f / 1048576.0f) && t->skin.merged) ? t->skin.merged : t->skin.base;
2369 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2371 // fullbright is not affected by r_lightmapintensity
2372 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
2373 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->skin.pants)
2374 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.pants, &t->currenttexmatrix, ent->colormap_pantscolor[0] * ent->colormod[0], ent->colormap_pantscolor[1] * ent->colormod[1], ent->colormap_pantscolor[2] * ent->colormod[2], t->currentalpha);
2375 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->skin.shirt)
2376 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);
2382 // q3bsp has no lightmap updates, so the lightstylevalue that
2383 // would normally be baked into the lightmap must be
2384 // applied to the color
2385 if (ent->model->type == mod_brushq3)
2386 colorscale *= r_refdef.lightstylevalue[0] * (1.0f / 256.0f);
2387 colorscale *= r_lightmapintensity;
2388 if (r_textureunits.integer >= 2 && gl_combine.integer)
2389 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);
2390 else if ((t->currentmaterialflags & MATERIALFLAG_BLENDED) == 0)
2391 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);
2393 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);
2394 if (r_ambient.value >= (1.0f/64.0f))
2395 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);
2396 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->skin.pants)
2398 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);
2399 if (r_ambient.value >= (1.0f/64.0f))
2400 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);
2402 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->skin.shirt)
2404 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);
2405 if (r_ambient.value >= (1.0f/64.0f))
2406 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);
2409 if (t->skin.glow != NULL)
2410 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.glow, &t->currenttexmatrix, 1, 1, 1, t->currentalpha);
2411 if (fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
2413 // if this is opaque use alpha blend which will darken the earlier
2416 // if this is an alpha blended material, all the earlier passes
2417 // were darkened by fog already, so we only need to add the fog
2418 // color ontop through the fog mask texture
2420 // if this is an additive blended material, all the earlier passes
2421 // were darkened by fog already, and we should not add fog color
2422 // (because the background was not darkened, there is no fog color
2423 // that was lost behind it).
2424 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, (t->currentmaterialflags & MATERIALFLAG_BLENDED) ? GL_ONE : GL_ONE_MINUS_SRC_ALPHA, TEXTURELAYERTYPE_FOG, t->skin.fog, &identitymatrix, fogcolor[0], fogcolor[1], fogcolor[2], t->currentalpha);
2431 void R_UpdateAllTextureInfo(entity_render_t *ent)
2435 for (i = 0;i < ent->model->num_textures;i++)
2436 R_UpdateTextureInfo(ent, ent->model->data_textures + i);
2439 int rsurface_array_size = 0;
2440 float *rsurface_array_modelvertex3f = NULL;
2441 float *rsurface_array_modelsvector3f = NULL;
2442 float *rsurface_array_modeltvector3f = NULL;
2443 float *rsurface_array_modelnormal3f = NULL;
2444 float *rsurface_array_deformedvertex3f = NULL;
2445 float *rsurface_array_deformedsvector3f = NULL;
2446 float *rsurface_array_deformedtvector3f = NULL;
2447 float *rsurface_array_deformednormal3f = NULL;
2448 float *rsurface_array_color4f = NULL;
2449 float *rsurface_array_texcoord3f = NULL;
2451 void R_Mesh_ResizeArrays(int newvertices)
2454 if (rsurface_array_size >= newvertices)
2456 if (rsurface_array_modelvertex3f)
2457 Mem_Free(rsurface_array_modelvertex3f);
2458 rsurface_array_size = (newvertices + 1023) & ~1023;
2459 base = (float *)Mem_Alloc(r_main_mempool, rsurface_array_size * sizeof(float[31]));
2460 rsurface_array_modelvertex3f = base + rsurface_array_size * 0;
2461 rsurface_array_modelsvector3f = base + rsurface_array_size * 3;
2462 rsurface_array_modeltvector3f = base + rsurface_array_size * 6;
2463 rsurface_array_modelnormal3f = base + rsurface_array_size * 9;
2464 rsurface_array_deformedvertex3f = base + rsurface_array_size * 12;
2465 rsurface_array_deformedsvector3f = base + rsurface_array_size * 15;
2466 rsurface_array_deformedtvector3f = base + rsurface_array_size * 18;
2467 rsurface_array_deformednormal3f = base + rsurface_array_size * 21;
2468 rsurface_array_texcoord3f = base + rsurface_array_size * 24;
2469 rsurface_array_color4f = base + rsurface_array_size * 27;
2472 float *rsurface_modelvertex3f;
2473 float *rsurface_modelsvector3f;
2474 float *rsurface_modeltvector3f;
2475 float *rsurface_modelnormal3f;
2476 float *rsurface_vertex3f;
2477 float *rsurface_svector3f;
2478 float *rsurface_tvector3f;
2479 float *rsurface_normal3f;
2480 float *rsurface_lightmapcolor4f;
2481 vec3_t rsurface_modelorg;
2482 qboolean rsurface_generatedvertex;
2483 const entity_render_t *rsurface_entity;
2484 const model_t *rsurface_model;
2485 texture_t *rsurface_texture;
2486 rtexture_t *rsurface_lightmaptexture;
2487 rsurfmode_t rsurface_mode;
2488 texture_t *rsurface_glsl_texture;
2489 qboolean rsurface_glsl_uselightmap;
2491 void RSurf_ActiveEntity(const entity_render_t *ent)
2493 Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, rsurface_modelorg);
2494 rsurface_entity = ent;
2495 rsurface_model = ent->model;
2496 if (rsurface_array_size < rsurface_model->surfmesh.num_vertices)
2497 R_Mesh_ResizeArrays(rsurface_model->surfmesh.num_vertices);
2498 R_Mesh_Matrix(&ent->matrix);
2499 Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, rsurface_modelorg);
2500 if ((rsurface_entity->frameblend[0].lerp != 1 || rsurface_entity->frameblend[0].frame != 0) && (rsurface_model->surfmesh.data_morphvertex3f || rsurface_model->surfmesh.data_vertexboneweights))
2502 rsurface_modelvertex3f = rsurface_array_modelvertex3f;
2503 rsurface_modelsvector3f = NULL;
2504 rsurface_modeltvector3f = NULL;
2505 rsurface_modelnormal3f = NULL;
2506 Mod_Alias_GetMesh_Vertex3f(rsurface_model, rsurface_entity->frameblend, rsurface_array_modelvertex3f);
2507 rsurface_generatedvertex = true;
2511 rsurface_modelvertex3f = rsurface_model->surfmesh.data_vertex3f;
2512 rsurface_modelsvector3f = rsurface_model->surfmesh.data_svector3f;
2513 rsurface_modeltvector3f = rsurface_model->surfmesh.data_tvector3f;
2514 rsurface_modelnormal3f = rsurface_model->surfmesh.data_normal3f;
2515 rsurface_generatedvertex = false;
2517 rsurface_vertex3f = rsurface_modelvertex3f;
2518 rsurface_svector3f = rsurface_modelsvector3f;
2519 rsurface_tvector3f = rsurface_modeltvector3f;
2520 rsurface_normal3f = rsurface_modelnormal3f;
2521 rsurface_mode = RSURFMODE_NONE;
2522 rsurface_lightmaptexture = NULL;
2523 rsurface_texture = NULL;
2524 rsurface_glsl_texture = NULL;
2525 rsurface_glsl_uselightmap = false;
2528 void RSurf_CleanUp(void)
2531 if (rsurface_mode == RSURFMODE_GLSL)
2533 qglUseProgramObjectARB(0);CHECKGLERROR
2535 GL_AlphaTest(false);
2536 rsurface_mode = RSURFMODE_NONE;
2537 rsurface_lightmaptexture = NULL;
2538 rsurface_texture = NULL;
2539 rsurface_glsl_texture = NULL;
2540 rsurface_glsl_uselightmap = false;
2543 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, msurface_t **texturesurfacelist)
2545 if (rsurface_generatedvertex)
2547 if (rsurface_texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
2548 generatetangents = true;
2549 if (generatetangents)
2550 generatenormals = true;
2551 if (generatenormals && !rsurface_modelnormal3f)
2553 rsurface_normal3f = rsurface_modelnormal3f = rsurface_array_modelnormal3f;
2554 Mod_BuildNormals(0, rsurface_model->surfmesh.num_vertices, rsurface_model->surfmesh.num_triangles, rsurface_modelvertex3f, rsurface_model->surfmesh.data_element3i, rsurface_array_modelnormal3f, r_smoothnormals_areaweighting.integer);
2556 if (generatetangents && !rsurface_modelsvector3f)
2558 rsurface_svector3f = rsurface_modelsvector3f = rsurface_array_modelsvector3f;
2559 rsurface_tvector3f = rsurface_modeltvector3f = rsurface_array_modeltvector3f;
2560 Mod_BuildTextureVectorsFromNormals(0, rsurface_model->surfmesh.num_vertices, rsurface_model->surfmesh.num_triangles, rsurface_modelvertex3f, rsurface_model->surfmesh.data_texcoordtexture2f, rsurface_modelnormal3f, rsurface_model->surfmesh.data_element3i, rsurface_array_modelsvector3f, rsurface_array_modeltvector3f, r_smoothnormals_areaweighting.integer);
2563 if (rsurface_texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
2565 int texturesurfaceindex;
2566 float center[3], forward[3], right[3], up[3], v[4][3];
2567 matrix4x4_t matrix1, imatrix1;
2568 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_viewforward, forward);
2569 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_viewright, right);
2570 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_viewup, up);
2571 // make deformed versions of only the vertices used by the specified surfaces
2572 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2575 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2576 // a single autosprite surface can contain multiple sprites...
2577 for (j = 0;j < surface->num_vertices - 3;j += 4)
2579 VectorClear(center);
2580 for (i = 0;i < 4;i++)
2581 VectorAdd(center, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
2582 VectorScale(center, 0.25f, center);
2583 if (rsurface_texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE2)
2585 forward[0] = rsurface_modelorg[0] - center[0];
2586 forward[1] = rsurface_modelorg[1] - center[1];
2588 VectorNormalize(forward);
2589 right[0] = forward[1];
2590 right[1] = -forward[0];
2592 VectorSet(up, 0, 0, 1);
2594 // FIXME: calculate vectors from triangle edges instead of using texture vectors as an easy way out?
2595 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);
2596 Matrix4x4_Invert_Simple(&imatrix1, &matrix1);
2597 for (i = 0;i < 4;i++)
2598 Matrix4x4_Transform(&imatrix1, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, v[i]);
2599 for (i = 0;i < 4;i++)
2600 VectorMAMAMAM(1, center, v[i][0], forward, v[i][1], right, v[i][2], up, rsurface_array_modelvertex3f + (surface->num_firstvertex+i+j) * 3);
2602 Mod_BuildNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface_modelvertex3f, rsurface_model->surfmesh.data_element3i + surface->num_firsttriangle * 3, rsurface_array_deformednormal3f, r_smoothnormals_areaweighting.integer);
2603 Mod_BuildTextureVectorsFromNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface_modelvertex3f, rsurface_model->surfmesh.data_texcoordtexture2f, rsurface_array_deformednormal3f, rsurface_model->surfmesh.data_element3i + surface->num_firsttriangle * 3, rsurface_array_deformedsvector3f, rsurface_array_deformedtvector3f, r_smoothnormals_areaweighting.integer);
2605 rsurface_vertex3f = rsurface_array_deformedvertex3f;
2606 rsurface_svector3f = rsurface_array_deformedsvector3f;
2607 rsurface_tvector3f = rsurface_array_deformedtvector3f;
2608 rsurface_normal3f = rsurface_array_deformednormal3f;
2610 R_Mesh_VertexPointer(rsurface_vertex3f);
2613 static void RSurf_Draw(const msurface_t *surface)
2615 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2616 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
2619 static void RSurf_DrawLightmap(const msurface_t *surface, float r, float g, float b, float a, int lightmode, qboolean applycolor, qboolean applyfog)
2627 vec3_t ambientcolor;
2628 vec3_t diffusecolor;
2630 VectorCopy(rsurface_entity->modellight_lightdir, lightdir);
2631 ambientcolor[0] = rsurface_entity->modellight_ambient[0] * r * 0.5f;
2632 ambientcolor[1] = rsurface_entity->modellight_ambient[1] * g * 0.5f;
2633 ambientcolor[2] = rsurface_entity->modellight_ambient[2] * b * 0.5f;
2634 diffusecolor[0] = rsurface_entity->modellight_diffuse[0] * r * 0.5f;
2635 diffusecolor[1] = rsurface_entity->modellight_diffuse[1] * g * 0.5f;
2636 diffusecolor[2] = rsurface_entity->modellight_diffuse[2] * b * 0.5f;
2637 if (VectorLength2(diffusecolor) > 0)
2639 int numverts = surface->num_vertices;
2640 v = rsurface_vertex3f + 3 * surface->num_firstvertex;
2641 c2 = rsurface_normal3f + 3 * surface->num_firstvertex;
2642 c = rsurface_array_color4f + 4 * surface->num_firstvertex;
2643 // q3-style directional shading
2644 for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
2646 if ((f = DotProduct(c2, lightdir)) > 0)
2647 VectorMA(ambientcolor, f, diffusecolor, c);
2649 VectorCopy(ambientcolor, c);
2657 rsurface_lightmapcolor4f = rsurface_array_color4f;
2661 r = ambientcolor[0];
2662 g = ambientcolor[1];
2663 b = ambientcolor[2];
2664 rsurface_lightmapcolor4f = NULL;
2667 else if (lightmode >= 1)
2669 if (surface->lightmapinfo && surface->lightmapinfo->stainsamples)
2671 for (i = 0, c = rsurface_array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
2673 if (surface->lightmapinfo->samples)
2675 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface_model->surfmesh.data_lightmapoffsets + surface->num_firstvertex)[i];
2676 float scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
2677 VectorScale(lm, scale, c);
2678 if (surface->lightmapinfo->styles[1] != 255)
2680 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
2682 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
2683 VectorMA(c, scale, lm, c);
2684 if (surface->lightmapinfo->styles[2] != 255)
2687 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
2688 VectorMA(c, scale, lm, c);
2689 if (surface->lightmapinfo->styles[3] != 255)
2692 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
2693 VectorMA(c, scale, lm, c);
2701 rsurface_lightmapcolor4f = rsurface_array_color4f;
2704 rsurface_lightmapcolor4f = rsurface_model->surfmesh.data_lightmapcolor4f;
2707 rsurface_lightmapcolor4f = NULL;
2710 if (rsurface_lightmapcolor4f)
2712 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)
2714 f = 1 - VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
2723 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)
2725 f = 1 - VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
2732 rsurface_lightmapcolor4f = rsurface_array_color4f;
2734 if (applycolor && rsurface_lightmapcolor4f)
2736 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)
2743 rsurface_lightmapcolor4f = rsurface_array_color4f;
2745 R_Mesh_ColorPointer(rsurface_lightmapcolor4f);
2746 GL_Color(r, g, b, a);
2747 RSurf_Draw(surface);
2750 static void R_DrawTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist)
2752 int texturesurfaceindex;
2754 qboolean applycolor;
2757 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_NODRAW)
2759 r_shadow_rtlight = NULL;
2760 renderstats.entities_surfaces += texturenumsurfaces;
2761 // FIXME: identify models using a better check than rsurface_model->brush.shadowmesh
2762 lightmode = ((rsurface_entity->effects & EF_FULLBRIGHT) || rsurface_model->brush.shadowmesh) ? 0 : 2;
2764 GL_DepthTest(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
2765 if ((rsurface_texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (rsurface_entity->flags & RENDER_NOCULLFACE))
2767 qglDisable(GL_CULL_FACE);CHECKGLERROR
2769 if (r_showsurfaces.integer)
2771 if (rsurface_mode != RSURFMODE_SHOWSURFACES)
2773 rsurface_mode = RSURFMODE_SHOWSURFACES;
2775 GL_BlendFunc(GL_ONE, GL_ZERO);
2776 R_Mesh_ColorPointer(NULL);
2777 R_Mesh_ResetTextureState();
2779 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
2780 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2782 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2783 int k = (int)(((size_t)surface) / sizeof(msurface_t));
2784 GL_Color((k & 15) * (1.0f / 16.0f), ((k >> 4) & 15) * (1.0f / 16.0f), ((k >> 8) & 15) * (1.0f / 16.0f), 0.2f);
2785 RSurf_Draw(surface);
2788 else if (rsurface_texture->currentmaterialflags & MATERIALFLAG_SKY)
2790 // transparent sky would be ridiculous
2791 if (!(rsurface_texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
2793 if (rsurface_mode != RSURFMODE_SKY)
2795 if (rsurface_mode == RSURFMODE_GLSL)
2797 qglUseProgramObjectARB(0);CHECKGLERROR
2799 rsurface_mode = RSURFMODE_SKY;
2802 skyrendernow = false;
2804 // restore entity matrix
2805 R_Mesh_Matrix(&rsurface_entity->matrix);
2808 // LordHavoc: HalfLife maps have freaky skypolys so don't use
2809 // skymasking on them, and Quake3 never did sky masking (unlike
2810 // software Quake and software Quake2), so disable the sky masking
2811 // in Quake3 maps as it causes problems with q3map2 sky tricks,
2812 // and skymasking also looks very bad when noclipping outside the
2813 // level, so don't use it then either.
2814 if (rsurface_model->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_worldnovis)
2816 GL_Color(fogcolor[0], fogcolor[1], fogcolor[2], 1);
2817 R_Mesh_ColorPointer(NULL);
2818 R_Mesh_ResetTextureState();
2819 if (skyrendermasked)
2821 // depth-only (masking)
2822 GL_ColorMask(0,0,0,0);
2823 // just to make sure that braindead drivers don't draw
2824 // anything despite that colormask...
2825 GL_BlendFunc(GL_ZERO, GL_ONE);
2830 GL_BlendFunc(GL_ONE, GL_ZERO);
2834 // LordHavoc: HalfLife maps have freaky skypolys so don't use
2835 // skymasking on them, and Quake3 never did sky masking (unlike
2836 // software Quake and software Quake2), so disable the sky masking
2837 // in Quake3 maps as it causes problems with q3map2 sky tricks,
2838 // and skymasking also looks very bad when noclipping outside the
2839 // level, so don't use it then either.
2840 if (rsurface_model->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_worldnovis)
2842 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
2843 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2845 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2846 RSurf_Draw(surface);
2848 if (skyrendermasked)
2849 GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
2853 else if (rsurface_texture->currentnumlayers && r_glsl.integer && gl_support_fragment_shader)
2855 if (rsurface_mode != RSURFMODE_GLSL)
2857 rsurface_mode = RSURFMODE_GLSL;
2858 rsurface_glsl_texture = NULL;
2859 rsurface_glsl_uselightmap = false;
2860 R_Mesh_ResetTextureState();
2862 if (rsurface_glsl_texture != rsurface_texture || rsurface_glsl_uselightmap != (rsurface_lightmaptexture != NULL))
2864 rsurface_glsl_texture = rsurface_texture;
2865 rsurface_glsl_uselightmap = rsurface_lightmaptexture != NULL;
2866 GL_BlendFunc(rsurface_texture->currentlayers[0].blendfunc1, rsurface_texture->currentlayers[0].blendfunc2);
2867 GL_DepthMask(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_BLENDED));
2868 GL_Color(rsurface_entity->colormod[0], rsurface_entity->colormod[1], rsurface_entity->colormod[2], rsurface_texture->currentalpha);
2869 R_SetupSurfaceShader(vec3_origin, lightmode == 2);
2870 //permutation_deluxemapping = permutation_lightmapping = R_SetupSurfaceShader(vec3_origin, lightmode == 2, false);
2871 //if (r_glsl_deluxemapping.integer)
2872 // permutation_deluxemapping = R_SetupSurfaceShader(vec3_origin, lightmode == 2, true);
2873 R_Mesh_TexCoordPointer(0, 2, rsurface_model->surfmesh.data_texcoordtexture2f);
2874 R_Mesh_TexCoordPointer(4, 2, rsurface_model->surfmesh.data_texcoordlightmap2f);
2875 GL_AlphaTest((rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2877 if (!r_glsl_permutation)
2879 RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
2880 R_Mesh_TexCoordPointer(1, 3, rsurface_svector3f);
2881 R_Mesh_TexCoordPointer(2, 3, rsurface_tvector3f);
2882 R_Mesh_TexCoordPointer(3, 3, rsurface_normal3f);
2883 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2885 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
2886 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
2887 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
2888 R_Mesh_ColorPointer(NULL);
2890 else if (rsurface_lightmaptexture)
2892 R_Mesh_TexBind(7, R_GetTexture(rsurface_lightmaptexture));
2893 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
2894 R_Mesh_TexBind(8, R_GetTexture(texturesurfacelist[0]->deluxemaptexture));
2895 R_Mesh_ColorPointer(NULL);
2899 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
2900 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
2901 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
2902 R_Mesh_ColorPointer(rsurface_model->surfmesh.data_lightmapcolor4f);
2904 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2906 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2907 RSurf_Draw(surface);
2910 else if (rsurface_texture->currentnumlayers)
2913 const texturelayer_t *layer;
2915 if (rsurface_mode != RSURFMODE_MULTIPASS)
2917 if (rsurface_mode == RSURFMODE_GLSL)
2919 qglUseProgramObjectARB(0);CHECKGLERROR
2921 rsurface_mode = RSURFMODE_MULTIPASS;
2923 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
2924 for (layerindex = 0, layer = rsurface_texture->currentlayers;layerindex < rsurface_texture->currentnumlayers;layerindex++, layer++)
2927 int layertexrgbscale;
2928 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2930 if (layerindex == 0)
2934 GL_AlphaTest(false);
2935 qglDepthFunc(GL_EQUAL);CHECKGLERROR
2938 GL_DepthMask(layer->depthmask);
2939 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
2940 if ((layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2) && (gl_combine.integer || layer->depthmask))
2942 layertexrgbscale = 4;
2943 VectorScale(layer->color, 0.25f, layercolor);
2945 else if ((layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1) && (gl_combine.integer || layer->depthmask))
2947 layertexrgbscale = 2;
2948 VectorScale(layer->color, 0.5f, layercolor);
2952 layertexrgbscale = 1;
2953 VectorScale(layer->color, 1.0f, layercolor);
2955 layercolor[3] = layer->color[3];
2956 R_Mesh_ColorPointer(NULL);
2957 GL_Color(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
2958 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
2959 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
2960 switch (layer->type)
2962 case TEXTURELAYERTYPE_LITTEXTURE_COMBINE:
2963 memset(&m, 0, sizeof(m));
2964 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordlightmap2f;
2965 m.tex[1] = R_GetTexture(layer->texture);
2966 m.texmatrix[1] = layer->texmatrix;
2967 m.texrgbscale[1] = layertexrgbscale;
2968 m.pointer_texcoord[1] = rsurface_model->surfmesh.data_texcoordtexture2f;
2969 R_Mesh_TextureState(&m);
2972 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2974 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2975 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2976 RSurf_DrawLightmap(surface, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 2, applycolor, applyfog);
2979 else if (rsurface_lightmaptexture)
2981 R_Mesh_TexBind(0, R_GetTexture(rsurface_lightmaptexture));
2982 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2984 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2985 RSurf_DrawLightmap(surface, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, applyfog);
2990 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2991 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2993 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2994 RSurf_DrawLightmap(surface, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 1, applycolor, applyfog);
2998 case TEXTURELAYERTYPE_LITTEXTURE_MULTIPASS:
2999 memset(&m, 0, sizeof(m));
3000 m.tex[0] = R_GetTexture(layer->texture);
3001 m.texmatrix[0] = layer->texmatrix;
3002 m.texrgbscale[0] = layertexrgbscale;
3003 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordlightmap2f;
3004 R_Mesh_TextureState(&m);
3007 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3009 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3010 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
3011 RSurf_DrawLightmap(surface, 1, 1, 1, 1, 2, false, false);
3014 else if (rsurface_lightmaptexture)
3016 R_Mesh_TexBind(0, R_GetTexture(rsurface_lightmaptexture));
3017 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3019 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3020 RSurf_DrawLightmap(surface, 1, 1, 1, 1, 0, false, false);
3025 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
3026 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3028 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3029 RSurf_DrawLightmap(surface, 1, 1, 1, 1, 1, false, false);
3032 GL_LockArrays(0, 0);
3033 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
3034 memset(&m, 0, sizeof(m));
3035 m.tex[0] = R_GetTexture(layer->texture);
3036 m.texmatrix[0] = layer->texmatrix;
3037 m.texrgbscale[0] = layertexrgbscale;
3038 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3039 R_Mesh_TextureState(&m);
3040 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3042 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3043 RSurf_DrawLightmap(surface, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, false);
3046 case TEXTURELAYERTYPE_LITTEXTURE_VERTEX:
3047 memset(&m, 0, sizeof(m));
3048 m.tex[0] = R_GetTexture(layer->texture);
3049 m.texmatrix[0] = layer->texmatrix;
3050 m.texrgbscale[0] = layertexrgbscale;
3051 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3052 R_Mesh_TextureState(&m);
3055 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3057 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3058 RSurf_DrawLightmap(surface, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 2, applycolor, applyfog);
3063 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3065 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3066 RSurf_DrawLightmap(surface, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 1, applycolor, applyfog);
3070 case TEXTURELAYERTYPE_TEXTURE:
3071 memset(&m, 0, sizeof(m));
3072 m.tex[0] = R_GetTexture(layer->texture);
3073 m.texmatrix[0] = layer->texmatrix;
3074 m.texrgbscale[0] = layertexrgbscale;
3075 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3076 R_Mesh_TextureState(&m);
3077 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3079 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3080 RSurf_DrawLightmap(surface, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, applyfog);
3083 case TEXTURELAYERTYPE_FOG:
3084 R_Mesh_ColorPointer(rsurface_array_color4f);
3087 memset(&m, 0, sizeof(m));
3088 m.tex[0] = R_GetTexture(layer->texture);
3089 m.texmatrix[0] = layer->texmatrix;
3090 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3091 R_Mesh_TextureState(&m);
3094 R_Mesh_ResetTextureState();
3095 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3099 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3100 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)
3102 f = VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
3103 c[0] = layercolor[0];
3104 c[1] = layercolor[1];
3105 c[2] = layercolor[2];
3106 c[3] = f * layercolor[3];
3108 RSurf_Draw(surface);
3112 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
3114 GL_LockArrays(0, 0);
3115 // if trying to do overbright on first pass of an opaque surface
3116 // when combine is not supported, brighten as a post process
3117 if (layertexrgbscale > 1 && !gl_combine.integer && layer->depthmask)
3120 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
3121 R_Mesh_ColorPointer(NULL);
3122 GL_Color(1, 1, 1, 1);
3123 R_Mesh_ResetTextureState();
3124 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3126 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3127 for (scale = 1;scale < layertexrgbscale;scale <<= 1)
3128 RSurf_Draw(surface);
3130 GL_LockArrays(0, 0);
3134 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
3136 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3137 GL_AlphaTest(false);
3141 GL_LockArrays(0, 0);
3142 if ((rsurface_texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (rsurface_entity->flags & RENDER_NOCULLFACE))
3144 qglEnable(GL_CULL_FACE);CHECKGLERROR
3148 #define BATCHSIZE 256
3149 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
3151 int surfacelistindex;
3154 msurface_t *texturesurfacelist[BATCHSIZE];
3155 RSurf_ActiveEntity(ent);
3158 for (surfacelistindex = 0;surfacelistindex < numsurfaces;surfacelistindex++)
3160 msurface_t *surface = ent->model->data_surfaces + surfacelist[surfacelistindex];
3162 if (t != surface->texture || rsurface_lightmaptexture != surface->lightmaptexture)
3165 R_DrawTextureSurfaceList(batchcount, texturesurfacelist);
3167 t = surface->texture;
3168 rsurface_lightmaptexture = surface->lightmaptexture;
3169 R_UpdateTextureInfo(ent, t);
3170 rsurface_texture = t->currentframe;
3172 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_SKY)
3173 continue; // transparent sky is too difficult
3175 texturesurfacelist[batchcount++] = surface;
3178 R_DrawTextureSurfaceList(batchcount, texturesurfacelist);
3182 void R_QueueTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist)
3184 int texturesurfaceindex;
3185 vec3_t tempcenter, center;
3186 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_BLENDED)
3188 // drawing sky transparently would be too difficult
3189 if (!(rsurface_texture->currentmaterialflags & MATERIALFLAG_SKY))
3191 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3193 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3194 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
3195 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
3196 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
3197 Matrix4x4_Transform(&rsurface_entity->matrix, tempcenter, center);
3198 R_MeshQueue_AddTransparent(rsurface_texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_vieworigin : center, R_DrawSurface_TransparentCallback, rsurface_entity, surface - rsurface_model->data_surfaces, r_shadow_rtlight);
3203 R_DrawTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
3206 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
3207 void R_DrawSurfaces(entity_render_t *ent, qboolean skysurfaces)
3209 int i, j, f, flagsmask;
3210 int counttriangles = 0;
3212 model_t *model = ent->model;
3213 const int maxsurfacelist = 1024;
3214 int numsurfacelist = 0;
3215 msurface_t *surfacelist[1024];
3219 RSurf_ActiveEntity(ent);
3221 // update light styles
3222 if (!skysurfaces && model->brushq1.light_styleupdatechains)
3224 msurface_t *surface, **surfacechain;
3225 for (i = 0;i < model->brushq1.light_styles;i++)
3227 if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
3229 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
3230 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
3231 for (;(surface = *surfacechain);surfacechain++)
3232 surface->cached_dlight = true;
3237 R_UpdateAllTextureInfo(ent);
3238 flagsmask = skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL);
3241 rsurface_lightmaptexture = NULL;
3242 rsurface_texture = NULL;
3244 if (ent == r_refdef.worldentity)
3246 msurface_t *surface;
3247 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
3249 if (!r_worldsurfacevisible[j])
3251 if (t != surface->texture || rsurface_lightmaptexture != surface->lightmaptexture)
3255 R_QueueTextureSurfaceList(numsurfacelist, surfacelist);
3258 t = surface->texture;
3259 rsurface_lightmaptexture = surface->lightmaptexture;
3260 rsurface_texture = t->currentframe;
3261 f = rsurface_texture->currentmaterialflags & flagsmask;
3263 if (f && surface->num_triangles)
3265 // if lightmap parameters changed, rebuild lightmap texture
3266 if (surface->cached_dlight)
3267 R_BuildLightMap(ent, surface);
3268 // add face to draw list
3269 surfacelist[numsurfacelist++] = surface;
3270 counttriangles += surface->num_triangles;
3271 if (numsurfacelist >= maxsurfacelist)
3273 R_QueueTextureSurfaceList(numsurfacelist, surfacelist);
3281 msurface_t *surface;
3282 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
3284 if (t != surface->texture || rsurface_lightmaptexture != surface->lightmaptexture)
3288 R_QueueTextureSurfaceList(numsurfacelist, surfacelist);
3291 t = surface->texture;
3292 rsurface_lightmaptexture = surface->lightmaptexture;
3293 rsurface_texture = t->currentframe;
3294 f = rsurface_texture->currentmaterialflags & flagsmask;
3296 if (f && surface->num_triangles)
3298 // if lightmap parameters changed, rebuild lightmap texture
3299 if (surface->cached_dlight)
3300 R_BuildLightMap(ent, surface);
3301 // add face to draw list
3302 surfacelist[numsurfacelist++] = surface;
3303 counttriangles += surface->num_triangles;
3304 if (numsurfacelist >= maxsurfacelist)
3306 R_QueueTextureSurfaceList(numsurfacelist, surfacelist);
3313 R_QueueTextureSurfaceList(numsurfacelist, surfacelist);
3314 renderstats.entities_triangles += counttriangles;
3317 if (r_showcollisionbrushes.integer && model->brush.num_brushes && !skysurfaces)
3320 const msurface_t *surface;
3323 R_Mesh_Matrix(&ent->matrix);
3324 R_Mesh_ColorPointer(NULL);
3325 R_Mesh_ResetTextureState();
3326 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
3327 GL_DepthMask(false);
3328 GL_DepthTest(!r_showdisabledepthtest.integer);
3329 qglPolygonOffset(r_polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_polygonoffset + r_showcollisionbrushes_polygonoffset.value);CHECKGLERROR
3330 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
3331 if (brush->colbrushf && brush->colbrushf->numtriangles)
3332 R_DrawCollisionBrush(brush->colbrushf);
3333 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
3334 if (surface->num_collisiontriangles)
3335 R_DrawCollisionSurface(ent, surface);
3336 qglPolygonOffset(r_polygonfactor, r_polygonoffset);CHECKGLERROR
3339 if (r_showtris.integer || r_shownormals.integer)
3342 msurface_t *surface;
3343 const int *elements;
3348 if (r_showdisabledepthtest.integer)
3350 qglDepthFunc(GL_ALWAYS);CHECKGLERROR
3352 GL_BlendFunc(GL_ONE, GL_ZERO);
3353 R_Mesh_ColorPointer(NULL);
3354 R_Mesh_ResetTextureState();
3355 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
3357 if (ent == r_refdef.worldentity && !r_worldsurfacevisible[j])
3359 rsurface_texture = surface->texture->currentframe;
3360 if ((rsurface_texture->currentmaterialflags & flagsmask) && surface->num_triangles)
3362 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
3363 if (r_showtris.integer)
3365 if (!rsurface_texture->currentlayers->depthmask)
3366 GL_Color(r_showtris.value, 0, 0, 1);
3367 else if (ent == r_refdef.worldentity)
3368 GL_Color(r_showtris.value, r_showtris.value, r_showtris.value, 1);
3370 GL_Color(0, r_showtris.value, 0, 1);
3371 elements = (ent->model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
3374 for (k = 0;k < surface->num_triangles;k++, elements += 3)
3376 qglArrayElement(elements[0]);qglArrayElement(elements[1]);
3377 qglArrayElement(elements[1]);qglArrayElement(elements[2]);
3378 qglArrayElement(elements[2]);qglArrayElement(elements[0]);
3383 if (r_shownormals.integer)
3385 GL_Color(r_shownormals.value, 0, 0, 1);
3387 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
3389 VectorCopy(rsurface_vertex3f + l * 3, v);
3390 qglVertex3f(v[0], v[1], v[2]);
3391 VectorMA(v, 8, rsurface_svector3f + l * 3, v);
3392 qglVertex3f(v[0], v[1], v[2]);
3396 GL_Color(0, 0, r_shownormals.value, 1);
3398 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
3400 VectorCopy(rsurface_vertex3f + l * 3, v);
3401 qglVertex3f(v[0], v[1], v[2]);
3402 VectorMA(v, 8, rsurface_tvector3f + l * 3, v);
3403 qglVertex3f(v[0], v[1], v[2]);
3407 GL_Color(0, r_shownormals.value, 0, 1);
3409 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
3411 VectorCopy(rsurface_vertex3f + l * 3, v);
3412 qglVertex3f(v[0], v[1], v[2]);
3413 VectorMA(v, 8, rsurface_normal3f + l * 3, v);
3414 qglVertex3f(v[0], v[1], v[2]);
3421 rsurface_texture = NULL;
3422 if (r_showdisabledepthtest.integer)
3424 qglDepthFunc(GL_LEQUAL);CHECKGLERROR