2 Copyright (C) 1996-1997 Id Software, Inc.
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26 mempool_t *r_main_mempool;
27 rtexturepool_t *r_main_texturepool;
29 // used for dlight push checking and other things
34 renderstats_t renderstats;
36 // true during envmap command capture
39 // maximum visible distance (recalculated from world box each frame)
41 // brightness of world lightmaps and related lighting
42 // (often reduced when world rtlights are enabled)
43 float r_lightmapintensity;
44 // whether to draw world lights realtime, dlights realtime, and their shadows
46 qboolean r_rtworldshadows;
48 qboolean r_rtdlightshadows;
63 matrix4x4_t r_view_matrix;
64 float r_polygonfactor;
65 float r_polygonoffset;
66 float r_shadowpolygonfactor;
67 float r_shadowpolygonoffset;
73 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
74 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
75 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
76 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"};
77 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"};
78 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
79 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"};
80 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"};
81 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"};
82 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
83 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
84 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
85 cvar_t r_fullbright = {0, "r_fullbright","0", "make everything bright cheat (not allowed in multiplayer)"};
86 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
87 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
88 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
90 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
91 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
92 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
93 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
94 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
95 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
96 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
98 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)"};
100 cvar_t r_glsl = {0, "r_glsl", "1", "enables use of OpenGL 2.0 pixel shaders for lighting"};
101 cvar_t r_glsl_offsetmapping = {0, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
102 cvar_t r_glsl_offsetmapping_reliefmapping = {0, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
103 cvar_t r_glsl_offsetmapping_scale = {0, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
104 cvar_t r_glsl_usehalffloat = {0, "r_glsl_usehalffloat", "0", "use half and hvec variables in GLSL shader for a speed gain (NVIDIA only)"};
105 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"};
106 cvar_t r_glsl_deluxemapping = {0, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"};
108 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1", "enables animation smoothing on sprites (requires r_lerpmodels 1)"};
109 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
110 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
112 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
113 cvar_t r_bloom_intensity = {CVAR_SAVE, "r_bloom_intensity", "1.5", "how bright the glow is"};
114 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
115 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
116 cvar_t r_bloom_power = {CVAR_SAVE, "r_bloom_power", "2", "how much to darken the image before blurring to make the bloom effect"};
118 cvar_t r_smoothnormals_areaweighting = {0, "r_smoothnormals_areaweighting", "1", "uses significantly faster (and supposedly higher quality) area-weighted vertex normals and tangent vectors rather than summing normalized triangle normals and tangents"};
120 cvar_t developer_texturelogging = {0, "developer_texturelogging", "0", "produces a textures.log file containing names of skins and map textures the engine tried to load"};
122 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
124 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"}; // used for testing renderer code changes, otherwise does nothing
126 rtexture_t *r_bloom_texture_screen;
127 rtexture_t *r_bloom_texture_bloom;
128 rtexture_t *r_texture_blanknormalmap;
129 rtexture_t *r_texture_white;
130 rtexture_t *r_texture_black;
131 rtexture_t *r_texture_notexture;
132 rtexture_t *r_texture_whitecube;
133 rtexture_t *r_texture_normalizationcube;
134 rtexture_t *r_texture_fogattenuation;
135 rtexture_t *r_texture_fogintensity;
137 // information about each possible shader permutation
138 r_glsl_permutation_t r_glsl_permutations[SHADERPERMUTATION_COUNT];
139 // currently selected permutation
140 r_glsl_permutation_t *r_glsl_permutation;
142 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
145 for (i = 0;i < verts;i++)
156 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
159 for (i = 0;i < verts;i++)
174 vec_t fogtabledistmultiplier;
175 float fogtable[FOGTABLEWIDTH];
176 float fog_density, fog_red, fog_green, fog_blue;
178 qboolean oldgl_fogenable;
179 void R_UpdateFog(void)
181 if (gamemode == GAME_NEHAHRA)
183 if (gl_fogenable.integer)
185 oldgl_fogenable = true;
186 fog_density = gl_fogdensity.value;
187 fog_red = gl_fogred.value;
188 fog_green = gl_foggreen.value;
189 fog_blue = gl_fogblue.value;
191 else if (oldgl_fogenable)
193 oldgl_fogenable = false;
202 fogcolor[0] = fog_red = bound(0.0f, fog_red , 1.0f);
203 fogcolor[1] = fog_green = bound(0.0f, fog_green, 1.0f);
204 fogcolor[2] = fog_blue = bound(0.0f, fog_blue , 1.0f);
209 fogdensity = -4000.0f / (fog_density * fog_density);
210 // this is the point where the fog reaches 0.9986 alpha, which we
211 // consider a good enough cutoff point for the texture
212 // (0.9986 * 256 == 255.6)
213 fogrange = 400 / fog_density;
214 fograngerecip = 1.0f / fogrange;
215 fogtabledistmultiplier = FOGTABLEWIDTH * fograngerecip;
216 // fog color was already set
222 // FIXME: move this to client?
225 if (gamemode == GAME_NEHAHRA)
227 Cvar_Set("gl_fogenable", "0");
228 Cvar_Set("gl_fogdensity", "0.2");
229 Cvar_Set("gl_fogred", "0.3");
230 Cvar_Set("gl_foggreen", "0.3");
231 Cvar_Set("gl_fogblue", "0.3");
233 fog_density = fog_red = fog_green = fog_blue = 0.0f;
236 // FIXME: move this to client?
237 void FOG_registercvars(void)
242 if (gamemode == GAME_NEHAHRA)
244 Cvar_RegisterVariable (&gl_fogenable);
245 Cvar_RegisterVariable (&gl_fogdensity);
246 Cvar_RegisterVariable (&gl_fogred);
247 Cvar_RegisterVariable (&gl_foggreen);
248 Cvar_RegisterVariable (&gl_fogblue);
249 Cvar_RegisterVariable (&gl_fogstart);
250 Cvar_RegisterVariable (&gl_fogend);
253 r = (-1.0/256.0) * (FOGTABLEWIDTH * FOGTABLEWIDTH);
254 for (x = 0;x < FOGTABLEWIDTH;x++)
256 alpha = exp(r / ((double)x*(double)x));
257 if (x == FOGTABLEWIDTH - 1)
259 fogtable[x] = bound(0, alpha, 1);
263 static void R_BuildBlankTextures(void)
265 unsigned char data[4];
266 data[0] = 128; // normal X
267 data[1] = 128; // normal Y
268 data[2] = 255; // normal Z
269 data[3] = 128; // height
270 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
275 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
280 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
283 static void R_BuildNoTexture(void)
286 unsigned char pix[16][16][4];
287 // this makes a light grey/dark grey checkerboard texture
288 for (y = 0;y < 16;y++)
290 for (x = 0;x < 16;x++)
292 if ((y < 8) ^ (x < 8))
308 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_RGBA, TEXF_MIPMAP, NULL);
311 static void R_BuildWhiteCube(void)
313 unsigned char data[6*1*1*4];
314 data[ 0] = 255;data[ 1] = 255;data[ 2] = 255;data[ 3] = 255;
315 data[ 4] = 255;data[ 5] = 255;data[ 6] = 255;data[ 7] = 255;
316 data[ 8] = 255;data[ 9] = 255;data[10] = 255;data[11] = 255;
317 data[12] = 255;data[13] = 255;data[14] = 255;data[15] = 255;
318 data[16] = 255;data[17] = 255;data[18] = 255;data[19] = 255;
319 data[20] = 255;data[21] = 255;data[22] = 255;data[23] = 255;
320 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
323 static void R_BuildNormalizationCube(void)
327 vec_t s, t, intensity;
329 unsigned char data[6][NORMSIZE][NORMSIZE][4];
330 for (side = 0;side < 6;side++)
332 for (y = 0;y < NORMSIZE;y++)
334 for (x = 0;x < NORMSIZE;x++)
336 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
337 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
372 intensity = 127.0f / sqrt(DotProduct(v, v));
373 data[side][y][x][0] = 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"
447 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
448 "varying myhvec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
449 "varying myhvec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
450 "varying myhvec3 VectorR; // direction of R texcoord (surface normal)\n"
456 "// vertex shader specific:\n"
457 "#ifdef VERTEX_SHADER\n"
459 "#ifdef MODE_LIGHTSOURCE\n"
460 "uniform vec3 LightPosition;\n"
463 "#if defined(USESPECULAR) || defined(USEFOG) || defined(USEOFFSETMAPPING)\n"
464 "uniform vec3 EyePosition;\n"
467 "#ifdef MODE_LIGHTDIRECTION\n"
468 "uniform myhvec3 LightDir;\n"
471 "// TODO: get rid of tangentt (texcoord2) and use a crossproduct to regenerate it from tangents (texcoord1) and normal (texcoord3)\n"
475 " // copy the surface texcoord\n"
476 " TexCoord = vec2(gl_TextureMatrix[0] * gl_MultiTexCoord0);\n"
477 "#if !defined(MODE_LIGHTSOURCE) && !defined(MODE_LIGHTDIRECTION)\n"
478 " TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
480 " gl_FrontColor = gl_Color;\n"
482 "#ifdef MODE_LIGHTSOURCE\n"
483 " // transform vertex position into light attenuation/cubemap space\n"
484 " // (-1 to +1 across the light box)\n"
485 " CubeVector = vec3(gl_TextureMatrix[3] * gl_Vertex);\n"
487 " // transform unnormalized light direction into tangent space\n"
488 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
489 " // normalize it per pixel)\n"
490 " vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
491 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
492 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
493 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
496 "#ifdef MODE_LIGHTDIRECTION\n"
497 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
498 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
499 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
502 "#if defined(USESPECULAR) || defined(USEFOG) || defined(USEOFFSETMAPPING)\n"
503 " // transform unnormalized eye direction into tangent space\n"
504 " vec3 eyeminusvertex = EyePosition - gl_Vertex.xyz;\n"
505 " EyeVector.x = dot(eyeminusvertex, gl_MultiTexCoord1.xyz);\n"
506 " EyeVector.y = dot(eyeminusvertex, gl_MultiTexCoord2.xyz);\n"
507 " EyeVector.z = dot(eyeminusvertex, gl_MultiTexCoord3.xyz);\n"
510 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
511 " VectorS = gl_MultiTexCoord1.xyz;\n"
512 " VectorT = gl_MultiTexCoord2.xyz;\n"
513 " VectorR = gl_MultiTexCoord3.xyz;\n"
516 " // transform vertex to camera space, using ftransform to match non-VS\n"
518 " gl_Position = ftransform();\n"
526 "// fragment shader specific:\n"
527 "#ifdef FRAGMENT_SHADER\n"
529 "uniform myhvec3 LightColor;\n"
530 "#ifdef USEOFFSETMAPPING\n"
531 "uniform myhalf OffsetMapping_Scale;\n"
532 "uniform myhalf OffsetMapping_Bias;\n"
535 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE) || defined(MODE_LIGHTDIRECTION) || defined(USEOFFSETMAPPING)\n"
536 "uniform sampler2D Texture_Normal;\n"
539 "#ifdef MODE_LIGHTDIRECTION\n"
540 "uniform myhvec3 AmbientColor;\n"
541 "uniform myhvec3 DiffuseColor;\n"
542 "uniform myhvec3 SpecularColor;\n"
545 "uniform sampler2D Texture_Color;\n"
547 "#if !defined(MODE_LIGHTSOURCE) && !defined(MODE_LIGHTDIRECTION)\n"
548 "uniform sampler2D Texture_Lightmap;\n"
550 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
551 "uniform sampler2D Texture_Deluxemap;\n"
555 "uniform sampler2D Texture_Glow;\n"
558 "#ifdef USECOLORMAPPING\n"
559 "uniform sampler2D Texture_Pants;\n"
560 "uniform sampler2D Texture_Shirt;\n"
561 "uniform myhvec3 Color_Pants;\n"
562 "uniform myhvec3 Color_Shirt;\n"
565 "uniform myhalf AmbientScale;\n"
566 "uniform myhalf DiffuseScale;\n"
567 "#ifdef USESPECULAR\n"
568 "uniform myhalf SpecularScale;\n"
569 "uniform myhalf SpecularPower;\n"
570 "uniform sampler2D Texture_Gloss;\n"
573 "#ifdef USECUBEFILTER\n"
574 "uniform samplerCube Texture_Cube;\n"
578 "uniform myhvec3 FogColor;\n"
579 "uniform myhalf FogRangeRecip;\n"
580 "uniform sampler2D Texture_FogMask;\n"
583 "#ifdef USEEASTEREGG\n"
586 " gl_FragColor = myhvec4(0, 0, 0, 1);;\n"
589 " vec2 p = vec2(CubeVector.x * 16.0, CubeVector.y * 16.0);\n"
590 " vec2 c = vec2(CubeVector.x * 16.0, CubeVector.y * 16.0);\n"
591 " for (i = 0;i < 1000 && dot(p,p) < 4.0;i = i + 1)\n"
593 " o = p.x * p.x - p.y * p.y;\n"
594 " p.y = 2.0 * p.x * p.y;\n"
598 " o = float(i) * 0.314;\n"
600 " gl_FragColor = vec4(cos(o), sin(o), sin(o * 0.2), 1);\n"
602 "#else // USEEASTEREGG\n"
608 " // apply offsetmapping\n"
609 "#ifdef USEOFFSETMAPPING\n"
610 " myhvec2 TexCoordOffset = TexCoord;\n"
611 "#define TexCoord TexCoordOffset\n"
613 " myhvec3 eyedir = myhvec3(normalize(EyeVector));\n"
614 " myhalf depthbias = 1.0 - eyedir.z; // should this be a -?\n"
615 " depthbias = 1.0 - depthbias * depthbias;\n"
617 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
618 " // 14 sample relief mapping: linear search and then binary search\n"
619 " myhvec3 OffsetVector = myhvec3(EyeVector.xy * (1.0 / EyeVector.z) * depthbias * OffsetMapping_Scale * myhvec2(-0.1, 0.1), -0.1);\n"
620 " vec3 RT = vec3(TexCoord - OffsetVector.xy * 10.0, 1.0) + OffsetVector;\n"
621 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
622 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
623 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
624 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
625 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
626 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
627 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
628 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
629 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;OffsetVector *= 0.5;RT -= OffsetVector;\n"
630 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;OffsetVector *= 0.5;RT -= OffsetVector;\n"
631 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;OffsetVector *= 0.5;RT -= OffsetVector;\n"
632 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;OffsetVector *= 0.5;RT -= OffsetVector;\n"
633 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;OffsetVector *= 0.5;RT -= OffsetVector;\n"
634 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;OffsetVector *= 0.5;RT -= OffsetVector;\n"
635 " TexCoord = RT.xy;\n"
637 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
638 " myhvec2 OffsetVector = myhvec2((EyeVector.xy * (1.0 / EyeVector.z) * depthbias) * OffsetMapping_Scale * myhvec2(-0.333, 0.333));\n"
639 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
640 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
641 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
645 " // combine the diffuse textures (base, pants, shirt)\n"
646 " myhvec4 color = myhvec4(texture2D(Texture_Color, TexCoord));\n"
647 "#ifdef USECOLORMAPPING\n"
648 " color.rgb += myhvec3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhvec3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
654 "#ifdef MODE_LIGHTSOURCE\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"
665 " // calculate directional shading\n"
666 " color.rgb *= (AmbientScale + DiffuseScale * max(dot(surfacenormal, diffusenormal), 0.0));\n"
667 "#ifdef USESPECULAR\n"
668 " myhvec3 specularnormal = myhvec3(normalize(diffusenormal + myhvec3(normalize(EyeVector))));\n"
669 " color.rgb += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(max(dot(surfacenormal, specularnormal), 0.0), SpecularPower);\n"
672 "#ifdef USECUBEFILTER\n"
673 " // apply light cubemap filter\n"
674 " color.rgb *= myhvec3(textureCube(Texture_Cube, CubeVector));\n"
677 " // apply light color\n"
678 " color.rgb = color.rgb * LightColor;\n"
680 " // apply attenuation\n"
682 " // the attenuation is (1-(x*x+y*y+z*z)) which gives a large bright\n"
683 " // center and sharp falloff at the edge, this is about the most efficient\n"
684 " // we can get away with as far as providing illumination.\n"
686 " // pow(1-(x*x+y*y+z*z), 4) is far more realistic but needs large lights to\n"
687 " // provide significant illumination, large = slow = pain.\n"
688 " color.rgb *= max(1.0 - dot(CubeVector, CubeVector), 0.0);\n"
693 "#elif defined(MODE_LIGHTDIRECTION)\n"
694 " // directional model lighting\n"
696 " // get the surface normal and light normal\n"
697 "#ifdef SURFACENORMALIZE\n"
698 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - 0.5);\n"
700 " myhvec3 surfacenormal = -1.0 + 2.0 * myhvec3(texture2D(Texture_Normal, TexCoord));\n"
702 " myhvec3 diffusenormal = myhvec3(normalize(LightVector));\n"
705 " // calculate directional shading\n"
706 " color.rgb *= AmbientColor + DiffuseColor * max(dot(surfacenormal, diffusenormal), 0.0);\n"
707 "#ifdef USESPECULAR\n"
708 " myhvec3 specularnormal = myhvec3(normalize(diffusenormal + myhvec3(normalize(EyeVector))));\n"
709 " color.rgb += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(max(dot(surfacenormal, specularnormal), 0.0), SpecularPower);\n"
715 "#elif defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE)\n"
716 " // deluxemap lightmapping using light vectors in modelspace (evil q3map2)\n"
718 " // get the surface normal and light normal\n"
719 "#ifdef SURFACENORMALIZE\n"
720 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - 0.5);\n"
722 " myhvec3 surfacenormal = -1.0 + 2.0 * myhvec3(texture2D(Texture_Normal, TexCoord));\n"
724 " myhvec3 diffusenormal_modelspace = myhvec3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - 0.5;\n"
725 " myhvec3 diffusenormal = normalize(myhvec3(dot(diffusenormal_modelspace, VectorS), dot(diffusenormal_modelspace, VectorT), dot(diffusenormal_modelspace, VectorR)));\n"
727 " // calculate directional shading\n"
728 " myhvec3 tempcolor = color.rgb * (DiffuseScale * max(dot(surfacenormal, diffusenormal), 0.0));\n"
729 "#ifdef USESPECULAR\n"
730 " myhvec3 specularnormal = myhvec3(normalize(diffusenormal + myhvec3(normalize(EyeVector))));\n"
731 " tempcolor += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(max(dot(surfacenormal, specularnormal), 0.0), SpecularPower);\n"
734 " // apply lightmap color\n"
735 " color.rgb = tempcolor * myhvec3(texture2D(Texture_Lightmap, TexCoordLightmap)) + color.rgb * myhvec3(AmbientScale);\n"
740 "#elif defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
741 " // deluxemap lightmapping using light vectors in tangentspace\n"
743 " // get the surface normal and light normal\n"
744 "#ifdef SURFACENORMALIZE\n"
745 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - 0.5);\n"
746 " myhvec3 diffusenormal = normalize(myhvec3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - 0.5);\n"
748 " myhvec3 surfacenormal = -1.0 + 2.0 * myhvec3(texture2D(Texture_Normal, TexCoord));\n"
749 " myhvec3 diffusenormal = -1.0 + 2.0 * myhvec3(texture2D(Texture_Deluxemap, TexCoordLightmap));\n"
752 " // calculate directional shading\n"
753 " myhvec3 tempcolor = color.rgb * (DiffuseScale * max(dot(surfacenormal, diffusenormal), 0.0));\n"
754 "#ifdef USESPECULAR\n"
755 " myhvec3 specularnormal = myhvec3(normalize(diffusenormal + myhvec3(normalize(EyeVector))));\n"
756 " tempcolor += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(max(dot(surfacenormal, specularnormal), 0.0), SpecularPower);\n"
759 " // apply lightmap color\n"
760 " color.rgb = tempcolor * myhvec3(texture2D(Texture_Lightmap, TexCoordLightmap)) + color.rgb * myhvec3(AmbientScale);\n"
765 "#else // MODE none (lightmap)\n"
766 " // apply lightmap color\n"
767 " color.rgb *= myhvec3(texture2D(Texture_Lightmap, TexCoordLightmap)) * DiffuseScale + myhvec3(AmbientScale);\n"
771 " color.rgb += myhvec3(texture2D(Texture_Glow, TexCoord));\n"
776 " myhalf fog = texture2D(Texture_FogMask, myhvec2(length(EyeVector)*FogRangeRecip, 0.0)).x;\n"
777 " color.rgb = color.rgb * fog + FogColor * (1.0 - fog);\n"
780 " gl_FragColor = color * gl_Color;\n"
782 "#endif // !USEEASTEREGG\n"
787 void R_GLSL_CompilePermutation(int permutation)
789 r_glsl_permutation_t *p = r_glsl_permutations + permutation;
790 int vertstrings_count;
791 int fragstrings_count;
793 const char *vertstrings_list[SHADERPERMUTATION_COUNT+1];
794 const char *fragstrings_list[SHADERPERMUTATION_COUNT+1];
795 char permutationname[256];
799 vertstrings_list[0] = "#define VERTEX_SHADER\n";
800 fragstrings_list[0] = "#define FRAGMENT_SHADER\n";
801 vertstrings_count = 1;
802 fragstrings_count = 1;
803 permutationname[0] = 0;
804 if (permutation & SHADERPERMUTATION_MODE_LIGHTSOURCE)
806 vertstrings_list[vertstrings_count++] = "#define MODE_LIGHTSOURCE\n";
807 fragstrings_list[fragstrings_count++] = "#define MODE_LIGHTSOURCE\n";
808 strlcat(permutationname, " lightsource", sizeof(permutationname));
810 if (permutation & SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_MODELSPACE)
812 vertstrings_list[vertstrings_count++] = "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n";
813 fragstrings_list[fragstrings_count++] = "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n";
814 strlcat(permutationname, " lightdirectionmap_modelspace", sizeof(permutationname));
816 if (permutation & SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)
818 vertstrings_list[vertstrings_count++] = "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n";
819 fragstrings_list[fragstrings_count++] = "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n";
820 strlcat(permutationname, " lightdirectionmap_tangentspace", sizeof(permutationname));
822 if (permutation & SHADERPERMUTATION_MODE_LIGHTDIRECTION)
824 vertstrings_list[vertstrings_count++] = "#define MODE_LIGHTDIRECTION\n";
825 fragstrings_list[fragstrings_count++] = "#define MODE_LIGHTDIRECTION\n";
826 strlcat(permutationname, " lightdirection", sizeof(permutationname));
828 if (permutation & SHADERPERMUTATION_GLOW)
830 vertstrings_list[vertstrings_count++] = "#define USEGLOW\n";
831 fragstrings_list[fragstrings_count++] = "#define USEGLOW\n";
832 strlcat(permutationname, " glow", sizeof(permutationname));
834 if (permutation & SHADERPERMUTATION_COLORMAPPING)
836 vertstrings_list[vertstrings_count++] = "#define USECOLORMAPPING\n";
837 fragstrings_list[fragstrings_count++] = "#define USECOLORMAPPING\n";
838 strlcat(permutationname, " colormapping", sizeof(permutationname));
840 if (permutation & SHADERPERMUTATION_SPECULAR)
842 vertstrings_list[vertstrings_count++] = "#define USESPECULAR\n";
843 fragstrings_list[fragstrings_count++] = "#define USESPECULAR\n";
844 strlcat(permutationname, " specular", sizeof(permutationname));
846 if (permutation & SHADERPERMUTATION_FOG)
848 vertstrings_list[vertstrings_count++] = "#define USEFOG\n";
849 fragstrings_list[fragstrings_count++] = "#define USEFOG\n";
850 strlcat(permutationname, " fog", sizeof(permutationname));
852 if (permutation & SHADERPERMUTATION_CUBEFILTER)
854 vertstrings_list[vertstrings_count++] = "#define USECUBEFILTER\n";
855 fragstrings_list[fragstrings_count++] = "#define USECUBEFILTER\n";
856 strlcat(permutationname, " cubefilter", sizeof(permutationname));
858 if (permutation & SHADERPERMUTATION_OFFSETMAPPING)
860 vertstrings_list[vertstrings_count++] = "#define USEOFFSETMAPPING\n";
861 fragstrings_list[fragstrings_count++] = "#define USEOFFSETMAPPING\n";
862 strlcat(permutationname, " offsetmapping", sizeof(permutationname));
864 if (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING)
866 vertstrings_list[vertstrings_count++] = "#define USEOFFSETMAPPING_RELIEFMAPPING\n";
867 fragstrings_list[fragstrings_count++] = "#define USEOFFSETMAPPING_RELIEFMAPPING\n";
868 strlcat(permutationname, " OFFSETMAPPING_RELIEFMAPPING", sizeof(permutationname));
870 if (permutation & SHADERPERMUTATION_SURFACENORMALIZE)
872 vertstrings_list[vertstrings_count++] = "#define SURFACENORMALIZE\n";
873 fragstrings_list[fragstrings_count++] = "#define SURFACENORMALIZE\n";
874 strlcat(permutationname, " surfacenormalize", sizeof(permutationname));
876 if (permutation & SHADERPERMUTATION_GEFORCEFX)
878 vertstrings_list[vertstrings_count++] = "#define GEFORCEFX\n";
879 fragstrings_list[fragstrings_count++] = "#define GEFORCEFX\n";
880 strlcat(permutationname, " halffloat", sizeof(permutationname));
882 shaderstring = (char *)FS_LoadFile("glsl/default.glsl", r_main_mempool, false, NULL);
885 Con_DPrintf("GLSL shader text loaded from disk\n");
886 vertstrings_list[vertstrings_count++] = shaderstring;
887 fragstrings_list[fragstrings_count++] = shaderstring;
891 vertstrings_list[vertstrings_count++] = builtinshaderstring;
892 fragstrings_list[fragstrings_count++] = builtinshaderstring;
894 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, fragstrings_count, fragstrings_list);
898 qglUseProgramObjectARB(p->program);
899 p->loc_Texture_Normal = qglGetUniformLocationARB(p->program, "Texture_Normal");
900 p->loc_Texture_Color = qglGetUniformLocationARB(p->program, "Texture_Color");
901 p->loc_Texture_Gloss = qglGetUniformLocationARB(p->program, "Texture_Gloss");
902 p->loc_Texture_Cube = qglGetUniformLocationARB(p->program, "Texture_Cube");
903 p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
904 p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
905 p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
906 p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
907 p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
908 p->loc_Texture_Glow = qglGetUniformLocationARB(p->program, "Texture_Glow");
909 p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
910 p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
911 p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
912 p->loc_LightColor = qglGetUniformLocationARB(p->program, "LightColor");
913 p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants");
914 p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt");
915 p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip");
916 p->loc_AmbientScale = qglGetUniformLocationARB(p->program, "AmbientScale");
917 p->loc_DiffuseScale = qglGetUniformLocationARB(p->program, "DiffuseScale");
918 p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
919 p->loc_SpecularScale = qglGetUniformLocationARB(p->program, "SpecularScale");
920 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
921 p->loc_AmbientColor = qglGetUniformLocationARB(p->program, "AmbientColor");
922 p->loc_DiffuseColor = qglGetUniformLocationARB(p->program, "DiffuseColor");
923 p->loc_SpecularColor = qglGetUniformLocationARB(p->program, "SpecularColor");
924 p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
925 if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal, 0);
926 if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color, 1);
927 if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss, 2);
928 if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube, 3);
929 if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask, 4);
930 if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants, 5);
931 if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt, 6);
932 if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap, 7);
933 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap, 8);
934 if (p->loc_Texture_Glow >= 0) qglUniform1iARB(p->loc_Texture_Glow, 9);
935 qglUseProgramObjectARB(0);
939 Con_Printf("permutation%s failed for shader %s, some features may not work properly!\n", permutationname, "glsl/default.glsl");
941 Mem_Free(shaderstring);
944 void R_GLSL_Restart_f(void)
947 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
948 if (r_glsl_permutations[i].program)
949 GL_Backend_FreeProgram(r_glsl_permutations[i].program);
950 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
953 void R_SetupSurfaceShader(const entity_render_t *ent, const texture_t *texture, const vec3_t modelorg, const vec3_t lightcolorbase, qboolean modellighting)
955 // select a permutation of the lighting shader appropriate to this
956 // combination of texture, entity, light source, and fogging, only use the
957 // minimum features necessary to avoid wasting rendering time in the
958 // fragment shader on features that are not being used
960 float specularscale = texture->specularscale;
961 r_glsl_permutation = NULL;
962 if (r_shadow_rtlight)
964 permutation |= SHADERPERMUTATION_MODE_LIGHTSOURCE;
965 specularscale *= r_shadow_rtlight->specularscale;
966 if (r_shadow_rtlight->currentcubemap != r_texture_whitecube)
967 permutation |= SHADERPERMUTATION_CUBEFILTER;
972 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTION;
973 else if (r_glsl_deluxemapping.integer >= 1 && r_refdef.worldmodel && r_refdef.worldmodel->brushq3.deluxemapping)
975 if (r_refdef.worldmodel->brushq3.deluxemapping_modelspace)
976 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_MODELSPACE;
978 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
980 else if (r_glsl_deluxemapping.integer >= 2) // fake mode
981 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
982 if (texture->skin.glow)
983 permutation |= SHADERPERMUTATION_GLOW;
985 if (specularscale > 0)
986 permutation |= SHADERPERMUTATION_SPECULAR;
988 permutation |= SHADERPERMUTATION_FOG;
989 if (texture->colormapping)
990 permutation |= SHADERPERMUTATION_COLORMAPPING;
991 if (r_glsl_offsetmapping.integer)
993 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
994 if (r_glsl_offsetmapping_reliefmapping.integer)
995 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
997 if (r_glsl_surfacenormalize.integer)
998 permutation |= SHADERPERMUTATION_SURFACENORMALIZE;
999 if (r_glsl_usehalffloat.integer)
1000 permutation |= SHADERPERMUTATION_GEFORCEFX;
1001 if (!r_glsl_permutations[permutation].program)
1003 if (!r_glsl_permutations[permutation].compiled)
1004 R_GLSL_CompilePermutation(permutation);
1005 if (!r_glsl_permutations[permutation].program)
1007 // remove features until we find a valid permutation
1009 for (i = SHADERPERMUTATION_COUNT-1;;i>>=1)
1011 // reduce i more quickly whenever it would not remove any bits
1012 if (permutation < i)
1015 if (!r_glsl_permutations[permutation].compiled)
1016 R_GLSL_CompilePermutation(permutation);
1017 if (r_glsl_permutations[permutation].program)
1020 return; // utterly failed
1024 r_glsl_permutation = r_glsl_permutations + permutation;
1026 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
1027 R_Mesh_TexMatrix(0, &texture->currenttexmatrix);
1028 if (permutation & SHADERPERMUTATION_MODE_LIGHTSOURCE)
1030 R_Mesh_TexMatrix(3, &r_shadow_entitytolight);
1031 //if (r_glsl_permutation->loc_Texture_Cube >= 0) R_Mesh_TexBindCubeMap(3, R_GetTexture(r_shadow_rtlight->currentcubemap));
1032 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]);
1033 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
1034 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_shadow_rtlight->ambientscale);
1035 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_shadow_rtlight->diffusescale);
1036 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, specularscale);
1038 else if (permutation & SHADERPERMUTATION_MODE_LIGHTDIRECTION)
1040 if (texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
1042 if (r_glsl_permutation->loc_AmbientColor >= 0)
1043 qglUniform3fARB(r_glsl_permutation->loc_AmbientColor, 1, 1, 1);
1044 if (r_glsl_permutation->loc_DiffuseColor >= 0)
1045 qglUniform3fARB(r_glsl_permutation->loc_DiffuseColor, 0, 0, 0);
1046 if (r_glsl_permutation->loc_SpecularColor >= 0)
1047 qglUniform3fARB(r_glsl_permutation->loc_SpecularColor, 0, 0, 0);
1048 if (r_glsl_permutation->loc_LightDir >= 0)
1049 qglUniform3fARB(r_glsl_permutation->loc_LightDir, 0, 0, -1);
1053 if (r_glsl_permutation->loc_AmbientColor >= 0)
1054 qglUniform3fARB(r_glsl_permutation->loc_AmbientColor, ent->modellight_ambient[0], ent->modellight_ambient[1], ent->modellight_ambient[2]);
1055 if (r_glsl_permutation->loc_DiffuseColor >= 0)
1056 qglUniform3fARB(r_glsl_permutation->loc_DiffuseColor, ent->modellight_diffuse[0], ent->modellight_diffuse[1], ent->modellight_diffuse[2]);
1057 if (r_glsl_permutation->loc_SpecularColor >= 0)
1058 qglUniform3fARB(r_glsl_permutation->loc_SpecularColor, ent->modellight_diffuse[0] * texture->specularscale, ent->modellight_diffuse[1] * texture->specularscale, ent->modellight_diffuse[2] * texture->specularscale);
1059 if (r_glsl_permutation->loc_LightDir >= 0)
1060 qglUniform3fARB(r_glsl_permutation->loc_LightDir, ent->modellight_lightdir[0], ent->modellight_lightdir[1], ent->modellight_lightdir[2]);
1065 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_ambient.value * 2.0f / 128.0f);
1066 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_lightmapintensity * 2.0f);
1067 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, r_lightmapintensity * specularscale * 2.0f);
1069 if (r_glsl_permutation->loc_Texture_Normal >= 0) R_Mesh_TexBind(0, R_GetTexture(texture->skin.nmap));
1070 if (r_glsl_permutation->loc_Texture_Color >= 0) R_Mesh_TexBind(1, R_GetTexture(texture->basetexture));
1071 if (r_glsl_permutation->loc_Texture_Gloss >= 0) R_Mesh_TexBind(2, R_GetTexture(texture->glosstexture));
1072 if (r_glsl_permutation->loc_Texture_FogMask >= 0) R_Mesh_TexBind(4, R_GetTexture(r_texture_fogattenuation));
1073 if (r_glsl_permutation->loc_Texture_Pants >= 0) R_Mesh_TexBind(5, R_GetTexture(texture->skin.pants));
1074 if (r_glsl_permutation->loc_Texture_Shirt >= 0) R_Mesh_TexBind(6, R_GetTexture(texture->skin.shirt));
1075 if (r_glsl_permutation->loc_Texture_Glow >= 0) R_Mesh_TexBind(9, R_GetTexture(texture->skin.glow));
1076 if (r_glsl_permutation->loc_FogColor >= 0)
1078 // additive passes are only darkened by fog, not tinted
1079 if (r_shadow_rtlight || (texture->currentmaterialflags & MATERIALFLAG_ADD))
1080 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
1082 qglUniform3fARB(r_glsl_permutation->loc_FogColor, fogcolor[0], fogcolor[1], fogcolor[2]);
1084 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, modelorg[0], modelorg[1], modelorg[2]);
1085 if (r_glsl_permutation->loc_Color_Pants >= 0)
1087 if (texture->skin.pants)
1088 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, ent->colormap_pantscolor[0], ent->colormap_pantscolor[1], ent->colormap_pantscolor[2]);
1090 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
1092 if (r_glsl_permutation->loc_Color_Shirt >= 0)
1094 if (texture->skin.shirt)
1095 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, ent->colormap_shirtcolor[0], ent->colormap_shirtcolor[1], ent->colormap_shirtcolor[2]);
1097 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
1099 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, fograngerecip);
1100 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, texture->specularpower);
1101 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
1105 void gl_main_start(void)
1107 // use half float math where available (speed gain on NVIDIA GFFX and GF6)
1108 if (gl_support_half_float)
1109 Cvar_SetValue("r_glsl_usehalffloat", 1);
1110 r_main_texturepool = R_AllocTexturePool();
1111 r_bloom_texture_screen = NULL;
1112 r_bloom_texture_bloom = NULL;
1113 R_BuildBlankTextures();
1115 if (gl_texturecubemap)
1118 R_BuildNormalizationCube();
1120 R_BuildFogTexture();
1121 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
1124 void gl_main_shutdown(void)
1126 R_FreeTexturePool(&r_main_texturepool);
1127 r_bloom_texture_screen = NULL;
1128 r_bloom_texture_bloom = NULL;
1129 r_texture_blanknormalmap = NULL;
1130 r_texture_white = NULL;
1131 r_texture_black = NULL;
1132 r_texture_whitecube = NULL;
1133 r_texture_normalizationcube = NULL;
1137 extern void CL_ParseEntityLump(char *entitystring);
1138 void gl_main_newmap(void)
1140 // FIXME: move this code to client
1142 char *entities, entname[MAX_QPATH];
1146 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
1147 l = (int)strlen(entname) - 4;
1148 if (l >= 0 && !strcmp(entname + l, ".bsp"))
1150 strcpy(entname + l, ".ent");
1151 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
1153 CL_ParseEntityLump(entities);
1158 if (cl.worldmodel->brush.entities)
1159 CL_ParseEntityLump(cl.worldmodel->brush.entities);
1163 void GL_Main_Init(void)
1165 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
1167 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed\n");
1168 FOG_registercvars(); // FIXME: move this fog stuff to client?
1169 Cvar_RegisterVariable(&r_nearclip);
1170 Cvar_RegisterVariable(&r_showtris);
1171 Cvar_RegisterVariable(&r_shownormals);
1172 Cvar_RegisterVariable(&r_showlighting);
1173 Cvar_RegisterVariable(&r_showshadowvolumes);
1174 Cvar_RegisterVariable(&r_showcollisionbrushes);
1175 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
1176 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
1177 Cvar_RegisterVariable(&r_showdisabledepthtest);
1178 Cvar_RegisterVariable(&r_drawentities);
1179 Cvar_RegisterVariable(&r_drawviewmodel);
1180 Cvar_RegisterVariable(&r_speeds);
1181 Cvar_RegisterVariable(&r_fullbrights);
1182 Cvar_RegisterVariable(&r_wateralpha);
1183 Cvar_RegisterVariable(&r_dynamic);
1184 Cvar_RegisterVariable(&r_fullbright);
1185 Cvar_RegisterVariable(&r_textureunits);
1186 Cvar_RegisterVariable(&r_glsl);
1187 Cvar_RegisterVariable(&r_glsl_offsetmapping);
1188 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
1189 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
1190 Cvar_RegisterVariable(&r_glsl_usehalffloat);
1191 Cvar_RegisterVariable(&r_glsl_surfacenormalize);
1192 Cvar_RegisterVariable(&r_glsl_deluxemapping);
1193 Cvar_RegisterVariable(&r_lerpsprites);
1194 Cvar_RegisterVariable(&r_lerpmodels);
1195 Cvar_RegisterVariable(&r_waterscroll);
1196 Cvar_RegisterVariable(&r_bloom);
1197 Cvar_RegisterVariable(&r_bloom_intensity);
1198 Cvar_RegisterVariable(&r_bloom_blur);
1199 Cvar_RegisterVariable(&r_bloom_resolution);
1200 Cvar_RegisterVariable(&r_bloom_power);
1201 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
1202 Cvar_RegisterVariable(&developer_texturelogging);
1203 Cvar_RegisterVariable(&gl_lightmaps);
1204 Cvar_RegisterVariable(&r_test);
1205 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
1206 Cvar_SetValue("r_fullbrights", 0);
1207 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
1210 static vec3_t r_farclip_origin;
1211 static vec3_t r_farclip_direction;
1212 static vec_t r_farclip_directiondist;
1213 static vec_t r_farclip_meshfarclip;
1214 static int r_farclip_directionbit0;
1215 static int r_farclip_directionbit1;
1216 static int r_farclip_directionbit2;
1218 // enlarge farclip to accomodate box
1219 static void R_FarClip_Box(vec3_t mins, vec3_t maxs)
1222 d = (r_farclip_directionbit0 ? mins[0] : maxs[0]) * r_farclip_direction[0]
1223 + (r_farclip_directionbit1 ? mins[1] : maxs[1]) * r_farclip_direction[1]
1224 + (r_farclip_directionbit2 ? mins[2] : maxs[2]) * r_farclip_direction[2];
1225 if (r_farclip_meshfarclip < d)
1226 r_farclip_meshfarclip = d;
1229 // return farclip value
1230 static float R_FarClip(vec3_t origin, vec3_t direction, vec_t startfarclip)
1234 VectorCopy(origin, r_farclip_origin);
1235 VectorCopy(direction, r_farclip_direction);
1236 r_farclip_directiondist = DotProduct(r_farclip_origin, r_farclip_direction);
1237 r_farclip_directionbit0 = r_farclip_direction[0] < 0;
1238 r_farclip_directionbit1 = r_farclip_direction[1] < 0;
1239 r_farclip_directionbit2 = r_farclip_direction[2] < 0;
1240 r_farclip_meshfarclip = r_farclip_directiondist + startfarclip;
1242 if (r_refdef.worldmodel)
1243 R_FarClip_Box(r_refdef.worldmodel->normalmins, r_refdef.worldmodel->normalmaxs);
1244 for (i = 0;i < r_refdef.numentities;i++)
1245 R_FarClip_Box(r_refdef.entities[i]->mins, r_refdef.entities[i]->maxs);
1247 return r_farclip_meshfarclip - r_farclip_directiondist;
1250 extern void R_Textures_Init(void);
1251 extern void GL_Draw_Init(void);
1252 extern void GL_Main_Init(void);
1253 extern void R_Shadow_Init(void);
1254 extern void R_Sky_Init(void);
1255 extern void GL_Surf_Init(void);
1256 extern void R_Crosshairs_Init(void);
1257 extern void R_Light_Init(void);
1258 extern void R_Particles_Init(void);
1259 extern void R_Explosion_Init(void);
1260 extern void gl_backend_init(void);
1261 extern void Sbar_Init(void);
1262 extern void R_LightningBeams_Init(void);
1263 extern void Mod_RenderInit(void);
1265 void Render_Init(void)
1275 R_Crosshairs_Init();
1280 R_LightningBeams_Init();
1289 extern char *ENGINE_EXTENSIONS;
1292 VID_CheckExtensions();
1294 // LordHavoc: report supported extensions
1295 Con_DPrintf("\nengine extensions: %s\n", vm_sv_extensions );
1297 // clear to black (loading plaque will be seen over this)
1298 qglClearColor(0,0,0,1);
1299 qglClear(GL_COLOR_BUFFER_BIT);
1302 int R_CullBox(const vec3_t mins, const vec3_t maxs)
1306 for (i = 0;i < 4;i++)
1313 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1317 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1321 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1325 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1329 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1333 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1337 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1341 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1349 //==================================================================================
1351 static void R_UpdateEntityLighting(entity_render_t *ent)
1353 vec3_t tempdiffusenormal;
1354 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));
1355 VectorClear(ent->modellight_diffuse);
1356 VectorClear(ent->modellight_lightdir);
1357 if ((ent->flags & RENDER_LIGHT) && r_refdef.worldmodel && r_refdef.worldmodel->brush.LightPoint)
1358 r_refdef.worldmodel->brush.LightPoint(r_refdef.worldmodel, ent->origin, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
1360 VectorSet(ent->modellight_ambient, 1, 1, 1);
1361 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
1362 VectorNormalize(ent->modellight_lightdir);
1363 ent->modellight_ambient[0] *= ent->colormod[0] * r_lightmapintensity;
1364 ent->modellight_ambient[1] *= ent->colormod[1] * r_lightmapintensity;
1365 ent->modellight_ambient[2] *= ent->colormod[2] * r_lightmapintensity;
1366 ent->modellight_diffuse[0] *= ent->colormod[0] * r_lightmapintensity;
1367 ent->modellight_diffuse[1] *= ent->colormod[1] * r_lightmapintensity;
1368 ent->modellight_diffuse[2] *= ent->colormod[2] * r_lightmapintensity;
1371 static void R_MarkEntities (void)
1374 entity_render_t *ent;
1376 if (!r_drawentities.integer)
1379 r_refdef.worldentity->visframe = r_framecount;
1380 renderimask = envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : (chase_active.integer ? 0 : RENDER_EXTERIORMODEL);
1381 if (r_refdef.worldmodel && r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs)
1383 // worldmodel can check visibility
1384 for (i = 0;i < r_refdef.numentities;i++)
1386 ent = r_refdef.entities[i];
1387 // some of the renderer still relies on origin...
1388 Matrix4x4_OriginFromMatrix(&ent->matrix, ent->origin);
1389 // some of the renderer still relies on scale...
1390 ent->scale = Matrix4x4_ScaleFromMatrix(&ent->matrix);
1391 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)))
1393 ent->visframe = r_framecount;
1394 R_UpdateEntityLighting(ent);
1400 // no worldmodel or it can't check visibility
1401 for (i = 0;i < r_refdef.numentities;i++)
1403 ent = r_refdef.entities[i];
1404 // some of the renderer still relies on origin...
1405 Matrix4x4_OriginFromMatrix(&ent->matrix, ent->origin);
1406 // some of the renderer still relies on scale...
1407 ent->scale = Matrix4x4_ScaleFromMatrix(&ent->matrix);
1408 if (!(ent->flags & renderimask) && !R_CullBox(ent->mins, ent->maxs) && (ent->effects & EF_NODEPTHTEST))
1410 ent->visframe = r_framecount;
1411 R_UpdateEntityLighting(ent);
1417 // only used if skyrendermasked, and normally returns false
1418 int R_DrawBrushModelsSky (void)
1421 entity_render_t *ent;
1423 if (!r_drawentities.integer)
1427 for (i = 0;i < r_refdef.numentities;i++)
1429 ent = r_refdef.entities[i];
1430 if (ent->visframe == r_framecount && ent->model && ent->model->DrawSky)
1432 ent->model->DrawSky(ent);
1439 void R_DrawNoModel(entity_render_t *ent);
1440 void R_DrawModels(void)
1443 entity_render_t *ent;
1445 if (!r_drawentities.integer)
1448 for (i = 0;i < r_refdef.numentities;i++)
1450 ent = r_refdef.entities[i];
1451 if (ent->visframe == r_framecount)
1453 renderstats.entities++;
1454 if (ent->model && ent->model->Draw != NULL)
1455 ent->model->Draw(ent);
1462 static void R_SetFrustum(void)
1464 // break apart the view matrix into vectors for various purposes
1465 Matrix4x4_ToVectors(&r_view_matrix, r_viewforward, r_viewleft, r_viewup, r_vieworigin);
1466 VectorNegate(r_viewleft, r_viewright);
1469 frustum[0].normal[0] = 0 - 1.0 / r_refdef.frustum_x;
1470 frustum[0].normal[1] = 0 - 0;
1471 frustum[0].normal[2] = -1 - 0;
1472 frustum[1].normal[0] = 0 + 1.0 / r_refdef.frustum_x;
1473 frustum[1].normal[1] = 0 + 0;
1474 frustum[1].normal[2] = -1 + 0;
1475 frustum[2].normal[0] = 0 - 0;
1476 frustum[2].normal[1] = 0 - 1.0 / r_refdef.frustum_y;
1477 frustum[2].normal[2] = -1 - 0;
1478 frustum[3].normal[0] = 0 + 0;
1479 frustum[3].normal[1] = 0 + 1.0 / r_refdef.frustum_y;
1480 frustum[3].normal[2] = -1 + 0;
1484 zNear = r_nearclip.value;
1485 nudge = 1.0 - 1.0 / (1<<23);
1486 frustum[4].normal[0] = 0 - 0;
1487 frustum[4].normal[1] = 0 - 0;
1488 frustum[4].normal[2] = -1 - -nudge;
1489 frustum[4].dist = 0 - -2 * zNear * nudge;
1490 frustum[5].normal[0] = 0 + 0;
1491 frustum[5].normal[1] = 0 + 0;
1492 frustum[5].normal[2] = -1 + -nudge;
1493 frustum[5].dist = 0 + -2 * zNear * nudge;
1499 frustum[0].normal[0] = m[3] - m[0];
1500 frustum[0].normal[1] = m[7] - m[4];
1501 frustum[0].normal[2] = m[11] - m[8];
1502 frustum[0].dist = m[15] - m[12];
1504 frustum[1].normal[0] = m[3] + m[0];
1505 frustum[1].normal[1] = m[7] + m[4];
1506 frustum[1].normal[2] = m[11] + m[8];
1507 frustum[1].dist = m[15] + m[12];
1509 frustum[2].normal[0] = m[3] - m[1];
1510 frustum[2].normal[1] = m[7] - m[5];
1511 frustum[2].normal[2] = m[11] - m[9];
1512 frustum[2].dist = m[15] - m[13];
1514 frustum[3].normal[0] = m[3] + m[1];
1515 frustum[3].normal[1] = m[7] + m[5];
1516 frustum[3].normal[2] = m[11] + m[9];
1517 frustum[3].dist = m[15] + m[13];
1519 frustum[4].normal[0] = m[3] - m[2];
1520 frustum[4].normal[1] = m[7] - m[6];
1521 frustum[4].normal[2] = m[11] - m[10];
1522 frustum[4].dist = m[15] - m[14];
1524 frustum[5].normal[0] = m[3] + m[2];
1525 frustum[5].normal[1] = m[7] + m[6];
1526 frustum[5].normal[2] = m[11] + m[10];
1527 frustum[5].dist = m[15] + m[14];
1532 VectorMAM(1, r_viewforward, 1.0 / -r_refdef.frustum_x, r_viewleft, frustum[0].normal);
1533 VectorMAM(1, r_viewforward, 1.0 / r_refdef.frustum_x, r_viewleft, frustum[1].normal);
1534 VectorMAM(1, r_viewforward, 1.0 / -r_refdef.frustum_y, r_viewup, frustum[2].normal);
1535 VectorMAM(1, r_viewforward, 1.0 / r_refdef.frustum_y, r_viewup, frustum[3].normal);
1536 VectorCopy(r_viewforward, frustum[4].normal);
1537 VectorNormalize(frustum[0].normal);
1538 VectorNormalize(frustum[1].normal);
1539 VectorNormalize(frustum[2].normal);
1540 VectorNormalize(frustum[3].normal);
1541 frustum[0].dist = DotProduct (r_vieworigin, frustum[0].normal);
1542 frustum[1].dist = DotProduct (r_vieworigin, frustum[1].normal);
1543 frustum[2].dist = DotProduct (r_vieworigin, frustum[2].normal);
1544 frustum[3].dist = DotProduct (r_vieworigin, frustum[3].normal);
1545 frustum[4].dist = DotProduct (r_vieworigin, frustum[4].normal) + r_nearclip.value;
1546 PlaneClassify(&frustum[0]);
1547 PlaneClassify(&frustum[1]);
1548 PlaneClassify(&frustum[2]);
1549 PlaneClassify(&frustum[3]);
1550 PlaneClassify(&frustum[4]);
1552 // LordHavoc: note to all quake engine coders, Quake had a special case
1553 // for 90 degrees which assumed a square view (wrong), so I removed it,
1554 // Quake2 has it disabled as well.
1556 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
1557 //RotatePointAroundVector( frustum[0].normal, r_viewup, r_viewforward, -(90 - r_refdef.fov_x / 2));
1558 //frustum[0].dist = DotProduct (r_vieworigin, frustum[0].normal);
1559 //PlaneClassify(&frustum[0]);
1561 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
1562 //RotatePointAroundVector( frustum[1].normal, r_viewup, r_viewforward, (90 - r_refdef.fov_x / 2));
1563 //frustum[1].dist = DotProduct (r_vieworigin, frustum[1].normal);
1564 //PlaneClassify(&frustum[1]);
1566 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
1567 //RotatePointAroundVector( frustum[2].normal, r_viewleft, r_viewforward, -(90 - r_refdef.fov_y / 2));
1568 //frustum[2].dist = DotProduct (r_vieworigin, frustum[2].normal);
1569 //PlaneClassify(&frustum[2]);
1571 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
1572 //RotatePointAroundVector( frustum[3].normal, r_viewleft, r_viewforward, (90 - r_refdef.fov_y / 2));
1573 //frustum[3].dist = DotProduct (r_vieworigin, frustum[3].normal);
1574 //PlaneClassify(&frustum[3]);
1577 //VectorCopy(r_viewforward, frustum[4].normal);
1578 //frustum[4].dist = DotProduct (r_vieworigin, frustum[4].normal) + r_nearclip.value;
1579 //PlaneClassify(&frustum[4]);
1582 static void R_BlendView(void)
1584 int screenwidth, screenheight;
1589 float texcoord2f[3][8];
1591 // set the (poorly named) screenwidth and screenheight variables to
1592 // a power of 2 at least as large as the screen, these will define the
1593 // size of the texture to allocate
1594 for (screenwidth = 1;screenwidth < vid.width;screenwidth *= 2);
1595 for (screenheight = 1;screenheight < vid.height;screenheight *= 2);
1597 doblend = r_refdef.viewblend[3] >= 0.01f;
1598 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;
1600 if (!dobloom && !doblend)
1603 GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
1605 GL_DepthTest(false);
1606 R_Mesh_Matrix(&identitymatrix);
1607 // vertex coordinates for a quad that covers the screen exactly
1608 vertex3f[0] = 0;vertex3f[1] = 0;vertex3f[2] = 0;
1609 vertex3f[3] = 1;vertex3f[4] = 0;vertex3f[5] = 0;
1610 vertex3f[6] = 1;vertex3f[7] = 1;vertex3f[8] = 0;
1611 vertex3f[9] = 0;vertex3f[10] = 1;vertex3f[11] = 0;
1614 int bloomwidth, bloomheight, x, dobloomblend, range;
1615 float xoffset, yoffset, r;
1616 renderstats.bloom++;
1617 // allocate textures as needed
1618 if (!r_bloom_texture_screen)
1619 r_bloom_texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", screenwidth, screenheight, NULL, TEXTYPE_RGBA, TEXF_FORCENEAREST | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
1620 if (!r_bloom_texture_bloom)
1621 r_bloom_texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", screenwidth, screenheight, NULL, TEXTYPE_RGBA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
1622 // set bloomwidth and bloomheight to the bloom resolution that will be
1623 // used (often less than the screen resolution for faster rendering)
1624 bloomwidth = min(r_view_width, r_bloom_resolution.integer);
1625 bloomheight = min(r_view_height, bloomwidth * r_view_height / r_view_width);
1626 // set up a texcoord array for the full resolution screen image
1627 // (we have to keep this around to copy back during final render)
1628 texcoord2f[0][0] = 0;
1629 texcoord2f[0][1] = (float)r_view_height / (float)screenheight;
1630 texcoord2f[0][2] = (float)r_view_width / (float)screenwidth;
1631 texcoord2f[0][3] = (float)r_view_height / (float)screenheight;
1632 texcoord2f[0][4] = (float)r_view_width / (float)screenwidth;
1633 texcoord2f[0][5] = 0;
1634 texcoord2f[0][6] = 0;
1635 texcoord2f[0][7] = 0;
1636 // set up a texcoord array for the reduced resolution bloom image
1637 // (which will be additive blended over the screen image)
1638 texcoord2f[1][0] = 0;
1639 texcoord2f[1][1] = (float)bloomheight / (float)screenheight;
1640 texcoord2f[1][2] = (float)bloomwidth / (float)screenwidth;
1641 texcoord2f[1][3] = (float)bloomheight / (float)screenheight;
1642 texcoord2f[1][4] = (float)bloomwidth / (float)screenwidth;
1643 texcoord2f[1][5] = 0;
1644 texcoord2f[1][6] = 0;
1645 texcoord2f[1][7] = 0;
1646 memset(&m, 0, sizeof(m));
1647 m.pointer_vertex = vertex3f;
1648 m.pointer_texcoord[0] = texcoord2f[0];
1649 m.tex[0] = R_GetTexture(r_bloom_texture_screen);
1651 // copy view into the full resolution screen image texture
1652 GL_ActiveTexture(0);
1653 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
1654 renderstats.bloom_copypixels += r_view_width * r_view_height;
1655 // now scale it down to the bloom size and raise to a power of itself
1656 // to darken it (this leaves the really bright stuff bright, and
1657 // everything else becomes very dark)
1658 // TODO: optimize with multitexture or GLSL
1659 qglViewport(r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
1660 GL_BlendFunc(GL_ONE, GL_ZERO);
1661 GL_Color(1, 1, 1, 1);
1662 R_Mesh_Draw(0, 4, 2, polygonelements);
1663 renderstats.bloom_drawpixels += bloomwidth * bloomheight;
1664 // render multiple times with a multiply blendfunc to raise to a power
1665 GL_BlendFunc(GL_DST_COLOR, GL_ZERO);
1666 for (x = 1;x < r_bloom_power.integer;x++)
1668 R_Mesh_Draw(0, 4, 2, polygonelements);
1669 renderstats.bloom_drawpixels += bloomwidth * bloomheight;
1671 // we now have a darkened bloom image in the framebuffer, copy it into
1672 // the bloom image texture for more processing
1673 memset(&m, 0, sizeof(m));
1674 m.pointer_vertex = vertex3f;
1675 m.tex[0] = R_GetTexture(r_bloom_texture_bloom);
1676 m.pointer_texcoord[0] = texcoord2f[2];
1678 GL_ActiveTexture(0);
1679 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
1680 renderstats.bloom_copypixels += bloomwidth * bloomheight;
1681 // blend on at multiple vertical offsets to achieve a vertical blur
1682 // TODO: do offset blends using GLSL
1683 range = r_bloom_blur.integer * bloomwidth / 320;
1684 GL_BlendFunc(GL_ONE, GL_ZERO);
1685 for (x = -range;x <= range;x++)
1687 xoffset = 0 / (float)bloomwidth * (float)bloomwidth / (float)screenwidth;
1688 yoffset = x / (float)bloomheight * (float)bloomheight / (float)screenheight;
1689 // compute a texcoord array with the specified x and y offset
1690 texcoord2f[2][0] = xoffset+0;
1691 texcoord2f[2][1] = yoffset+(float)bloomheight / (float)screenheight;
1692 texcoord2f[2][2] = xoffset+(float)bloomwidth / (float)screenwidth;
1693 texcoord2f[2][3] = yoffset+(float)bloomheight / (float)screenheight;
1694 texcoord2f[2][4] = xoffset+(float)bloomwidth / (float)screenwidth;
1695 texcoord2f[2][5] = yoffset+0;
1696 texcoord2f[2][6] = xoffset+0;
1697 texcoord2f[2][7] = yoffset+0;
1698 // this r value looks like a 'dot' particle, fading sharply to
1699 // black at the edges
1700 // (probably not realistic but looks good enough)
1701 r = r_bloom_intensity.value/(range*2+1)*(1 - x*x/(float)(range*range));
1704 GL_Color(r, r, r, 1);
1705 R_Mesh_Draw(0, 4, 2, polygonelements);
1706 renderstats.bloom_drawpixels += bloomwidth * bloomheight;
1707 GL_BlendFunc(GL_ONE, GL_ONE);
1709 // copy the vertically blurred bloom view to a texture
1710 GL_ActiveTexture(0);
1711 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
1712 renderstats.bloom_copypixels += bloomwidth * bloomheight;
1713 // blend the vertically blurred image at multiple offsets horizontally
1714 // to finish the blur effect
1715 // TODO: do offset blends using GLSL
1716 range = r_bloom_blur.integer * bloomwidth / 320;
1717 GL_BlendFunc(GL_ONE, GL_ZERO);
1718 for (x = -range;x <= range;x++)
1720 xoffset = x / (float)bloomwidth * (float)bloomwidth / (float)screenwidth;
1721 yoffset = 0 / (float)bloomheight * (float)bloomheight / (float)screenheight;
1722 // compute a texcoord array with the specified x and y offset
1723 texcoord2f[2][0] = xoffset+0;
1724 texcoord2f[2][1] = yoffset+(float)bloomheight / (float)screenheight;
1725 texcoord2f[2][2] = xoffset+(float)bloomwidth / (float)screenwidth;
1726 texcoord2f[2][3] = yoffset+(float)bloomheight / (float)screenheight;
1727 texcoord2f[2][4] = xoffset+(float)bloomwidth / (float)screenwidth;
1728 texcoord2f[2][5] = yoffset+0;
1729 texcoord2f[2][6] = xoffset+0;
1730 texcoord2f[2][7] = yoffset+0;
1731 // this r value looks like a 'dot' particle, fading sharply to
1732 // black at the edges
1733 // (probably not realistic but looks good enough)
1734 r = r_bloom_intensity.value/(range*2+1)*(1 - x*x/(float)(range*range));
1737 GL_Color(r, r, r, 1);
1738 R_Mesh_Draw(0, 4, 2, polygonelements);
1739 renderstats.bloom_drawpixels += bloomwidth * bloomheight;
1740 GL_BlendFunc(GL_ONE, GL_ONE);
1742 // copy the blurred bloom view to a texture
1743 GL_ActiveTexture(0);
1744 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
1745 renderstats.bloom_copypixels += bloomwidth * bloomheight;
1746 // go back to full view area
1747 qglViewport(r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
1748 // put the original screen image back in place and blend the bloom
1750 memset(&m, 0, sizeof(m));
1751 m.pointer_vertex = vertex3f;
1752 m.tex[0] = R_GetTexture(r_bloom_texture_screen);
1753 m.pointer_texcoord[0] = texcoord2f[0];
1755 dobloomblend = false;
1757 // do both in one pass if possible
1758 if (r_textureunits.integer >= 2 && gl_combine.integer)
1760 dobloomblend = false;
1761 m.texcombinergb[1] = GL_ADD;
1762 m.tex[1] = R_GetTexture(r_bloom_texture_bloom);
1763 m.pointer_texcoord[1] = texcoord2f[1];
1766 dobloomblend = true;
1769 GL_BlendFunc(GL_ONE, GL_ZERO);
1771 R_Mesh_Draw(0, 4, 2, polygonelements);
1772 renderstats.bloom_drawpixels += r_view_width * r_view_height;
1773 // now blend on the bloom texture if multipass
1776 memset(&m, 0, sizeof(m));
1777 m.pointer_vertex = vertex3f;
1778 m.tex[0] = R_GetTexture(r_bloom_texture_bloom);
1779 m.pointer_texcoord[0] = texcoord2f[1];
1781 GL_BlendFunc(GL_ONE, GL_ONE);
1783 R_Mesh_Draw(0, 4, 2, polygonelements);
1784 renderstats.bloom_drawpixels += r_view_width * r_view_height;
1789 // apply a color tint to the whole view
1790 memset(&m, 0, sizeof(m));
1791 m.pointer_vertex = vertex3f;
1793 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1794 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
1795 R_Mesh_Draw(0, 4, 2, polygonelements);
1799 void R_RenderScene(void);
1801 matrix4x4_t r_waterscrollmatrix;
1808 void R_RenderView(void)
1810 if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
1811 return; //Host_Error ("R_RenderView: NULL worldmodel");
1813 r_view_width = bound(0, r_refdef.width, vid.width);
1814 r_view_height = bound(0, r_refdef.height, vid.height);
1816 r_view_x = bound(0, r_refdef.x, vid.width - r_refdef.width);
1817 r_view_y = bound(0, r_refdef.y, vid.height - r_refdef.height);
1819 r_view_matrix = r_refdef.viewentitymatrix;
1820 GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
1821 r_rtworld = r_shadow_realtime_world.integer;
1822 r_rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
1823 r_rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer;
1824 r_rtdlightshadows = r_rtdlight && (r_rtworld ? r_shadow_realtime_world_dlightshadows.integer : r_shadow_realtime_dlight_shadows.integer) && gl_stencil;
1825 r_lightmapintensity = r_rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
1826 r_polygonfactor = 0;
1827 r_polygonoffset = 0;
1828 r_shadowpolygonfactor = r_polygonfactor + r_shadow_shadow_polygonfactor.value;
1829 r_shadowpolygonoffset = r_polygonoffset + r_shadow_shadow_polygonoffset.value;
1831 // GL is weird because it's bottom to top, r_view_y is top to bottom
1832 qglViewport(r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
1833 GL_Scissor(r_view_x, r_view_y, r_view_width, r_view_height);
1834 GL_ScissorTest(true);
1839 if (r_timereport_active)
1840 R_TimeReport("setup");
1842 qglDepthFunc(GL_LEQUAL);
1843 qglPolygonOffset(r_polygonfactor, r_polygonoffset);
1844 qglEnable(GL_POLYGON_OFFSET_FILL);
1848 qglPolygonOffset(r_polygonfactor, r_polygonoffset);
1849 qglDisable(GL_POLYGON_OFFSET_FILL);
1852 if (r_timereport_active)
1853 R_TimeReport("blendview");
1855 GL_Scissor(0, 0, vid.width, vid.height);
1856 GL_ScissorTest(false);
1860 void CSQC_R_ClearScreen (void)
1862 if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
1863 return; //Host_Error ("R_RenderView: NULL worldmodel");
1865 r_view_width = bound(0, r_refdef.width, vid.width);
1866 r_view_height = bound(0, r_refdef.height, vid.height);
1868 r_view_x = bound(0, r_refdef.x, vid.width - r_refdef.width);
1869 r_view_y = bound(0, r_refdef.y, vid.height - r_refdef.height);
1871 r_view_matrix = r_refdef.viewentitymatrix;
1872 GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
1873 r_rtworld = r_shadow_realtime_world.integer;
1874 r_rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
1875 r_rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer;
1876 r_rtdlightshadows = r_rtdlight && (r_rtworld ? r_shadow_realtime_world_dlightshadows.integer : r_shadow_realtime_dlight_shadows.integer) && gl_stencil;
1877 r_lightmapintensity = r_rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
1879 // GL is weird because it's bottom to top, r_view_y is top to bottom
1880 qglViewport(r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
1881 GL_Scissor(r_view_x, r_view_y, r_view_width, r_view_height);
1882 GL_ScissorTest(true);
1887 if (r_timereport_active)
1888 R_TimeReport("setup");
1892 void CSQC_R_RenderScene (void)
1894 qglDepthFunc(GL_LEQUAL);
1895 qglPolygonOffset(r_polygonfactor, r_polygonoffset);
1896 qglEnable(GL_POLYGON_OFFSET_FILL);
1900 qglPolygonOffset(r_polygonfactor, r_polygonoffset);
1901 qglDisable(GL_POLYGON_OFFSET_FILL);
1904 if (r_timereport_active)
1905 R_TimeReport("blendview");
1907 GL_Scissor(0, 0, vid.width, vid.height);
1908 GL_ScissorTest(false);
1911 extern void R_DrawLightningBeams (void);
1912 extern void VM_AddPolygonsToMeshQueue (void);
1913 void R_RenderScene(void)
1917 // don't let sound skip if going slow
1918 if (r_refdef.extraupdate)
1923 if (gl_support_fragment_shader)
1924 qglUseProgramObjectARB(0);
1926 R_MeshQueue_BeginScene();
1930 r_farclip = R_FarClip(r_vieworigin, r_viewforward, 768.0f) + 256.0f;
1931 nearclip = bound (0.001f, r_nearclip.value, r_farclip - 1.0f);
1933 if (r_rtworldshadows || r_rtdlightshadows)
1934 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_refdef.frustum_x, r_refdef.frustum_y, nearclip);
1936 GL_SetupView_Mode_Perspective(r_refdef.frustum_x, r_refdef.frustum_y, nearclip, r_farclip);
1938 GL_SetupView_Orientation_FromEntity(&r_view_matrix);
1940 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);
1944 R_WorldVisibility();
1945 if (r_timereport_active)
1946 R_TimeReport("worldvis");
1949 if (r_timereport_active)
1950 R_TimeReport("markentity");
1952 R_Shadow_UpdateWorldLightSelection();
1954 if (cl.csqc_vidvars.drawworld)
1956 // don't let sound skip if going slow
1957 if (r_refdef.extraupdate)
1960 if (r_refdef.worldmodel && r_refdef.worldmodel->DrawSky)
1962 r_refdef.worldmodel->DrawSky(r_refdef.worldentity);
1963 if (r_timereport_active)
1964 R_TimeReport("worldsky");
1967 if (R_DrawBrushModelsSky() && r_timereport_active)
1968 R_TimeReport("bmodelsky");
1970 if (r_refdef.worldmodel && r_refdef.worldmodel->Draw)
1972 r_refdef.worldmodel->Draw(r_refdef.worldentity);
1973 if (r_timereport_active)
1974 R_TimeReport("world");
1978 // don't let sound skip if going slow
1979 if (r_refdef.extraupdate)
1983 if (r_timereport_active)
1984 R_TimeReport("models");
1986 // don't let sound skip if going slow
1987 if (r_refdef.extraupdate)
1990 R_ShadowVolumeLighting(false);
1991 if (r_timereport_active)
1992 R_TimeReport("rtlights");
1994 // don't let sound skip if going slow
1995 if (r_refdef.extraupdate)
1998 if (cl.csqc_vidvars.drawworld)
2000 R_DrawLightningBeams();
2001 if (r_timereport_active)
2002 R_TimeReport("lightning");
2005 if (r_timereport_active)
2006 R_TimeReport("particles");
2009 if (r_timereport_active)
2010 R_TimeReport("explosions");
2013 R_MeshQueue_RenderTransparent();
2014 if (r_timereport_active)
2015 R_TimeReport("drawtrans");
2017 if (cl.csqc_vidvars.drawworld)
2020 if (r_timereport_active)
2021 R_TimeReport("coronas");
2023 if(cl.csqc_vidvars.drawcrosshair)
2025 R_DrawWorldCrosshair();
2026 if (r_timereport_active)
2027 R_TimeReport("crosshair");
2030 VM_AddPolygonsToMeshQueue();
2032 R_MeshQueue_Render();
2034 R_MeshQueue_EndScene();
2036 // don't let sound skip if going slow
2037 if (r_refdef.extraupdate)
2040 if (gl_support_fragment_shader)
2041 qglUseProgramObjectARB(0);
2045 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
2048 float *v, *c, f1, f2, diff[3], vertex3f[8*3], color4f[8*4];
2050 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2051 GL_DepthMask(false);
2053 R_Mesh_Matrix(&identitymatrix);
2055 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2];
2056 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
2057 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
2058 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
2059 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
2060 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
2061 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
2062 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
2063 R_FillColors(color, 8, cr, cg, cb, ca);
2066 for (i = 0, v = vertex, c = color;i < 8;i++, v += 4, c += 4)
2068 f2 = VERTEXFOGTABLE(VectorDistance(v, r_vieworigin));
2070 c[0] = c[0] * f1 + fogcolor[0] * f2;
2071 c[1] = c[1] * f1 + fogcolor[1] * f2;
2072 c[2] = c[2] * f1 + fogcolor[2] * f2;
2075 memset(&m, 0, sizeof(m));
2076 m.pointer_vertex = vertex3f;
2077 m.pointer_color = color;
2083 int nomodelelements[24] =
2095 float nomodelvertex3f[6*3] =
2105 float nomodelcolor4f[6*4] =
2107 0.0f, 0.0f, 0.5f, 1.0f,
2108 0.0f, 0.0f, 0.5f, 1.0f,
2109 0.0f, 0.5f, 0.0f, 1.0f,
2110 0.0f, 0.5f, 0.0f, 1.0f,
2111 0.5f, 0.0f, 0.0f, 1.0f,
2112 0.5f, 0.0f, 0.0f, 1.0f
2115 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight)
2121 R_Mesh_Matrix(&ent->matrix);
2123 memset(&m, 0, sizeof(m));
2124 m.pointer_vertex = nomodelvertex3f;
2126 if (ent->flags & EF_ADDITIVE)
2128 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2129 GL_DepthMask(false);
2131 else if (ent->alpha < 1)
2133 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2134 GL_DepthMask(false);
2138 GL_BlendFunc(GL_ONE, GL_ZERO);
2141 GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
2144 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
2145 m.pointer_color = color4f;
2146 f2 = VERTEXFOGTABLE(VectorDistance(ent->origin, r_vieworigin));
2148 for (i = 0, c = color4f;i < 6;i++, c += 4)
2150 c[0] = (c[0] * f1 + fogcolor[0] * f2);
2151 c[1] = (c[1] * f1 + fogcolor[1] * f2);
2152 c[2] = (c[2] * f1 + fogcolor[2] * f2);
2156 else if (ent->alpha != 1)
2158 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
2159 m.pointer_color = color4f;
2160 for (i = 0, c = color4f;i < 6;i++, c += 4)
2164 m.pointer_color = nomodelcolor4f;
2166 R_Mesh_Draw(0, 6, 8, nomodelelements);
2169 void R_DrawNoModel(entity_render_t *ent)
2171 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
2172 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_vieworigin : ent->origin, R_DrawNoModel_TransparentCallback, ent, 0, r_shadow_rtlight);
2174 // R_DrawNoModelCallback(ent, 0);
2177 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
2179 vec3_t right1, right2, diff, normal;
2181 VectorSubtract (org2, org1, normal);
2183 // calculate 'right' vector for start
2184 VectorSubtract (r_vieworigin, org1, diff);
2185 CrossProduct (normal, diff, right1);
2186 VectorNormalize (right1);
2188 // calculate 'right' vector for end
2189 VectorSubtract (r_vieworigin, org2, diff);
2190 CrossProduct (normal, diff, right2);
2191 VectorNormalize (right2);
2193 vert[ 0] = org1[0] + width * right1[0];
2194 vert[ 1] = org1[1] + width * right1[1];
2195 vert[ 2] = org1[2] + width * right1[2];
2196 vert[ 3] = org1[0] - width * right1[0];
2197 vert[ 4] = org1[1] - width * right1[1];
2198 vert[ 5] = org1[2] - width * right1[2];
2199 vert[ 6] = org2[0] - width * right2[0];
2200 vert[ 7] = org2[1] - width * right2[1];
2201 vert[ 8] = org2[2] - width * right2[2];
2202 vert[ 9] = org2[0] + width * right2[0];
2203 vert[10] = org2[1] + width * right2[1];
2204 vert[11] = org2[2] + width * right2[2];
2207 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
2209 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)
2211 float fog = 0.0f, ifog;
2216 fog = VERTEXFOGTABLE(VectorDistance(origin, r_vieworigin));
2219 R_Mesh_Matrix(&identitymatrix);
2220 GL_BlendFunc(blendfunc1, blendfunc2);
2221 GL_DepthMask(false);
2222 GL_DepthTest(!depthdisable);
2224 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
2225 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
2226 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
2227 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
2228 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
2229 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
2230 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
2231 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
2232 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
2233 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
2234 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
2235 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
2237 memset(&m, 0, sizeof(m));
2238 m.tex[0] = R_GetTexture(texture);
2239 m.pointer_texcoord[0] = spritetexcoord2f;
2240 m.pointer_vertex = vertex3f;
2242 GL_Color(cr * ifog, cg * ifog, cb * ifog, ca);
2243 R_Mesh_Draw(0, 4, 2, polygonelements);
2245 if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
2247 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
2248 GL_BlendFunc(blendfunc1, GL_ONE);
2249 GL_Color(fogcolor[0] * fog, fogcolor[1] * fog, fogcolor[2] * fog, ca);
2250 R_Mesh_Draw(0, 4, 2, polygonelements);
2254 int R_Mesh_AddVertex3f(rmesh_t *mesh, const float *v)
2258 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
2259 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
2261 if (i == mesh->numvertices)
2263 if (mesh->numvertices < mesh->maxvertices)
2265 VectorCopy(v, vertex3f);
2266 mesh->numvertices++;
2268 return mesh->numvertices;
2274 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
2278 element[0] = R_Mesh_AddVertex3f(mesh, vertex3f);vertex3f += 3;
2279 element[1] = R_Mesh_AddVertex3f(mesh, vertex3f);vertex3f += 3;
2280 e = mesh->element3i + mesh->numtriangles * 3;
2281 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
2283 element[2] = R_Mesh_AddVertex3f(mesh, vertex3f);
2284 if (mesh->numtriangles < mesh->maxtriangles)
2289 mesh->numtriangles++;
2291 element[1] = element[2];
2295 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
2297 int planenum, planenum2;
2300 mplane_t *plane, *plane2;
2301 float temppoints[2][256*3];
2302 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
2306 PolygonF_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->normal[3], 1024.0*1024.0*1024.0);
2307 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
2309 if (planenum2 == planenum)
2311 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);
2314 if (tempnumpoints < 3)
2316 // generate elements forming a triangle fan for this polygon
2317 R_Mesh_AddPolygon3f(mesh, tempnumpoints, temppoints[w]);
2321 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)
2323 texturelayer_t *layer;
2324 layer = t->currentlayers + t->currentnumlayers++;
2326 layer->depthmask = depthmask;
2327 layer->blendfunc1 = blendfunc1;
2328 layer->blendfunc2 = blendfunc2;
2329 layer->texture = texture;
2330 layer->texmatrix = *matrix;
2331 layer->color[0] = r;
2332 layer->color[1] = g;
2333 layer->color[2] = b;
2334 layer->color[3] = a;
2337 void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
2339 // FIXME: identify models using a better check than ent->model->brush.shadowmesh
2340 //int lightmode = ((ent->effects & EF_FULLBRIGHT) || ent->model->brush.shadowmesh) ? 0 : 2;
2343 texture_t *texture = t;
2344 model_t *model = ent->model;
2345 int s = ent->skinnum;
2346 if ((unsigned int)s >= (unsigned int)model->numskins)
2348 if (model->skinscenes)
2350 if (model->skinscenes[s].framecount > 1)
2351 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
2353 s = model->skinscenes[s].firstframe;
2356 t = t + s * model->num_surfaces;
2358 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];
2359 texture->currentframe = t;
2362 t->currentmaterialflags = t->basematerialflags;
2363 t->currentalpha = ent->alpha;
2364 if (t->basematerialflags & MATERIALFLAG_WATERALPHA)
2365 t->currentalpha *= r_wateralpha.value;
2366 if (!(ent->flags & RENDER_LIGHT))
2367 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
2368 if (ent->effects & EF_ADDITIVE)
2369 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_TRANSPARENT;
2370 else if (t->currentalpha < 1)
2371 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_TRANSPARENT;
2372 if (ent->effects & EF_NODEPTHTEST)
2373 t->currentmaterialflags |= MATERIALFLAG_NODEPTHTEST;
2374 if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
2375 t->currenttexmatrix = r_waterscrollmatrix;
2377 t->currenttexmatrix = identitymatrix;
2379 t->colormapping = VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f);
2380 t->basetexture = (!t->colormapping && t->skin.merged) ? t->skin.merged : t->skin.base;
2381 t->glosstexture = r_texture_white;
2382 t->specularpower = 8;
2383 t->specularscale = 0;
2384 if (r_shadow_gloss.integer > 0)
2388 if (r_shadow_glossintensity.value > 0)
2390 t->glosstexture = t->skin.gloss;
2391 t->specularscale = r_shadow_glossintensity.value;
2394 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
2395 t->specularscale = r_shadow_gloss2intensity.value;
2398 t->currentnumlayers = 0;
2399 if (!(t->currentmaterialflags & MATERIALFLAG_NODRAW))
2401 if (gl_lightmaps.integer)
2402 R_Texture_AddLayer(t, true, GL_ONE, GL_ZERO, TEXTURELAYERTYPE_LITTEXTURE_MULTIPASS, r_texture_white, &identitymatrix, 1, 1, 1, 1);
2403 else if (!(t->currentmaterialflags & MATERIALFLAG_SKY))
2405 int blendfunc1, blendfunc2, depthmask;
2406 if (t->currentmaterialflags & MATERIALFLAG_ADD)
2408 blendfunc1 = GL_SRC_ALPHA;
2409 blendfunc2 = GL_ONE;
2412 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
2414 blendfunc1 = GL_SRC_ALPHA;
2415 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
2420 blendfunc1 = GL_ONE;
2421 blendfunc2 = GL_ZERO;
2424 if (t->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL))
2426 rtexture_t *currentbasetexture;
2428 if (fogenabled && (t->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
2429 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
2430 currentbasetexture = (VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) < (1.0f / 1048576.0f) && t->skin.merged) ? t->skin.merged : t->skin.base;
2431 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2433 // fullbright is not affected by r_lightmapintensity
2434 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
2435 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->skin.pants)
2436 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);
2437 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->skin.shirt)
2438 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);
2444 // q3bsp has no lightmap updates, so the lightstylevalue that
2445 // would normally be baked into the lightmaptexture must be
2446 // applied to the color
2447 if (ent->model->type == mod_brushq3)
2448 colorscale *= r_refdef.lightstylevalue[0] * (1.0f / 256.0f);
2449 colorscale *= r_lightmapintensity;
2450 if (r_textureunits.integer >= 2 && gl_combine.integer)
2451 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);
2452 else if ((t->currentmaterialflags & MATERIALFLAG_TRANSPARENT) == 0)
2453 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);
2455 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);
2456 if (r_ambient.value >= (1.0f/64.0f))
2457 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);
2458 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->skin.pants)
2460 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);
2461 if (r_ambient.value >= (1.0f/64.0f))
2462 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);
2464 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->skin.shirt)
2466 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);
2467 if (r_ambient.value >= (1.0f/64.0f))
2468 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);
2471 if (t->skin.glow != NULL)
2472 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.glow, &t->currenttexmatrix, 1, 1, 1, t->currentalpha);
2473 if (fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
2475 // if this is opaque use alpha blend which will darken the earlier
2478 // if this is an alpha blended material, all the earlier passes
2479 // were darkened by fog already, so we only need to add the fog
2480 // color ontop through the fog mask texture
2482 // if this is an additive blended material, all the earlier passes
2483 // were darkened by fog already, and we should not add fog color
2484 // (because the background was not darkened, there is no fog color
2485 // that was lost behind it).
2486 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);
2493 void R_UpdateAllTextureInfo(entity_render_t *ent)
2497 for (i = 0;i < ent->model->num_textures;i++)
2498 R_UpdateTextureInfo(ent, ent->model->data_textures + i);
2501 int rsurface_array_size = 0;
2502 float *rsurface_array_vertex3f = NULL;
2503 float *rsurface_array_svector3f = NULL;
2504 float *rsurface_array_tvector3f = NULL;
2505 float *rsurface_array_normal3f = NULL;
2506 float *rsurface_array_color4f = NULL;
2507 float *rsurface_array_texcoord3f = NULL;
2509 void R_Mesh_ResizeArrays(int newvertices)
2511 if (rsurface_array_size >= newvertices)
2513 if (rsurface_array_vertex3f)
2514 Mem_Free(rsurface_array_vertex3f);
2515 rsurface_array_size = (newvertices + 1023) & ~1023;
2516 rsurface_array_vertex3f = Mem_Alloc(r_main_mempool, rsurface_array_size * sizeof(float[19]));
2517 rsurface_array_svector3f = rsurface_array_vertex3f + rsurface_array_size * 3;
2518 rsurface_array_tvector3f = rsurface_array_vertex3f + rsurface_array_size * 6;
2519 rsurface_array_normal3f = rsurface_array_vertex3f + rsurface_array_size * 9;
2520 rsurface_array_color4f = rsurface_array_vertex3f + rsurface_array_size * 12;
2521 rsurface_array_texcoord3f = rsurface_array_vertex3f + rsurface_array_size * 16;
2524 float *rsurface_vertex3f;
2525 float *rsurface_svector3f;
2526 float *rsurface_tvector3f;
2527 float *rsurface_normal3f;
2528 float *rsurface_lightmapcolor4f;
2530 void RSurf_SetVertexPointer(const entity_render_t *ent, const texture_t *texture, const msurface_t *surface, const vec3_t modelorg, qboolean generatenormals, qboolean generatetangents)
2532 if (rsurface_array_size < surface->groupmesh->num_vertices)
2533 R_Mesh_ResizeArrays(surface->groupmesh->num_vertices);
2534 if ((ent->frameblend[0].lerp != 1 || ent->frameblend[0].frame != 0) && (surface->groupmesh->data_morphvertex3f || surface->groupmesh->data_vertexboneweights))
2536 rsurface_vertex3f = rsurface_array_vertex3f;
2537 Mod_Alias_GetMesh_Vertex3f(ent->model, ent->frameblend, surface->groupmesh, rsurface_vertex3f);
2538 if (generatetangents || (texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2)))
2540 rsurface_svector3f = rsurface_array_svector3f;
2541 rsurface_tvector3f = rsurface_array_tvector3f;
2542 rsurface_normal3f = rsurface_array_normal3f;
2543 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);
2547 rsurface_svector3f = NULL;
2548 rsurface_tvector3f = NULL;
2549 if (generatenormals)
2551 rsurface_normal3f = rsurface_array_normal3f;
2552 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);
2555 rsurface_normal3f = NULL;
2560 rsurface_vertex3f = surface->groupmesh->data_vertex3f;
2561 rsurface_svector3f = surface->groupmesh->data_svector3f;
2562 rsurface_tvector3f = surface->groupmesh->data_tvector3f;
2563 rsurface_normal3f = surface->groupmesh->data_normal3f;
2565 if (texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
2568 float center[3], forward[3], right[3], up[3], v[4][3];
2569 matrix4x4_t matrix1, imatrix1;
2570 Matrix4x4_Transform(&ent->inversematrix, r_viewforward, forward);
2571 Matrix4x4_Transform(&ent->inversematrix, r_viewright, right);
2572 Matrix4x4_Transform(&ent->inversematrix, r_viewup, up);
2573 // a single autosprite surface can contain multiple sprites...
2574 for (j = 0;j < surface->num_vertices - 3;j += 4)
2576 VectorClear(center);
2577 for (i = 0;i < 4;i++)
2578 VectorAdd(center, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
2579 VectorScale(center, 0.25f, center);
2580 // FIXME: calculate vectors from triangle edges instead of using texture vectors as an easy way out?
2581 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);
2582 Matrix4x4_Invert_Simple(&imatrix1, &matrix1);
2583 for (i = 0;i < 4;i++)
2584 Matrix4x4_Transform(&imatrix1, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, v[i]);
2585 if (texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE2)
2587 forward[0] = modelorg[0] - center[0];
2588 forward[1] = modelorg[1] - center[1];
2590 VectorNormalize(forward);
2591 right[0] = forward[1];
2592 right[1] = -forward[0];
2594 VectorSet(up, 0, 0, 1);
2596 for (i = 0;i < 4;i++)
2597 VectorMAMAMAM(1, center, v[i][0], forward, v[i][1], right, v[i][2], up, rsurface_array_vertex3f + (surface->num_firstvertex+i+j) * 3);
2599 rsurface_vertex3f = rsurface_array_vertex3f;
2600 rsurface_svector3f = rsurface_array_svector3f;
2601 rsurface_tvector3f = rsurface_array_tvector3f;
2602 rsurface_normal3f = rsurface_array_normal3f;
2603 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);
2605 R_Mesh_VertexPointer(rsurface_vertex3f);
2608 static void RSurf_Draw(const msurface_t *surface)
2610 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2611 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2612 GL_LockArrays(0, 0);
2615 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)
2620 RSurf_SetVertexPointer(ent, texture, surface, modelorg, lightmode >= 2, false);
2624 vec3_t ambientcolor;
2625 vec3_t diffusecolor;
2627 VectorCopy(ent->modellight_lightdir, lightdir);
2628 ambientcolor[0] = ent->modellight_ambient[0] * r * 0.5f;
2629 ambientcolor[1] = ent->modellight_ambient[1] * g * 0.5f;
2630 ambientcolor[2] = ent->modellight_ambient[2] * b * 0.5f;
2631 diffusecolor[0] = ent->modellight_diffuse[0] * r * 0.5f;
2632 diffusecolor[1] = ent->modellight_diffuse[1] * g * 0.5f;
2633 diffusecolor[2] = ent->modellight_diffuse[2] * b * 0.5f;
2634 if (VectorLength2(diffusecolor) > 0)
2636 int numverts = surface->num_vertices;
2637 v = rsurface_vertex3f + 3 * surface->num_firstvertex;
2638 c2 = rsurface_normal3f + 3 * surface->num_firstvertex;
2639 c = rsurface_array_color4f + 4 * surface->num_firstvertex;
2640 // q3-style directional shading
2641 for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
2643 if ((f = DotProduct(c2, lightdir)) > 0)
2644 VectorMA(ambientcolor, f, diffusecolor, c);
2646 VectorCopy(ambientcolor, c);
2654 rsurface_lightmapcolor4f = rsurface_array_color4f;
2658 r = ambientcolor[0];
2659 g = ambientcolor[1];
2660 b = ambientcolor[2];
2661 rsurface_lightmapcolor4f = NULL;
2664 else if (lightmode >= 1)
2666 if (surface->lightmapinfo && surface->lightmapinfo->stainsamples)
2668 for (i = 0, c = rsurface_array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
2670 if (surface->lightmapinfo->samples)
2672 const unsigned char *lm = surface->lightmapinfo->samples + (surface->groupmesh->data_lightmapoffsets + surface->num_firstvertex)[i];
2673 float scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
2674 VectorScale(lm, scale, c);
2675 if (surface->lightmapinfo->styles[1] != 255)
2677 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
2679 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
2680 VectorMA(c, scale, lm, c);
2681 if (surface->lightmapinfo->styles[2] != 255)
2684 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
2685 VectorMA(c, scale, lm, c);
2686 if (surface->lightmapinfo->styles[3] != 255)
2689 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
2690 VectorMA(c, scale, lm, c);
2698 rsurface_lightmapcolor4f = rsurface_array_color4f;
2701 rsurface_lightmapcolor4f = surface->groupmesh->data_lightmapcolor4f;
2704 rsurface_lightmapcolor4f = NULL;
2707 if (rsurface_lightmapcolor4f)
2709 for (i = 0, v = (rsurface_vertex3f + 3 * surface->num_firstvertex), c = (rsurface_lightmapcolor4f + 4 * surface->num_firstvertex), c2 = (rsurface_array_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4, c2 += 4)
2711 f = 1 - VERTEXFOGTABLE(VectorDistance(v, modelorg));
2720 for (i = 0, v = (rsurface_vertex3f + 3 * surface->num_firstvertex), c2 = (rsurface_array_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c2 += 4)
2722 f = 1 - VERTEXFOGTABLE(VectorDistance(v, modelorg));
2729 rsurface_lightmapcolor4f = rsurface_array_color4f;
2731 if (applycolor && rsurface_lightmapcolor4f)
2733 for (i = 0, c = (rsurface_lightmapcolor4f + 4 * surface->num_firstvertex), c2 = (rsurface_array_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, c += 4, c2 += 4)
2740 rsurface_lightmapcolor4f = rsurface_array_color4f;
2742 R_Mesh_ColorPointer(rsurface_lightmapcolor4f);
2743 GL_Color(r, g, b, a);
2744 RSurf_Draw(surface);
2747 static void R_DrawTextureSurfaceList(const entity_render_t *ent, texture_t *texture, int texturenumsurfaces, const msurface_t **texturesurfacelist, const vec3_t modelorg)
2749 int texturesurfaceindex;
2751 const msurface_t *surface;
2752 qboolean applycolor;
2755 if (texture->currentmaterialflags & MATERIALFLAG_NODRAW)
2757 r_shadow_rtlight = NULL;
2758 renderstats.entities_surfaces += texturenumsurfaces;
2759 // FIXME: identify models using a better check than ent->model->brush.shadowmesh
2760 lightmode = ((ent->effects & EF_FULLBRIGHT) || ent->model->brush.shadowmesh) ? 0 : 2;
2761 GL_DepthTest(!(texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
2762 if ((texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (ent->flags & RENDER_NOCULLFACE))
2763 qglDisable(GL_CULL_FACE);
2764 if (texture->currentmaterialflags & MATERIALFLAG_SKY)
2766 // transparent sky would be ridiculous
2767 if (!(texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
2771 skyrendernow = false;
2773 // restore entity matrix
2774 R_Mesh_Matrix(&ent->matrix);
2777 // LordHavoc: HalfLife maps have freaky skypolys...
2778 // LordHavoc: Quake3 never did sky masking (unlike software Quake
2779 // and Quake2), so disable the sky masking in Quake3 maps as it
2780 // causes problems with q3map2 sky tricks
2781 if (!ent->model->brush.ishlbsp && ent->model->type != mod_brushq3)
2783 GL_Color(fogcolor[0], fogcolor[1], fogcolor[2], 1);
2784 memset(&m, 0, sizeof(m));
2786 if (skyrendermasked)
2788 // depth-only (masking)
2789 GL_ColorMask(0,0,0,0);
2790 // just to make sure that braindead drivers don't draw
2791 // anything despite that colormask...
2792 GL_BlendFunc(GL_ZERO, GL_ONE);
2797 GL_BlendFunc(GL_ONE, GL_ZERO);
2799 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2801 surface = texturesurfacelist[texturesurfaceindex];
2802 RSurf_SetVertexPointer(ent, texture, surface, modelorg, false, false);
2803 RSurf_Draw(surface);
2805 if (skyrendermasked)
2806 GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
2810 else if (r_glsl.integer && gl_support_fragment_shader)
2812 if (texture->currentmaterialflags & MATERIALFLAG_ADD)
2814 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2815 GL_DepthMask(false);
2817 else if (texture->currentmaterialflags & MATERIALFLAG_ALPHA)
2819 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2820 GL_DepthMask(false);
2824 GL_BlendFunc(GL_ONE, GL_ZERO);
2828 memset(&m, 0, sizeof(m));
2830 GL_Color(ent->colormod[0], ent->colormod[1], ent->colormod[2], texture->currentalpha);
2831 R_SetupSurfaceShader(ent, texture, modelorg, vec3_origin, lightmode == 2);
2832 if (!r_glsl_permutation)
2836 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2838 surface = texturesurfacelist[texturesurfaceindex];
2839 RSurf_SetVertexPointer(ent, texture, surface, modelorg, false, true);
2840 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2841 R_Mesh_TexCoordPointer(1, 3, rsurface_svector3f);
2842 R_Mesh_TexCoordPointer(2, 3, rsurface_tvector3f);
2843 R_Mesh_TexCoordPointer(3, 3, rsurface_normal3f);
2844 RSurf_Draw(surface);
2849 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2851 surface = texturesurfacelist[texturesurfaceindex];
2852 RSurf_SetVertexPointer(ent, texture, surface, modelorg, false, true);
2853 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2854 R_Mesh_TexCoordPointer(1, 3, rsurface_svector3f);
2855 R_Mesh_TexCoordPointer(2, 3, rsurface_tvector3f);
2856 R_Mesh_TexCoordPointer(3, 3, rsurface_normal3f);
2857 R_Mesh_TexCoordPointer(4, 2, surface->groupmesh->data_texcoordlightmap2f);
2858 if (surface->lightmaptexture)
2860 R_Mesh_TexBind(7, R_GetTexture(surface->lightmaptexture));
2861 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
2862 R_Mesh_TexBind(8, R_GetTexture(surface->deluxemaptexture));
2863 R_Mesh_ColorPointer(NULL);
2867 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
2868 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
2869 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
2870 R_Mesh_ColorPointer(surface->groupmesh->data_lightmapcolor4f);
2872 RSurf_Draw(surface);
2875 qglUseProgramObjectARB(0);
2877 else if (texture->currentnumlayers)
2880 texturelayer_t *layer;
2881 for (layerindex = 0, layer = texture->currentlayers;layerindex < texture->currentnumlayers;layerindex++, layer++)
2884 int layertexrgbscale;
2885 GL_DepthMask(layer->depthmask);
2886 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
2887 if ((layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2) && (gl_combine.integer || layer->depthmask))
2889 layertexrgbscale = 4;
2890 VectorScale(layer->color, 0.25f, layercolor);
2892 else if ((layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1) && (gl_combine.integer || layer->depthmask))
2894 layertexrgbscale = 2;
2895 VectorScale(layer->color, 0.5f, layercolor);
2899 layertexrgbscale = 1;
2900 VectorScale(layer->color, 1.0f, layercolor);
2902 layercolor[3] = layer->color[3];
2903 GL_Color(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
2904 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
2905 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
2906 switch (layer->type)
2908 case TEXTURELAYERTYPE_LITTEXTURE_COMBINE:
2909 memset(&m, 0, sizeof(m));
2910 m.tex[1] = R_GetTexture(layer->texture);
2911 m.texmatrix[1] = layer->texmatrix;
2912 m.texrgbscale[1] = layertexrgbscale;
2913 m.pointer_color = rsurface_array_color4f;
2917 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2919 surface = texturesurfacelist[texturesurfaceindex];
2920 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
2921 R_Mesh_TexCoordPointer(1, 2, surface->groupmesh->data_texcoordtexture2f);
2922 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2923 RSurf_DrawLightmap(ent, texture, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 2, applycolor, applyfog);
2928 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2930 surface = texturesurfacelist[texturesurfaceindex];
2931 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
2932 R_Mesh_TexCoordPointer(1, 2, surface->groupmesh->data_texcoordtexture2f);
2933 if (surface->lightmaptexture)
2935 R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
2936 RSurf_DrawLightmap(ent, texture, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, applyfog);
2940 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2941 RSurf_DrawLightmap(ent, texture, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 1, applycolor, applyfog);
2946 case TEXTURELAYERTYPE_LITTEXTURE_MULTIPASS:
2947 memset(&m, 0, sizeof(m));
2948 m.tex[0] = R_GetTexture(layer->texture);
2949 m.texmatrix[0] = layer->texmatrix;
2950 m.pointer_color = rsurface_array_color4f;
2951 m.texrgbscale[0] = layertexrgbscale;
2955 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2957 surface = texturesurfacelist[texturesurfaceindex];
2958 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
2959 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2960 RSurf_DrawLightmap(ent, texture, surface, modelorg, 1, 1, 1, 1, 2, false, false);
2965 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2967 surface = texturesurfacelist[texturesurfaceindex];
2968 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
2969 if (surface->lightmaptexture)
2971 R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
2972 RSurf_DrawLightmap(ent, texture, surface, modelorg, 1, 1, 1, 1, 0, false, false);
2976 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2977 RSurf_DrawLightmap(ent, texture, surface, modelorg, 1, 1, 1, 1, 1, false, false);
2981 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
2982 memset(&m, 0, sizeof(m));
2983 m.tex[0] = R_GetTexture(layer->texture);
2984 m.texmatrix[0] = layer->texmatrix;
2985 m.pointer_color = rsurface_array_color4f;
2986 m.texrgbscale[0] = layertexrgbscale;
2988 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2990 surface = texturesurfacelist[texturesurfaceindex];
2991 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2992 RSurf_DrawLightmap(ent, texture, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, applyfog);
2995 case TEXTURELAYERTYPE_LITTEXTURE_VERTEX:
2996 memset(&m, 0, sizeof(m));
2997 m.tex[0] = R_GetTexture(layer->texture);
2998 m.texmatrix[0] = layer->texmatrix;
2999 m.texrgbscale[0] = layertexrgbscale;
3000 m.pointer_color = rsurface_array_color4f;
3004 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3006 surface = texturesurfacelist[texturesurfaceindex];
3007 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
3008 RSurf_DrawLightmap(ent, texture, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 2, applycolor, applyfog);
3013 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3015 surface = texturesurfacelist[texturesurfaceindex];
3016 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
3017 RSurf_DrawLightmap(ent, texture, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 1, applycolor, applyfog);
3021 case TEXTURELAYERTYPE_TEXTURE:
3022 memset(&m, 0, sizeof(m));
3023 m.tex[0] = R_GetTexture(layer->texture);
3024 m.texmatrix[0] = layer->texmatrix;
3025 m.pointer_color = rsurface_array_color4f;
3026 m.texrgbscale[0] = layertexrgbscale;
3028 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3030 surface = texturesurfacelist[texturesurfaceindex];
3031 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
3032 RSurf_DrawLightmap(ent, texture, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, applyfog);
3035 case TEXTURELAYERTYPE_FOG:
3036 memset(&m, 0, sizeof(m));
3039 m.tex[0] = R_GetTexture(layer->texture);
3040 m.texmatrix[0] = layer->texmatrix;
3043 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3047 surface = texturesurfacelist[texturesurfaceindex];
3048 RSurf_SetVertexPointer(ent, texture, surface, modelorg, false, false);
3050 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
3051 R_Mesh_ColorPointer(rsurface_array_color4f);
3052 for (i = 0, v = (rsurface_vertex3f + 3 * surface->num_firstvertex), c = (rsurface_array_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4)
3054 f = VERTEXFOGTABLE(VectorDistance(v, modelorg));
3055 c[0] = layercolor[0];
3056 c[1] = layercolor[1];
3057 c[2] = layercolor[2];
3058 c[3] = f * layercolor[3];
3060 RSurf_Draw(surface);
3064 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
3066 // if trying to do overbright on first pass of an opaque surface
3067 // when combine is not supported, brighten as a post process
3068 if (layertexrgbscale > 1 && !gl_combine.integer && layer->depthmask)
3071 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
3072 GL_Color(1, 1, 1, 1);
3073 memset(&m, 0, sizeof(m));
3075 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3077 surface = texturesurfacelist[texturesurfaceindex];
3078 RSurf_SetVertexPointer(ent, texture, surface, modelorg, false, false);
3079 for (scale = 1;scale < layertexrgbscale;scale <<= 1)
3080 RSurf_Draw(surface);
3085 if ((texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (ent->flags & RENDER_NOCULLFACE))
3086 qglEnable(GL_CULL_FACE);
3089 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight)
3091 const msurface_t *surface = ent->model->data_surfaces + surfacenumber;
3095 texture = surface->texture;
3096 if (texture->basematerialflags & MATERIALFLAG_SKY)
3097 return; // transparent sky is too difficult
3098 R_UpdateTextureInfo(ent, texture);
3100 R_Mesh_Matrix(&ent->matrix);
3101 Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
3102 R_DrawTextureSurfaceList(ent, texture->currentframe, 1, &surface, modelorg);
3105 void R_QueueTextureSurfaceList(entity_render_t *ent, texture_t *texture, int texturenumsurfaces, const msurface_t **texturesurfacelist, const vec3_t modelorg)
3107 int texturesurfaceindex;
3108 const msurface_t *surface;
3109 vec3_t tempcenter, center;
3110 if (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT)
3112 // drawing sky transparently would be too difficult
3113 if (!(texture->currentmaterialflags & MATERIALFLAG_SKY))
3115 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3117 surface = texturesurfacelist[texturesurfaceindex];
3118 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
3119 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
3120 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
3121 Matrix4x4_Transform(&ent->matrix, tempcenter, center);
3122 R_MeshQueue_AddTransparent(texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_vieworigin : center, R_DrawSurface_TransparentCallback, ent, surface - ent->model->data_surfaces, r_shadow_rtlight);
3127 R_DrawTextureSurfaceList(ent, texture, texturenumsurfaces, texturesurfacelist, modelorg);
3130 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
3131 void R_DrawSurfaces(entity_render_t *ent, qboolean skysurfaces)
3133 int i, j, f, flagsmask;
3134 int counttriangles = 0;
3135 msurface_t *surface, **surfacechain;
3136 texture_t *t, *texture;
3137 model_t *model = ent->model;
3139 const int maxsurfacelist = 1024;
3140 int numsurfacelist = 0;
3141 const msurface_t *surfacelist[1024];
3144 R_Mesh_Matrix(&ent->matrix);
3145 Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
3147 // update light styles
3148 if (!skysurfaces && model->brushq1.light_styleupdatechains)
3150 for (i = 0;i < model->brushq1.light_styles;i++)
3152 if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
3154 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
3155 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
3156 for (;(surface = *surfacechain);surfacechain++)
3157 surface->cached_dlight = true;
3162 R_UpdateAllTextureInfo(ent);
3163 flagsmask = skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL);
3168 if (ent == r_refdef.worldentity)
3170 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
3172 if (!r_worldsurfacevisible[j])
3174 if (t != surface->texture)
3178 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
3181 t = surface->texture;
3182 texture = t->currentframe;
3183 f = texture->currentmaterialflags & flagsmask;
3185 if (f && surface->num_triangles)
3187 // if lightmap parameters changed, rebuild lightmap texture
3188 if (surface->cached_dlight)
3189 R_BuildLightMap(ent, surface);
3190 // add face to draw list
3191 surfacelist[numsurfacelist++] = surface;
3192 counttriangles += surface->num_triangles;
3193 if (numsurfacelist >= maxsurfacelist)
3195 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
3203 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
3205 if (t != surface->texture)
3209 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
3212 t = surface->texture;
3213 texture = t->currentframe;
3214 f = texture->currentmaterialflags & flagsmask;
3216 if (f && surface->num_triangles)
3218 // if lightmap parameters changed, rebuild lightmap texture
3219 if (surface->cached_dlight)
3220 R_BuildLightMap(ent, surface);
3221 // add face to draw list
3222 surfacelist[numsurfacelist++] = surface;
3223 counttriangles += surface->num_triangles;
3224 if (numsurfacelist >= maxsurfacelist)
3226 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
3233 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
3234 renderstats.entities_triangles += counttriangles;
3235 if (gl_support_fragment_shader)
3236 qglUseProgramObjectARB(0);
3238 if (r_showtris.integer || r_shownormals.integer)
3241 const int *elements;
3246 if (r_showdisabledepthtest.integer)
3247 qglDepthFunc(GL_ALWAYS);
3248 GL_BlendFunc(GL_ONE, GL_ZERO);
3249 memset(&m, 0, sizeof(m));
3251 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
3253 if (ent == r_refdef.worldentity && !r_worldsurfacevisible[j])
3255 texture = surface->texture->currentframe;
3256 if ((texture->currentmaterialflags & flagsmask) && surface->num_triangles)
3258 RSurf_SetVertexPointer(ent, texture, surface, modelorg, false, r_shownormals.integer != 0);
3259 if (r_showtris.integer)
3261 if (!texture->currentlayers->depthmask)
3262 GL_Color(r_showtris.value, 0, 0, 1);
3263 else if (ent == r_refdef.worldentity)
3264 GL_Color(r_showtris.value, r_showtris.value, r_showtris.value, 1);
3266 GL_Color(0, r_showtris.value, 0, 1);
3267 elements = (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle);
3269 for (k = 0;k < surface->num_triangles;k++, elements += 3)
3271 qglArrayElement(elements[0]);qglArrayElement(elements[1]);
3272 qglArrayElement(elements[1]);qglArrayElement(elements[2]);
3273 qglArrayElement(elements[2]);qglArrayElement(elements[0]);
3277 if (r_shownormals.integer)
3279 GL_Color(r_shownormals.value, 0, 0, 1);
3281 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
3283 VectorCopy(rsurface_vertex3f + l * 3, v);
3284 qglVertex3f(v[0], v[1], v[2]);
3285 VectorMA(v, 8, rsurface_svector3f + l * 3, v);
3286 qglVertex3f(v[0], v[1], v[2]);
3289 GL_Color(0, 0, r_shownormals.value, 1);
3291 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
3293 VectorCopy(rsurface_vertex3f + l * 3, v);
3294 qglVertex3f(v[0], v[1], v[2]);
3295 VectorMA(v, 8, rsurface_tvector3f + l * 3, v);
3296 qglVertex3f(v[0], v[1], v[2]);
3299 GL_Color(0, r_shownormals.value, 0, 1);
3301 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
3303 VectorCopy(rsurface_vertex3f + l * 3, v);
3304 qglVertex3f(v[0], v[1], v[2]);
3305 VectorMA(v, 8, rsurface_normal3f + l * 3, v);
3306 qglVertex3f(v[0], v[1], v[2]);
3312 if (r_showdisabledepthtest.integer)
3313 qglDepthFunc(GL_LEQUAL);