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