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;
51 // forces all rendering to draw triangle outlines
66 matrix4x4_t r_view_matrix;
73 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
74 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
75 cvar_t r_showtris_polygonoffset = {0, "r_showtris_polygonoffset", "-10", "nudges triangle outlines in hardware depth units, used to make outlines appear infront of walls"};
76 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
77 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
78 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
79 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
80 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
81 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
82 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing\n"};
83 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
84 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
85 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
86 cvar_t r_fullbright = {0, "r_fullbright","0", "make everything bright cheat (not allowed in multiplayer)"};
87 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
88 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
89 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
91 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
92 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
93 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
94 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
95 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
96 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
97 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
99 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of hardware texture units reported by driver (note: setting this to 1 turns off gl_combine)"};
101 cvar_t r_glsl = {0, "r_glsl", "1", "enables use of OpenGL 2.0 pixel shaders for lighting"};
102 cvar_t r_glsl_offsetmapping = {0, "r_glsl_offsetmapping", "0", "enables offset mapping effect (also known as parallax mapping or sometimes as virtual displacement mapping, not as good as relief mapping or silohuette mapping but much faster), can cause strange artifacts on many textures, requires bumpmaps for depth information (normalmaps can have depth information as alpha channel, but most do not)"};
103 cvar_t r_glsl_offsetmapping_scale = {0, "r_glsl_offsetmapping_scale", "-0.04", "how deep the offset mapping effect is, and whether it is inward or outward"};
104 cvar_t r_glsl_offsetmapping_bias = {0, "r_glsl_offsetmapping_bias", "0.04", "pushes the effect closer/further"};
105 cvar_t r_glsl_usehalffloat = {0, "r_glsl_usehalffloat", "0", "use half and hvec variables in GLSL shader for a speed gain (NVIDIA only)"};
106 cvar_t r_glsl_surfacenormalize = {0, "r_glsl_surfacenormalize", "1", "normalize bumpmap texels in GLSL shader, produces a more rounded look on small bumps and dents"};
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] = 128.0f + intensity * v[0];
374 data[side][y][x][1] = 128.0f + intensity * v[1];
375 data[side][y][x][2] = 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 "// use half floats if available for math performance\n"
419 "#define myhalf half\n"
420 "#define myhvec2 hvec2\n"
421 "#define myhvec3 hvec3\n"
422 "#define myhvec4 hvec4\n"
424 "#define myhalf float\n"
425 "#define myhvec2 vec2\n"
426 "#define myhvec3 vec3\n"
427 "#define myhvec4 vec4\n"
430 "varying vec2 TexCoord;\n"
431 "#if !defined(MODE_LIGHTSOURCE) && !defined(MODE_LIGHTDIRECTION)\n"
432 "varying vec2 TexCoordLightmap;\n"
435 "#ifdef MODE_LIGHTSOURCE\n"
436 "varying myhvec3 CubeVector;\n"
439 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
440 "varying vec3 LightVector;\n"
443 "#if defined(USESPECULAR) || defined(USEFOG) || defined(USEOFFSETMAPPING)\n"
444 "varying vec3 EyeVector;\n"
450 "// vertex shader specific:\n"
451 "#ifdef VERTEX_SHADER\n"
453 "#ifdef MODE_LIGHTSOURCE\n"
454 "uniform vec3 LightPosition;\n"
457 "#if defined(USESPECULAR) || defined(USEFOG) || defined(USEOFFSETMAPPING)\n"
458 "uniform vec3 EyePosition;\n"
461 "#ifdef MODE_LIGHTDIRECTION\n"
462 "uniform myhvec3 LightDir;\n"
465 "// TODO: get rid of tangentt (texcoord2) and use a crossproduct to regenerate it from tangents (texcoord1) and normal (texcoord3)\n"
469 " // copy the surface texcoord\n"
470 " TexCoord = vec2(gl_TextureMatrix[0] * gl_MultiTexCoord0);\n"
471 "#if !defined(MODE_LIGHTSOURCE) && !defined(MODE_LIGHTDIRECTION)\n"
472 " TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
474 " gl_FrontColor = gl_Color;\n"
476 "#ifdef MODE_LIGHTSOURCE\n"
477 " // transform vertex position into light attenuation/cubemap space\n"
478 " // (-1 to +1 across the light box)\n"
479 " CubeVector = vec3(gl_TextureMatrix[3] * gl_Vertex);\n"
481 " // transform unnormalized light direction into tangent space\n"
482 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
483 " // normalize it per pixel)\n"
484 " vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
485 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
486 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
487 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
490 "#ifdef MODE_LIGHTDIRECTION\n"
491 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
492 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
493 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
496 "#if defined(USESPECULAR) || defined(USEFOG) || defined(USEOFFSETMAPPING)\n"
497 " // transform unnormalized eye direction into tangent space\n"
498 " vec3 eyeminusvertex = EyePosition - gl_Vertex.xyz;\n"
499 " EyeVector.x = dot(eyeminusvertex, gl_MultiTexCoord1.xyz);\n"
500 " EyeVector.y = dot(eyeminusvertex, gl_MultiTexCoord2.xyz);\n"
501 " EyeVector.z = dot(eyeminusvertex, gl_MultiTexCoord3.xyz);\n"
504 " // transform vertex to camera space, using ftransform to match non-VS\n"
506 " gl_Position = ftransform();\n"
514 "// fragment shader specific:\n"
515 "#ifdef FRAGMENT_SHADER\n"
517 "uniform myhvec3 LightColor;\n"
518 "#ifdef USEOFFSETMAPPING\n"
519 "uniform myhalf OffsetMapping_Scale;\n"
520 "uniform myhalf OffsetMapping_Bias;\n"
523 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTIONMAP) || defined(MODE_LIGHTDIRECTION) || defined(USEOFFSETMAPPING)\n"
524 "uniform sampler2D Texture_Normal;\n"
527 "#ifdef MODE_LIGHTDIRECTION\n"
528 "uniform myhvec3 AmbientColor;\n"
529 "uniform myhvec3 DiffuseColor;\n"
530 "uniform myhvec3 SpecularColor;\n"
533 "uniform sampler2D Texture_Color;\n"
535 "#if !defined(MODE_LIGHTSOURCE) && !defined(MODE_LIGHTDIRECTION)\n"
536 "uniform sampler2D Texture_Lightmap;\n"
538 "#ifdef MODE_LIGHTDIRECTIONMAP\n"
539 "uniform sampler2D Texture_Deluxemap;\n"
543 "uniform sampler2D Texture_Glow;\n"
546 "#ifdef USECOLORMAPPING\n"
547 "uniform sampler2D Texture_Pants;\n"
548 "uniform sampler2D Texture_Shirt;\n"
549 "uniform myhvec3 Color_Pants;\n"
550 "uniform myhvec3 Color_Shirt;\n"
553 "uniform myhalf AmbientScale;\n"
554 "uniform myhalf DiffuseScale;\n"
555 "#ifdef USESPECULAR\n"
556 "uniform myhalf SpecularScale;\n"
557 "uniform myhalf SpecularPower;\n"
558 "uniform sampler2D Texture_Gloss;\n"
561 "#ifdef USECUBEFILTER\n"
562 "uniform samplerCube Texture_Cube;\n"
566 "uniform myhvec3 FogColor;\n"
567 "uniform myhalf FogRangeRecip;\n"
568 "uniform sampler2D Texture_FogMask;\n"
571 "#ifdef USEEASTEREGG\n"
574 " gl_FragColor = myhvec4(0, 0, 0, 1);;\n"
577 " vec2 p = vec2(CubeVector.x * 16.0, CubeVector.y * 16.0);\n"
578 " vec2 c = vec2(CubeVector.x * 16.0, CubeVector.y * 16.0);\n"
579 " for (i = 0;i < 1000 && dot(p,p) < 4.0;i = i + 1)\n"
581 " o = p.x * p.x - p.y * p.y;\n"
582 " p.y = 2.0 * p.x * p.y;\n"
586 " o = float(i) * 0.314;\n"
588 " gl_FragColor = vec4(cos(o), sin(o), sin(o * 0.2), 1);\n"
590 "#else // USEEASTEREGG\n"
596 " // apply offsetmapping\n"
597 "#ifdef USEOFFSETMAPPING\n"
598 " // this is 3 sample because of ATI Radeon 9500-9800/X300 limits\n"
599 " myhvec2 OffsetVector = normalize(EyeVector).xy * vec2(-0.333, 0.333);\n"
600 " myhvec2 TexCoordOffset = TexCoord + OffsetVector * (OffsetMapping_Bias + OffsetMapping_Scale * texture2D(Texture_Normal, TexCoord).w);\n"
601 " TexCoordOffset += OffsetVector * (OffsetMapping_Bias + OffsetMapping_Scale * texture2D(Texture_Normal, TexCoordOffset).w);\n"
602 " TexCoordOffset += OffsetVector * (OffsetMapping_Bias + OffsetMapping_Scale * texture2D(Texture_Normal, TexCoordOffset).w);\n"
603 "#define TexCoord TexCoordOffset\n"
606 " // combine the diffuse textures (base, pants, shirt)\n"
607 " myhvec4 color = myhvec4(texture2D(Texture_Color, TexCoord));\n"
608 "#ifdef USECOLORMAPPING\n"
609 " color.rgb += myhvec3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhvec3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
615 "#ifdef MODE_LIGHTSOURCE\n"
618 " // get the surface normal and light normal\n"
619 "#ifdef SURFACENORMALIZE\n"
620 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - 0.5);\n"
622 " myhvec3 surfacenormal = -1.0 + 2.0 * myhvec3(texture2D(Texture_Normal, TexCoord));\n"
624 " myhvec3 diffusenormal = myhvec3(normalize(LightVector));\n"
626 " // calculate directional shading\n"
627 " color.rgb *= (AmbientScale + DiffuseScale * max(dot(surfacenormal, diffusenormal), 0.0));\n"
628 "#ifdef USESPECULAR\n"
629 " myhvec3 specularnormal = myhvec3(normalize(diffusenormal + myhvec3(normalize(EyeVector))));\n"
630 " color.rgb += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(max(dot(surfacenormal, specularnormal), 0.0), SpecularPower);\n"
633 "#ifdef USECUBEFILTER\n"
634 " // apply light cubemap filter\n"
635 " color.rgb *= myhvec3(textureCube(Texture_Cube, CubeVector));\n"
638 " // apply light color\n"
639 " color.rgb = color.rgb * LightColor;\n"
641 " // apply attenuation\n"
643 " // the attenuation is (1-(x*x+y*y+z*z)) which gives a large bright\n"
644 " // center and sharp falloff at the edge, this is about the most efficient\n"
645 " // we can get away with as far as providing illumination.\n"
647 " // pow(1-(x*x+y*y+z*z), 4) is far more realistic but needs large lights to\n"
648 " // provide significant illumination, large = slow = pain.\n"
649 " color.rgb *= max(1.0 - dot(CubeVector, CubeVector), 0.0);\n"
654 "#elif defined(MODE_LIGHTDIRECTION)\n"
655 " // directional model lighting\n"
657 " // get the surface normal and light normal\n"
658 "#ifdef SURFACENORMALIZE\n"
659 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - 0.5);\n"
661 " myhvec3 surfacenormal = -1.0 + 2.0 * myhvec3(texture2D(Texture_Normal, TexCoord));\n"
663 " myhvec3 diffusenormal = myhvec3(normalize(LightVector));\n"
666 " // calculate directional shading\n"
667 " color.rgb *= AmbientColor + DiffuseColor * max(dot(surfacenormal, diffusenormal), 0.0);\n"
668 " //color.rgb *= AmbientColor + DiffuseColor * max(dot(surfacenormal, diffusenormal), 0.0);\n"
669 "#ifdef USESPECULAR\n"
670 " myhvec3 specularnormal = myhvec3(normalize(diffusenormal + myhvec3(normalize(EyeVector))));\n"
671 " color.rgb += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(max(dot(surfacenormal, specularnormal), 0.0), SpecularPower);\n"
677 "#elif defined(MODE_LIGHTDIRECTIONMAP)\n"
678 " // deluxemap lightmapping\n"
680 " // get the surface normal and light normal\n"
681 "#ifdef SURFACENORMALIZE\n"
682 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - 0.5);\n"
683 " myhvec3 diffusenormal = normalize(myhvec3(texture2D(Texture_Deluxemap, TexCoordLightmap)));\n"
685 " myhvec3 surfacenormal = -1.0 + 2.0 * myhvec3(texture2D(Texture_Normal, TexCoord));\n"
686 " myhvec3 diffusenormal = myhvec3(texture2D(Texture_Deluxemap, TexCoordLightmap));\n"
689 " // calculate directional shading\n"
690 " myhvec3 tempcolor = color.rgb * (DiffuseScale * max(dot(surfacenormal, diffusenormal), 0.0)));\n"
691 "#ifdef USESPECULAR\n"
692 " myhvec3 specularnormal = myhvec3(normalize(diffusenormal + myhvec3(normalize(EyeVector))));\n"
693 " tempcolor += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(max(dot(surfacenormal, specularnormal), 0.0), SpecularPower);\n"
696 " // apply lightmap color\n"
697 " color.rgb = tempcolor * myhvec3(texture2D(Texture_Lightmap, TexCoordLightmap)) + color.rgb * myhvec3(AmbientScale);\n"
702 "#else // MODE none (lightmap)\n"
703 " // apply lightmap color\n"
704 " color.rgb *= myhvec3(texture2D(Texture_Lightmap, TexCoordLightmap)) * DiffuseScale + myhvec3(AmbientScale);\n"
708 " color.rgb += myhvec3(texture2D(Texture_Glow, TexCoord));\n"
713 " myhalf fog = texture2D(Texture_FogMask, myhvec2(length(EyeVector)*FogRangeRecip, 0.0)).x;\n"
714 " color.rgb = color.rgb * fog + FogColor * (1.0 - fog);\n"
717 " gl_FragColor = color * gl_Color;\n"
719 "#endif // !USEEASTEREGG\n"
724 // the loaded GLSL shader file for compiling shader permutations as needed
725 static char *shaderstring = NULL;
727 void R_GLSL_CompilePermutation(int permutation)
729 r_glsl_permutation_t *p = r_glsl_permutations + permutation;
730 int vertstrings_count;
731 int fragstrings_count;
732 const char *vertstrings_list[SHADERPERMUTATION_COUNT+1];
733 const char *fragstrings_list[SHADERPERMUTATION_COUNT+1];
734 char permutationname[256];
738 vertstrings_list[0] = "#define VERTEX_SHADER\n";
739 fragstrings_list[0] = "#define FRAGMENT_SHADER\n";
740 vertstrings_count = 1;
741 fragstrings_count = 1;
742 permutationname[0] = 0;
743 if (permutation & SHADERPERMUTATION_MODE_LIGHTSOURCE)
745 vertstrings_list[vertstrings_count++] = "#define MODE_LIGHTSOURCE\n";
746 fragstrings_list[fragstrings_count++] = "#define MODE_LIGHTSOURCE\n";
747 strlcat(permutationname, " lightsource", sizeof(permutationname));
749 if (permutation & SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP)
751 vertstrings_list[vertstrings_count++] = "#define MODE_LIGHTDIRECTIONMAP\n";
752 fragstrings_list[fragstrings_count++] = "#define MODE_LIGHTDIRECTIONMAP\n";
753 strlcat(permutationname, " lightdirectionmap", sizeof(permutationname));
755 if (permutation & SHADERPERMUTATION_MODE_LIGHTDIRECTION)
757 vertstrings_list[vertstrings_count++] = "#define MODE_LIGHTDIRECTION\n";
758 fragstrings_list[fragstrings_count++] = "#define MODE_LIGHTDIRECTION\n";
759 strlcat(permutationname, " lightdirection", sizeof(permutationname));
761 if (permutation & SHADERPERMUTATION_GLOW)
763 vertstrings_list[vertstrings_count++] = "#define USEGLOW\n";
764 fragstrings_list[fragstrings_count++] = "#define USEGLOW\n";
765 strlcat(permutationname, " glow", sizeof(permutationname));
767 if (permutation & SHADERPERMUTATION_COLORMAPPING)
769 vertstrings_list[vertstrings_count++] = "#define USECOLORMAPPING\n";
770 fragstrings_list[fragstrings_count++] = "#define USECOLORMAPPING\n";
771 strlcat(permutationname, " colormapping", sizeof(permutationname));
773 if (permutation & SHADERPERMUTATION_SPECULAR)
775 vertstrings_list[vertstrings_count++] = "#define USESPECULAR\n";
776 fragstrings_list[fragstrings_count++] = "#define USESPECULAR\n";
777 strlcat(permutationname, " specular", sizeof(permutationname));
779 if (permutation & SHADERPERMUTATION_FOG)
781 vertstrings_list[vertstrings_count++] = "#define USEFOG\n";
782 fragstrings_list[fragstrings_count++] = "#define USEFOG\n";
783 strlcat(permutationname, " fog", sizeof(permutationname));
785 if (permutation & SHADERPERMUTATION_CUBEFILTER)
787 vertstrings_list[vertstrings_count++] = "#define USECUBEFILTER\n";
788 fragstrings_list[fragstrings_count++] = "#define USECUBEFILTER\n";
789 strlcat(permutationname, " cubefilter", sizeof(permutationname));
791 if (permutation & SHADERPERMUTATION_OFFSETMAPPING)
793 vertstrings_list[vertstrings_count++] = "#define USEOFFSETMAPPING\n";
794 fragstrings_list[fragstrings_count++] = "#define USEOFFSETMAPPING\n";
795 strlcat(permutationname, " offsetmapping", sizeof(permutationname));
797 if (permutation & SHADERPERMUTATION_SURFACENORMALIZE)
799 vertstrings_list[vertstrings_count++] = "#define SURFACENORMALIZE\n";
800 fragstrings_list[fragstrings_count++] = "#define SURFACENORMALIZE\n";
801 strlcat(permutationname, " surfacenormalize", sizeof(permutationname));
803 if (permutation & SHADERPERMUTATION_GEFORCEFX)
805 vertstrings_list[vertstrings_count++] = "#define GEFORCEFX\n";
806 fragstrings_list[fragstrings_count++] = "#define GEFORCEFX\n";
807 strlcat(permutationname, " halffloat", sizeof(permutationname));
811 vertstrings_list[vertstrings_count++] = shaderstring;
812 fragstrings_list[fragstrings_count++] = shaderstring;
816 vertstrings_list[vertstrings_count++] = builtinshaderstring;
817 fragstrings_list[fragstrings_count++] = builtinshaderstring;
819 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, fragstrings_count, fragstrings_list);
823 qglUseProgramObjectARB(p->program);
824 p->loc_Texture_Normal = qglGetUniformLocationARB(p->program, "Texture_Normal");
825 p->loc_Texture_Color = qglGetUniformLocationARB(p->program, "Texture_Color");
826 p->loc_Texture_Gloss = qglGetUniformLocationARB(p->program, "Texture_Gloss");
827 p->loc_Texture_Cube = qglGetUniformLocationARB(p->program, "Texture_Cube");
828 p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
829 p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
830 p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
831 p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
832 p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
833 p->loc_Texture_Glow = qglGetUniformLocationARB(p->program, "Texture_Glow");
834 p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
835 p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
836 p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
837 p->loc_LightColor = qglGetUniformLocationARB(p->program, "LightColor");
838 p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants");
839 p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt");
840 p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip");
841 p->loc_AmbientScale = qglGetUniformLocationARB(p->program, "AmbientScale");
842 p->loc_DiffuseScale = qglGetUniformLocationARB(p->program, "DiffuseScale");
843 p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
844 p->loc_SpecularScale = qglGetUniformLocationARB(p->program, "SpecularScale");
845 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
846 p->loc_OffsetMapping_Bias = qglGetUniformLocationARB(p->program, "OffsetMapping_Bias");
847 p->loc_AmbientColor = qglGetUniformLocationARB(p->program, "AmbientColor");
848 p->loc_DiffuseColor = qglGetUniformLocationARB(p->program, "DiffuseColor");
849 p->loc_SpecularColor = qglGetUniformLocationARB(p->program, "SpecularColor");
850 p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
851 if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal, 0);
852 if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color, 1);
853 if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss, 2);
854 if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube, 3);
855 if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask, 4);
856 if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants, 5);
857 if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt, 6);
858 if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap, 7);
859 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap, 8);
860 if (p->loc_Texture_Glow >= 0) qglUniform1iARB(p->loc_Texture_Glow, 9);
861 qglUseProgramObjectARB(0);
865 Con_Printf("permutation%s failed for shader %s, some features may not work properly!\n", permutationname, "glsl/default.glsl");
868 void R_SetupSurfaceShader(const entity_render_t *ent, const texture_t *texture, const vec3_t modelorg, const vec3_t lightcolorbase, qboolean modellighting)
870 // select a permutation of the lighting shader appropriate to this
871 // combination of texture, entity, light source, and fogging, only use the
872 // minimum features necessary to avoid wasting rendering time in the
873 // fragment shader on features that are not being used
875 float specularscale = texture->specularscale;
876 r_glsl_permutation = NULL;
877 if (r_shadow_rtlight)
879 permutation |= SHADERPERMUTATION_MODE_LIGHTSOURCE;
880 specularscale *= r_shadow_rtlight->specularscale;
881 if (r_shadow_rtlight->currentcubemap != r_texture_whitecube)
882 permutation |= SHADERPERMUTATION_CUBEFILTER;
884 else if (modellighting)
886 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTION;
887 if (texture->skin.glow)
888 permutation |= SHADERPERMUTATION_GLOW;
892 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP;
893 if (texture->skin.glow)
894 permutation |= SHADERPERMUTATION_GLOW;
898 if (texture->skin.glow)
899 permutation |= SHADERPERMUTATION_GLOW;
901 if (specularscale > 0)
902 permutation |= SHADERPERMUTATION_SPECULAR;
904 permutation |= SHADERPERMUTATION_FOG;
905 if (texture->colormapping)
906 permutation |= SHADERPERMUTATION_COLORMAPPING;
907 if (r_glsl_offsetmapping.integer)
908 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
909 if (r_glsl_surfacenormalize.integer)
910 permutation |= SHADERPERMUTATION_SURFACENORMALIZE;
911 if (r_glsl_usehalffloat.integer)
912 permutation |= SHADERPERMUTATION_GEFORCEFX;
913 if (!r_glsl_permutations[permutation].program)
915 if (!r_glsl_permutations[permutation].compiled)
916 R_GLSL_CompilePermutation(permutation);
917 if (!r_glsl_permutations[permutation].program)
919 // remove features until we find a valid permutation
921 for (i = SHADERPERMUTATION_COUNT-1;;i>>=1)
923 // reduce i more quickly whenever it would not remove any bits
927 if (!r_glsl_permutations[permutation].compiled)
928 R_GLSL_CompilePermutation(permutation);
929 if (r_glsl_permutations[permutation].program)
932 return; // utterly failed
936 r_glsl_permutation = r_glsl_permutations + permutation;
938 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
939 R_Mesh_TexMatrix(0, &texture->currenttexmatrix);
940 if (permutation & SHADERPERMUTATION_MODE_LIGHTSOURCE)
942 R_Mesh_TexMatrix(3, &r_shadow_entitytolight);
943 if (r_glsl_permutation->loc_Texture_Cube >= 0) R_Mesh_TexBind(3, R_GetTexture(r_shadow_rtlight->currentcubemap));
944 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]);
945 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
946 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_shadow_rtlight->ambientscale);
947 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_shadow_rtlight->diffusescale);
948 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, specularscale);
950 else if (permutation & SHADERPERMUTATION_MODE_LIGHTDIRECTION)
952 if (r_glsl_permutation->loc_AmbientColor >= 0)
953 qglUniform3fARB(r_glsl_permutation->loc_AmbientColor, ent->modellight_ambient[0], ent->modellight_ambient[1], ent->modellight_ambient[2]);
954 if (r_glsl_permutation->loc_DiffuseColor >= 0)
955 qglUniform3fARB(r_glsl_permutation->loc_DiffuseColor, ent->modellight_diffuse[0], ent->modellight_diffuse[1], ent->modellight_diffuse[2]);
956 if (r_glsl_permutation->loc_SpecularColor >= 0)
957 qglUniform3fARB(r_glsl_permutation->loc_SpecularColor, ent->modellight_diffuse[0] * texture->specularscale, ent->modellight_diffuse[1] * texture->specularscale, ent->modellight_diffuse[2] * texture->specularscale);
958 if (r_glsl_permutation->loc_LightDir >= 0)
959 qglUniform3fARB(r_glsl_permutation->loc_LightDir, ent->modellight_lightdir[0], ent->modellight_lightdir[1], ent->modellight_lightdir[2]);
963 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_ambient.value * 2.0f / 128.0f);
964 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_lightmapintensity * 2.0f);
965 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, specularscale * 2.0f);
967 if (r_glsl_permutation->loc_Texture_Normal >= 0) R_Mesh_TexBind(0, R_GetTexture(texture->skin.nmap));
968 if (r_glsl_permutation->loc_Texture_Color >= 0) R_Mesh_TexBind(1, R_GetTexture(texture->basetexture));
969 if (r_glsl_permutation->loc_Texture_Gloss >= 0) R_Mesh_TexBind(2, R_GetTexture(texture->glosstexture));
970 if (r_glsl_permutation->loc_Texture_FogMask >= 0) R_Mesh_TexBind(4, R_GetTexture(r_texture_fogattenuation));
971 if (r_glsl_permutation->loc_Texture_Pants >= 0) R_Mesh_TexBind(5, R_GetTexture(texture->skin.pants));
972 if (r_glsl_permutation->loc_Texture_Shirt >= 0) R_Mesh_TexBind(6, R_GetTexture(texture->skin.shirt));
973 if (r_glsl_permutation->loc_Texture_Glow >= 0) R_Mesh_TexBind(9, R_GetTexture(texture->skin.glow));
974 if (r_glsl_permutation->loc_FogColor >= 0)
976 // additive passes are only darkened by fog, not tinted
977 if (r_shadow_rtlight || (texture->currentmaterialflags & MATERIALFLAG_ADD))
978 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
980 qglUniform3fARB(r_glsl_permutation->loc_FogColor, fogcolor[0], fogcolor[1], fogcolor[2]);
982 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, modelorg[0], modelorg[1], modelorg[2]);
983 if (r_glsl_permutation->loc_Color_Pants >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, ent->colormap_pantscolor[0], ent->colormap_pantscolor[1], ent->colormap_pantscolor[2]);
984 if (r_glsl_permutation->loc_Color_Shirt >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, ent->colormap_shirtcolor[0], ent->colormap_shirtcolor[1], ent->colormap_shirtcolor[2]);
985 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, fograngerecip);
986 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, texture->specularpower);
987 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
988 if (r_glsl_permutation->loc_OffsetMapping_Bias >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Bias, r_glsl_offsetmapping_bias.value);
992 void gl_main_start(void)
994 // use half float math where available (speed gain on NVIDIA GFFX and GF6)
995 if (gl_support_half_float)
996 Cvar_SetValue("r_glsl_usehalffloat", 1);
997 r_main_texturepool = R_AllocTexturePool();
998 r_bloom_texture_screen = NULL;
999 r_bloom_texture_bloom = NULL;
1000 R_BuildBlankTextures();
1002 if (gl_texturecubemap)
1005 R_BuildNormalizationCube();
1007 R_BuildFogTexture();
1008 shaderstring = NULL;
1009 if (gl_support_fragment_shader)
1011 shaderstring = (char *)FS_LoadFile("glsl/default.glsl", r_main_mempool, false, NULL);
1013 Con_Printf("GLSL shader text loaded from disk\n");
1014 // if we couldn't load the shader file, fall back to builtin shader
1018 Con_Printf("GLSL shader text loaded from fallback\n");
1019 shaderstring = Mem_Alloc(r_main_mempool, strlen(builtinshaderstring) + 1);
1020 strcpy(shaderstring, builtinshaderstring);
1024 Con_Printf("GLSL shader text loaded\n");
1025 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
1028 void gl_main_shutdown(void)
1031 R_FreeTexturePool(&r_main_texturepool);
1032 r_bloom_texture_screen = NULL;
1033 r_bloom_texture_bloom = NULL;
1034 r_texture_blanknormalmap = NULL;
1035 r_texture_white = NULL;
1036 r_texture_black = NULL;
1037 r_texture_whitecube = NULL;
1038 r_texture_normalizationcube = NULL;
1040 Mem_Free(shaderstring);
1041 shaderstring = NULL;
1042 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1043 if (r_glsl_permutations[i].program)
1044 GL_Backend_FreeProgram(r_glsl_permutations[i].program);
1045 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
1048 extern void CL_ParseEntityLump(char *entitystring);
1049 void gl_main_newmap(void)
1051 // FIXME: move this code to client
1053 char *entities, entname[MAX_QPATH];
1057 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
1058 l = (int)strlen(entname) - 4;
1059 if (l >= 0 && !strcmp(entname + l, ".bsp"))
1061 strcpy(entname + l, ".ent");
1062 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
1064 CL_ParseEntityLump(entities);
1069 if (cl.worldmodel->brush.entities)
1070 CL_ParseEntityLump(cl.worldmodel->brush.entities);
1074 void GL_Main_Init(void)
1076 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
1078 FOG_registercvars(); // FIXME: move this fog stuff to client?
1079 Cvar_RegisterVariable(&r_nearclip);
1080 Cvar_RegisterVariable(&r_showtris);
1081 Cvar_RegisterVariable(&r_showtris_polygonoffset);
1082 Cvar_RegisterVariable(&r_shownormals);
1083 Cvar_RegisterVariable(&r_showlighting);
1084 Cvar_RegisterVariable(&r_showshadowvolumes);
1085 Cvar_RegisterVariable(&r_showcollisionbrushes);
1086 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
1087 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
1088 Cvar_RegisterVariable(&r_showdisabledepthtest);
1089 Cvar_RegisterVariable(&r_drawentities);
1090 Cvar_RegisterVariable(&r_drawviewmodel);
1091 Cvar_RegisterVariable(&r_speeds);
1092 Cvar_RegisterVariable(&r_fullbrights);
1093 Cvar_RegisterVariable(&r_wateralpha);
1094 Cvar_RegisterVariable(&r_dynamic);
1095 Cvar_RegisterVariable(&r_fullbright);
1096 Cvar_RegisterVariable(&r_textureunits);
1097 Cvar_RegisterVariable(&r_glsl);
1098 Cvar_RegisterVariable(&r_glsl_offsetmapping);
1099 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
1100 Cvar_RegisterVariable(&r_glsl_offsetmapping_bias);
1101 Cvar_RegisterVariable(&r_glsl_usehalffloat);
1102 Cvar_RegisterVariable(&r_glsl_surfacenormalize);
1103 Cvar_RegisterVariable(&r_lerpsprites);
1104 Cvar_RegisterVariable(&r_lerpmodels);
1105 Cvar_RegisterVariable(&r_waterscroll);
1106 Cvar_RegisterVariable(&r_bloom);
1107 Cvar_RegisterVariable(&r_bloom_intensity);
1108 Cvar_RegisterVariable(&r_bloom_blur);
1109 Cvar_RegisterVariable(&r_bloom_resolution);
1110 Cvar_RegisterVariable(&r_bloom_power);
1111 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
1112 Cvar_RegisterVariable(&developer_texturelogging);
1113 Cvar_RegisterVariable(&gl_lightmaps);
1114 Cvar_RegisterVariable(&r_test);
1115 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
1116 Cvar_SetValue("r_fullbrights", 0);
1117 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
1120 static vec3_t r_farclip_origin;
1121 static vec3_t r_farclip_direction;
1122 static vec_t r_farclip_directiondist;
1123 static vec_t r_farclip_meshfarclip;
1124 static int r_farclip_directionbit0;
1125 static int r_farclip_directionbit1;
1126 static int r_farclip_directionbit2;
1128 // enlarge farclip to accomodate box
1129 static void R_FarClip_Box(vec3_t mins, vec3_t maxs)
1132 d = (r_farclip_directionbit0 ? mins[0] : maxs[0]) * r_farclip_direction[0]
1133 + (r_farclip_directionbit1 ? mins[1] : maxs[1]) * r_farclip_direction[1]
1134 + (r_farclip_directionbit2 ? mins[2] : maxs[2]) * r_farclip_direction[2];
1135 if (r_farclip_meshfarclip < d)
1136 r_farclip_meshfarclip = d;
1139 // return farclip value
1140 static float R_FarClip(vec3_t origin, vec3_t direction, vec_t startfarclip)
1144 VectorCopy(origin, r_farclip_origin);
1145 VectorCopy(direction, r_farclip_direction);
1146 r_farclip_directiondist = DotProduct(r_farclip_origin, r_farclip_direction);
1147 r_farclip_directionbit0 = r_farclip_direction[0] < 0;
1148 r_farclip_directionbit1 = r_farclip_direction[1] < 0;
1149 r_farclip_directionbit2 = r_farclip_direction[2] < 0;
1150 r_farclip_meshfarclip = r_farclip_directiondist + startfarclip;
1152 if (r_refdef.worldmodel)
1153 R_FarClip_Box(r_refdef.worldmodel->normalmins, r_refdef.worldmodel->normalmaxs);
1154 for (i = 0;i < r_refdef.numentities;i++)
1155 R_FarClip_Box(r_refdef.entities[i]->mins, r_refdef.entities[i]->maxs);
1157 return r_farclip_meshfarclip - r_farclip_directiondist;
1160 extern void R_Textures_Init(void);
1161 extern void GL_Draw_Init(void);
1162 extern void GL_Main_Init(void);
1163 extern void R_Shadow_Init(void);
1164 extern void R_Sky_Init(void);
1165 extern void GL_Surf_Init(void);
1166 extern void R_Crosshairs_Init(void);
1167 extern void R_Light_Init(void);
1168 extern void R_Particles_Init(void);
1169 extern void R_Explosion_Init(void);
1170 extern void gl_backend_init(void);
1171 extern void Sbar_Init(void);
1172 extern void R_LightningBeams_Init(void);
1173 extern void Mod_RenderInit(void);
1175 void Render_Init(void)
1185 R_Crosshairs_Init();
1190 R_LightningBeams_Init();
1199 extern char *ENGINE_EXTENSIONS;
1202 VID_CheckExtensions();
1204 // LordHavoc: report supported extensions
1205 Con_DPrintf("\nengine extensions: %s\n", vm_sv_extensions );
1207 // clear to black (loading plaque will be seen over this)
1208 qglClearColor(0,0,0,1);
1209 qglClear(GL_COLOR_BUFFER_BIT);
1212 int R_CullBox(const vec3_t mins, const vec3_t maxs)
1216 for (i = 0;i < 4;i++)
1223 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1227 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1231 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1235 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1239 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1243 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1247 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1251 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1259 //==================================================================================
1261 static void R_UpdateEntityLighting(entity_render_t *ent)
1263 vec3_t tempdiffusenormal;
1264 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));
1265 VectorClear(ent->modellight_diffuse);
1266 VectorClear(ent->modellight_lightdir);
1267 if ((ent->flags & RENDER_LIGHT) && r_refdef.worldmodel && r_refdef.worldmodel->brush.LightPoint)
1268 r_refdef.worldmodel->brush.LightPoint(r_refdef.worldmodel, ent->origin, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
1270 VectorSet(ent->modellight_ambient, 1, 1, 1);
1271 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
1272 VectorNormalize(ent->modellight_lightdir);
1273 ent->modellight_ambient[0] *= ent->colormod[0] * r_lightmapintensity;
1274 ent->modellight_ambient[1] *= ent->colormod[1] * r_lightmapintensity;
1275 ent->modellight_ambient[2] *= ent->colormod[2] * r_lightmapintensity;
1276 ent->modellight_diffuse[0] *= ent->colormod[0] * r_lightmapintensity;
1277 ent->modellight_diffuse[1] *= ent->colormod[1] * r_lightmapintensity;
1278 ent->modellight_diffuse[2] *= ent->colormod[2] * r_lightmapintensity;
1281 static void R_MarkEntities (void)
1284 entity_render_t *ent;
1286 if (!r_drawentities.integer)
1289 r_refdef.worldentity->visframe = r_framecount;
1290 renderimask = envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : (chase_active.integer ? 0 : RENDER_EXTERIORMODEL);
1291 if (r_refdef.worldmodel && r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs)
1293 // worldmodel can check visibility
1294 for (i = 0;i < r_refdef.numentities;i++)
1296 ent = r_refdef.entities[i];
1297 // some of the renderer still relies on origin...
1298 Matrix4x4_OriginFromMatrix(&ent->matrix, ent->origin);
1299 // some of the renderer still relies on scale...
1300 ent->scale = Matrix4x4_ScaleFromMatrix(&ent->matrix);
1301 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)))
1303 ent->visframe = r_framecount;
1304 R_UpdateEntityLighting(ent);
1310 // no worldmodel or it can't check visibility
1311 for (i = 0;i < r_refdef.numentities;i++)
1313 ent = r_refdef.entities[i];
1314 // some of the renderer still relies on origin...
1315 Matrix4x4_OriginFromMatrix(&ent->matrix, ent->origin);
1316 // some of the renderer still relies on scale...
1317 ent->scale = Matrix4x4_ScaleFromMatrix(&ent->matrix);
1318 if (!(ent->flags & renderimask) && !R_CullBox(ent->mins, ent->maxs) && (ent->effects & EF_NODEPTHTEST))
1320 ent->visframe = r_framecount;
1321 R_UpdateEntityLighting(ent);
1327 // only used if skyrendermasked, and normally returns false
1328 int R_DrawBrushModelsSky (void)
1331 entity_render_t *ent;
1333 if (!r_drawentities.integer)
1337 for (i = 0;i < r_refdef.numentities;i++)
1339 ent = r_refdef.entities[i];
1340 if (ent->visframe == r_framecount && ent->model && ent->model->DrawSky)
1342 ent->model->DrawSky(ent);
1349 void R_DrawNoModel(entity_render_t *ent);
1350 void R_DrawModels(void)
1353 entity_render_t *ent;
1355 if (!r_drawentities.integer)
1358 for (i = 0;i < r_refdef.numentities;i++)
1360 ent = r_refdef.entities[i];
1361 if (ent->visframe == r_framecount)
1363 renderstats.entities++;
1364 if (ent->model && ent->model->Draw != NULL)
1365 ent->model->Draw(ent);
1372 static void R_SetFrustum(void)
1374 // break apart the view matrix into vectors for various purposes
1375 Matrix4x4_ToVectors(&r_view_matrix, r_viewforward, r_viewleft, r_viewup, r_vieworigin);
1376 VectorNegate(r_viewleft, r_viewright);
1379 frustum[0].normal[0] = 0 - 1.0 / r_refdef.frustum_x;
1380 frustum[0].normal[1] = 0 - 0;
1381 frustum[0].normal[2] = -1 - 0;
1382 frustum[1].normal[0] = 0 + 1.0 / r_refdef.frustum_x;
1383 frustum[1].normal[1] = 0 + 0;
1384 frustum[1].normal[2] = -1 + 0;
1385 frustum[2].normal[0] = 0 - 0;
1386 frustum[2].normal[1] = 0 - 1.0 / r_refdef.frustum_y;
1387 frustum[2].normal[2] = -1 - 0;
1388 frustum[3].normal[0] = 0 + 0;
1389 frustum[3].normal[1] = 0 + 1.0 / r_refdef.frustum_y;
1390 frustum[3].normal[2] = -1 + 0;
1394 zNear = r_nearclip.value;
1395 nudge = 1.0 - 1.0 / (1<<23);
1396 frustum[4].normal[0] = 0 - 0;
1397 frustum[4].normal[1] = 0 - 0;
1398 frustum[4].normal[2] = -1 - -nudge;
1399 frustum[4].dist = 0 - -2 * zNear * nudge;
1400 frustum[5].normal[0] = 0 + 0;
1401 frustum[5].normal[1] = 0 + 0;
1402 frustum[5].normal[2] = -1 + -nudge;
1403 frustum[5].dist = 0 + -2 * zNear * nudge;
1409 frustum[0].normal[0] = m[3] - m[0];
1410 frustum[0].normal[1] = m[7] - m[4];
1411 frustum[0].normal[2] = m[11] - m[8];
1412 frustum[0].dist = m[15] - m[12];
1414 frustum[1].normal[0] = m[3] + m[0];
1415 frustum[1].normal[1] = m[7] + m[4];
1416 frustum[1].normal[2] = m[11] + m[8];
1417 frustum[1].dist = m[15] + m[12];
1419 frustum[2].normal[0] = m[3] - m[1];
1420 frustum[2].normal[1] = m[7] - m[5];
1421 frustum[2].normal[2] = m[11] - m[9];
1422 frustum[2].dist = m[15] - m[13];
1424 frustum[3].normal[0] = m[3] + m[1];
1425 frustum[3].normal[1] = m[7] + m[5];
1426 frustum[3].normal[2] = m[11] + m[9];
1427 frustum[3].dist = m[15] + m[13];
1429 frustum[4].normal[0] = m[3] - m[2];
1430 frustum[4].normal[1] = m[7] - m[6];
1431 frustum[4].normal[2] = m[11] - m[10];
1432 frustum[4].dist = m[15] - m[14];
1434 frustum[5].normal[0] = m[3] + m[2];
1435 frustum[5].normal[1] = m[7] + m[6];
1436 frustum[5].normal[2] = m[11] + m[10];
1437 frustum[5].dist = m[15] + m[14];
1442 VectorMAM(1, r_viewforward, 1.0 / -r_refdef.frustum_x, r_viewleft, frustum[0].normal);
1443 VectorMAM(1, r_viewforward, 1.0 / r_refdef.frustum_x, r_viewleft, frustum[1].normal);
1444 VectorMAM(1, r_viewforward, 1.0 / -r_refdef.frustum_y, r_viewup, frustum[2].normal);
1445 VectorMAM(1, r_viewforward, 1.0 / r_refdef.frustum_y, r_viewup, frustum[3].normal);
1446 VectorCopy(r_viewforward, frustum[4].normal);
1447 VectorNormalize(frustum[0].normal);
1448 VectorNormalize(frustum[1].normal);
1449 VectorNormalize(frustum[2].normal);
1450 VectorNormalize(frustum[3].normal);
1451 frustum[0].dist = DotProduct (r_vieworigin, frustum[0].normal);
1452 frustum[1].dist = DotProduct (r_vieworigin, frustum[1].normal);
1453 frustum[2].dist = DotProduct (r_vieworigin, frustum[2].normal);
1454 frustum[3].dist = DotProduct (r_vieworigin, frustum[3].normal);
1455 frustum[4].dist = DotProduct (r_vieworigin, frustum[4].normal) + r_nearclip.value;
1456 PlaneClassify(&frustum[0]);
1457 PlaneClassify(&frustum[1]);
1458 PlaneClassify(&frustum[2]);
1459 PlaneClassify(&frustum[3]);
1460 PlaneClassify(&frustum[4]);
1462 // LordHavoc: note to all quake engine coders, Quake had a special case
1463 // for 90 degrees which assumed a square view (wrong), so I removed it,
1464 // Quake2 has it disabled as well.
1466 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
1467 //RotatePointAroundVector( frustum[0].normal, r_viewup, r_viewforward, -(90 - r_refdef.fov_x / 2));
1468 //frustum[0].dist = DotProduct (r_vieworigin, frustum[0].normal);
1469 //PlaneClassify(&frustum[0]);
1471 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
1472 //RotatePointAroundVector( frustum[1].normal, r_viewup, r_viewforward, (90 - r_refdef.fov_x / 2));
1473 //frustum[1].dist = DotProduct (r_vieworigin, frustum[1].normal);
1474 //PlaneClassify(&frustum[1]);
1476 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
1477 //RotatePointAroundVector( frustum[2].normal, r_viewleft, r_viewforward, -(90 - r_refdef.fov_y / 2));
1478 //frustum[2].dist = DotProduct (r_vieworigin, frustum[2].normal);
1479 //PlaneClassify(&frustum[2]);
1481 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
1482 //RotatePointAroundVector( frustum[3].normal, r_viewleft, r_viewforward, (90 - r_refdef.fov_y / 2));
1483 //frustum[3].dist = DotProduct (r_vieworigin, frustum[3].normal);
1484 //PlaneClassify(&frustum[3]);
1487 //VectorCopy(r_viewforward, frustum[4].normal);
1488 //frustum[4].dist = DotProduct (r_vieworigin, frustum[4].normal) + r_nearclip.value;
1489 //PlaneClassify(&frustum[4]);
1492 static void R_BlendView(void)
1494 int screenwidth, screenheight;
1499 // set the (poorly named) screenwidth and screenheight variables to
1500 // a power of 2 at least as large as the screen, these will define the
1501 // size of the texture to allocate
1502 for (screenwidth = 1;screenwidth < vid.width;screenwidth *= 2);
1503 for (screenheight = 1;screenheight < vid.height;screenheight *= 2);
1505 doblend = r_refdef.viewblend[3] >= 0.01f;
1506 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;
1508 if (!dobloom && !doblend)
1511 GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
1513 GL_DepthTest(false);
1514 R_Mesh_Matrix(&identitymatrix);
1515 // vertex coordinates for a quad that covers the screen exactly
1516 varray_vertex3f[0] = 0;varray_vertex3f[1] = 0;varray_vertex3f[2] = 0;
1517 varray_vertex3f[3] = 1;varray_vertex3f[4] = 0;varray_vertex3f[5] = 0;
1518 varray_vertex3f[6] = 1;varray_vertex3f[7] = 1;varray_vertex3f[8] = 0;
1519 varray_vertex3f[9] = 0;varray_vertex3f[10] = 1;varray_vertex3f[11] = 0;
1522 int bloomwidth, bloomheight, x, dobloomblend, range;
1523 float xoffset, yoffset, r;
1524 renderstats.bloom++;
1525 // allocate textures as needed
1526 if (!r_bloom_texture_screen)
1527 r_bloom_texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", screenwidth, screenheight, NULL, TEXTYPE_RGBA, TEXF_FORCENEAREST | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
1528 if (!r_bloom_texture_bloom)
1529 r_bloom_texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", screenwidth, screenheight, NULL, TEXTYPE_RGBA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
1530 // set bloomwidth and bloomheight to the bloom resolution that will be
1531 // used (often less than the screen resolution for faster rendering)
1532 bloomwidth = min(r_view_width, r_bloom_resolution.integer);
1533 bloomheight = min(r_view_height, bloomwidth * r_view_height / r_view_width);
1534 // set up a texcoord array for the full resolution screen image
1535 // (we have to keep this around to copy back during final render)
1536 varray_texcoord2f[0][0] = 0;
1537 varray_texcoord2f[0][1] = (float)r_view_height / (float)screenheight;
1538 varray_texcoord2f[0][2] = (float)r_view_width / (float)screenwidth;
1539 varray_texcoord2f[0][3] = (float)r_view_height / (float)screenheight;
1540 varray_texcoord2f[0][4] = (float)r_view_width / (float)screenwidth;
1541 varray_texcoord2f[0][5] = 0;
1542 varray_texcoord2f[0][6] = 0;
1543 varray_texcoord2f[0][7] = 0;
1544 // set up a texcoord array for the reduced resolution bloom image
1545 // (which will be additive blended over the screen image)
1546 varray_texcoord2f[1][0] = 0;
1547 varray_texcoord2f[1][1] = (float)bloomheight / (float)screenheight;
1548 varray_texcoord2f[1][2] = (float)bloomwidth / (float)screenwidth;
1549 varray_texcoord2f[1][3] = (float)bloomheight / (float)screenheight;
1550 varray_texcoord2f[1][4] = (float)bloomwidth / (float)screenwidth;
1551 varray_texcoord2f[1][5] = 0;
1552 varray_texcoord2f[1][6] = 0;
1553 varray_texcoord2f[1][7] = 0;
1554 memset(&m, 0, sizeof(m));
1555 m.pointer_vertex = varray_vertex3f;
1556 m.pointer_texcoord[0] = varray_texcoord2f[0];
1557 m.tex[0] = R_GetTexture(r_bloom_texture_screen);
1559 // copy view into the full resolution screen image texture
1560 GL_ActiveTexture(0);
1561 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
1562 renderstats.bloom_copypixels += r_view_width * r_view_height;
1563 // now scale it down to the bloom size and raise to a power of itself
1564 // to darken it (this leaves the really bright stuff bright, and
1565 // everything else becomes very dark)
1566 // TODO: optimize with multitexture or GLSL
1567 qglViewport(r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
1568 GL_BlendFunc(GL_ONE, GL_ZERO);
1569 GL_Color(1, 1, 1, 1);
1570 R_Mesh_Draw(0, 4, 2, polygonelements);
1571 renderstats.bloom_drawpixels += bloomwidth * bloomheight;
1572 // render multiple times with a multiply blendfunc to raise to a power
1573 GL_BlendFunc(GL_DST_COLOR, GL_ZERO);
1574 for (x = 1;x < r_bloom_power.integer;x++)
1576 R_Mesh_Draw(0, 4, 2, polygonelements);
1577 renderstats.bloom_drawpixels += bloomwidth * bloomheight;
1579 // we now have a darkened bloom image in the framebuffer, copy it into
1580 // the bloom image texture for more processing
1581 memset(&m, 0, sizeof(m));
1582 m.pointer_vertex = varray_vertex3f;
1583 m.tex[0] = R_GetTexture(r_bloom_texture_bloom);
1584 m.pointer_texcoord[0] = varray_texcoord2f[2];
1586 GL_ActiveTexture(0);
1587 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
1588 renderstats.bloom_copypixels += bloomwidth * bloomheight;
1589 // blend on at multiple vertical offsets to achieve a vertical blur
1590 // TODO: do offset blends using GLSL
1591 range = r_bloom_blur.integer * bloomwidth / 320;
1592 GL_BlendFunc(GL_ONE, GL_ZERO);
1593 for (x = -range;x <= range;x++)
1595 xoffset = 0 / (float)bloomwidth * (float)bloomwidth / (float)screenwidth;
1596 yoffset = x / (float)bloomheight * (float)bloomheight / (float)screenheight;
1597 // compute a texcoord array with the specified x and y offset
1598 varray_texcoord2f[2][0] = xoffset+0;
1599 varray_texcoord2f[2][1] = yoffset+(float)bloomheight / (float)screenheight;
1600 varray_texcoord2f[2][2] = xoffset+(float)bloomwidth / (float)screenwidth;
1601 varray_texcoord2f[2][3] = yoffset+(float)bloomheight / (float)screenheight;
1602 varray_texcoord2f[2][4] = xoffset+(float)bloomwidth / (float)screenwidth;
1603 varray_texcoord2f[2][5] = yoffset+0;
1604 varray_texcoord2f[2][6] = xoffset+0;
1605 varray_texcoord2f[2][7] = yoffset+0;
1606 // this r value looks like a 'dot' particle, fading sharply to
1607 // black at the edges
1608 // (probably not realistic but looks good enough)
1609 r = r_bloom_intensity.value/(range*2+1)*(1 - x*x/(float)(range*range));
1612 GL_Color(r, r, r, 1);
1613 R_Mesh_Draw(0, 4, 2, polygonelements);
1614 renderstats.bloom_drawpixels += bloomwidth * bloomheight;
1615 GL_BlendFunc(GL_ONE, GL_ONE);
1617 // copy the vertically blurred bloom view to a texture
1618 GL_ActiveTexture(0);
1619 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
1620 renderstats.bloom_copypixels += bloomwidth * bloomheight;
1621 // blend the vertically blurred image at multiple offsets horizontally
1622 // to finish the blur effect
1623 // TODO: do offset blends using GLSL
1624 range = r_bloom_blur.integer * bloomwidth / 320;
1625 GL_BlendFunc(GL_ONE, GL_ZERO);
1626 for (x = -range;x <= range;x++)
1628 xoffset = x / (float)bloomwidth * (float)bloomwidth / (float)screenwidth;
1629 yoffset = 0 / (float)bloomheight * (float)bloomheight / (float)screenheight;
1630 // compute a texcoord array with the specified x and y offset
1631 varray_texcoord2f[2][0] = xoffset+0;
1632 varray_texcoord2f[2][1] = yoffset+(float)bloomheight / (float)screenheight;
1633 varray_texcoord2f[2][2] = xoffset+(float)bloomwidth / (float)screenwidth;
1634 varray_texcoord2f[2][3] = yoffset+(float)bloomheight / (float)screenheight;
1635 varray_texcoord2f[2][4] = xoffset+(float)bloomwidth / (float)screenwidth;
1636 varray_texcoord2f[2][5] = yoffset+0;
1637 varray_texcoord2f[2][6] = xoffset+0;
1638 varray_texcoord2f[2][7] = yoffset+0;
1639 // this r value looks like a 'dot' particle, fading sharply to
1640 // black at the edges
1641 // (probably not realistic but looks good enough)
1642 r = r_bloom_intensity.value/(range*2+1)*(1 - x*x/(float)(range*range));
1645 GL_Color(r, r, r, 1);
1646 R_Mesh_Draw(0, 4, 2, polygonelements);
1647 renderstats.bloom_drawpixels += bloomwidth * bloomheight;
1648 GL_BlendFunc(GL_ONE, GL_ONE);
1650 // copy the blurred bloom view to a texture
1651 GL_ActiveTexture(0);
1652 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
1653 renderstats.bloom_copypixels += bloomwidth * bloomheight;
1654 // go back to full view area
1655 qglViewport(r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
1656 // put the original screen image back in place and blend the bloom
1658 memset(&m, 0, sizeof(m));
1659 m.pointer_vertex = varray_vertex3f;
1660 m.tex[0] = R_GetTexture(r_bloom_texture_screen);
1661 m.pointer_texcoord[0] = varray_texcoord2f[0];
1663 dobloomblend = false;
1665 // do both in one pass if possible
1666 if (r_textureunits.integer >= 2 && gl_combine.integer)
1668 dobloomblend = false;
1669 m.texcombinergb[1] = GL_ADD;
1670 m.tex[1] = R_GetTexture(r_bloom_texture_bloom);
1671 m.pointer_texcoord[1] = varray_texcoord2f[1];
1674 dobloomblend = true;
1677 GL_BlendFunc(GL_ONE, GL_ZERO);
1679 R_Mesh_Draw(0, 4, 2, polygonelements);
1680 renderstats.bloom_drawpixels += r_view_width * r_view_height;
1681 // now blend on the bloom texture if multipass
1684 memset(&m, 0, sizeof(m));
1685 m.pointer_vertex = varray_vertex3f;
1686 m.tex[0] = R_GetTexture(r_bloom_texture_bloom);
1687 m.pointer_texcoord[0] = varray_texcoord2f[1];
1689 GL_BlendFunc(GL_ONE, GL_ONE);
1691 R_Mesh_Draw(0, 4, 2, polygonelements);
1692 renderstats.bloom_drawpixels += r_view_width * r_view_height;
1697 // apply a color tint to the whole view
1698 memset(&m, 0, sizeof(m));
1699 m.pointer_vertex = varray_vertex3f;
1701 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1702 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
1703 R_Mesh_Draw(0, 4, 2, polygonelements);
1707 void R_RenderScene(void);
1709 matrix4x4_t r_waterscrollmatrix;
1716 void R_RenderView(void)
1718 if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
1719 return; //Host_Error ("R_RenderView: NULL worldmodel");
1721 r_view_width = bound(0, r_refdef.width, vid.width);
1722 r_view_height = bound(0, r_refdef.height, vid.height);
1724 r_view_x = bound(0, r_refdef.x, vid.width - r_refdef.width);
1725 r_view_y = bound(0, r_refdef.y, vid.height - r_refdef.height);
1727 r_view_matrix = r_refdef.viewentitymatrix;
1728 GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
1729 r_rtworld = r_shadow_realtime_world.integer;
1730 r_rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
1731 r_rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer;
1732 r_rtdlightshadows = r_rtdlight && (r_rtworld ? r_shadow_realtime_world_dlightshadows.integer : r_shadow_realtime_dlight_shadows.integer) && gl_stencil;
1733 r_lightmapintensity = r_rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
1735 // GL is weird because it's bottom to top, r_view_y is top to bottom
1736 qglViewport(r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
1737 GL_Scissor(r_view_x, r_view_y, r_view_width, r_view_height);
1738 GL_ScissorTest(true);
1743 if (r_timereport_active)
1744 R_TimeReport("setup");
1746 qglDepthFunc(GL_LEQUAL);
1747 qglPolygonOffset(0, 0);
1748 qglEnable(GL_POLYGON_OFFSET_FILL);
1752 qglPolygonOffset(0, 0);
1753 qglDisable(GL_POLYGON_OFFSET_FILL);
1756 if (r_timereport_active)
1757 R_TimeReport("blendview");
1759 GL_Scissor(0, 0, vid.width, vid.height);
1760 GL_ScissorTest(false);
1764 void CSQC_R_ClearScreen (void)
1766 if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
1767 return; //Host_Error ("R_RenderView: NULL worldmodel");
1769 r_view_width = bound(0, r_refdef.width, vid.width);
1770 r_view_height = bound(0, r_refdef.height, vid.height);
1772 r_view_x = bound(0, r_refdef.x, vid.width - r_refdef.width);
1773 r_view_y = bound(0, r_refdef.y, vid.height - r_refdef.height);
1775 r_view_matrix = r_refdef.viewentitymatrix;
1776 GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
1777 r_rtworld = r_shadow_realtime_world.integer;
1778 r_rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
1779 r_rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer;
1780 r_rtdlightshadows = r_rtdlight && (r_rtworld ? r_shadow_realtime_world_dlightshadows.integer : r_shadow_realtime_dlight_shadows.integer) && gl_stencil;
1781 r_lightmapintensity = r_rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
1783 // GL is weird because it's bottom to top, r_view_y is top to bottom
1784 qglViewport(r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
1785 GL_Scissor(r_view_x, r_view_y, r_view_width, r_view_height);
1786 GL_ScissorTest(true);
1791 if (r_timereport_active)
1792 R_TimeReport("setup");
1796 void CSQC_R_RenderScene (void)
1798 qglDepthFunc(GL_LEQUAL);
1799 qglPolygonOffset(0, 0);
1800 qglEnable(GL_POLYGON_OFFSET_FILL);
1804 qglPolygonOffset(0, 0);
1805 qglDisable(GL_POLYGON_OFFSET_FILL);
1808 if (r_timereport_active)
1809 R_TimeReport("blendview");
1811 GL_Scissor(0, 0, vid.width, vid.height);
1812 GL_ScissorTest(false);
1815 extern void R_DrawLightningBeams (void);
1816 extern void VM_AddPolygonsToMeshQueue (void);
1817 void R_RenderScene(void)
1821 // don't let sound skip if going slow
1822 if (r_refdef.extraupdate)
1827 if (gl_support_fragment_shader)
1828 qglUseProgramObjectARB(0);
1830 R_MeshQueue_BeginScene();
1834 r_farclip = R_FarClip(r_vieworigin, r_viewforward, 768.0f) + 256.0f;
1835 nearclip = bound (0.001f, r_nearclip.value, r_farclip - 1.0f);
1837 if (r_rtworldshadows || r_rtdlightshadows)
1838 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_refdef.frustum_x, r_refdef.frustum_y, nearclip);
1840 GL_SetupView_Mode_Perspective(r_refdef.frustum_x, r_refdef.frustum_y, nearclip, r_farclip);
1842 GL_SetupView_Orientation_FromEntity(&r_view_matrix);
1844 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);
1848 R_WorldVisibility();
1849 if (r_timereport_active)
1850 R_TimeReport("worldvis");
1853 if (r_timereport_active)
1854 R_TimeReport("markentity");
1856 R_Shadow_UpdateWorldLightSelection();
1858 for (r_showtrispass = 0;r_showtrispass <= (r_showtris.value > 0);r_showtrispass++)
1864 GL_BlendFunc(GL_ONE, GL_ONE);
1865 GL_DepthTest(!r_showdisabledepthtest.integer);
1866 GL_DepthMask(GL_FALSE);
1867 memset(&m, 0, sizeof(m));
1869 //qglEnable(GL_LINE_SMOOTH);
1870 qglEnable(GL_POLYGON_OFFSET_LINE);
1871 qglPolygonOffset(0, r_showtris_polygonoffset.value);
1875 if (cl.csqc_vidvars.drawworld)
1877 // don't let sound skip if going slow
1878 if (r_refdef.extraupdate)
1882 GL_ShowTrisColor(0.025, 0.025, 0, 1);
1883 if (r_refdef.worldmodel && r_refdef.worldmodel->DrawSky)
1885 r_refdef.worldmodel->DrawSky(r_refdef.worldentity);
1886 if (r_timereport_active)
1887 R_TimeReport("worldsky");
1890 if (R_DrawBrushModelsSky() && r_timereport_active)
1891 R_TimeReport("bmodelsky");
1894 GL_ShowTrisColor(0.05, 0.05, 0.05, 1);
1895 if (r_refdef.worldmodel && r_refdef.worldmodel->Draw)
1897 r_refdef.worldmodel->Draw(r_refdef.worldentity);
1898 if (r_timereport_active)
1899 R_TimeReport("world");
1903 // don't let sound skip if going slow
1904 if (r_refdef.extraupdate)
1908 GL_ShowTrisColor(0, 0.015, 0, 1);
1911 if (r_timereport_active)
1912 R_TimeReport("models");
1914 // don't let sound skip if going slow
1915 if (r_refdef.extraupdate)
1919 GL_ShowTrisColor(0, 0, 0.033, 1);
1920 R_ShadowVolumeLighting(false);
1921 if (r_timereport_active)
1922 R_TimeReport("rtlights");
1924 // don't let sound skip if going slow
1925 if (r_refdef.extraupdate)
1929 GL_ShowTrisColor(0.1, 0, 0, 1);
1931 if (cl.csqc_vidvars.drawworld)
1933 R_DrawLightningBeams();
1934 if (r_timereport_active)
1935 R_TimeReport("lightning");
1938 if (r_timereport_active)
1939 R_TimeReport("particles");
1942 if (r_timereport_active)
1943 R_TimeReport("explosions");
1946 R_MeshQueue_RenderTransparent();
1947 if (r_timereport_active)
1948 R_TimeReport("drawtrans");
1950 if (cl.csqc_vidvars.drawworld)
1953 if (r_timereport_active)
1954 R_TimeReport("coronas");
1956 if(cl.csqc_vidvars.drawcrosshair)
1958 R_DrawWorldCrosshair();
1959 if (r_timereport_active)
1960 R_TimeReport("crosshair");
1963 VM_AddPolygonsToMeshQueue();
1965 R_MeshQueue_Render();
1969 //qglDisable(GL_LINE_SMOOTH);
1970 qglDisable(GL_POLYGON_OFFSET_LINE);
1976 R_MeshQueue_EndScene();
1978 // don't let sound skip if going slow
1979 if (r_refdef.extraupdate)
1982 if (gl_support_fragment_shader)
1983 qglUseProgramObjectARB(0);
1987 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
1990 float *v, *c, f1, f2, diff[3], vertex3f[8*3], color4f[8*4];
1992 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1993 GL_DepthMask(false);
1995 R_Mesh_Matrix(&identitymatrix);
1997 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2];
1998 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
1999 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
2000 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
2001 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
2002 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
2003 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
2004 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
2005 R_FillColors(color, 8, cr, cg, cb, ca);
2008 for (i = 0, v = vertex, c = color;i < 8;i++, v += 4, c += 4)
2010 f2 = VERTEXFOGTABLE(VectorDistance(v, r_vieworigin));
2012 c[0] = c[0] * f1 + fogcolor[0] * f2;
2013 c[1] = c[1] * f1 + fogcolor[1] * f2;
2014 c[2] = c[2] * f1 + fogcolor[2] * f2;
2017 memset(&m, 0, sizeof(m));
2018 m.pointer_vertex = vertex3f;
2019 m.pointer_color = color;
2025 int nomodelelements[24] =
2037 float nomodelvertex3f[6*3] =
2047 float nomodelcolor4f[6*4] =
2049 0.0f, 0.0f, 0.5f, 1.0f,
2050 0.0f, 0.0f, 0.5f, 1.0f,
2051 0.0f, 0.5f, 0.0f, 1.0f,
2052 0.0f, 0.5f, 0.0f, 1.0f,
2053 0.5f, 0.0f, 0.0f, 1.0f,
2054 0.5f, 0.0f, 0.0f, 1.0f
2057 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight)
2063 R_Mesh_Matrix(&ent->matrix);
2065 memset(&m, 0, sizeof(m));
2066 m.pointer_vertex = nomodelvertex3f;
2068 if (ent->flags & EF_ADDITIVE)
2070 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2071 GL_DepthMask(false);
2073 else if (ent->alpha < 1)
2075 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2076 GL_DepthMask(false);
2080 GL_BlendFunc(GL_ONE, GL_ZERO);
2083 GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
2086 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
2087 m.pointer_color = color4f;
2088 f2 = VERTEXFOGTABLE(VectorDistance(ent->origin, r_vieworigin));
2090 for (i = 0, c = color4f;i < 6;i++, c += 4)
2092 c[0] = (c[0] * f1 + fogcolor[0] * f2);
2093 c[1] = (c[1] * f1 + fogcolor[1] * f2);
2094 c[2] = (c[2] * f1 + fogcolor[2] * f2);
2098 else if (ent->alpha != 1)
2100 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
2101 m.pointer_color = color4f;
2102 for (i = 0, c = color4f;i < 6;i++, c += 4)
2106 m.pointer_color = nomodelcolor4f;
2108 R_Mesh_Draw(0, 6, 8, nomodelelements);
2111 void R_DrawNoModel(entity_render_t *ent)
2113 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
2114 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_vieworigin : ent->origin, R_DrawNoModel_TransparentCallback, ent, 0, r_shadow_rtlight);
2116 // R_DrawNoModelCallback(ent, 0);
2119 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
2121 vec3_t right1, right2, diff, normal;
2123 VectorSubtract (org2, org1, normal);
2125 // calculate 'right' vector for start
2126 VectorSubtract (r_vieworigin, org1, diff);
2127 CrossProduct (normal, diff, right1);
2128 VectorNormalize (right1);
2130 // calculate 'right' vector for end
2131 VectorSubtract (r_vieworigin, org2, diff);
2132 CrossProduct (normal, diff, right2);
2133 VectorNormalize (right2);
2135 vert[ 0] = org1[0] + width * right1[0];
2136 vert[ 1] = org1[1] + width * right1[1];
2137 vert[ 2] = org1[2] + width * right1[2];
2138 vert[ 3] = org1[0] - width * right1[0];
2139 vert[ 4] = org1[1] - width * right1[1];
2140 vert[ 5] = org1[2] - width * right1[2];
2141 vert[ 6] = org2[0] - width * right2[0];
2142 vert[ 7] = org2[1] - width * right2[1];
2143 vert[ 8] = org2[2] - width * right2[2];
2144 vert[ 9] = org2[0] + width * right2[0];
2145 vert[10] = org2[1] + width * right2[1];
2146 vert[11] = org2[2] + width * right2[2];
2149 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
2151 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)
2153 float fog = 0.0f, ifog;
2157 fog = VERTEXFOGTABLE(VectorDistance(origin, r_vieworigin));
2160 R_Mesh_Matrix(&identitymatrix);
2161 GL_BlendFunc(blendfunc1, blendfunc2);
2162 GL_DepthMask(false);
2163 GL_DepthTest(!depthdisable);
2165 varray_vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
2166 varray_vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
2167 varray_vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
2168 varray_vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
2169 varray_vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
2170 varray_vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
2171 varray_vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
2172 varray_vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
2173 varray_vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
2174 varray_vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
2175 varray_vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
2176 varray_vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
2178 memset(&m, 0, sizeof(m));
2179 m.tex[0] = R_GetTexture(texture);
2180 m.pointer_texcoord[0] = spritetexcoord2f;
2181 m.pointer_vertex = varray_vertex3f;
2183 GL_Color(cr * ifog, cg * ifog, cb * ifog, ca);
2184 R_Mesh_Draw(0, 4, 2, polygonelements);
2186 if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
2188 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
2189 GL_BlendFunc(blendfunc1, GL_ONE);
2190 GL_Color(fogcolor[0] * fog, fogcolor[1] * fog, fogcolor[2] * fog, ca);
2191 R_Mesh_Draw(0, 4, 2, polygonelements);
2195 int R_Mesh_AddVertex3f(rmesh_t *mesh, const float *v)
2199 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
2200 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
2202 if (i == mesh->numvertices)
2204 if (mesh->numvertices < mesh->maxvertices)
2206 VectorCopy(v, vertex3f);
2207 mesh->numvertices++;
2209 return mesh->numvertices;
2215 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
2219 element[0] = R_Mesh_AddVertex3f(mesh, vertex3f);vertex3f += 3;
2220 element[1] = R_Mesh_AddVertex3f(mesh, vertex3f);vertex3f += 3;
2221 e = mesh->element3i + mesh->numtriangles * 3;
2222 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
2224 element[2] = R_Mesh_AddVertex3f(mesh, vertex3f);
2225 if (mesh->numtriangles < mesh->maxtriangles)
2230 mesh->numtriangles++;
2232 element[1] = element[2];
2236 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
2238 int planenum, planenum2;
2241 mplane_t *plane, *plane2;
2242 float temppoints[2][256*3];
2243 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
2247 PolygonF_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->normal[3], 1024.0*1024.0*1024.0);
2248 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
2250 if (planenum2 == planenum)
2252 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);
2255 if (tempnumpoints < 3)
2257 // generate elements forming a triangle fan for this polygon
2258 R_Mesh_AddPolygon3f(mesh, tempnumpoints, temppoints[w]);
2262 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)
2264 texturelayer_t *layer;
2265 layer = t->currentlayers + t->currentnumlayers++;
2267 layer->depthmask = depthmask;
2268 layer->blendfunc1 = blendfunc1;
2269 layer->blendfunc2 = blendfunc2;
2270 layer->texture = texture;
2271 layer->texmatrix = *matrix;
2272 layer->color[0] = r;
2273 layer->color[1] = g;
2274 layer->color[2] = b;
2275 layer->color[3] = a;
2278 void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
2280 // FIXME: identify models using a better check than ent->model->brush.shadowmesh
2281 //int lightmode = ((ent->effects & EF_FULLBRIGHT) || ent->model->brush.shadowmesh) ? 0 : 2;
2284 texture_t *texture = t;
2285 model_t *model = ent->model;
2286 int s = ent->skinnum;
2287 if ((unsigned int)s >= (unsigned int)model->numskins)
2289 if (model->skinscenes)
2291 if (model->skinscenes[s].framecount > 1)
2292 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
2294 s = model->skinscenes[s].firstframe;
2297 t = t + s * model->num_surfaces;
2299 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];
2300 texture->currentframe = t;
2303 t->currentmaterialflags = t->basematerialflags;
2304 t->currentalpha = ent->alpha;
2305 if (t->basematerialflags & MATERIALFLAG_WATERALPHA)
2306 t->currentalpha *= r_wateralpha.value;
2307 if (!(ent->flags & RENDER_LIGHT))
2308 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
2309 if (ent->effects & EF_ADDITIVE)
2310 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_TRANSPARENT;
2311 else if (t->currentalpha < 1)
2312 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_TRANSPARENT;
2313 if (ent->effects & EF_NODEPTHTEST)
2314 t->currentmaterialflags |= MATERIALFLAG_NODEPTHTEST;
2315 if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
2316 t->currenttexmatrix = r_waterscrollmatrix;
2318 t->currenttexmatrix = identitymatrix;
2320 t->colormapping = VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f);
2321 t->basetexture = (!t->colormapping && t->skin.merged) ? t->skin.merged : t->skin.base;
2322 t->glosstexture = r_texture_white;
2323 t->specularpower = 8;
2324 t->specularscale = 0;
2325 if (r_shadow_gloss.integer > 0)
2329 if (r_shadow_glossintensity.value > 0)
2331 t->glosstexture = t->skin.gloss;
2332 t->specularscale = r_shadow_glossintensity.value;
2335 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
2336 t->specularscale = r_shadow_gloss2intensity.value;
2339 t->currentnumlayers = 0;
2340 if (!(t->currentmaterialflags & MATERIALFLAG_NODRAW))
2342 if (gl_lightmaps.integer)
2343 R_Texture_AddLayer(t, true, GL_ONE, GL_ZERO, TEXTURELAYERTYPE_LITTEXTURE_MULTIPASS, r_texture_white, &identitymatrix, 1, 1, 1, 1);
2344 else if (!(t->currentmaterialflags & MATERIALFLAG_SKY))
2346 int blendfunc1, blendfunc2, depthmask;
2347 if (t->currentmaterialflags & MATERIALFLAG_ADD)
2349 blendfunc1 = GL_SRC_ALPHA;
2350 blendfunc2 = GL_ONE;
2353 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
2355 blendfunc1 = GL_SRC_ALPHA;
2356 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
2361 blendfunc1 = GL_ONE;
2362 blendfunc2 = GL_ZERO;
2365 if (t->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL))
2367 rtexture_t *currentbasetexture;
2369 if (fogenabled && (t->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
2370 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
2371 currentbasetexture = (VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) < (1.0f / 1048576.0f) && t->skin.merged) ? t->skin.merged : t->skin.base;
2372 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2374 // fullbright is not affected by r_lightmapintensity
2375 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
2376 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->skin.pants)
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], ent->colormap_pantscolor[1] * ent->colormod[1], ent->colormap_pantscolor[2] * ent->colormod[2], t->currentalpha);
2378 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->skin.shirt)
2379 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);
2385 // q3bsp has no lightmap updates, so the lightstylevalue that
2386 // would normally be baked into the lightmaptexture must be
2387 // applied to the color
2388 if (ent->model->type == mod_brushq3)
2389 colorscale *= r_refdef.lightstylevalue[0] * (1.0f / 256.0f);
2390 colorscale *= r_lightmapintensity;
2391 if (r_textureunits.integer >= 2 && gl_combine.integer)
2392 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);
2393 else if ((t->currentmaterialflags & MATERIALFLAG_TRANSPARENT) == 0)
2394 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);
2396 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);
2397 if (r_ambient.value >= (1.0f/64.0f))
2398 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);
2399 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->skin.pants)
2401 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);
2402 if (r_ambient.value >= (1.0f/64.0f))
2403 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);
2405 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->skin.shirt)
2407 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);
2408 if (r_ambient.value >= (1.0f/64.0f))
2409 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);
2412 if (t->skin.glow != NULL)
2413 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.glow, &t->currenttexmatrix, 1, 1, 1, t->currentalpha);
2414 if (fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
2416 // if this is opaque use alpha blend which will darken the earlier
2419 // if this is an alpha blended material, all the earlier passes
2420 // were darkened by fog already, so we only need to add the fog
2421 // color ontop through the fog mask texture
2423 // if this is an additive blended material, all the earlier passes
2424 // were darkened by fog already, and we should not add fog color
2425 // (because the background was not darkened, there is no fog color
2426 // that was lost behind it).
2427 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, (t->currentmaterialflags & MATERIALFLAG_TRANSPARENT) ? GL_ONE : GL_ONE_MINUS_SRC_ALPHA, TEXTURELAYERTYPE_FOG, t->skin.fog, &identitymatrix, fogcolor[0], fogcolor[1], fogcolor[2], t->currentalpha);
2434 void R_UpdateAllTextureInfo(entity_render_t *ent)
2438 for (i = 0;i < ent->model->num_textures;i++)
2439 R_UpdateTextureInfo(ent, ent->model->data_textures + i);
2442 float *rsurface_vertex3f;
2443 float *rsurface_svector3f;
2444 float *rsurface_tvector3f;
2445 float *rsurface_normal3f;
2446 float *rsurface_lightmapcolor4f;
2448 void RSurf_SetVertexPointer(const entity_render_t *ent, const texture_t *texture, const msurface_t *surface, const vec3_t modelorg, qboolean generatenormals, qboolean generatetangents)
2450 if ((ent->frameblend[0].lerp != 1 || ent->frameblend[0].frame != 0) && (surface->groupmesh->data_morphvertex3f || surface->groupmesh->data_vertexboneweights))
2452 rsurface_vertex3f = varray_vertex3f;
2453 Mod_Alias_GetMesh_Vertex3f(ent->model, ent->frameblend, surface->groupmesh, rsurface_vertex3f);
2454 if (generatetangents || (texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2)))
2456 rsurface_svector3f = varray_svector3f;
2457 rsurface_tvector3f = varray_tvector3f;
2458 rsurface_normal3f = varray_normal3f;
2459 Mod_BuildTextureVectorsAndNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface_vertex3f, surface->groupmesh->data_texcoordtexture2f, surface->groupmesh->data_element3i + surface->num_firsttriangle * 3, rsurface_svector3f, rsurface_tvector3f, rsurface_normal3f, r_smoothnormals_areaweighting.integer);
2463 rsurface_svector3f = NULL;
2464 rsurface_tvector3f = NULL;
2465 if (generatenormals)
2467 rsurface_normal3f = varray_normal3f;
2468 Mod_BuildNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface_vertex3f, surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle, rsurface_normal3f, r_smoothnormals_areaweighting.integer);
2471 rsurface_normal3f = NULL;
2476 rsurface_vertex3f = surface->groupmesh->data_vertex3f;
2477 rsurface_svector3f = surface->groupmesh->data_svector3f;
2478 rsurface_tvector3f = surface->groupmesh->data_tvector3f;
2479 rsurface_normal3f = surface->groupmesh->data_normal3f;
2481 if (texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
2484 float center[3], forward[3], right[3], up[3], v[4][3];
2485 matrix4x4_t matrix1, imatrix1;
2486 Matrix4x4_Transform(&ent->inversematrix, r_viewforward, forward);
2487 Matrix4x4_Transform(&ent->inversematrix, r_viewright, right);
2488 Matrix4x4_Transform(&ent->inversematrix, r_viewup, up);
2489 // a single autosprite surface can contain multiple sprites...
2490 for (j = 0;j < surface->num_vertices - 3;j += 4)
2492 VectorClear(center);
2493 for (i = 0;i < 4;i++)
2494 VectorAdd(center, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
2495 VectorScale(center, 0.25f, center);
2496 // FIXME: calculate vectors from triangle edges instead of using texture vectors as an easy way out?
2497 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);
2498 Matrix4x4_Invert_Simple(&imatrix1, &matrix1);
2499 for (i = 0;i < 4;i++)
2500 Matrix4x4_Transform(&imatrix1, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, v[i]);
2501 if (texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE2)
2503 forward[0] = modelorg[0] - center[0];
2504 forward[1] = modelorg[1] - center[1];
2506 VectorNormalize(forward);
2507 right[0] = forward[1];
2508 right[1] = -forward[0];
2510 VectorSet(up, 0, 0, 1);
2512 for (i = 0;i < 4;i++)
2513 VectorMAMAMAM(1, center, v[i][0], forward, v[i][1], right, v[i][2], up, varray_vertex3f + (surface->num_firstvertex+i+j) * 3);
2515 rsurface_vertex3f = varray_vertex3f;
2516 rsurface_svector3f = varray_svector3f;
2517 rsurface_tvector3f = varray_tvector3f;
2518 rsurface_normal3f = varray_normal3f;
2519 Mod_BuildTextureVectorsAndNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface_vertex3f, surface->groupmesh->data_texcoordtexture2f, surface->groupmesh->data_element3i + surface->num_firsttriangle * 3, rsurface_svector3f, rsurface_tvector3f, rsurface_normal3f, r_smoothnormals_areaweighting.integer);
2521 R_Mesh_VertexPointer(rsurface_vertex3f);
2524 static void RSurf_Draw(const msurface_t *surface)
2526 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2527 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2528 GL_LockArrays(0, 0);
2531 static void RSurf_DrawLightmap(const entity_render_t *ent, const texture_t *texture, const msurface_t *surface, const vec3_t modelorg, float r, float g, float b, float a, int lightmode, qboolean applycolor, qboolean applyfog)
2536 RSurf_SetVertexPointer(ent, texture, surface, modelorg, lightmode >= 2, false);
2540 vec4_t ambientcolor;
2541 vec3_t diffusecolor;
2543 VectorCopy(ent->modellight_lightdir, lightdir);
2544 ambientcolor[0] = ent->modellight_ambient[0] * r * 0.5f;
2545 ambientcolor[1] = ent->modellight_ambient[1] * g * 0.5f;
2546 ambientcolor[2] = ent->modellight_ambient[2] * b * 0.5f;
2547 diffusecolor[0] = ent->modellight_diffuse[0] * r * 0.5f;
2548 diffusecolor[1] = ent->modellight_diffuse[1] * g * 0.5f;
2549 diffusecolor[2] = ent->modellight_diffuse[2] * b * 0.5f;
2550 if (VectorLength2(diffusecolor) > 0)
2552 int numverts = surface->num_vertices;
2553 v = rsurface_vertex3f + 3 * surface->num_firstvertex;
2554 c2 = rsurface_normal3f + 3 * surface->num_firstvertex;
2555 c = varray_color4f + 4 * surface->num_firstvertex;
2556 // q3-style directional shading
2557 for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
2559 if ((f = DotProduct(c2, lightdir)) > 0)
2561 VectorMA(ambientcolor, f, diffusecolor, c);
2565 VectorCopy4(ambientcolor, c);
2572 rsurface_lightmapcolor4f = varray_color4f;
2576 r = ambientcolor[0];
2577 g = ambientcolor[1];
2578 b = ambientcolor[2];
2579 rsurface_lightmapcolor4f = NULL;
2582 else if (lightmode >= 1)
2584 if (surface->lightmapinfo && surface->lightmapinfo->stainsamples)
2586 for (i = 0, c = varray_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
2588 if (surface->lightmapinfo->samples)
2590 const unsigned char *lm = surface->lightmapinfo->samples + (surface->groupmesh->data_lightmapoffsets + surface->num_firstvertex)[i];
2591 float scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
2592 VectorScale(lm, scale, c);
2593 if (surface->lightmapinfo->styles[1] != 255)
2595 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
2597 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
2598 VectorMA(c, scale, lm, c);
2599 if (surface->lightmapinfo->styles[2] != 255)
2602 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
2603 VectorMA(c, scale, lm, c);
2604 if (surface->lightmapinfo->styles[3] != 255)
2607 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
2608 VectorMA(c, scale, lm, c);
2616 rsurface_lightmapcolor4f = varray_color4f;
2619 rsurface_lightmapcolor4f = surface->groupmesh->data_lightmapcolor4f;
2622 rsurface_lightmapcolor4f = NULL;
2625 if (rsurface_lightmapcolor4f)
2627 for (i = 0, v = (rsurface_vertex3f + 3 * surface->num_firstvertex), c = (rsurface_lightmapcolor4f + 4 * surface->num_firstvertex), c2 = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4, c2 += 4)
2629 f = 1 - VERTEXFOGTABLE(VectorDistance(v, modelorg));
2638 for (i = 0, v = (rsurface_vertex3f + 3 * surface->num_firstvertex), c2 = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c2 += 4)
2640 f = 1 - VERTEXFOGTABLE(VectorDistance(v, modelorg));
2647 rsurface_lightmapcolor4f = varray_color4f;
2649 if (applycolor && rsurface_lightmapcolor4f)
2651 for (i = 0, c = (rsurface_lightmapcolor4f + 4 * surface->num_firstvertex), c2 = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, c += 4, c2 += 4)
2658 rsurface_lightmapcolor4f = varray_color4f;
2660 R_Mesh_ColorPointer(rsurface_lightmapcolor4f);
2661 GL_Color(r, g, b, a);
2662 RSurf_Draw(surface);
2665 static void R_DrawTextureSurfaceList(const entity_render_t *ent, texture_t *texture, int texturenumsurfaces, const msurface_t **texturesurfacelist, const vec3_t modelorg)
2667 int texturesurfaceindex;
2669 const msurface_t *surface;
2670 qboolean applycolor;
2673 if (texture->currentmaterialflags & MATERIALFLAG_NODRAW)
2675 r_shadow_rtlight = NULL;
2676 renderstats.entities_surfaces += texturenumsurfaces;
2677 // FIXME: identify models using a better check than ent->model->brush.shadowmesh
2678 lightmode = ((ent->effects & EF_FULLBRIGHT) || ent->model->brush.shadowmesh) ? 0 : 2;
2679 GL_DepthTest(!(texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
2680 if ((texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (ent->flags & RENDER_NOCULLFACE))
2681 qglDisable(GL_CULL_FACE);
2682 if (texture->currentmaterialflags & MATERIALFLAG_SKY)
2684 // transparent sky would be ridiculous
2685 if (!(texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
2690 skyrendernow = false;
2691 if (skyrendermasked)
2694 // restore entity matrix and GL_Color
2695 R_Mesh_Matrix(&ent->matrix);
2699 // LordHavoc: HalfLife maps have freaky skypolys...
2700 //if (!ent->model->brush.ishlbsp)
2702 if (skyrendermasked)
2704 // depth-only (masking)
2705 GL_ColorMask(0,0,0,0);
2706 // just to make sure that braindead drivers don't draw anything
2707 // despite that colormask...
2708 GL_BlendFunc(GL_ZERO, GL_ONE);
2713 GL_BlendFunc(GL_ONE, GL_ZERO);
2715 GL_Color(fogcolor[0], fogcolor[1], fogcolor[2], 1);
2716 memset(&m, 0, sizeof(m));
2718 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2720 surface = texturesurfacelist[texturesurfaceindex];
2721 RSurf_SetVertexPointer(ent, texture, surface, modelorg, false, false);
2722 RSurf_Draw(surface);
2724 if (skyrendermasked)
2725 GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
2729 else if (r_glsl.integer && gl_support_fragment_shader)
2731 if (texture->currentmaterialflags & MATERIALFLAG_ADD)
2733 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2734 GL_DepthMask(false);
2736 else if (texture->currentmaterialflags & MATERIALFLAG_ALPHA)
2738 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2739 GL_DepthMask(false);
2743 GL_BlendFunc(GL_ONE, GL_ZERO);
2747 memset(&m, 0, sizeof(m));
2749 GL_Color(ent->colormod[0], ent->colormod[1], ent->colormod[2], texture->currentalpha);
2750 R_SetupSurfaceShader(ent, texture, modelorg, vec3_origin, lightmode == 2);
2751 if (!r_glsl_permutation)
2755 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2757 surface = texturesurfacelist[texturesurfaceindex];
2758 RSurf_SetVertexPointer(ent, texture, surface, modelorg, false, true);
2759 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2760 R_Mesh_TexCoordPointer(1, 3, rsurface_svector3f);
2761 R_Mesh_TexCoordPointer(2, 3, rsurface_tvector3f);
2762 R_Mesh_TexCoordPointer(3, 3, rsurface_normal3f);
2763 RSurf_Draw(surface);
2768 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2770 surface = texturesurfacelist[texturesurfaceindex];
2771 RSurf_SetVertexPointer(ent, texture, surface, modelorg, false, true);
2772 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2773 R_Mesh_TexCoordPointer(1, 3, rsurface_svector3f);
2774 R_Mesh_TexCoordPointer(2, 3, rsurface_tvector3f);
2775 R_Mesh_TexCoordPointer(3, 3, rsurface_normal3f);
2776 R_Mesh_TexCoordPointer(4, 2, surface->groupmesh->data_texcoordlightmap2f);
2777 if (surface->lightmaptexture)
2779 R_Mesh_TexBind(7, R_GetTexture(surface->lightmaptexture));
2780 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
2781 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
2782 //R_Mesh_TexBind(8, R_GetTexture(surface->deluxemaptexture));
2783 R_Mesh_ColorPointer(NULL);
2787 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
2788 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
2789 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
2790 R_Mesh_ColorPointer(surface->groupmesh->data_lightmapcolor4f);
2792 RSurf_Draw(surface);
2795 qglUseProgramObjectARB(0);
2797 else if (texture->currentnumlayers)
2800 texturelayer_t *layer;
2801 for (layerindex = 0, layer = texture->currentlayers;layerindex < texture->currentnumlayers;layerindex++, layer++)
2804 int layertexrgbscale;
2805 GL_DepthMask(layer->depthmask);
2806 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
2807 if ((layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2) && (gl_combine.integer || layer->depthmask))
2809 layertexrgbscale = 4;
2810 VectorScale(layer->color, 0.25f, layercolor);
2812 else if ((layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1) && (gl_combine.integer || layer->depthmask))
2814 layertexrgbscale = 2;
2815 VectorScale(layer->color, 0.5f, layercolor);
2819 layertexrgbscale = 1;
2820 VectorScale(layer->color, 1.0f, layercolor);
2822 layercolor[3] = layer->color[3];
2823 GL_Color(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
2824 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
2825 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
2826 switch (layer->type)
2828 case TEXTURELAYERTYPE_LITTEXTURE_COMBINE:
2829 memset(&m, 0, sizeof(m));
2830 m.tex[1] = R_GetTexture(layer->texture);
2831 m.texmatrix[1] = layer->texmatrix;
2832 m.texrgbscale[1] = layertexrgbscale;
2833 m.pointer_color = varray_color4f;
2837 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2839 surface = texturesurfacelist[texturesurfaceindex];
2840 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
2841 R_Mesh_TexCoordPointer(1, 2, surface->groupmesh->data_texcoordtexture2f);
2842 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2843 RSurf_DrawLightmap(ent, texture, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 2, applycolor, applyfog);
2848 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2850 surface = texturesurfacelist[texturesurfaceindex];
2851 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
2852 R_Mesh_TexCoordPointer(1, 2, surface->groupmesh->data_texcoordtexture2f);
2853 if (surface->lightmaptexture)
2855 R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
2856 RSurf_DrawLightmap(ent, texture, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, applyfog);
2860 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2861 RSurf_DrawLightmap(ent, texture, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 1, applycolor, applyfog);
2866 case TEXTURELAYERTYPE_LITTEXTURE_MULTIPASS:
2867 memset(&m, 0, sizeof(m));
2868 m.tex[0] = R_GetTexture(layer->texture);
2869 m.texmatrix[0] = layer->texmatrix;
2870 m.pointer_color = varray_color4f;
2871 m.texrgbscale[0] = layertexrgbscale;
2875 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2877 surface = texturesurfacelist[texturesurfaceindex];
2878 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
2879 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2880 RSurf_DrawLightmap(ent, texture, surface, modelorg, 1, 1, 1, 1, 2, false, false);
2885 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2887 surface = texturesurfacelist[texturesurfaceindex];
2888 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
2889 if (surface->lightmaptexture)
2891 R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
2892 RSurf_DrawLightmap(ent, texture, surface, modelorg, 1, 1, 1, 1, 0, false, false);
2896 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2897 RSurf_DrawLightmap(ent, texture, surface, modelorg, 1, 1, 1, 1, 1, false, false);
2901 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
2902 memset(&m, 0, sizeof(m));
2903 m.tex[0] = R_GetTexture(layer->texture);
2904 m.texmatrix[0] = layer->texmatrix;
2905 m.pointer_color = varray_color4f;
2906 m.texrgbscale[0] = layertexrgbscale;
2908 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2910 surface = texturesurfacelist[texturesurfaceindex];
2911 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2912 RSurf_DrawLightmap(ent, texture, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, applyfog);
2915 case TEXTURELAYERTYPE_LITTEXTURE_VERTEX:
2916 memset(&m, 0, sizeof(m));
2917 m.tex[0] = R_GetTexture(layer->texture);
2918 m.texmatrix[0] = layer->texmatrix;
2919 m.texrgbscale[0] = layertexrgbscale;
2920 m.pointer_color = varray_color4f;
2924 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2926 surface = texturesurfacelist[texturesurfaceindex];
2927 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2928 RSurf_DrawLightmap(ent, texture, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 2, applycolor, applyfog);
2933 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2935 surface = texturesurfacelist[texturesurfaceindex];
2936 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2937 RSurf_DrawLightmap(ent, texture, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 1, applycolor, applyfog);
2941 case TEXTURELAYERTYPE_TEXTURE:
2942 memset(&m, 0, sizeof(m));
2943 m.tex[0] = R_GetTexture(layer->texture);
2944 m.texmatrix[0] = layer->texmatrix;
2945 m.pointer_color = varray_color4f;
2946 m.texrgbscale[0] = layertexrgbscale;
2948 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2950 surface = texturesurfacelist[texturesurfaceindex];
2951 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2952 RSurf_DrawLightmap(ent, texture, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, applyfog);
2955 case TEXTURELAYERTYPE_FOG:
2956 memset(&m, 0, sizeof(m));
2959 m.tex[0] = R_GetTexture(layer->texture);
2960 m.texmatrix[0] = layer->texmatrix;
2963 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2967 surface = texturesurfacelist[texturesurfaceindex];
2968 RSurf_SetVertexPointer(ent, texture, surface, modelorg, false, false);
2970 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2971 R_Mesh_ColorPointer(varray_color4f);
2972 for (i = 0, v = (rsurface_vertex3f + 3 * surface->num_firstvertex), c = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4)
2974 f = VERTEXFOGTABLE(VectorDistance(v, modelorg));
2975 c[0] = layercolor[0];
2976 c[1] = layercolor[1];
2977 c[2] = layercolor[2];
2978 c[3] = f * layercolor[3];
2980 RSurf_Draw(surface);
2984 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
2986 // if trying to do overbright on first pass of an opaque surface
2987 // when combine is not supported, brighten as a post process
2988 if (layertexrgbscale > 1 && !gl_combine.integer && layer->depthmask)
2991 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
2992 GL_Color(1, 1, 1, 1);
2993 memset(&m, 0, sizeof(m));
2995 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2997 surface = texturesurfacelist[texturesurfaceindex];
2998 RSurf_SetVertexPointer(ent, texture, surface, modelorg, false, false);
2999 for (scale = 1;scale < layertexrgbscale;scale <<= 1)
3000 RSurf_Draw(surface);
3004 if (r_shownormals.integer && !r_showtrispass)
3008 GL_DepthTest(!r_showdisabledepthtest.integer);
3009 GL_DepthMask(texture->currentlayers->depthmask);
3010 GL_BlendFunc(texture->currentlayers->blendfunc1, texture->currentlayers->blendfunc2);
3011 memset(&m, 0, sizeof(m));
3013 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3015 surface = texturesurfacelist[texturesurfaceindex];
3016 RSurf_SetVertexPointer(ent, texture, surface, modelorg, false, true);
3017 GL_Color(1, 0, 0, 1);
3019 for (j = 0, k = surface->num_firstvertex;j < surface->num_vertices;j++, k++)
3021 VectorCopy(rsurface_vertex3f + k * 3, v);
3022 qglVertex3f(v[0], v[1], v[2]);
3023 VectorMA(v, 8, rsurface_svector3f + k * 3, v);
3024 qglVertex3f(v[0], v[1], v[2]);
3026 GL_Color(0, 0, 1, 1);
3027 for (j = 0, k = surface->num_firstvertex;j < surface->num_vertices;j++, k++)
3029 VectorCopy(rsurface_vertex3f + k * 3, v);
3030 qglVertex3f(v[0], v[1], v[2]);
3031 VectorMA(v, 8, rsurface_tvector3f + k * 3, v);
3032 qglVertex3f(v[0], v[1], v[2]);
3034 GL_Color(0, 1, 0, 1);
3035 for (j = 0, k = surface->num_firstvertex;j < surface->num_vertices;j++, k++)
3037 VectorCopy(rsurface_vertex3f + k * 3, v);
3038 qglVertex3f(v[0], v[1], v[2]);
3039 VectorMA(v, 8, rsurface_normal3f + k * 3, v);
3040 qglVertex3f(v[0], v[1], v[2]);
3046 if ((texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (ent->flags & RENDER_NOCULLFACE))
3047 qglEnable(GL_CULL_FACE);
3050 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight)
3052 const msurface_t *surface = ent->model->data_surfaces + surfacenumber;
3056 texture = surface->texture;
3057 if (texture->basematerialflags & MATERIALFLAG_SKY)
3058 return; // transparent sky is too difficult
3059 R_UpdateTextureInfo(ent, texture);
3061 R_Mesh_Matrix(&ent->matrix);
3062 Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
3063 R_DrawTextureSurfaceList(ent, texture->currentframe, 1, &surface, modelorg);
3066 void R_QueueTextureSurfaceList(entity_render_t *ent, texture_t *texture, int texturenumsurfaces, const msurface_t **texturesurfacelist, const vec3_t modelorg)
3068 int texturesurfaceindex;
3069 const msurface_t *surface;
3070 vec3_t tempcenter, center;
3071 if (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT)
3073 // drawing sky transparently would be too difficult
3074 if (!(texture->currentmaterialflags & MATERIALFLAG_SKY))
3076 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3078 surface = texturesurfacelist[texturesurfaceindex];
3079 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
3080 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
3081 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
3082 Matrix4x4_Transform(&ent->matrix, tempcenter, center);
3083 R_MeshQueue_AddTransparent(texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_vieworigin : center, R_DrawSurface_TransparentCallback, ent, surface - ent->model->data_surfaces, r_shadow_rtlight);
3088 R_DrawTextureSurfaceList(ent, texture, texturenumsurfaces, texturesurfacelist, modelorg);
3091 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
3092 void R_DrawSurfaces(entity_render_t *ent, qboolean skysurfaces)
3094 int i, j, f, flagsmask;
3095 int counttriangles = 0;
3096 msurface_t *surface, **surfacechain;
3097 texture_t *t, *texture;
3098 model_t *model = ent->model;
3100 const int maxsurfacelist = 1024;
3101 int numsurfacelist = 0;
3102 const msurface_t *surfacelist[1024];
3105 R_Mesh_Matrix(&ent->matrix);
3106 Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
3108 // update light styles
3109 if (!skysurfaces && model->brushq1.light_styleupdatechains)
3111 for (i = 0;i < model->brushq1.light_styles;i++)
3113 if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
3115 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
3116 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
3117 for (;(surface = *surfacechain);surfacechain++)
3118 surface->cached_dlight = true;
3123 R_UpdateAllTextureInfo(ent);
3124 flagsmask = skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL);
3129 if (ent == r_refdef.worldentity)
3131 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
3133 if (!r_worldsurfacevisible[j])
3135 if (t != surface->texture)
3139 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
3142 t = surface->texture;
3143 texture = t->currentframe;
3144 f = texture->currentmaterialflags & flagsmask;
3146 if (f && surface->num_triangles)
3148 // if lightmap parameters changed, rebuild lightmap texture
3149 if (surface->cached_dlight)
3150 R_BuildLightMap(ent, surface);
3151 // add face to draw list
3152 surfacelist[numsurfacelist++] = surface;
3153 counttriangles += surface->num_triangles;
3154 if (numsurfacelist >= maxsurfacelist)
3156 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
3164 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
3166 if (t != surface->texture)
3170 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
3173 t = surface->texture;
3174 texture = t->currentframe;
3175 f = texture->currentmaterialflags & flagsmask;
3177 if (f && surface->num_triangles)
3179 // if lightmap parameters changed, rebuild lightmap texture
3180 if (surface->cached_dlight)
3181 R_BuildLightMap(ent, surface);
3182 // add face to draw list
3183 surfacelist[numsurfacelist++] = surface;
3184 counttriangles += surface->num_triangles;
3185 if (numsurfacelist >= maxsurfacelist)
3187 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
3194 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
3195 if (!r_showtrispass)
3196 renderstats.entities_triangles += counttriangles;
3197 if (gl_support_fragment_shader)
3198 qglUseProgramObjectARB(0);