2 Copyright (C) 1996-1997 Id Software, Inc.
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26 mempool_t *r_main_mempool;
27 rtexturepool_t *r_main_texturepool;
29 // used for dlight push checking and other things
34 renderstats_t renderstats;
36 // true during envmap command capture
39 // maximum visible distance (recalculated from world box each frame)
41 // brightness of world lightmaps and related lighting
42 // (often reduced when world rtlights are enabled)
43 float r_lightmapintensity;
44 // whether to draw world lights realtime, dlights realtime, and their shadows
46 qboolean r_rtworldshadows;
48 qboolean r_rtdlightshadows;
51 // forces all rendering to draw triangle outlines
66 matrix4x4_t r_view_matrix;
73 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
74 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
75 cvar_t r_showtris_polygonoffset = {0, "r_showtris_polygonoffset", "-10", "nudges triangle outlines in hardware depth units, used to make outlines appear infront of walls"};
76 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
77 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
78 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
79 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
80 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
81 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
82 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing\n"};
83 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
84 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
85 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
86 cvar_t r_fullbright = {0, "r_fullbright","0", "make everything bright cheat (not allowed in multiplayer)"};
87 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
88 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
89 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
91 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
92 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
93 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
94 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
95 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
96 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
97 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
99 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of hardware texture units reported by driver (note: setting this to 1 turns off gl_combine)"};
101 cvar_t r_glsl = {0, "r_glsl", "1", "enables use of OpenGL 2.0 pixel shaders for lighting"};
102 cvar_t r_glsl_offsetmapping = {0, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
103 cvar_t r_glsl_offsetmapping_reliefmapping = {0, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
104 cvar_t r_glsl_offsetmapping_scale = {0, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
105 cvar_t r_glsl_usehalffloat = {0, "r_glsl_usehalffloat", "0", "use half and hvec variables in GLSL shader for a speed gain (NVIDIA only)"};
106 cvar_t r_glsl_surfacenormalize = {0, "r_glsl_surfacenormalize", "1", "normalize bumpmap texels in GLSL shader, produces a more rounded look on small bumps and dents"};
107 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)"};
109 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1", "enables animation smoothing on sprites (requires r_lerpmodels 1)"};
110 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
111 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
113 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
114 cvar_t r_bloom_intensity = {CVAR_SAVE, "r_bloom_intensity", "1.5", "how bright the glow is"};
115 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
116 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
117 cvar_t r_bloom_power = {CVAR_SAVE, "r_bloom_power", "2", "how much to darken the image before blurring to make the bloom effect"};
119 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"};
121 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"};
123 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
125 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
127 rtexture_t *r_bloom_texture_screen;
128 rtexture_t *r_bloom_texture_bloom;
129 rtexture_t *r_texture_blanknormalmap;
130 rtexture_t *r_texture_white;
131 rtexture_t *r_texture_black;
132 rtexture_t *r_texture_notexture;
133 rtexture_t *r_texture_whitecube;
134 rtexture_t *r_texture_normalizationcube;
135 rtexture_t *r_texture_fogattenuation;
136 rtexture_t *r_texture_fogintensity;
138 // information about each possible shader permutation
139 r_glsl_permutation_t r_glsl_permutations[SHADERPERMUTATION_COUNT];
140 // currently selected permutation
141 r_glsl_permutation_t *r_glsl_permutation;
143 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
146 for (i = 0;i < verts;i++)
157 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
160 for (i = 0;i < verts;i++)
175 vec_t fogtabledistmultiplier;
176 float fogtable[FOGTABLEWIDTH];
177 float fog_density, fog_red, fog_green, fog_blue;
179 qboolean oldgl_fogenable;
180 void R_UpdateFog(void)
182 if (gamemode == GAME_NEHAHRA)
184 if (gl_fogenable.integer)
186 oldgl_fogenable = true;
187 fog_density = gl_fogdensity.value;
188 fog_red = gl_fogred.value;
189 fog_green = gl_foggreen.value;
190 fog_blue = gl_fogblue.value;
192 else if (oldgl_fogenable)
194 oldgl_fogenable = false;
203 fogcolor[0] = fog_red = bound(0.0f, fog_red , 1.0f);
204 fogcolor[1] = fog_green = bound(0.0f, fog_green, 1.0f);
205 fogcolor[2] = fog_blue = bound(0.0f, fog_blue , 1.0f);
210 fogdensity = -4000.0f / (fog_density * fog_density);
211 // this is the point where the fog reaches 0.9986 alpha, which we
212 // consider a good enough cutoff point for the texture
213 // (0.9986 * 256 == 255.6)
214 fogrange = 400 / fog_density;
215 fograngerecip = 1.0f / fogrange;
216 fogtabledistmultiplier = FOGTABLEWIDTH * fograngerecip;
217 // fog color was already set
223 // FIXME: move this to client?
226 if (gamemode == GAME_NEHAHRA)
228 Cvar_Set("gl_fogenable", "0");
229 Cvar_Set("gl_fogdensity", "0.2");
230 Cvar_Set("gl_fogred", "0.3");
231 Cvar_Set("gl_foggreen", "0.3");
232 Cvar_Set("gl_fogblue", "0.3");
234 fog_density = fog_red = fog_green = fog_blue = 0.0f;
237 // FIXME: move this to client?
238 void FOG_registercvars(void)
243 if (gamemode == GAME_NEHAHRA)
245 Cvar_RegisterVariable (&gl_fogenable);
246 Cvar_RegisterVariable (&gl_fogdensity);
247 Cvar_RegisterVariable (&gl_fogred);
248 Cvar_RegisterVariable (&gl_foggreen);
249 Cvar_RegisterVariable (&gl_fogblue);
250 Cvar_RegisterVariable (&gl_fogstart);
251 Cvar_RegisterVariable (&gl_fogend);
254 r = (-1.0/256.0) * (FOGTABLEWIDTH * FOGTABLEWIDTH);
255 for (x = 0;x < FOGTABLEWIDTH;x++)
257 alpha = exp(r / ((double)x*(double)x));
258 if (x == FOGTABLEWIDTH - 1)
260 fogtable[x] = bound(0, alpha, 1);
264 static void R_BuildBlankTextures(void)
266 unsigned char data[4];
267 data[0] = 128; // normal X
268 data[1] = 128; // normal Y
269 data[2] = 255; // normal Z
270 data[3] = 128; // height
271 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
276 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
281 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
284 static void R_BuildNoTexture(void)
287 unsigned char pix[16][16][4];
288 // this makes a light grey/dark grey checkerboard texture
289 for (y = 0;y < 16;y++)
291 for (x = 0;x < 16;x++)
293 if ((y < 8) ^ (x < 8))
309 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_RGBA, TEXF_MIPMAP, NULL);
312 static void R_BuildWhiteCube(void)
314 unsigned char data[6*1*1*4];
315 data[ 0] = 255;data[ 1] = 255;data[ 2] = 255;data[ 3] = 255;
316 data[ 4] = 255;data[ 5] = 255;data[ 6] = 255;data[ 7] = 255;
317 data[ 8] = 255;data[ 9] = 255;data[10] = 255;data[11] = 255;
318 data[12] = 255;data[13] = 255;data[14] = 255;data[15] = 255;
319 data[16] = 255;data[17] = 255;data[18] = 255;data[19] = 255;
320 data[20] = 255;data[21] = 255;data[22] = 255;data[23] = 255;
321 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
324 static void R_BuildNormalizationCube(void)
328 vec_t s, t, intensity;
330 unsigned char data[6][NORMSIZE][NORMSIZE][4];
331 for (side = 0;side < 6;side++)
333 for (y = 0;y < NORMSIZE;y++)
335 for (x = 0;x < NORMSIZE;x++)
337 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
338 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
373 intensity = 127.0f / sqrt(DotProduct(v, v));
374 data[side][y][x][0] = 128.0f + intensity * v[0];
375 data[side][y][x][1] = 128.0f + intensity * v[1];
376 data[side][y][x][2] = 128.0f + intensity * v[2];
377 data[side][y][x][3] = 255;
381 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, &data[0][0][0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
384 static void R_BuildFogTexture(void)
389 unsigned char data1[FOGWIDTH][4];
390 unsigned char data2[FOGWIDTH][4];
391 r = (-1.0/256.0) * (FOGWIDTH * FOGWIDTH);
392 for (x = 0;x < FOGWIDTH;x++)
394 alpha = exp(r / ((double)x*(double)x));
395 if (x == FOGWIDTH - 1)
397 b = (int)(256.0 * alpha);
398 b = bound(0, b, 255);
399 data1[x][0] = 255 - b;
400 data1[x][1] = 255 - b;
401 data1[x][2] = 255 - b;
408 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
409 r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
412 static const char *builtinshaderstring =
413 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
414 "// written by Forest 'LordHavoc' Hale\n"
416 "// common definitions between vertex shader and fragment shader:\n"
418 "// use half floats if available for math performance\n"
420 "#define myhalf half\n"
421 "#define myhvec2 hvec2\n"
422 "#define myhvec3 hvec3\n"
423 "#define myhvec4 hvec4\n"
425 "#define myhalf float\n"
426 "#define myhvec2 vec2\n"
427 "#define myhvec3 vec3\n"
428 "#define myhvec4 vec4\n"
431 "varying vec2 TexCoord;\n"
432 "#if !defined(MODE_LIGHTSOURCE) && !defined(MODE_LIGHTDIRECTION)\n"
433 "varying vec2 TexCoordLightmap;\n"
436 "#ifdef MODE_LIGHTSOURCE\n"
437 "varying myhvec3 CubeVector;\n"
440 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
441 "varying vec3 LightVector;\n"
444 "#if defined(USESPECULAR) || defined(USEFOG) || defined(USEOFFSETMAPPING)\n"
445 "varying vec3 EyeVector;\n"
448 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
449 "varying myhvec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
450 "varying myhvec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
451 "varying myhvec3 VectorR; // direction of R texcoord (surface normal)\n"
457 "// vertex shader specific:\n"
458 "#ifdef VERTEX_SHADER\n"
460 "#ifdef MODE_LIGHTSOURCE\n"
461 "uniform vec3 LightPosition;\n"
464 "#if defined(USESPECULAR) || defined(USEFOG) || defined(USEOFFSETMAPPING)\n"
465 "uniform vec3 EyePosition;\n"
468 "#ifdef MODE_LIGHTDIRECTION\n"
469 "uniform myhvec3 LightDir;\n"
472 "// TODO: get rid of tangentt (texcoord2) and use a crossproduct to regenerate it from tangents (texcoord1) and normal (texcoord3)\n"
476 " // copy the surface texcoord\n"
477 " TexCoord = vec2(gl_TextureMatrix[0] * gl_MultiTexCoord0);\n"
478 "#if !defined(MODE_LIGHTSOURCE) && !defined(MODE_LIGHTDIRECTION)\n"
479 " TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
481 " gl_FrontColor = gl_Color;\n"
483 "#ifdef MODE_LIGHTSOURCE\n"
484 " // transform vertex position into light attenuation/cubemap space\n"
485 " // (-1 to +1 across the light box)\n"
486 " CubeVector = vec3(gl_TextureMatrix[3] * gl_Vertex);\n"
488 " // transform unnormalized light direction into tangent space\n"
489 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
490 " // normalize it per pixel)\n"
491 " vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
492 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
493 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
494 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
497 "#ifdef MODE_LIGHTDIRECTION\n"
498 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
499 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
500 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
503 "#if defined(USESPECULAR) || defined(USEFOG) || defined(USEOFFSETMAPPING)\n"
504 " // transform unnormalized eye direction into tangent space\n"
505 " vec3 eyeminusvertex = EyePosition - gl_Vertex.xyz;\n"
506 " EyeVector.x = dot(eyeminusvertex, gl_MultiTexCoord1.xyz);\n"
507 " EyeVector.y = dot(eyeminusvertex, gl_MultiTexCoord2.xyz);\n"
508 " EyeVector.z = dot(eyeminusvertex, gl_MultiTexCoord3.xyz);\n"
511 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
512 " VectorS = gl_MultiTexCoord1.xyz;\n"
513 " VectorT = gl_MultiTexCoord2.xyz;\n"
514 " VectorR = gl_MultiTexCoord3.xyz;\n"
517 " // transform vertex to camera space, using ftransform to match non-VS\n"
519 " gl_Position = ftransform();\n"
527 "// fragment shader specific:\n"
528 "#ifdef FRAGMENT_SHADER\n"
530 "uniform myhvec3 LightColor;\n"
531 "#ifdef USEOFFSETMAPPING\n"
532 "uniform myhalf OffsetMapping_Scale;\n"
533 "uniform myhalf OffsetMapping_Bias;\n"
536 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE) || defined(MODE_LIGHTDIRECTION) || defined(USEOFFSETMAPPING)\n"
537 "uniform sampler2D Texture_Normal;\n"
540 "#ifdef MODE_LIGHTDIRECTION\n"
541 "uniform myhvec3 AmbientColor;\n"
542 "uniform myhvec3 DiffuseColor;\n"
543 "uniform myhvec3 SpecularColor;\n"
546 "uniform sampler2D Texture_Color;\n"
548 "#if !defined(MODE_LIGHTSOURCE) && !defined(MODE_LIGHTDIRECTION)\n"
549 "uniform sampler2D Texture_Lightmap;\n"
551 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
552 "uniform sampler2D Texture_Deluxemap;\n"
556 "uniform sampler2D Texture_Glow;\n"
559 "#ifdef USECOLORMAPPING\n"
560 "uniform sampler2D Texture_Pants;\n"
561 "uniform sampler2D Texture_Shirt;\n"
562 "uniform myhvec3 Color_Pants;\n"
563 "uniform myhvec3 Color_Shirt;\n"
566 "uniform myhalf AmbientScale;\n"
567 "uniform myhalf DiffuseScale;\n"
568 "#ifdef USESPECULAR\n"
569 "uniform myhalf SpecularScale;\n"
570 "uniform myhalf SpecularPower;\n"
571 "uniform sampler2D Texture_Gloss;\n"
574 "#ifdef USECUBEFILTER\n"
575 "uniform samplerCube Texture_Cube;\n"
579 "uniform myhvec3 FogColor;\n"
580 "uniform myhalf FogRangeRecip;\n"
581 "uniform sampler2D Texture_FogMask;\n"
584 "#ifdef USEEASTEREGG\n"
587 " gl_FragColor = myhvec4(0, 0, 0, 1);;\n"
590 " vec2 p = vec2(CubeVector.x * 16.0, CubeVector.y * 16.0);\n"
591 " vec2 c = vec2(CubeVector.x * 16.0, CubeVector.y * 16.0);\n"
592 " for (i = 0;i < 1000 && dot(p,p) < 4.0;i = i + 1)\n"
594 " o = p.x * p.x - p.y * p.y;\n"
595 " p.y = 2.0 * p.x * p.y;\n"
599 " o = float(i) * 0.314;\n"
601 " gl_FragColor = vec4(cos(o), sin(o), sin(o * 0.2), 1);\n"
603 "#else // USEEASTEREGG\n"
609 " // apply offsetmapping\n"
610 "#ifdef USEOFFSETMAPPING\n"
611 " myhvec2 TexCoordOffset = TexCoord;\n"
612 "#define TexCoord TexCoordOffset\n"
614 " myhvec3 eyedir = myhvec3(normalize(EyeVector));\n"
615 " myhalf depthbias = 1.0 - eyedir.z; // should this be a -?\n"
616 " depthbias = 1.0 - depthbias * depthbias;\n"
618 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
619 " // 14 sample relief mapping: linear search and then binary search\n"
620 " myhvec3 OffsetVector = myhvec3(EyeVector.xy * (1.0 / EyeVector.z) * depthbias * OffsetMapping_Scale * myhvec2(-0.1, 0.1), -0.1);\n"
621 " vec3 RT = vec3(TexCoord - OffsetVector.xy * 10.0, 1.0) + 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;\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 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;OffsetVector *= 0.5;RT -= OffsetVector;\n"
636 " TexCoord = RT.xy;\n"
638 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
639 " myhvec2 OffsetVector = myhvec2((EyeVector.xy * (1.0 / EyeVector.z) * depthbias) * OffsetMapping_Scale * myhvec2(-0.333, 0.333));\n"
640 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
641 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
642 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
646 " // combine the diffuse textures (base, pants, shirt)\n"
647 " myhvec4 color = myhvec4(texture2D(Texture_Color, TexCoord));\n"
648 "#ifdef USECOLORMAPPING\n"
649 " color.rgb += myhvec3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhvec3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
655 "#ifdef MODE_LIGHTSOURCE\n"
658 " // get the surface normal and light normal\n"
659 "#ifdef SURFACENORMALIZE\n"
660 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - 0.5);\n"
662 " myhvec3 surfacenormal = -1.0 + 2.0 * myhvec3(texture2D(Texture_Normal, TexCoord));\n"
664 " myhvec3 diffusenormal = myhvec3(normalize(LightVector));\n"
666 " // calculate directional shading\n"
667 " color.rgb *= (AmbientScale + DiffuseScale * max(dot(surfacenormal, diffusenormal), 0.0));\n"
668 "#ifdef USESPECULAR\n"
669 " myhvec3 specularnormal = myhvec3(normalize(diffusenormal + myhvec3(normalize(EyeVector))));\n"
670 " color.rgb += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(max(dot(surfacenormal, specularnormal), 0.0), SpecularPower);\n"
673 "#ifdef USECUBEFILTER\n"
674 " // apply light cubemap filter\n"
675 " color.rgb *= myhvec3(textureCube(Texture_Cube, CubeVector));\n"
678 " // apply light color\n"
679 " color.rgb = color.rgb * LightColor;\n"
681 " // apply attenuation\n"
683 " // the attenuation is (1-(x*x+y*y+z*z)) which gives a large bright\n"
684 " // center and sharp falloff at the edge, this is about the most efficient\n"
685 " // we can get away with as far as providing illumination.\n"
687 " // pow(1-(x*x+y*y+z*z), 4) is far more realistic but needs large lights to\n"
688 " // provide significant illumination, large = slow = pain.\n"
689 " color.rgb *= max(1.0 - dot(CubeVector, CubeVector), 0.0);\n"
694 "#elif defined(MODE_LIGHTDIRECTION)\n"
695 " // directional model lighting\n"
697 " // get the surface normal and light normal\n"
698 "#ifdef SURFACENORMALIZE\n"
699 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - 0.5);\n"
701 " myhvec3 surfacenormal = -1.0 + 2.0 * myhvec3(texture2D(Texture_Normal, TexCoord));\n"
703 " myhvec3 diffusenormal = myhvec3(normalize(LightVector));\n"
706 " // calculate directional shading\n"
707 " color.rgb *= AmbientColor + DiffuseColor * max(dot(surfacenormal, diffusenormal), 0.0);\n"
708 "#ifdef USESPECULAR\n"
709 " myhvec3 specularnormal = myhvec3(normalize(diffusenormal + myhvec3(normalize(EyeVector))));\n"
710 " color.rgb += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(max(dot(surfacenormal, specularnormal), 0.0), SpecularPower);\n"
716 "#elif defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE)\n"
717 " // deluxemap lightmapping using light vectors in modelspace (evil q3map2)\n"
719 " // get the surface normal and light normal\n"
720 "#ifdef SURFACENORMALIZE\n"
721 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - 0.5);\n"
723 " myhvec3 surfacenormal = -1.0 + 2.0 * myhvec3(texture2D(Texture_Normal, TexCoord));\n"
725 " myhvec3 diffusenormal_modelspace = myhvec3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - 0.5;\n"
726 " myhvec3 diffusenormal = normalize(myhvec3(dot(diffusenormal_modelspace, VectorS), dot(diffusenormal_modelspace, VectorT), dot(diffusenormal_modelspace, VectorR)));\n"
728 " // calculate directional shading\n"
729 " myhvec3 tempcolor = color.rgb * (DiffuseScale * max(dot(surfacenormal, diffusenormal), 0.0));\n"
730 "#ifdef USESPECULAR\n"
731 " myhvec3 specularnormal = myhvec3(normalize(diffusenormal + myhvec3(normalize(EyeVector))));\n"
732 " tempcolor += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(max(dot(surfacenormal, specularnormal), 0.0), SpecularPower);\n"
735 " // apply lightmap color\n"
736 " color.rgb = tempcolor * myhvec3(texture2D(Texture_Lightmap, TexCoordLightmap)) + color.rgb * myhvec3(AmbientScale);\n"
741 "#elif defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
742 " // deluxemap lightmapping using light vectors in tangentspace\n"
744 " // get the surface normal and light normal\n"
745 "#ifdef SURFACENORMALIZE\n"
746 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - 0.5);\n"
747 " myhvec3 diffusenormal = normalize(myhvec3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - 0.5);\n"
749 " myhvec3 surfacenormal = -1.0 + 2.0 * myhvec3(texture2D(Texture_Normal, TexCoord));\n"
750 " myhvec3 diffusenormal = -1.0 + 2.0 * myhvec3(texture2D(Texture_Deluxemap, TexCoordLightmap));\n"
753 " // calculate directional shading\n"
754 " myhvec3 tempcolor = color.rgb * (DiffuseScale * max(dot(surfacenormal, diffusenormal), 0.0));\n"
755 "#ifdef USESPECULAR\n"
756 " myhvec3 specularnormal = myhvec3(normalize(diffusenormal + myhvec3(normalize(EyeVector))));\n"
757 " tempcolor += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(max(dot(surfacenormal, specularnormal), 0.0), SpecularPower);\n"
760 " // apply lightmap color\n"
761 " color.rgb = tempcolor * myhvec3(texture2D(Texture_Lightmap, TexCoordLightmap)) + color.rgb * myhvec3(AmbientScale);\n"
766 "#else // MODE none (lightmap)\n"
767 " // apply lightmap color\n"
768 " color.rgb *= myhvec3(texture2D(Texture_Lightmap, TexCoordLightmap)) * DiffuseScale + myhvec3(AmbientScale);\n"
772 " color.rgb += myhvec3(texture2D(Texture_Glow, TexCoord));\n"
777 " myhalf fog = texture2D(Texture_FogMask, myhvec2(length(EyeVector)*FogRangeRecip, 0.0)).x;\n"
778 " color.rgb = color.rgb * fog + FogColor * (1.0 - fog);\n"
781 " gl_FragColor = color * gl_Color;\n"
783 "#endif // !USEEASTEREGG\n"
788 void R_GLSL_CompilePermutation(int permutation)
790 r_glsl_permutation_t *p = r_glsl_permutations + permutation;
791 int vertstrings_count;
792 int fragstrings_count;
794 const char *vertstrings_list[SHADERPERMUTATION_COUNT+1];
795 const char *fragstrings_list[SHADERPERMUTATION_COUNT+1];
796 char permutationname[256];
800 vertstrings_list[0] = "#define VERTEX_SHADER\n";
801 fragstrings_list[0] = "#define FRAGMENT_SHADER\n";
802 vertstrings_count = 1;
803 fragstrings_count = 1;
804 permutationname[0] = 0;
805 if (permutation & SHADERPERMUTATION_MODE_LIGHTSOURCE)
807 vertstrings_list[vertstrings_count++] = "#define MODE_LIGHTSOURCE\n";
808 fragstrings_list[fragstrings_count++] = "#define MODE_LIGHTSOURCE\n";
809 strlcat(permutationname, " lightsource", sizeof(permutationname));
811 if (permutation & SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_MODELSPACE)
813 vertstrings_list[vertstrings_count++] = "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n";
814 fragstrings_list[fragstrings_count++] = "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n";
815 strlcat(permutationname, " lightdirectionmap_modelspace", sizeof(permutationname));
817 if (permutation & SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)
819 vertstrings_list[vertstrings_count++] = "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n";
820 fragstrings_list[fragstrings_count++] = "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n";
821 strlcat(permutationname, " lightdirectionmap_tangentspace", sizeof(permutationname));
823 if (permutation & SHADERPERMUTATION_MODE_LIGHTDIRECTION)
825 vertstrings_list[vertstrings_count++] = "#define MODE_LIGHTDIRECTION\n";
826 fragstrings_list[fragstrings_count++] = "#define MODE_LIGHTDIRECTION\n";
827 strlcat(permutationname, " lightdirection", sizeof(permutationname));
829 if (permutation & SHADERPERMUTATION_GLOW)
831 vertstrings_list[vertstrings_count++] = "#define USEGLOW\n";
832 fragstrings_list[fragstrings_count++] = "#define USEGLOW\n";
833 strlcat(permutationname, " glow", sizeof(permutationname));
835 if (permutation & SHADERPERMUTATION_COLORMAPPING)
837 vertstrings_list[vertstrings_count++] = "#define USECOLORMAPPING\n";
838 fragstrings_list[fragstrings_count++] = "#define USECOLORMAPPING\n";
839 strlcat(permutationname, " colormapping", sizeof(permutationname));
841 if (permutation & SHADERPERMUTATION_SPECULAR)
843 vertstrings_list[vertstrings_count++] = "#define USESPECULAR\n";
844 fragstrings_list[fragstrings_count++] = "#define USESPECULAR\n";
845 strlcat(permutationname, " specular", sizeof(permutationname));
847 if (permutation & SHADERPERMUTATION_FOG)
849 vertstrings_list[vertstrings_count++] = "#define USEFOG\n";
850 fragstrings_list[fragstrings_count++] = "#define USEFOG\n";
851 strlcat(permutationname, " fog", sizeof(permutationname));
853 if (permutation & SHADERPERMUTATION_CUBEFILTER)
855 vertstrings_list[vertstrings_count++] = "#define USECUBEFILTER\n";
856 fragstrings_list[fragstrings_count++] = "#define USECUBEFILTER\n";
857 strlcat(permutationname, " cubefilter", sizeof(permutationname));
859 if (permutation & SHADERPERMUTATION_OFFSETMAPPING)
861 vertstrings_list[vertstrings_count++] = "#define USEOFFSETMAPPING\n";
862 fragstrings_list[fragstrings_count++] = "#define USEOFFSETMAPPING\n";
863 strlcat(permutationname, " offsetmapping", sizeof(permutationname));
865 if (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING)
867 vertstrings_list[vertstrings_count++] = "#define USEOFFSETMAPPING_RELIEFMAPPING\n";
868 fragstrings_list[fragstrings_count++] = "#define USEOFFSETMAPPING_RELIEFMAPPING\n";
869 strlcat(permutationname, " OFFSETMAPPING_RELIEFMAPPING", sizeof(permutationname));
871 if (permutation & SHADERPERMUTATION_SURFACENORMALIZE)
873 vertstrings_list[vertstrings_count++] = "#define SURFACENORMALIZE\n";
874 fragstrings_list[fragstrings_count++] = "#define SURFACENORMALIZE\n";
875 strlcat(permutationname, " surfacenormalize", sizeof(permutationname));
877 if (permutation & SHADERPERMUTATION_GEFORCEFX)
879 vertstrings_list[vertstrings_count++] = "#define GEFORCEFX\n";
880 fragstrings_list[fragstrings_count++] = "#define GEFORCEFX\n";
881 strlcat(permutationname, " halffloat", sizeof(permutationname));
883 shaderstring = (char *)FS_LoadFile("glsl/default.glsl", r_main_mempool, false, NULL);
886 Con_DPrintf("GLSL shader text loaded from disk\n");
887 vertstrings_list[vertstrings_count++] = shaderstring;
888 fragstrings_list[fragstrings_count++] = shaderstring;
892 vertstrings_list[vertstrings_count++] = builtinshaderstring;
893 fragstrings_list[fragstrings_count++] = builtinshaderstring;
895 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, fragstrings_count, fragstrings_list);
899 qglUseProgramObjectARB(p->program);
900 p->loc_Texture_Normal = qglGetUniformLocationARB(p->program, "Texture_Normal");
901 p->loc_Texture_Color = qglGetUniformLocationARB(p->program, "Texture_Color");
902 p->loc_Texture_Gloss = qglGetUniformLocationARB(p->program, "Texture_Gloss");
903 p->loc_Texture_Cube = qglGetUniformLocationARB(p->program, "Texture_Cube");
904 p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
905 p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
906 p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
907 p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
908 p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
909 p->loc_Texture_Glow = qglGetUniformLocationARB(p->program, "Texture_Glow");
910 p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
911 p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
912 p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
913 p->loc_LightColor = qglGetUniformLocationARB(p->program, "LightColor");
914 p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants");
915 p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt");
916 p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip");
917 p->loc_AmbientScale = qglGetUniformLocationARB(p->program, "AmbientScale");
918 p->loc_DiffuseScale = qglGetUniformLocationARB(p->program, "DiffuseScale");
919 p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
920 p->loc_SpecularScale = qglGetUniformLocationARB(p->program, "SpecularScale");
921 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
922 p->loc_AmbientColor = qglGetUniformLocationARB(p->program, "AmbientColor");
923 p->loc_DiffuseColor = qglGetUniformLocationARB(p->program, "DiffuseColor");
924 p->loc_SpecularColor = qglGetUniformLocationARB(p->program, "SpecularColor");
925 p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
926 if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal, 0);
927 if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color, 1);
928 if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss, 2);
929 if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube, 3);
930 if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask, 4);
931 if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants, 5);
932 if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt, 6);
933 if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap, 7);
934 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap, 8);
935 if (p->loc_Texture_Glow >= 0) qglUniform1iARB(p->loc_Texture_Glow, 9);
936 qglUseProgramObjectARB(0);
940 Con_Printf("permutation%s failed for shader %s, some features may not work properly!\n", permutationname, "glsl/default.glsl");
942 Mem_Free(shaderstring);
945 void R_GLSL_Restart_f(void)
948 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
949 if (r_glsl_permutations[i].program)
950 GL_Backend_FreeProgram(r_glsl_permutations[i].program);
951 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
954 void R_SetupSurfaceShader(const entity_render_t *ent, const texture_t *texture, const vec3_t modelorg, const vec3_t lightcolorbase, qboolean modellighting)
956 // select a permutation of the lighting shader appropriate to this
957 // combination of texture, entity, light source, and fogging, only use the
958 // minimum features necessary to avoid wasting rendering time in the
959 // fragment shader on features that are not being used
961 float specularscale = texture->specularscale;
962 r_glsl_permutation = NULL;
963 if (r_shadow_rtlight)
965 permutation |= SHADERPERMUTATION_MODE_LIGHTSOURCE;
966 specularscale *= r_shadow_rtlight->specularscale;
967 if (r_shadow_rtlight->currentcubemap != r_texture_whitecube)
968 permutation |= SHADERPERMUTATION_CUBEFILTER;
973 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTION;
974 else if (r_glsl_deluxemapping.integer >= 1 && r_refdef.worldmodel && r_refdef.worldmodel->brushq3.deluxemapping)
976 if (r_refdef.worldmodel->brushq3.deluxemapping_modelspace)
977 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_MODELSPACE;
979 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
981 else if (r_glsl_deluxemapping.integer >= 2) // fake mode
982 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
983 if (texture->skin.glow)
984 permutation |= SHADERPERMUTATION_GLOW;
986 if (specularscale > 0)
987 permutation |= SHADERPERMUTATION_SPECULAR;
989 permutation |= SHADERPERMUTATION_FOG;
990 if (texture->colormapping)
991 permutation |= SHADERPERMUTATION_COLORMAPPING;
992 if (r_glsl_offsetmapping.integer)
994 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
995 if (r_glsl_offsetmapping_reliefmapping.integer)
996 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
998 if (r_glsl_surfacenormalize.integer)
999 permutation |= SHADERPERMUTATION_SURFACENORMALIZE;
1000 if (r_glsl_usehalffloat.integer)
1001 permutation |= SHADERPERMUTATION_GEFORCEFX;
1002 if (!r_glsl_permutations[permutation].program)
1004 if (!r_glsl_permutations[permutation].compiled)
1005 R_GLSL_CompilePermutation(permutation);
1006 if (!r_glsl_permutations[permutation].program)
1008 // remove features until we find a valid permutation
1010 for (i = SHADERPERMUTATION_COUNT-1;;i>>=1)
1012 // reduce i more quickly whenever it would not remove any bits
1013 if (permutation < i)
1016 if (!r_glsl_permutations[permutation].compiled)
1017 R_GLSL_CompilePermutation(permutation);
1018 if (r_glsl_permutations[permutation].program)
1021 return; // utterly failed
1025 r_glsl_permutation = r_glsl_permutations + permutation;
1027 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
1028 R_Mesh_TexMatrix(0, &texture->currenttexmatrix);
1029 if (permutation & SHADERPERMUTATION_MODE_LIGHTSOURCE)
1031 R_Mesh_TexMatrix(3, &r_shadow_entitytolight);
1032 if (r_glsl_permutation->loc_Texture_Cube >= 0) R_Mesh_TexBind(3, R_GetTexture(r_shadow_rtlight->currentcubemap));
1033 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]);
1034 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
1035 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_shadow_rtlight->ambientscale);
1036 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_shadow_rtlight->diffusescale);
1037 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, specularscale);
1039 else if (permutation & SHADERPERMUTATION_MODE_LIGHTDIRECTION)
1041 if (texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
1043 if (r_glsl_permutation->loc_AmbientColor >= 0)
1044 qglUniform3fARB(r_glsl_permutation->loc_AmbientColor, 1, 1, 1);
1045 if (r_glsl_permutation->loc_DiffuseColor >= 0)
1046 qglUniform3fARB(r_glsl_permutation->loc_DiffuseColor, 0, 0, 0);
1047 if (r_glsl_permutation->loc_SpecularColor >= 0)
1048 qglUniform3fARB(r_glsl_permutation->loc_SpecularColor, 0, 0, 0);
1049 if (r_glsl_permutation->loc_LightDir >= 0)
1050 qglUniform3fARB(r_glsl_permutation->loc_LightDir, 0, 0, -1);
1054 if (r_glsl_permutation->loc_AmbientColor >= 0)
1055 qglUniform3fARB(r_glsl_permutation->loc_AmbientColor, ent->modellight_ambient[0], ent->modellight_ambient[1], ent->modellight_ambient[2]);
1056 if (r_glsl_permutation->loc_DiffuseColor >= 0)
1057 qglUniform3fARB(r_glsl_permutation->loc_DiffuseColor, ent->modellight_diffuse[0], ent->modellight_diffuse[1], ent->modellight_diffuse[2]);
1058 if (r_glsl_permutation->loc_SpecularColor >= 0)
1059 qglUniform3fARB(r_glsl_permutation->loc_SpecularColor, ent->modellight_diffuse[0] * texture->specularscale, ent->modellight_diffuse[1] * texture->specularscale, ent->modellight_diffuse[2] * texture->specularscale);
1060 if (r_glsl_permutation->loc_LightDir >= 0)
1061 qglUniform3fARB(r_glsl_permutation->loc_LightDir, ent->modellight_lightdir[0], ent->modellight_lightdir[1], ent->modellight_lightdir[2]);
1066 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_ambient.value * 2.0f / 128.0f);
1067 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_lightmapintensity * 2.0f);
1068 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, specularscale * 2.0f);
1070 if (r_glsl_permutation->loc_Texture_Normal >= 0) R_Mesh_TexBind(0, R_GetTexture(texture->skin.nmap));
1071 if (r_glsl_permutation->loc_Texture_Color >= 0) R_Mesh_TexBind(1, R_GetTexture(texture->basetexture));
1072 if (r_glsl_permutation->loc_Texture_Gloss >= 0) R_Mesh_TexBind(2, R_GetTexture(texture->glosstexture));
1073 if (r_glsl_permutation->loc_Texture_FogMask >= 0) R_Mesh_TexBind(4, R_GetTexture(r_texture_fogattenuation));
1074 if (r_glsl_permutation->loc_Texture_Pants >= 0) R_Mesh_TexBind(5, R_GetTexture(texture->skin.pants));
1075 if (r_glsl_permutation->loc_Texture_Shirt >= 0) R_Mesh_TexBind(6, R_GetTexture(texture->skin.shirt));
1076 if (r_glsl_permutation->loc_Texture_Glow >= 0) R_Mesh_TexBind(9, R_GetTexture(texture->skin.glow));
1077 if (r_glsl_permutation->loc_FogColor >= 0)
1079 // additive passes are only darkened by fog, not tinted
1080 if (r_shadow_rtlight || (texture->currentmaterialflags & MATERIALFLAG_ADD))
1081 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
1083 qglUniform3fARB(r_glsl_permutation->loc_FogColor, fogcolor[0], fogcolor[1], fogcolor[2]);
1085 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, modelorg[0], modelorg[1], modelorg[2]);
1086 if (r_glsl_permutation->loc_Color_Pants >= 0)
1088 if (texture->skin.pants)
1089 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, ent->colormap_pantscolor[0], ent->colormap_pantscolor[1], ent->colormap_pantscolor[2]);
1091 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
1093 if (r_glsl_permutation->loc_Color_Shirt >= 0)
1095 if (texture->skin.shirt)
1096 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, ent->colormap_shirtcolor[0], ent->colormap_shirtcolor[1], ent->colormap_shirtcolor[2]);
1098 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
1100 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, fograngerecip);
1101 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, texture->specularpower);
1102 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
1106 void gl_main_start(void)
1108 // use half float math where available (speed gain on NVIDIA GFFX and GF6)
1109 if (gl_support_half_float)
1110 Cvar_SetValue("r_glsl_usehalffloat", 1);
1111 r_main_texturepool = R_AllocTexturePool();
1112 r_bloom_texture_screen = NULL;
1113 r_bloom_texture_bloom = NULL;
1114 R_BuildBlankTextures();
1116 if (gl_texturecubemap)
1119 R_BuildNormalizationCube();
1121 R_BuildFogTexture();
1122 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
1125 void gl_main_shutdown(void)
1127 R_FreeTexturePool(&r_main_texturepool);
1128 r_bloom_texture_screen = NULL;
1129 r_bloom_texture_bloom = NULL;
1130 r_texture_blanknormalmap = NULL;
1131 r_texture_white = NULL;
1132 r_texture_black = NULL;
1133 r_texture_whitecube = NULL;
1134 r_texture_normalizationcube = NULL;
1138 extern void CL_ParseEntityLump(char *entitystring);
1139 void gl_main_newmap(void)
1141 // FIXME: move this code to client
1143 char *entities, entname[MAX_QPATH];
1147 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
1148 l = (int)strlen(entname) - 4;
1149 if (l >= 0 && !strcmp(entname + l, ".bsp"))
1151 strcpy(entname + l, ".ent");
1152 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
1154 CL_ParseEntityLump(entities);
1159 if (cl.worldmodel->brush.entities)
1160 CL_ParseEntityLump(cl.worldmodel->brush.entities);
1164 void GL_Main_Init(void)
1166 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
1168 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed\n");
1169 FOG_registercvars(); // FIXME: move this fog stuff to client?
1170 Cvar_RegisterVariable(&r_nearclip);
1171 Cvar_RegisterVariable(&r_showtris);
1172 Cvar_RegisterVariable(&r_showtris_polygonoffset);
1173 Cvar_RegisterVariable(&r_shownormals);
1174 Cvar_RegisterVariable(&r_showlighting);
1175 Cvar_RegisterVariable(&r_showshadowvolumes);
1176 Cvar_RegisterVariable(&r_showcollisionbrushes);
1177 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
1178 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
1179 Cvar_RegisterVariable(&r_showdisabledepthtest);
1180 Cvar_RegisterVariable(&r_drawentities);
1181 Cvar_RegisterVariable(&r_drawviewmodel);
1182 Cvar_RegisterVariable(&r_speeds);
1183 Cvar_RegisterVariable(&r_fullbrights);
1184 Cvar_RegisterVariable(&r_wateralpha);
1185 Cvar_RegisterVariable(&r_dynamic);
1186 Cvar_RegisterVariable(&r_fullbright);
1187 Cvar_RegisterVariable(&r_textureunits);
1188 Cvar_RegisterVariable(&r_glsl);
1189 Cvar_RegisterVariable(&r_glsl_offsetmapping);
1190 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
1191 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
1192 Cvar_RegisterVariable(&r_glsl_usehalffloat);
1193 Cvar_RegisterVariable(&r_glsl_surfacenormalize);
1194 Cvar_RegisterVariable(&r_glsl_deluxemapping);
1195 Cvar_RegisterVariable(&r_lerpsprites);
1196 Cvar_RegisterVariable(&r_lerpmodels);
1197 Cvar_RegisterVariable(&r_waterscroll);
1198 Cvar_RegisterVariable(&r_bloom);
1199 Cvar_RegisterVariable(&r_bloom_intensity);
1200 Cvar_RegisterVariable(&r_bloom_blur);
1201 Cvar_RegisterVariable(&r_bloom_resolution);
1202 Cvar_RegisterVariable(&r_bloom_power);
1203 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
1204 Cvar_RegisterVariable(&developer_texturelogging);
1205 Cvar_RegisterVariable(&gl_lightmaps);
1206 Cvar_RegisterVariable(&r_test);
1207 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
1208 Cvar_SetValue("r_fullbrights", 0);
1209 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
1212 static vec3_t r_farclip_origin;
1213 static vec3_t r_farclip_direction;
1214 static vec_t r_farclip_directiondist;
1215 static vec_t r_farclip_meshfarclip;
1216 static int r_farclip_directionbit0;
1217 static int r_farclip_directionbit1;
1218 static int r_farclip_directionbit2;
1220 // enlarge farclip to accomodate box
1221 static void R_FarClip_Box(vec3_t mins, vec3_t maxs)
1224 d = (r_farclip_directionbit0 ? mins[0] : maxs[0]) * r_farclip_direction[0]
1225 + (r_farclip_directionbit1 ? mins[1] : maxs[1]) * r_farclip_direction[1]
1226 + (r_farclip_directionbit2 ? mins[2] : maxs[2]) * r_farclip_direction[2];
1227 if (r_farclip_meshfarclip < d)
1228 r_farclip_meshfarclip = d;
1231 // return farclip value
1232 static float R_FarClip(vec3_t origin, vec3_t direction, vec_t startfarclip)
1236 VectorCopy(origin, r_farclip_origin);
1237 VectorCopy(direction, r_farclip_direction);
1238 r_farclip_directiondist = DotProduct(r_farclip_origin, r_farclip_direction);
1239 r_farclip_directionbit0 = r_farclip_direction[0] < 0;
1240 r_farclip_directionbit1 = r_farclip_direction[1] < 0;
1241 r_farclip_directionbit2 = r_farclip_direction[2] < 0;
1242 r_farclip_meshfarclip = r_farclip_directiondist + startfarclip;
1244 if (r_refdef.worldmodel)
1245 R_FarClip_Box(r_refdef.worldmodel->normalmins, r_refdef.worldmodel->normalmaxs);
1246 for (i = 0;i < r_refdef.numentities;i++)
1247 R_FarClip_Box(r_refdef.entities[i]->mins, r_refdef.entities[i]->maxs);
1249 return r_farclip_meshfarclip - r_farclip_directiondist;
1252 extern void R_Textures_Init(void);
1253 extern void GL_Draw_Init(void);
1254 extern void GL_Main_Init(void);
1255 extern void R_Shadow_Init(void);
1256 extern void R_Sky_Init(void);
1257 extern void GL_Surf_Init(void);
1258 extern void R_Crosshairs_Init(void);
1259 extern void R_Light_Init(void);
1260 extern void R_Particles_Init(void);
1261 extern void R_Explosion_Init(void);
1262 extern void gl_backend_init(void);
1263 extern void Sbar_Init(void);
1264 extern void R_LightningBeams_Init(void);
1265 extern void Mod_RenderInit(void);
1267 void Render_Init(void)
1277 R_Crosshairs_Init();
1282 R_LightningBeams_Init();
1291 extern char *ENGINE_EXTENSIONS;
1294 VID_CheckExtensions();
1296 // LordHavoc: report supported extensions
1297 Con_DPrintf("\nengine extensions: %s\n", vm_sv_extensions );
1299 // clear to black (loading plaque will be seen over this)
1300 qglClearColor(0,0,0,1);
1301 qglClear(GL_COLOR_BUFFER_BIT);
1304 int R_CullBox(const vec3_t mins, const vec3_t maxs)
1308 for (i = 0;i < 4;i++)
1315 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1319 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1323 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1327 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1331 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1335 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1339 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1343 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1351 //==================================================================================
1353 static void R_UpdateEntityLighting(entity_render_t *ent)
1355 vec3_t tempdiffusenormal;
1356 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));
1357 VectorClear(ent->modellight_diffuse);
1358 VectorClear(ent->modellight_lightdir);
1359 if ((ent->flags & RENDER_LIGHT) && r_refdef.worldmodel && r_refdef.worldmodel->brush.LightPoint)
1360 r_refdef.worldmodel->brush.LightPoint(r_refdef.worldmodel, ent->origin, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
1362 VectorSet(ent->modellight_ambient, 1, 1, 1);
1363 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
1364 VectorNormalize(ent->modellight_lightdir);
1365 ent->modellight_ambient[0] *= ent->colormod[0] * r_lightmapintensity;
1366 ent->modellight_ambient[1] *= ent->colormod[1] * r_lightmapintensity;
1367 ent->modellight_ambient[2] *= ent->colormod[2] * r_lightmapintensity;
1368 ent->modellight_diffuse[0] *= ent->colormod[0] * r_lightmapintensity;
1369 ent->modellight_diffuse[1] *= ent->colormod[1] * r_lightmapintensity;
1370 ent->modellight_diffuse[2] *= ent->colormod[2] * r_lightmapintensity;
1373 static void R_MarkEntities (void)
1376 entity_render_t *ent;
1378 if (!r_drawentities.integer)
1381 r_refdef.worldentity->visframe = r_framecount;
1382 renderimask = envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : (chase_active.integer ? 0 : RENDER_EXTERIORMODEL);
1383 if (r_refdef.worldmodel && r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs)
1385 // worldmodel can check visibility
1386 for (i = 0;i < r_refdef.numentities;i++)
1388 ent = r_refdef.entities[i];
1389 // some of the renderer still relies on origin...
1390 Matrix4x4_OriginFromMatrix(&ent->matrix, ent->origin);
1391 // some of the renderer still relies on scale...
1392 ent->scale = Matrix4x4_ScaleFromMatrix(&ent->matrix);
1393 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)))
1395 ent->visframe = r_framecount;
1396 R_UpdateEntityLighting(ent);
1402 // no worldmodel or it can't check visibility
1403 for (i = 0;i < r_refdef.numentities;i++)
1405 ent = r_refdef.entities[i];
1406 // some of the renderer still relies on origin...
1407 Matrix4x4_OriginFromMatrix(&ent->matrix, ent->origin);
1408 // some of the renderer still relies on scale...
1409 ent->scale = Matrix4x4_ScaleFromMatrix(&ent->matrix);
1410 if (!(ent->flags & renderimask) && !R_CullBox(ent->mins, ent->maxs) && (ent->effects & EF_NODEPTHTEST))
1412 ent->visframe = r_framecount;
1413 R_UpdateEntityLighting(ent);
1419 // only used if skyrendermasked, and normally returns false
1420 int R_DrawBrushModelsSky (void)
1423 entity_render_t *ent;
1425 if (!r_drawentities.integer)
1429 for (i = 0;i < r_refdef.numentities;i++)
1431 ent = r_refdef.entities[i];
1432 if (ent->visframe == r_framecount && ent->model && ent->model->DrawSky)
1434 ent->model->DrawSky(ent);
1441 void R_DrawNoModel(entity_render_t *ent);
1442 void R_DrawModels(void)
1445 entity_render_t *ent;
1447 if (!r_drawentities.integer)
1450 for (i = 0;i < r_refdef.numentities;i++)
1452 ent = r_refdef.entities[i];
1453 if (ent->visframe == r_framecount)
1455 renderstats.entities++;
1456 if (ent->model && ent->model->Draw != NULL)
1457 ent->model->Draw(ent);
1464 static void R_SetFrustum(void)
1466 // break apart the view matrix into vectors for various purposes
1467 Matrix4x4_ToVectors(&r_view_matrix, r_viewforward, r_viewleft, r_viewup, r_vieworigin);
1468 VectorNegate(r_viewleft, r_viewright);
1471 frustum[0].normal[0] = 0 - 1.0 / r_refdef.frustum_x;
1472 frustum[0].normal[1] = 0 - 0;
1473 frustum[0].normal[2] = -1 - 0;
1474 frustum[1].normal[0] = 0 + 1.0 / r_refdef.frustum_x;
1475 frustum[1].normal[1] = 0 + 0;
1476 frustum[1].normal[2] = -1 + 0;
1477 frustum[2].normal[0] = 0 - 0;
1478 frustum[2].normal[1] = 0 - 1.0 / r_refdef.frustum_y;
1479 frustum[2].normal[2] = -1 - 0;
1480 frustum[3].normal[0] = 0 + 0;
1481 frustum[3].normal[1] = 0 + 1.0 / r_refdef.frustum_y;
1482 frustum[3].normal[2] = -1 + 0;
1486 zNear = r_nearclip.value;
1487 nudge = 1.0 - 1.0 / (1<<23);
1488 frustum[4].normal[0] = 0 - 0;
1489 frustum[4].normal[1] = 0 - 0;
1490 frustum[4].normal[2] = -1 - -nudge;
1491 frustum[4].dist = 0 - -2 * zNear * nudge;
1492 frustum[5].normal[0] = 0 + 0;
1493 frustum[5].normal[1] = 0 + 0;
1494 frustum[5].normal[2] = -1 + -nudge;
1495 frustum[5].dist = 0 + -2 * zNear * nudge;
1501 frustum[0].normal[0] = m[3] - m[0];
1502 frustum[0].normal[1] = m[7] - m[4];
1503 frustum[0].normal[2] = m[11] - m[8];
1504 frustum[0].dist = m[15] - m[12];
1506 frustum[1].normal[0] = m[3] + m[0];
1507 frustum[1].normal[1] = m[7] + m[4];
1508 frustum[1].normal[2] = m[11] + m[8];
1509 frustum[1].dist = m[15] + m[12];
1511 frustum[2].normal[0] = m[3] - m[1];
1512 frustum[2].normal[1] = m[7] - m[5];
1513 frustum[2].normal[2] = m[11] - m[9];
1514 frustum[2].dist = m[15] - m[13];
1516 frustum[3].normal[0] = m[3] + m[1];
1517 frustum[3].normal[1] = m[7] + m[5];
1518 frustum[3].normal[2] = m[11] + m[9];
1519 frustum[3].dist = m[15] + m[13];
1521 frustum[4].normal[0] = m[3] - m[2];
1522 frustum[4].normal[1] = m[7] - m[6];
1523 frustum[4].normal[2] = m[11] - m[10];
1524 frustum[4].dist = m[15] - m[14];
1526 frustum[5].normal[0] = m[3] + m[2];
1527 frustum[5].normal[1] = m[7] + m[6];
1528 frustum[5].normal[2] = m[11] + m[10];
1529 frustum[5].dist = m[15] + m[14];
1534 VectorMAM(1, r_viewforward, 1.0 / -r_refdef.frustum_x, r_viewleft, frustum[0].normal);
1535 VectorMAM(1, r_viewforward, 1.0 / r_refdef.frustum_x, r_viewleft, frustum[1].normal);
1536 VectorMAM(1, r_viewforward, 1.0 / -r_refdef.frustum_y, r_viewup, frustum[2].normal);
1537 VectorMAM(1, r_viewforward, 1.0 / r_refdef.frustum_y, r_viewup, frustum[3].normal);
1538 VectorCopy(r_viewforward, frustum[4].normal);
1539 VectorNormalize(frustum[0].normal);
1540 VectorNormalize(frustum[1].normal);
1541 VectorNormalize(frustum[2].normal);
1542 VectorNormalize(frustum[3].normal);
1543 frustum[0].dist = DotProduct (r_vieworigin, frustum[0].normal);
1544 frustum[1].dist = DotProduct (r_vieworigin, frustum[1].normal);
1545 frustum[2].dist = DotProduct (r_vieworigin, frustum[2].normal);
1546 frustum[3].dist = DotProduct (r_vieworigin, frustum[3].normal);
1547 frustum[4].dist = DotProduct (r_vieworigin, frustum[4].normal) + r_nearclip.value;
1548 PlaneClassify(&frustum[0]);
1549 PlaneClassify(&frustum[1]);
1550 PlaneClassify(&frustum[2]);
1551 PlaneClassify(&frustum[3]);
1552 PlaneClassify(&frustum[4]);
1554 // LordHavoc: note to all quake engine coders, Quake had a special case
1555 // for 90 degrees which assumed a square view (wrong), so I removed it,
1556 // Quake2 has it disabled as well.
1558 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
1559 //RotatePointAroundVector( frustum[0].normal, r_viewup, r_viewforward, -(90 - r_refdef.fov_x / 2));
1560 //frustum[0].dist = DotProduct (r_vieworigin, frustum[0].normal);
1561 //PlaneClassify(&frustum[0]);
1563 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
1564 //RotatePointAroundVector( frustum[1].normal, r_viewup, r_viewforward, (90 - r_refdef.fov_x / 2));
1565 //frustum[1].dist = DotProduct (r_vieworigin, frustum[1].normal);
1566 //PlaneClassify(&frustum[1]);
1568 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
1569 //RotatePointAroundVector( frustum[2].normal, r_viewleft, r_viewforward, -(90 - r_refdef.fov_y / 2));
1570 //frustum[2].dist = DotProduct (r_vieworigin, frustum[2].normal);
1571 //PlaneClassify(&frustum[2]);
1573 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
1574 //RotatePointAroundVector( frustum[3].normal, r_viewleft, r_viewforward, (90 - r_refdef.fov_y / 2));
1575 //frustum[3].dist = DotProduct (r_vieworigin, frustum[3].normal);
1576 //PlaneClassify(&frustum[3]);
1579 //VectorCopy(r_viewforward, frustum[4].normal);
1580 //frustum[4].dist = DotProduct (r_vieworigin, frustum[4].normal) + r_nearclip.value;
1581 //PlaneClassify(&frustum[4]);
1584 static void R_BlendView(void)
1586 int screenwidth, screenheight;
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 varray_vertex3f[0] = 0;varray_vertex3f[1] = 0;varray_vertex3f[2] = 0;
1609 varray_vertex3f[3] = 1;varray_vertex3f[4] = 0;varray_vertex3f[5] = 0;
1610 varray_vertex3f[6] = 1;varray_vertex3f[7] = 1;varray_vertex3f[8] = 0;
1611 varray_vertex3f[9] = 0;varray_vertex3f[10] = 1;varray_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 varray_texcoord2f[0][0] = 0;
1629 varray_texcoord2f[0][1] = (float)r_view_height / (float)screenheight;
1630 varray_texcoord2f[0][2] = (float)r_view_width / (float)screenwidth;
1631 varray_texcoord2f[0][3] = (float)r_view_height / (float)screenheight;
1632 varray_texcoord2f[0][4] = (float)r_view_width / (float)screenwidth;
1633 varray_texcoord2f[0][5] = 0;
1634 varray_texcoord2f[0][6] = 0;
1635 varray_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 varray_texcoord2f[1][0] = 0;
1639 varray_texcoord2f[1][1] = (float)bloomheight / (float)screenheight;
1640 varray_texcoord2f[1][2] = (float)bloomwidth / (float)screenwidth;
1641 varray_texcoord2f[1][3] = (float)bloomheight / (float)screenheight;
1642 varray_texcoord2f[1][4] = (float)bloomwidth / (float)screenwidth;
1643 varray_texcoord2f[1][5] = 0;
1644 varray_texcoord2f[1][6] = 0;
1645 varray_texcoord2f[1][7] = 0;
1646 memset(&m, 0, sizeof(m));
1647 m.pointer_vertex = varray_vertex3f;
1648 m.pointer_texcoord[0] = varray_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 = varray_vertex3f;
1675 m.tex[0] = R_GetTexture(r_bloom_texture_bloom);
1676 m.pointer_texcoord[0] = varray_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 varray_texcoord2f[2][0] = xoffset+0;
1691 varray_texcoord2f[2][1] = yoffset+(float)bloomheight / (float)screenheight;
1692 varray_texcoord2f[2][2] = xoffset+(float)bloomwidth / (float)screenwidth;
1693 varray_texcoord2f[2][3] = yoffset+(float)bloomheight / (float)screenheight;
1694 varray_texcoord2f[2][4] = xoffset+(float)bloomwidth / (float)screenwidth;
1695 varray_texcoord2f[2][5] = yoffset+0;
1696 varray_texcoord2f[2][6] = xoffset+0;
1697 varray_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 varray_texcoord2f[2][0] = xoffset+0;
1724 varray_texcoord2f[2][1] = yoffset+(float)bloomheight / (float)screenheight;
1725 varray_texcoord2f[2][2] = xoffset+(float)bloomwidth / (float)screenwidth;
1726 varray_texcoord2f[2][3] = yoffset+(float)bloomheight / (float)screenheight;
1727 varray_texcoord2f[2][4] = xoffset+(float)bloomwidth / (float)screenwidth;
1728 varray_texcoord2f[2][5] = yoffset+0;
1729 varray_texcoord2f[2][6] = xoffset+0;
1730 varray_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 = varray_vertex3f;
1752 m.tex[0] = R_GetTexture(r_bloom_texture_screen);
1753 m.pointer_texcoord[0] = varray_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] = varray_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 = varray_vertex3f;
1778 m.tex[0] = R_GetTexture(r_bloom_texture_bloom);
1779 m.pointer_texcoord[0] = varray_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 = varray_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;
1827 // GL is weird because it's bottom to top, r_view_y is top to bottom
1828 qglViewport(r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
1829 GL_Scissor(r_view_x, r_view_y, r_view_width, r_view_height);
1830 GL_ScissorTest(true);
1835 if (r_timereport_active)
1836 R_TimeReport("setup");
1838 qglDepthFunc(GL_LEQUAL);
1839 qglPolygonOffset(0, 0);
1840 qglEnable(GL_POLYGON_OFFSET_FILL);
1844 qglPolygonOffset(0, 0);
1845 qglDisable(GL_POLYGON_OFFSET_FILL);
1848 if (r_timereport_active)
1849 R_TimeReport("blendview");
1851 GL_Scissor(0, 0, vid.width, vid.height);
1852 GL_ScissorTest(false);
1856 void CSQC_R_ClearScreen (void)
1858 if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
1859 return; //Host_Error ("R_RenderView: NULL worldmodel");
1861 r_view_width = bound(0, r_refdef.width, vid.width);
1862 r_view_height = bound(0, r_refdef.height, vid.height);
1864 r_view_x = bound(0, r_refdef.x, vid.width - r_refdef.width);
1865 r_view_y = bound(0, r_refdef.y, vid.height - r_refdef.height);
1867 r_view_matrix = r_refdef.viewentitymatrix;
1868 GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
1869 r_rtworld = r_shadow_realtime_world.integer;
1870 r_rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
1871 r_rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer;
1872 r_rtdlightshadows = r_rtdlight && (r_rtworld ? r_shadow_realtime_world_dlightshadows.integer : r_shadow_realtime_dlight_shadows.integer) && gl_stencil;
1873 r_lightmapintensity = r_rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
1875 // GL is weird because it's bottom to top, r_view_y is top to bottom
1876 qglViewport(r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
1877 GL_Scissor(r_view_x, r_view_y, r_view_width, r_view_height);
1878 GL_ScissorTest(true);
1883 if (r_timereport_active)
1884 R_TimeReport("setup");
1888 void CSQC_R_RenderScene (void)
1890 qglDepthFunc(GL_LEQUAL);
1891 qglPolygonOffset(0, 0);
1892 qglEnable(GL_POLYGON_OFFSET_FILL);
1896 qglPolygonOffset(0, 0);
1897 qglDisable(GL_POLYGON_OFFSET_FILL);
1900 if (r_timereport_active)
1901 R_TimeReport("blendview");
1903 GL_Scissor(0, 0, vid.width, vid.height);
1904 GL_ScissorTest(false);
1907 extern void R_DrawLightningBeams (void);
1908 extern void VM_AddPolygonsToMeshQueue (void);
1909 void R_RenderScene(void)
1913 // don't let sound skip if going slow
1914 if (r_refdef.extraupdate)
1919 if (gl_support_fragment_shader)
1920 qglUseProgramObjectARB(0);
1922 R_MeshQueue_BeginScene();
1926 r_farclip = R_FarClip(r_vieworigin, r_viewforward, 768.0f) + 256.0f;
1927 nearclip = bound (0.001f, r_nearclip.value, r_farclip - 1.0f);
1929 if (r_rtworldshadows || r_rtdlightshadows)
1930 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_refdef.frustum_x, r_refdef.frustum_y, nearclip);
1932 GL_SetupView_Mode_Perspective(r_refdef.frustum_x, r_refdef.frustum_y, nearclip, r_farclip);
1934 GL_SetupView_Orientation_FromEntity(&r_view_matrix);
1936 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);
1940 R_WorldVisibility();
1941 if (r_timereport_active)
1942 R_TimeReport("worldvis");
1945 if (r_timereport_active)
1946 R_TimeReport("markentity");
1948 R_Shadow_UpdateWorldLightSelection();
1950 for (r_showtrispass = 0;r_showtrispass <= (r_showtris.value > 0);r_showtrispass++)
1956 GL_BlendFunc(GL_ONE, GL_ONE);
1957 GL_DepthTest(!r_showdisabledepthtest.integer);
1958 GL_DepthMask(GL_FALSE);
1959 memset(&m, 0, sizeof(m));
1961 //qglEnable(GL_LINE_SMOOTH);
1962 qglEnable(GL_POLYGON_OFFSET_LINE);
1963 qglPolygonOffset(0, r_showtris_polygonoffset.value);
1967 if (cl.csqc_vidvars.drawworld)
1969 // don't let sound skip if going slow
1970 if (r_refdef.extraupdate)
1974 GL_ShowTrisColor(0.025, 0.025, 0, 1);
1975 if (r_refdef.worldmodel && r_refdef.worldmodel->DrawSky)
1977 r_refdef.worldmodel->DrawSky(r_refdef.worldentity);
1978 if (r_timereport_active)
1979 R_TimeReport("worldsky");
1982 if (R_DrawBrushModelsSky() && r_timereport_active)
1983 R_TimeReport("bmodelsky");
1986 GL_ShowTrisColor(0.05, 0.05, 0.05, 1);
1987 if (r_refdef.worldmodel && r_refdef.worldmodel->Draw)
1989 r_refdef.worldmodel->Draw(r_refdef.worldentity);
1990 if (r_timereport_active)
1991 R_TimeReport("world");
1995 // don't let sound skip if going slow
1996 if (r_refdef.extraupdate)
2000 GL_ShowTrisColor(0, 0.015, 0, 1);
2003 if (r_timereport_active)
2004 R_TimeReport("models");
2006 // don't let sound skip if going slow
2007 if (r_refdef.extraupdate)
2011 GL_ShowTrisColor(0, 0, 0.033, 1);
2012 R_ShadowVolumeLighting(false);
2013 if (r_timereport_active)
2014 R_TimeReport("rtlights");
2016 // don't let sound skip if going slow
2017 if (r_refdef.extraupdate)
2021 GL_ShowTrisColor(0.1, 0, 0, 1);
2023 if (cl.csqc_vidvars.drawworld)
2025 R_DrawLightningBeams();
2026 if (r_timereport_active)
2027 R_TimeReport("lightning");
2030 if (r_timereport_active)
2031 R_TimeReport("particles");
2034 if (r_timereport_active)
2035 R_TimeReport("explosions");
2038 R_MeshQueue_RenderTransparent();
2039 if (r_timereport_active)
2040 R_TimeReport("drawtrans");
2042 if (cl.csqc_vidvars.drawworld)
2045 if (r_timereport_active)
2046 R_TimeReport("coronas");
2048 if(cl.csqc_vidvars.drawcrosshair)
2050 R_DrawWorldCrosshair();
2051 if (r_timereport_active)
2052 R_TimeReport("crosshair");
2055 VM_AddPolygonsToMeshQueue();
2057 R_MeshQueue_Render();
2061 //qglDisable(GL_LINE_SMOOTH);
2062 qglDisable(GL_POLYGON_OFFSET_LINE);
2068 R_MeshQueue_EndScene();
2070 // don't let sound skip if going slow
2071 if (r_refdef.extraupdate)
2074 if (gl_support_fragment_shader)
2075 qglUseProgramObjectARB(0);
2079 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
2082 float *v, *c, f1, f2, diff[3], vertex3f[8*3], color4f[8*4];
2084 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2085 GL_DepthMask(false);
2087 R_Mesh_Matrix(&identitymatrix);
2089 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2];
2090 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
2091 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
2092 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
2093 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
2094 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
2095 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
2096 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
2097 R_FillColors(color, 8, cr, cg, cb, ca);
2100 for (i = 0, v = vertex, c = color;i < 8;i++, v += 4, c += 4)
2102 f2 = VERTEXFOGTABLE(VectorDistance(v, r_vieworigin));
2104 c[0] = c[0] * f1 + fogcolor[0] * f2;
2105 c[1] = c[1] * f1 + fogcolor[1] * f2;
2106 c[2] = c[2] * f1 + fogcolor[2] * f2;
2109 memset(&m, 0, sizeof(m));
2110 m.pointer_vertex = vertex3f;
2111 m.pointer_color = color;
2117 int nomodelelements[24] =
2129 float nomodelvertex3f[6*3] =
2139 float nomodelcolor4f[6*4] =
2141 0.0f, 0.0f, 0.5f, 1.0f,
2142 0.0f, 0.0f, 0.5f, 1.0f,
2143 0.0f, 0.5f, 0.0f, 1.0f,
2144 0.0f, 0.5f, 0.0f, 1.0f,
2145 0.5f, 0.0f, 0.0f, 1.0f,
2146 0.5f, 0.0f, 0.0f, 1.0f
2149 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight)
2155 R_Mesh_Matrix(&ent->matrix);
2157 memset(&m, 0, sizeof(m));
2158 m.pointer_vertex = nomodelvertex3f;
2160 if (ent->flags & EF_ADDITIVE)
2162 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2163 GL_DepthMask(false);
2165 else if (ent->alpha < 1)
2167 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2168 GL_DepthMask(false);
2172 GL_BlendFunc(GL_ONE, GL_ZERO);
2175 GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
2178 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
2179 m.pointer_color = color4f;
2180 f2 = VERTEXFOGTABLE(VectorDistance(ent->origin, r_vieworigin));
2182 for (i = 0, c = color4f;i < 6;i++, c += 4)
2184 c[0] = (c[0] * f1 + fogcolor[0] * f2);
2185 c[1] = (c[1] * f1 + fogcolor[1] * f2);
2186 c[2] = (c[2] * f1 + fogcolor[2] * f2);
2190 else if (ent->alpha != 1)
2192 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
2193 m.pointer_color = color4f;
2194 for (i = 0, c = color4f;i < 6;i++, c += 4)
2198 m.pointer_color = nomodelcolor4f;
2200 R_Mesh_Draw(0, 6, 8, nomodelelements);
2203 void R_DrawNoModel(entity_render_t *ent)
2205 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
2206 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_vieworigin : ent->origin, R_DrawNoModel_TransparentCallback, ent, 0, r_shadow_rtlight);
2208 // R_DrawNoModelCallback(ent, 0);
2211 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
2213 vec3_t right1, right2, diff, normal;
2215 VectorSubtract (org2, org1, normal);
2217 // calculate 'right' vector for start
2218 VectorSubtract (r_vieworigin, org1, diff);
2219 CrossProduct (normal, diff, right1);
2220 VectorNormalize (right1);
2222 // calculate 'right' vector for end
2223 VectorSubtract (r_vieworigin, org2, diff);
2224 CrossProduct (normal, diff, right2);
2225 VectorNormalize (right2);
2227 vert[ 0] = org1[0] + width * right1[0];
2228 vert[ 1] = org1[1] + width * right1[1];
2229 vert[ 2] = org1[2] + width * right1[2];
2230 vert[ 3] = org1[0] - width * right1[0];
2231 vert[ 4] = org1[1] - width * right1[1];
2232 vert[ 5] = org1[2] - width * right1[2];
2233 vert[ 6] = org2[0] - width * right2[0];
2234 vert[ 7] = org2[1] - width * right2[1];
2235 vert[ 8] = org2[2] - width * right2[2];
2236 vert[ 9] = org2[0] + width * right2[0];
2237 vert[10] = org2[1] + width * right2[1];
2238 vert[11] = org2[2] + width * right2[2];
2241 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
2243 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)
2245 float fog = 0.0f, ifog;
2249 fog = VERTEXFOGTABLE(VectorDistance(origin, r_vieworigin));
2252 R_Mesh_Matrix(&identitymatrix);
2253 GL_BlendFunc(blendfunc1, blendfunc2);
2254 GL_DepthMask(false);
2255 GL_DepthTest(!depthdisable);
2257 varray_vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
2258 varray_vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
2259 varray_vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
2260 varray_vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
2261 varray_vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
2262 varray_vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
2263 varray_vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
2264 varray_vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
2265 varray_vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
2266 varray_vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
2267 varray_vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
2268 varray_vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
2270 memset(&m, 0, sizeof(m));
2271 m.tex[0] = R_GetTexture(texture);
2272 m.pointer_texcoord[0] = spritetexcoord2f;
2273 m.pointer_vertex = varray_vertex3f;
2275 GL_Color(cr * ifog, cg * ifog, cb * ifog, ca);
2276 R_Mesh_Draw(0, 4, 2, polygonelements);
2278 if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
2280 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
2281 GL_BlendFunc(blendfunc1, GL_ONE);
2282 GL_Color(fogcolor[0] * fog, fogcolor[1] * fog, fogcolor[2] * fog, ca);
2283 R_Mesh_Draw(0, 4, 2, polygonelements);
2287 int R_Mesh_AddVertex3f(rmesh_t *mesh, const float *v)
2291 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
2292 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
2294 if (i == mesh->numvertices)
2296 if (mesh->numvertices < mesh->maxvertices)
2298 VectorCopy(v, vertex3f);
2299 mesh->numvertices++;
2301 return mesh->numvertices;
2307 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
2311 element[0] = R_Mesh_AddVertex3f(mesh, vertex3f);vertex3f += 3;
2312 element[1] = R_Mesh_AddVertex3f(mesh, vertex3f);vertex3f += 3;
2313 e = mesh->element3i + mesh->numtriangles * 3;
2314 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
2316 element[2] = R_Mesh_AddVertex3f(mesh, vertex3f);
2317 if (mesh->numtriangles < mesh->maxtriangles)
2322 mesh->numtriangles++;
2324 element[1] = element[2];
2328 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
2330 int planenum, planenum2;
2333 mplane_t *plane, *plane2;
2334 float temppoints[2][256*3];
2335 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
2339 PolygonF_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->normal[3], 1024.0*1024.0*1024.0);
2340 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
2342 if (planenum2 == planenum)
2344 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);
2347 if (tempnumpoints < 3)
2349 // generate elements forming a triangle fan for this polygon
2350 R_Mesh_AddPolygon3f(mesh, tempnumpoints, temppoints[w]);
2354 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)
2356 texturelayer_t *layer;
2357 layer = t->currentlayers + t->currentnumlayers++;
2359 layer->depthmask = depthmask;
2360 layer->blendfunc1 = blendfunc1;
2361 layer->blendfunc2 = blendfunc2;
2362 layer->texture = texture;
2363 layer->texmatrix = *matrix;
2364 layer->color[0] = r;
2365 layer->color[1] = g;
2366 layer->color[2] = b;
2367 layer->color[3] = a;
2370 void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
2372 // FIXME: identify models using a better check than ent->model->brush.shadowmesh
2373 //int lightmode = ((ent->effects & EF_FULLBRIGHT) || ent->model->brush.shadowmesh) ? 0 : 2;
2376 texture_t *texture = t;
2377 model_t *model = ent->model;
2378 int s = ent->skinnum;
2379 if ((unsigned int)s >= (unsigned int)model->numskins)
2381 if (model->skinscenes)
2383 if (model->skinscenes[s].framecount > 1)
2384 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
2386 s = model->skinscenes[s].firstframe;
2389 t = t + s * model->num_surfaces;
2391 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];
2392 texture->currentframe = t;
2395 t->currentmaterialflags = t->basematerialflags;
2396 t->currentalpha = ent->alpha;
2397 if (t->basematerialflags & MATERIALFLAG_WATERALPHA)
2398 t->currentalpha *= r_wateralpha.value;
2399 if (!(ent->flags & RENDER_LIGHT))
2400 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
2401 if (ent->effects & EF_ADDITIVE)
2402 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_TRANSPARENT;
2403 else if (t->currentalpha < 1)
2404 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_TRANSPARENT;
2405 if (ent->effects & EF_NODEPTHTEST)
2406 t->currentmaterialflags |= MATERIALFLAG_NODEPTHTEST;
2407 if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
2408 t->currenttexmatrix = r_waterscrollmatrix;
2410 t->currenttexmatrix = identitymatrix;
2412 t->colormapping = VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f);
2413 t->basetexture = (!t->colormapping && t->skin.merged) ? t->skin.merged : t->skin.base;
2414 t->glosstexture = r_texture_white;
2415 t->specularpower = 8;
2416 t->specularscale = 0;
2417 if (r_shadow_gloss.integer > 0)
2421 if (r_shadow_glossintensity.value > 0)
2423 t->glosstexture = t->skin.gloss;
2424 t->specularscale = r_shadow_glossintensity.value;
2427 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
2428 t->specularscale = r_shadow_gloss2intensity.value;
2431 t->currentnumlayers = 0;
2432 if (!(t->currentmaterialflags & MATERIALFLAG_NODRAW))
2434 if (gl_lightmaps.integer)
2435 R_Texture_AddLayer(t, true, GL_ONE, GL_ZERO, TEXTURELAYERTYPE_LITTEXTURE_MULTIPASS, r_texture_white, &identitymatrix, 1, 1, 1, 1);
2436 else if (!(t->currentmaterialflags & MATERIALFLAG_SKY))
2438 int blendfunc1, blendfunc2, depthmask;
2439 if (t->currentmaterialflags & MATERIALFLAG_ADD)
2441 blendfunc1 = GL_SRC_ALPHA;
2442 blendfunc2 = GL_ONE;
2445 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
2447 blendfunc1 = GL_SRC_ALPHA;
2448 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
2453 blendfunc1 = GL_ONE;
2454 blendfunc2 = GL_ZERO;
2457 if (t->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL))
2459 rtexture_t *currentbasetexture;
2461 if (fogenabled && (t->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
2462 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
2463 currentbasetexture = (VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) < (1.0f / 1048576.0f) && t->skin.merged) ? t->skin.merged : t->skin.base;
2464 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2466 // fullbright is not affected by r_lightmapintensity
2467 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
2468 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->skin.pants)
2469 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);
2470 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->skin.shirt)
2471 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);
2477 // q3bsp has no lightmap updates, so the lightstylevalue that
2478 // would normally be baked into the lightmaptexture must be
2479 // applied to the color
2480 if (ent->model->type == mod_brushq3)
2481 colorscale *= r_refdef.lightstylevalue[0] * (1.0f / 256.0f);
2482 colorscale *= r_lightmapintensity;
2483 if (r_textureunits.integer >= 2 && gl_combine.integer)
2484 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);
2485 else if ((t->currentmaterialflags & MATERIALFLAG_TRANSPARENT) == 0)
2486 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);
2488 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);
2489 if (r_ambient.value >= (1.0f/64.0f))
2490 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);
2491 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->skin.pants)
2493 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);
2494 if (r_ambient.value >= (1.0f/64.0f))
2495 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);
2497 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->skin.shirt)
2499 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);
2500 if (r_ambient.value >= (1.0f/64.0f))
2501 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);
2504 if (t->skin.glow != NULL)
2505 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.glow, &t->currenttexmatrix, 1, 1, 1, t->currentalpha);
2506 if (fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
2508 // if this is opaque use alpha blend which will darken the earlier
2511 // if this is an alpha blended material, all the earlier passes
2512 // were darkened by fog already, so we only need to add the fog
2513 // color ontop through the fog mask texture
2515 // if this is an additive blended material, all the earlier passes
2516 // were darkened by fog already, and we should not add fog color
2517 // (because the background was not darkened, there is no fog color
2518 // that was lost behind it).
2519 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);
2526 void R_UpdateAllTextureInfo(entity_render_t *ent)
2530 for (i = 0;i < ent->model->num_textures;i++)
2531 R_UpdateTextureInfo(ent, ent->model->data_textures + i);
2534 float *rsurface_vertex3f;
2535 float *rsurface_svector3f;
2536 float *rsurface_tvector3f;
2537 float *rsurface_normal3f;
2538 float *rsurface_lightmapcolor4f;
2540 void RSurf_SetVertexPointer(const entity_render_t *ent, const texture_t *texture, const msurface_t *surface, const vec3_t modelorg, qboolean generatenormals, qboolean generatetangents)
2542 if ((ent->frameblend[0].lerp != 1 || ent->frameblend[0].frame != 0) && (surface->groupmesh->data_morphvertex3f || surface->groupmesh->data_vertexboneweights))
2544 rsurface_vertex3f = varray_vertex3f;
2545 Mod_Alias_GetMesh_Vertex3f(ent->model, ent->frameblend, surface->groupmesh, rsurface_vertex3f);
2546 if (generatetangents || (texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2)))
2548 rsurface_svector3f = varray_svector3f;
2549 rsurface_tvector3f = varray_tvector3f;
2550 rsurface_normal3f = varray_normal3f;
2551 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);
2555 rsurface_svector3f = NULL;
2556 rsurface_tvector3f = NULL;
2557 if (generatenormals)
2559 rsurface_normal3f = varray_normal3f;
2560 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);
2563 rsurface_normal3f = NULL;
2568 rsurface_vertex3f = surface->groupmesh->data_vertex3f;
2569 rsurface_svector3f = surface->groupmesh->data_svector3f;
2570 rsurface_tvector3f = surface->groupmesh->data_tvector3f;
2571 rsurface_normal3f = surface->groupmesh->data_normal3f;
2573 if (texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
2576 float center[3], forward[3], right[3], up[3], v[4][3];
2577 matrix4x4_t matrix1, imatrix1;
2578 Matrix4x4_Transform(&ent->inversematrix, r_viewforward, forward);
2579 Matrix4x4_Transform(&ent->inversematrix, r_viewright, right);
2580 Matrix4x4_Transform(&ent->inversematrix, r_viewup, up);
2581 // a single autosprite surface can contain multiple sprites...
2582 for (j = 0;j < surface->num_vertices - 3;j += 4)
2584 VectorClear(center);
2585 for (i = 0;i < 4;i++)
2586 VectorAdd(center, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
2587 VectorScale(center, 0.25f, center);
2588 // FIXME: calculate vectors from triangle edges instead of using texture vectors as an easy way out?
2589 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);
2590 Matrix4x4_Invert_Simple(&imatrix1, &matrix1);
2591 for (i = 0;i < 4;i++)
2592 Matrix4x4_Transform(&imatrix1, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, v[i]);
2593 if (texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE2)
2595 forward[0] = modelorg[0] - center[0];
2596 forward[1] = modelorg[1] - center[1];
2598 VectorNormalize(forward);
2599 right[0] = forward[1];
2600 right[1] = -forward[0];
2602 VectorSet(up, 0, 0, 1);
2604 for (i = 0;i < 4;i++)
2605 VectorMAMAMAM(1, center, v[i][0], forward, v[i][1], right, v[i][2], up, varray_vertex3f + (surface->num_firstvertex+i+j) * 3);
2607 rsurface_vertex3f = varray_vertex3f;
2608 rsurface_svector3f = varray_svector3f;
2609 rsurface_tvector3f = varray_tvector3f;
2610 rsurface_normal3f = varray_normal3f;
2611 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);
2613 R_Mesh_VertexPointer(rsurface_vertex3f);
2616 static void RSurf_Draw(const msurface_t *surface)
2618 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2619 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2620 GL_LockArrays(0, 0);
2623 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)
2628 RSurf_SetVertexPointer(ent, texture, surface, modelorg, lightmode >= 2, false);
2632 vec3_t ambientcolor;
2633 vec3_t diffusecolor;
2635 VectorCopy(ent->modellight_lightdir, lightdir);
2636 ambientcolor[0] = ent->modellight_ambient[0] * r * 0.5f;
2637 ambientcolor[1] = ent->modellight_ambient[1] * g * 0.5f;
2638 ambientcolor[2] = ent->modellight_ambient[2] * b * 0.5f;
2639 diffusecolor[0] = ent->modellight_diffuse[0] * r * 0.5f;
2640 diffusecolor[1] = ent->modellight_diffuse[1] * g * 0.5f;
2641 diffusecolor[2] = ent->modellight_diffuse[2] * b * 0.5f;
2642 if (VectorLength2(diffusecolor) > 0)
2644 int numverts = surface->num_vertices;
2645 v = rsurface_vertex3f + 3 * surface->num_firstvertex;
2646 c2 = rsurface_normal3f + 3 * surface->num_firstvertex;
2647 c = varray_color4f + 4 * surface->num_firstvertex;
2648 // q3-style directional shading
2649 for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
2651 if ((f = DotProduct(c2, lightdir)) > 0)
2652 VectorMA(ambientcolor, f, diffusecolor, c);
2654 VectorCopy(ambientcolor, c);
2662 rsurface_lightmapcolor4f = varray_color4f;
2666 r = ambientcolor[0];
2667 g = ambientcolor[1];
2668 b = ambientcolor[2];
2669 rsurface_lightmapcolor4f = NULL;
2672 else if (lightmode >= 1)
2674 if (surface->lightmapinfo && surface->lightmapinfo->stainsamples)
2676 for (i = 0, c = varray_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
2678 if (surface->lightmapinfo->samples)
2680 const unsigned char *lm = surface->lightmapinfo->samples + (surface->groupmesh->data_lightmapoffsets + surface->num_firstvertex)[i];
2681 float scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
2682 VectorScale(lm, scale, c);
2683 if (surface->lightmapinfo->styles[1] != 255)
2685 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
2687 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
2688 VectorMA(c, scale, lm, c);
2689 if (surface->lightmapinfo->styles[2] != 255)
2692 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
2693 VectorMA(c, scale, lm, c);
2694 if (surface->lightmapinfo->styles[3] != 255)
2697 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
2698 VectorMA(c, scale, lm, c);
2706 rsurface_lightmapcolor4f = varray_color4f;
2709 rsurface_lightmapcolor4f = surface->groupmesh->data_lightmapcolor4f;
2712 rsurface_lightmapcolor4f = NULL;
2715 if (rsurface_lightmapcolor4f)
2717 for (i = 0, v = (rsurface_vertex3f + 3 * surface->num_firstvertex), c = (rsurface_lightmapcolor4f + 4 * surface->num_firstvertex), c2 = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4, c2 += 4)
2719 f = 1 - VERTEXFOGTABLE(VectorDistance(v, modelorg));
2728 for (i = 0, v = (rsurface_vertex3f + 3 * surface->num_firstvertex), c2 = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c2 += 4)
2730 f = 1 - VERTEXFOGTABLE(VectorDistance(v, modelorg));
2737 rsurface_lightmapcolor4f = varray_color4f;
2739 if (applycolor && rsurface_lightmapcolor4f)
2741 for (i = 0, c = (rsurface_lightmapcolor4f + 4 * surface->num_firstvertex), c2 = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, c += 4, c2 += 4)
2748 rsurface_lightmapcolor4f = varray_color4f;
2750 R_Mesh_ColorPointer(rsurface_lightmapcolor4f);
2751 GL_Color(r, g, b, a);
2752 RSurf_Draw(surface);
2755 static void R_DrawTextureSurfaceList(const entity_render_t *ent, texture_t *texture, int texturenumsurfaces, const msurface_t **texturesurfacelist, const vec3_t modelorg)
2757 int texturesurfaceindex;
2759 const msurface_t *surface;
2760 qboolean applycolor;
2763 if (texture->currentmaterialflags & MATERIALFLAG_NODRAW)
2765 r_shadow_rtlight = NULL;
2766 renderstats.entities_surfaces += texturenumsurfaces;
2767 // FIXME: identify models using a better check than ent->model->brush.shadowmesh
2768 lightmode = ((ent->effects & EF_FULLBRIGHT) || ent->model->brush.shadowmesh) ? 0 : 2;
2769 GL_DepthTest(!(texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
2770 if ((texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (ent->flags & RENDER_NOCULLFACE))
2771 qglDisable(GL_CULL_FACE);
2772 if (texture->currentmaterialflags & MATERIALFLAG_SKY)
2774 // transparent sky would be ridiculous
2775 if (!(texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
2780 skyrendernow = false;
2781 if (skyrendermasked)
2784 // restore entity matrix and GL_Color
2785 R_Mesh_Matrix(&ent->matrix);
2789 // LordHavoc: HalfLife maps have freaky skypolys...
2790 //if (!ent->model->brush.ishlbsp)
2792 if (skyrendermasked)
2794 // depth-only (masking)
2795 GL_ColorMask(0,0,0,0);
2796 // just to make sure that braindead drivers don't draw anything
2797 // despite that colormask...
2798 GL_BlendFunc(GL_ZERO, GL_ONE);
2803 GL_BlendFunc(GL_ONE, GL_ZERO);
2805 GL_Color(fogcolor[0], fogcolor[1], fogcolor[2], 1);
2806 memset(&m, 0, sizeof(m));
2808 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2810 surface = texturesurfacelist[texturesurfaceindex];
2811 RSurf_SetVertexPointer(ent, texture, surface, modelorg, false, false);
2812 RSurf_Draw(surface);
2814 if (skyrendermasked)
2815 GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
2819 else if (r_glsl.integer && gl_support_fragment_shader)
2821 if (texture->currentmaterialflags & MATERIALFLAG_ADD)
2823 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2824 GL_DepthMask(false);
2826 else if (texture->currentmaterialflags & MATERIALFLAG_ALPHA)
2828 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2829 GL_DepthMask(false);
2833 GL_BlendFunc(GL_ONE, GL_ZERO);
2837 memset(&m, 0, sizeof(m));
2839 GL_Color(ent->colormod[0], ent->colormod[1], ent->colormod[2], texture->currentalpha);
2840 R_SetupSurfaceShader(ent, texture, modelorg, vec3_origin, lightmode == 2);
2841 if (!r_glsl_permutation)
2845 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2847 surface = texturesurfacelist[texturesurfaceindex];
2848 RSurf_SetVertexPointer(ent, texture, surface, modelorg, false, true);
2849 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2850 R_Mesh_TexCoordPointer(1, 3, rsurface_svector3f);
2851 R_Mesh_TexCoordPointer(2, 3, rsurface_tvector3f);
2852 R_Mesh_TexCoordPointer(3, 3, rsurface_normal3f);
2853 RSurf_Draw(surface);
2858 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2860 surface = texturesurfacelist[texturesurfaceindex];
2861 RSurf_SetVertexPointer(ent, texture, surface, modelorg, false, true);
2862 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2863 R_Mesh_TexCoordPointer(1, 3, rsurface_svector3f);
2864 R_Mesh_TexCoordPointer(2, 3, rsurface_tvector3f);
2865 R_Mesh_TexCoordPointer(3, 3, rsurface_normal3f);
2866 R_Mesh_TexCoordPointer(4, 2, surface->groupmesh->data_texcoordlightmap2f);
2867 if (surface->lightmaptexture)
2869 R_Mesh_TexBind(7, R_GetTexture(surface->lightmaptexture));
2870 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
2871 R_Mesh_TexBind(8, R_GetTexture(surface->deluxemaptexture));
2872 R_Mesh_ColorPointer(NULL);
2876 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
2877 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
2878 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
2879 R_Mesh_ColorPointer(surface->groupmesh->data_lightmapcolor4f);
2881 RSurf_Draw(surface);
2884 qglUseProgramObjectARB(0);
2886 else if (texture->currentnumlayers)
2889 texturelayer_t *layer;
2890 for (layerindex = 0, layer = texture->currentlayers;layerindex < texture->currentnumlayers;layerindex++, layer++)
2893 int layertexrgbscale;
2894 GL_DepthMask(layer->depthmask);
2895 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
2896 if ((layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2) && (gl_combine.integer || layer->depthmask))
2898 layertexrgbscale = 4;
2899 VectorScale(layer->color, 0.25f, layercolor);
2901 else if ((layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1) && (gl_combine.integer || layer->depthmask))
2903 layertexrgbscale = 2;
2904 VectorScale(layer->color, 0.5f, layercolor);
2908 layertexrgbscale = 1;
2909 VectorScale(layer->color, 1.0f, layercolor);
2911 layercolor[3] = layer->color[3];
2912 GL_Color(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
2913 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
2914 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
2915 switch (layer->type)
2917 case TEXTURELAYERTYPE_LITTEXTURE_COMBINE:
2918 memset(&m, 0, sizeof(m));
2919 m.tex[1] = R_GetTexture(layer->texture);
2920 m.texmatrix[1] = layer->texmatrix;
2921 m.texrgbscale[1] = layertexrgbscale;
2922 m.pointer_color = varray_color4f;
2926 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2928 surface = texturesurfacelist[texturesurfaceindex];
2929 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
2930 R_Mesh_TexCoordPointer(1, 2, surface->groupmesh->data_texcoordtexture2f);
2931 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2932 RSurf_DrawLightmap(ent, texture, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 2, applycolor, applyfog);
2937 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2939 surface = texturesurfacelist[texturesurfaceindex];
2940 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
2941 R_Mesh_TexCoordPointer(1, 2, surface->groupmesh->data_texcoordtexture2f);
2942 if (surface->lightmaptexture)
2944 R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
2945 RSurf_DrawLightmap(ent, texture, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, applyfog);
2949 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2950 RSurf_DrawLightmap(ent, texture, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 1, applycolor, applyfog);
2955 case TEXTURELAYERTYPE_LITTEXTURE_MULTIPASS:
2956 memset(&m, 0, sizeof(m));
2957 m.tex[0] = R_GetTexture(layer->texture);
2958 m.texmatrix[0] = layer->texmatrix;
2959 m.pointer_color = varray_color4f;
2960 m.texrgbscale[0] = layertexrgbscale;
2964 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2966 surface = texturesurfacelist[texturesurfaceindex];
2967 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
2968 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2969 RSurf_DrawLightmap(ent, texture, surface, modelorg, 1, 1, 1, 1, 2, false, false);
2974 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2976 surface = texturesurfacelist[texturesurfaceindex];
2977 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
2978 if (surface->lightmaptexture)
2980 R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
2981 RSurf_DrawLightmap(ent, texture, surface, modelorg, 1, 1, 1, 1, 0, false, false);
2985 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2986 RSurf_DrawLightmap(ent, texture, surface, modelorg, 1, 1, 1, 1, 1, false, false);
2990 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
2991 memset(&m, 0, sizeof(m));
2992 m.tex[0] = R_GetTexture(layer->texture);
2993 m.texmatrix[0] = layer->texmatrix;
2994 m.pointer_color = varray_color4f;
2995 m.texrgbscale[0] = layertexrgbscale;
2997 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2999 surface = texturesurfacelist[texturesurfaceindex];
3000 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
3001 RSurf_DrawLightmap(ent, texture, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, applyfog);
3004 case TEXTURELAYERTYPE_LITTEXTURE_VERTEX:
3005 memset(&m, 0, sizeof(m));
3006 m.tex[0] = R_GetTexture(layer->texture);
3007 m.texmatrix[0] = layer->texmatrix;
3008 m.texrgbscale[0] = layertexrgbscale;
3009 m.pointer_color = varray_color4f;
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], 2, applycolor, applyfog);
3022 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3024 surface = texturesurfacelist[texturesurfaceindex];
3025 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
3026 RSurf_DrawLightmap(ent, texture, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 1, applycolor, applyfog);
3030 case TEXTURELAYERTYPE_TEXTURE:
3031 memset(&m, 0, sizeof(m));
3032 m.tex[0] = R_GetTexture(layer->texture);
3033 m.texmatrix[0] = layer->texmatrix;
3034 m.pointer_color = varray_color4f;
3035 m.texrgbscale[0] = layertexrgbscale;
3037 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3039 surface = texturesurfacelist[texturesurfaceindex];
3040 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
3041 RSurf_DrawLightmap(ent, texture, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, applyfog);
3044 case TEXTURELAYERTYPE_FOG:
3045 memset(&m, 0, sizeof(m));
3048 m.tex[0] = R_GetTexture(layer->texture);
3049 m.texmatrix[0] = layer->texmatrix;
3052 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3056 surface = texturesurfacelist[texturesurfaceindex];
3057 RSurf_SetVertexPointer(ent, texture, surface, modelorg, false, false);
3059 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
3060 R_Mesh_ColorPointer(varray_color4f);
3061 for (i = 0, v = (rsurface_vertex3f + 3 * surface->num_firstvertex), c = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4)
3063 f = VERTEXFOGTABLE(VectorDistance(v, modelorg));
3064 c[0] = layercolor[0];
3065 c[1] = layercolor[1];
3066 c[2] = layercolor[2];
3067 c[3] = f * layercolor[3];
3069 RSurf_Draw(surface);
3073 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
3075 // if trying to do overbright on first pass of an opaque surface
3076 // when combine is not supported, brighten as a post process
3077 if (layertexrgbscale > 1 && !gl_combine.integer && layer->depthmask)
3080 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
3081 GL_Color(1, 1, 1, 1);
3082 memset(&m, 0, sizeof(m));
3084 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3086 surface = texturesurfacelist[texturesurfaceindex];
3087 RSurf_SetVertexPointer(ent, texture, surface, modelorg, false, false);
3088 for (scale = 1;scale < layertexrgbscale;scale <<= 1)
3089 RSurf_Draw(surface);
3093 if (r_shownormals.integer && !r_showtrispass)
3097 GL_DepthTest(!r_showdisabledepthtest.integer);
3098 GL_DepthMask(texture->currentlayers->depthmask);
3099 GL_BlendFunc(texture->currentlayers->blendfunc1, texture->currentlayers->blendfunc2);
3100 memset(&m, 0, sizeof(m));
3102 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3104 surface = texturesurfacelist[texturesurfaceindex];
3105 RSurf_SetVertexPointer(ent, texture, surface, modelorg, false, true);
3106 GL_Color(1, 0, 0, 1);
3108 for (j = 0, k = surface->num_firstvertex;j < surface->num_vertices;j++, k++)
3110 VectorCopy(rsurface_vertex3f + k * 3, v);
3111 qglVertex3f(v[0], v[1], v[2]);
3112 VectorMA(v, 8, rsurface_svector3f + k * 3, v);
3113 qglVertex3f(v[0], v[1], v[2]);
3115 GL_Color(0, 0, 1, 1);
3116 for (j = 0, k = surface->num_firstvertex;j < surface->num_vertices;j++, k++)
3118 VectorCopy(rsurface_vertex3f + k * 3, v);
3119 qglVertex3f(v[0], v[1], v[2]);
3120 VectorMA(v, 8, rsurface_tvector3f + k * 3, v);
3121 qglVertex3f(v[0], v[1], v[2]);
3123 GL_Color(0, 1, 0, 1);
3124 for (j = 0, k = surface->num_firstvertex;j < surface->num_vertices;j++, k++)
3126 VectorCopy(rsurface_vertex3f + k * 3, v);
3127 qglVertex3f(v[0], v[1], v[2]);
3128 VectorMA(v, 8, rsurface_normal3f + k * 3, v);
3129 qglVertex3f(v[0], v[1], v[2]);
3135 if ((texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (ent->flags & RENDER_NOCULLFACE))
3136 qglEnable(GL_CULL_FACE);
3139 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight)
3141 const msurface_t *surface = ent->model->data_surfaces + surfacenumber;
3145 texture = surface->texture;
3146 if (texture->basematerialflags & MATERIALFLAG_SKY)
3147 return; // transparent sky is too difficult
3148 R_UpdateTextureInfo(ent, texture);
3150 R_Mesh_Matrix(&ent->matrix);
3151 Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
3152 R_DrawTextureSurfaceList(ent, texture->currentframe, 1, &surface, modelorg);
3155 void R_QueueTextureSurfaceList(entity_render_t *ent, texture_t *texture, int texturenumsurfaces, const msurface_t **texturesurfacelist, const vec3_t modelorg)
3157 int texturesurfaceindex;
3158 const msurface_t *surface;
3159 vec3_t tempcenter, center;
3160 if (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT)
3162 // drawing sky transparently would be too difficult
3163 if (!(texture->currentmaterialflags & MATERIALFLAG_SKY))
3165 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3167 surface = texturesurfacelist[texturesurfaceindex];
3168 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
3169 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
3170 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
3171 Matrix4x4_Transform(&ent->matrix, tempcenter, center);
3172 R_MeshQueue_AddTransparent(texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_vieworigin : center, R_DrawSurface_TransparentCallback, ent, surface - ent->model->data_surfaces, r_shadow_rtlight);
3177 R_DrawTextureSurfaceList(ent, texture, texturenumsurfaces, texturesurfacelist, modelorg);
3180 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
3181 void R_DrawSurfaces(entity_render_t *ent, qboolean skysurfaces)
3183 int i, j, f, flagsmask;
3184 int counttriangles = 0;
3185 msurface_t *surface, **surfacechain;
3186 texture_t *t, *texture;
3187 model_t *model = ent->model;
3189 const int maxsurfacelist = 1024;
3190 int numsurfacelist = 0;
3191 const msurface_t *surfacelist[1024];
3194 R_Mesh_Matrix(&ent->matrix);
3195 Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
3197 // update light styles
3198 if (!skysurfaces && model->brushq1.light_styleupdatechains)
3200 for (i = 0;i < model->brushq1.light_styles;i++)
3202 if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
3204 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
3205 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
3206 for (;(surface = *surfacechain);surfacechain++)
3207 surface->cached_dlight = true;
3212 R_UpdateAllTextureInfo(ent);
3213 flagsmask = skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL);
3218 if (ent == r_refdef.worldentity)
3220 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
3222 if (!r_worldsurfacevisible[j])
3224 if (t != surface->texture)
3228 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
3231 t = surface->texture;
3232 texture = t->currentframe;
3233 f = texture->currentmaterialflags & flagsmask;
3235 if (f && surface->num_triangles)
3237 // if lightmap parameters changed, rebuild lightmap texture
3238 if (surface->cached_dlight)
3239 R_BuildLightMap(ent, surface);
3240 // add face to draw list
3241 surfacelist[numsurfacelist++] = surface;
3242 counttriangles += surface->num_triangles;
3243 if (numsurfacelist >= maxsurfacelist)
3245 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
3253 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
3255 if (t != surface->texture)
3259 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
3262 t = surface->texture;
3263 texture = t->currentframe;
3264 f = texture->currentmaterialflags & flagsmask;
3266 if (f && surface->num_triangles)
3268 // if lightmap parameters changed, rebuild lightmap texture
3269 if (surface->cached_dlight)
3270 R_BuildLightMap(ent, surface);
3271 // add face to draw list
3272 surfacelist[numsurfacelist++] = surface;
3273 counttriangles += surface->num_triangles;
3274 if (numsurfacelist >= maxsurfacelist)
3276 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
3283 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
3284 if (!r_showtrispass)
3285 renderstats.entities_triangles += counttriangles;
3286 if (gl_support_fragment_shader)
3287 qglUseProgramObjectARB(0);