2 Copyright (C) 1996-1997 Id Software, Inc.
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26 mempool_t *r_main_mempool;
27 rtexturepool_t *r_main_texturepool;
29 // used for dlight push checking and other things
34 renderstats_t renderstats;
36 // true during envmap command capture
39 // maximum visible distance (recalculated from world box each frame)
41 // brightness of world lightmaps and related lighting
42 // (often reduced when world rtlights are enabled)
43 float r_lightmapintensity;
44 // whether to draw world lights realtime, dlights realtime, and their shadows
46 qboolean r_rtworldshadows;
48 qboolean r_rtdlightshadows;
63 matrix4x4_t r_view_matrix;
64 float r_polygonfactor;
65 float r_polygonoffset;
66 float r_shadowpolygonfactor;
67 float r_shadowpolygonoffset;
73 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
74 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "shows surfaces as different colors"};
75 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
76 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
77 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
78 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
79 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
80 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
81 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
82 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing\n"};
83 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
84 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
85 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
86 cvar_t r_fullbright = {0, "r_fullbright","0", "make everything bright cheat (not allowed in multiplayer)"};
87 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
88 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
89 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
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_TexBindCubeMap(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, r_lightmapintensity * 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_showsurfaces);
1172 Cvar_RegisterVariable(&r_showtris);
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 float texcoord2f[3][8];
1593 // set the (poorly named) screenwidth and screenheight variables to
1594 // a power of 2 at least as large as the screen, these will define the
1595 // size of the texture to allocate
1596 for (screenwidth = 1;screenwidth < vid.width;screenwidth *= 2);
1597 for (screenheight = 1;screenheight < vid.height;screenheight *= 2);
1599 doblend = r_refdef.viewblend[3] >= 0.01f;
1600 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;
1602 if (!dobloom && !doblend)
1605 GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
1607 GL_DepthTest(false);
1608 R_Mesh_Matrix(&identitymatrix);
1609 // vertex coordinates for a quad that covers the screen exactly
1610 vertex3f[0] = 0;vertex3f[1] = 0;vertex3f[2] = 0;
1611 vertex3f[3] = 1;vertex3f[4] = 0;vertex3f[5] = 0;
1612 vertex3f[6] = 1;vertex3f[7] = 1;vertex3f[8] = 0;
1613 vertex3f[9] = 0;vertex3f[10] = 1;vertex3f[11] = 0;
1616 int bloomwidth, bloomheight, x, dobloomblend, range;
1617 float xoffset, yoffset, r;
1618 renderstats.bloom++;
1619 // allocate textures as needed
1620 if (!r_bloom_texture_screen)
1621 r_bloom_texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", screenwidth, screenheight, NULL, TEXTYPE_RGBA, TEXF_FORCENEAREST | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
1622 if (!r_bloom_texture_bloom)
1623 r_bloom_texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", screenwidth, screenheight, NULL, TEXTYPE_RGBA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
1624 // set bloomwidth and bloomheight to the bloom resolution that will be
1625 // used (often less than the screen resolution for faster rendering)
1626 bloomwidth = min(r_view_width, r_bloom_resolution.integer);
1627 bloomheight = min(r_view_height, bloomwidth * r_view_height / r_view_width);
1628 // set up a texcoord array for the full resolution screen image
1629 // (we have to keep this around to copy back during final render)
1630 texcoord2f[0][0] = 0;
1631 texcoord2f[0][1] = (float)r_view_height / (float)screenheight;
1632 texcoord2f[0][2] = (float)r_view_width / (float)screenwidth;
1633 texcoord2f[0][3] = (float)r_view_height / (float)screenheight;
1634 texcoord2f[0][4] = (float)r_view_width / (float)screenwidth;
1635 texcoord2f[0][5] = 0;
1636 texcoord2f[0][6] = 0;
1637 texcoord2f[0][7] = 0;
1638 // set up a texcoord array for the reduced resolution bloom image
1639 // (which will be additive blended over the screen image)
1640 texcoord2f[1][0] = 0;
1641 texcoord2f[1][1] = (float)bloomheight / (float)screenheight;
1642 texcoord2f[1][2] = (float)bloomwidth / (float)screenwidth;
1643 texcoord2f[1][3] = (float)bloomheight / (float)screenheight;
1644 texcoord2f[1][4] = (float)bloomwidth / (float)screenwidth;
1645 texcoord2f[1][5] = 0;
1646 texcoord2f[1][6] = 0;
1647 texcoord2f[1][7] = 0;
1648 memset(&m, 0, sizeof(m));
1649 m.pointer_vertex = vertex3f;
1650 m.pointer_texcoord[0] = texcoord2f[0];
1651 m.tex[0] = R_GetTexture(r_bloom_texture_screen);
1653 // copy view into the full resolution screen image texture
1654 GL_ActiveTexture(0);
1655 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
1656 renderstats.bloom_copypixels += r_view_width * r_view_height;
1657 // now scale it down to the bloom size and raise to a power of itself
1658 // to darken it (this leaves the really bright stuff bright, and
1659 // everything else becomes very dark)
1660 // TODO: optimize with multitexture or GLSL
1661 qglViewport(r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
1662 GL_BlendFunc(GL_ONE, GL_ZERO);
1663 GL_Color(1, 1, 1, 1);
1664 R_Mesh_Draw(0, 4, 2, polygonelements);
1665 renderstats.bloom_drawpixels += bloomwidth * bloomheight;
1666 // render multiple times with a multiply blendfunc to raise to a power
1667 GL_BlendFunc(GL_DST_COLOR, GL_ZERO);
1668 for (x = 1;x < r_bloom_power.integer;x++)
1670 R_Mesh_Draw(0, 4, 2, polygonelements);
1671 renderstats.bloom_drawpixels += bloomwidth * bloomheight;
1673 // we now have a darkened bloom image in the framebuffer, copy it into
1674 // the bloom image texture for more processing
1675 memset(&m, 0, sizeof(m));
1676 m.pointer_vertex = vertex3f;
1677 m.tex[0] = R_GetTexture(r_bloom_texture_bloom);
1678 m.pointer_texcoord[0] = texcoord2f[2];
1680 GL_ActiveTexture(0);
1681 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
1682 renderstats.bloom_copypixels += bloomwidth * bloomheight;
1683 // blend on at multiple vertical offsets to achieve a vertical blur
1684 // TODO: do offset blends using GLSL
1685 range = r_bloom_blur.integer * bloomwidth / 320;
1686 GL_BlendFunc(GL_ONE, GL_ZERO);
1687 for (x = -range;x <= range;x++)
1689 xoffset = 0 / (float)bloomwidth * (float)bloomwidth / (float)screenwidth;
1690 yoffset = x / (float)bloomheight * (float)bloomheight / (float)screenheight;
1691 // compute a texcoord array with the specified x and y offset
1692 texcoord2f[2][0] = xoffset+0;
1693 texcoord2f[2][1] = yoffset+(float)bloomheight / (float)screenheight;
1694 texcoord2f[2][2] = xoffset+(float)bloomwidth / (float)screenwidth;
1695 texcoord2f[2][3] = yoffset+(float)bloomheight / (float)screenheight;
1696 texcoord2f[2][4] = xoffset+(float)bloomwidth / (float)screenwidth;
1697 texcoord2f[2][5] = yoffset+0;
1698 texcoord2f[2][6] = xoffset+0;
1699 texcoord2f[2][7] = yoffset+0;
1700 // this r value looks like a 'dot' particle, fading sharply to
1701 // black at the edges
1702 // (probably not realistic but looks good enough)
1703 r = r_bloom_intensity.value/(range*2+1)*(1 - x*x/(float)(range*range));
1706 GL_Color(r, r, r, 1);
1707 R_Mesh_Draw(0, 4, 2, polygonelements);
1708 renderstats.bloom_drawpixels += bloomwidth * bloomheight;
1709 GL_BlendFunc(GL_ONE, GL_ONE);
1711 // copy the vertically blurred bloom view to a texture
1712 GL_ActiveTexture(0);
1713 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
1714 renderstats.bloom_copypixels += bloomwidth * bloomheight;
1715 // blend the vertically blurred image at multiple offsets horizontally
1716 // to finish the blur effect
1717 // TODO: do offset blends using GLSL
1718 range = r_bloom_blur.integer * bloomwidth / 320;
1719 GL_BlendFunc(GL_ONE, GL_ZERO);
1720 for (x = -range;x <= range;x++)
1722 xoffset = x / (float)bloomwidth * (float)bloomwidth / (float)screenwidth;
1723 yoffset = 0 / (float)bloomheight * (float)bloomheight / (float)screenheight;
1724 // compute a texcoord array with the specified x and y offset
1725 texcoord2f[2][0] = xoffset+0;
1726 texcoord2f[2][1] = yoffset+(float)bloomheight / (float)screenheight;
1727 texcoord2f[2][2] = xoffset+(float)bloomwidth / (float)screenwidth;
1728 texcoord2f[2][3] = yoffset+(float)bloomheight / (float)screenheight;
1729 texcoord2f[2][4] = xoffset+(float)bloomwidth / (float)screenwidth;
1730 texcoord2f[2][5] = yoffset+0;
1731 texcoord2f[2][6] = xoffset+0;
1732 texcoord2f[2][7] = yoffset+0;
1733 // this r value looks like a 'dot' particle, fading sharply to
1734 // black at the edges
1735 // (probably not realistic but looks good enough)
1736 r = r_bloom_intensity.value/(range*2+1)*(1 - x*x/(float)(range*range));
1739 GL_Color(r, r, r, 1);
1740 R_Mesh_Draw(0, 4, 2, polygonelements);
1741 renderstats.bloom_drawpixels += bloomwidth * bloomheight;
1742 GL_BlendFunc(GL_ONE, GL_ONE);
1744 // copy the blurred bloom view to a texture
1745 GL_ActiveTexture(0);
1746 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
1747 renderstats.bloom_copypixels += bloomwidth * bloomheight;
1748 // go back to full view area
1749 qglViewport(r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
1750 // put the original screen image back in place and blend the bloom
1752 memset(&m, 0, sizeof(m));
1753 m.pointer_vertex = vertex3f;
1754 m.tex[0] = R_GetTexture(r_bloom_texture_screen);
1755 m.pointer_texcoord[0] = texcoord2f[0];
1757 dobloomblend = false;
1759 // do both in one pass if possible
1760 if (r_textureunits.integer >= 2 && gl_combine.integer)
1762 dobloomblend = false;
1763 m.texcombinergb[1] = GL_ADD;
1764 m.tex[1] = R_GetTexture(r_bloom_texture_bloom);
1765 m.pointer_texcoord[1] = texcoord2f[1];
1768 dobloomblend = true;
1771 GL_BlendFunc(GL_ONE, GL_ZERO);
1773 R_Mesh_Draw(0, 4, 2, polygonelements);
1774 renderstats.bloom_drawpixels += r_view_width * r_view_height;
1775 // now blend on the bloom texture if multipass
1778 memset(&m, 0, sizeof(m));
1779 m.pointer_vertex = vertex3f;
1780 m.tex[0] = R_GetTexture(r_bloom_texture_bloom);
1781 m.pointer_texcoord[0] = texcoord2f[1];
1783 GL_BlendFunc(GL_ONE, GL_ONE);
1785 R_Mesh_Draw(0, 4, 2, polygonelements);
1786 renderstats.bloom_drawpixels += r_view_width * r_view_height;
1791 // apply a color tint to the whole view
1792 memset(&m, 0, sizeof(m));
1793 m.pointer_vertex = vertex3f;
1795 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1796 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
1797 R_Mesh_Draw(0, 4, 2, polygonelements);
1801 void R_RenderScene(void);
1803 matrix4x4_t r_waterscrollmatrix;
1810 void R_RenderView(void)
1812 if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
1813 return; //Host_Error ("R_RenderView: NULL worldmodel");
1815 r_view_width = bound(0, r_refdef.width, vid.width);
1816 r_view_height = bound(0, r_refdef.height, vid.height);
1818 r_view_x = bound(0, r_refdef.x, vid.width - r_refdef.width);
1819 r_view_y = bound(0, r_refdef.y, vid.height - r_refdef.height);
1821 r_view_matrix = r_refdef.viewentitymatrix;
1822 GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
1823 r_rtworld = r_shadow_realtime_world.integer;
1824 r_rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
1825 r_rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer;
1826 r_rtdlightshadows = r_rtdlight && (r_rtworld ? r_shadow_realtime_world_dlightshadows.integer : r_shadow_realtime_dlight_shadows.integer) && gl_stencil;
1827 r_lightmapintensity = r_rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
1828 r_polygonfactor = 0;
1829 r_polygonoffset = 0;
1830 r_shadowpolygonfactor = r_polygonfactor + r_shadow_shadow_polygonfactor.value;
1831 r_shadowpolygonoffset = r_polygonoffset + r_shadow_shadow_polygonoffset.value;
1832 if (r_showsurfaces.integer)
1835 r_rtworldshadows = false;
1837 r_rtdlightshadows = false;
1838 r_lightmapintensity = 0;
1841 // GL is weird because it's bottom to top, r_view_y is top to bottom
1842 qglViewport(r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
1843 GL_Scissor(r_view_x, r_view_y, r_view_width, r_view_height);
1844 GL_ScissorTest(true);
1849 if (r_timereport_active)
1850 R_TimeReport("setup");
1852 qglDepthFunc(GL_LEQUAL);
1853 qglPolygonOffset(r_polygonfactor, r_polygonoffset);
1854 qglEnable(GL_POLYGON_OFFSET_FILL);
1858 qglPolygonOffset(r_polygonfactor, r_polygonoffset);
1859 qglDisable(GL_POLYGON_OFFSET_FILL);
1862 if (r_timereport_active)
1863 R_TimeReport("blendview");
1865 GL_Scissor(0, 0, vid.width, vid.height);
1866 GL_ScissorTest(false);
1870 void CSQC_R_ClearScreen (void)
1872 if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
1873 return; //Host_Error ("R_RenderView: NULL worldmodel");
1875 r_view_width = bound(0, r_refdef.width, vid.width);
1876 r_view_height = bound(0, r_refdef.height, vid.height);
1878 r_view_x = bound(0, r_refdef.x, vid.width - r_refdef.width);
1879 r_view_y = bound(0, r_refdef.y, vid.height - r_refdef.height);
1881 r_view_matrix = r_refdef.viewentitymatrix;
1882 GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
1883 r_rtworld = r_shadow_realtime_world.integer;
1884 r_rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
1885 r_rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer;
1886 r_rtdlightshadows = r_rtdlight && (r_rtworld ? r_shadow_realtime_world_dlightshadows.integer : r_shadow_realtime_dlight_shadows.integer) && gl_stencil;
1887 r_lightmapintensity = r_rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
1888 r_polygonfactor = 0;
1889 r_polygonoffset = 0;
1890 r_shadowpolygonfactor = r_polygonfactor + r_shadow_shadow_polygonfactor.value;
1891 r_shadowpolygonoffset = r_polygonoffset + r_shadow_shadow_polygonoffset.value;
1892 if (r_showsurfaces.integer)
1895 r_rtworldshadows = false;
1897 r_rtdlightshadows = false;
1898 r_lightmapintensity = 0;
1901 // GL is weird because it's bottom to top, r_view_y is top to bottom
1902 qglViewport(r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
1903 GL_Scissor(r_view_x, r_view_y, r_view_width, r_view_height);
1904 GL_ScissorTest(true);
1909 if (r_timereport_active)
1910 R_TimeReport("setup");
1914 void CSQC_R_RenderScene (void)
1916 qglDepthFunc(GL_LEQUAL);
1917 qglPolygonOffset(r_polygonfactor, r_polygonoffset);
1918 qglEnable(GL_POLYGON_OFFSET_FILL);
1922 qglPolygonOffset(r_polygonfactor, r_polygonoffset);
1923 qglDisable(GL_POLYGON_OFFSET_FILL);
1926 if (r_timereport_active)
1927 R_TimeReport("blendview");
1929 GL_Scissor(0, 0, vid.width, vid.height);
1930 GL_ScissorTest(false);
1933 extern void R_DrawLightningBeams (void);
1934 extern void VM_AddPolygonsToMeshQueue (void);
1935 void R_RenderScene(void)
1939 // don't let sound skip if going slow
1940 if (r_refdef.extraupdate)
1945 if (gl_support_fragment_shader)
1946 qglUseProgramObjectARB(0);
1948 R_MeshQueue_BeginScene();
1952 r_farclip = R_FarClip(r_vieworigin, r_viewforward, 768.0f) + 256.0f;
1953 nearclip = bound (0.001f, r_nearclip.value, r_farclip - 1.0f);
1955 if (r_rtworldshadows || r_rtdlightshadows)
1956 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_refdef.frustum_x, r_refdef.frustum_y, nearclip);
1958 GL_SetupView_Mode_Perspective(r_refdef.frustum_x, r_refdef.frustum_y, nearclip, r_farclip);
1960 GL_SetupView_Orientation_FromEntity(&r_view_matrix);
1962 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);
1966 R_WorldVisibility();
1967 if (r_timereport_active)
1968 R_TimeReport("worldvis");
1971 if (r_timereport_active)
1972 R_TimeReport("markentity");
1974 R_Shadow_UpdateWorldLightSelection();
1976 if (cl.csqc_vidvars.drawworld)
1978 // don't let sound skip if going slow
1979 if (r_refdef.extraupdate)
1982 if (r_refdef.worldmodel && r_refdef.worldmodel->DrawSky)
1984 r_refdef.worldmodel->DrawSky(r_refdef.worldentity);
1985 if (r_timereport_active)
1986 R_TimeReport("worldsky");
1989 if (R_DrawBrushModelsSky() && r_timereport_active)
1990 R_TimeReport("bmodelsky");
1992 if (r_refdef.worldmodel && r_refdef.worldmodel->Draw)
1994 r_refdef.worldmodel->Draw(r_refdef.worldentity);
1995 if (r_timereport_active)
1996 R_TimeReport("world");
2000 // don't let sound skip if going slow
2001 if (r_refdef.extraupdate)
2005 if (r_timereport_active)
2006 R_TimeReport("models");
2008 // don't let sound skip if going slow
2009 if (r_refdef.extraupdate)
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)
2020 if (cl.csqc_vidvars.drawworld)
2022 R_DrawLightningBeams();
2023 if (r_timereport_active)
2024 R_TimeReport("lightning");
2027 if (r_timereport_active)
2028 R_TimeReport("particles");
2031 if (r_timereport_active)
2032 R_TimeReport("explosions");
2035 R_MeshQueue_RenderTransparent();
2036 if (r_timereport_active)
2037 R_TimeReport("drawtrans");
2039 if (cl.csqc_vidvars.drawworld)
2042 if (r_timereport_active)
2043 R_TimeReport("coronas");
2045 if(cl.csqc_vidvars.drawcrosshair)
2047 R_DrawWorldCrosshair();
2048 if (r_timereport_active)
2049 R_TimeReport("crosshair");
2052 VM_AddPolygonsToMeshQueue();
2054 R_MeshQueue_Render();
2056 R_MeshQueue_EndScene();
2058 // don't let sound skip if going slow
2059 if (r_refdef.extraupdate)
2062 if (gl_support_fragment_shader)
2063 qglUseProgramObjectARB(0);
2067 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
2070 float *v, *c, f1, f2, diff[3], vertex3f[8*3], color4f[8*4];
2072 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2073 GL_DepthMask(false);
2075 R_Mesh_Matrix(&identitymatrix);
2077 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2];
2078 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
2079 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
2080 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
2081 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
2082 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
2083 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
2084 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
2085 R_FillColors(color, 8, cr, cg, cb, ca);
2088 for (i = 0, v = vertex, c = color;i < 8;i++, v += 4, c += 4)
2090 f2 = VERTEXFOGTABLE(VectorDistance(v, r_vieworigin));
2092 c[0] = c[0] * f1 + fogcolor[0] * f2;
2093 c[1] = c[1] * f1 + fogcolor[1] * f2;
2094 c[2] = c[2] * f1 + fogcolor[2] * f2;
2097 memset(&m, 0, sizeof(m));
2098 m.pointer_vertex = vertex3f;
2099 m.pointer_color = color;
2105 int nomodelelements[24] =
2117 float nomodelvertex3f[6*3] =
2127 float nomodelcolor4f[6*4] =
2129 0.0f, 0.0f, 0.5f, 1.0f,
2130 0.0f, 0.0f, 0.5f, 1.0f,
2131 0.0f, 0.5f, 0.0f, 1.0f,
2132 0.0f, 0.5f, 0.0f, 1.0f,
2133 0.5f, 0.0f, 0.0f, 1.0f,
2134 0.5f, 0.0f, 0.0f, 1.0f
2137 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight)
2143 R_Mesh_Matrix(&ent->matrix);
2145 memset(&m, 0, sizeof(m));
2146 m.pointer_vertex = nomodelvertex3f;
2148 if (ent->flags & EF_ADDITIVE)
2150 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2151 GL_DepthMask(false);
2153 else if (ent->alpha < 1)
2155 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2156 GL_DepthMask(false);
2160 GL_BlendFunc(GL_ONE, GL_ZERO);
2163 GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
2166 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
2167 m.pointer_color = color4f;
2168 f2 = VERTEXFOGTABLE(VectorDistance(ent->origin, r_vieworigin));
2170 for (i = 0, c = color4f;i < 6;i++, c += 4)
2172 c[0] = (c[0] * f1 + fogcolor[0] * f2);
2173 c[1] = (c[1] * f1 + fogcolor[1] * f2);
2174 c[2] = (c[2] * f1 + fogcolor[2] * f2);
2178 else if (ent->alpha != 1)
2180 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
2181 m.pointer_color = color4f;
2182 for (i = 0, c = color4f;i < 6;i++, c += 4)
2186 m.pointer_color = nomodelcolor4f;
2188 R_Mesh_Draw(0, 6, 8, nomodelelements);
2191 void R_DrawNoModel(entity_render_t *ent)
2193 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
2194 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_vieworigin : ent->origin, R_DrawNoModel_TransparentCallback, ent, 0, r_shadow_rtlight);
2196 // R_DrawNoModelCallback(ent, 0);
2199 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
2201 vec3_t right1, right2, diff, normal;
2203 VectorSubtract (org2, org1, normal);
2205 // calculate 'right' vector for start
2206 VectorSubtract (r_vieworigin, org1, diff);
2207 CrossProduct (normal, diff, right1);
2208 VectorNormalize (right1);
2210 // calculate 'right' vector for end
2211 VectorSubtract (r_vieworigin, org2, diff);
2212 CrossProduct (normal, diff, right2);
2213 VectorNormalize (right2);
2215 vert[ 0] = org1[0] + width * right1[0];
2216 vert[ 1] = org1[1] + width * right1[1];
2217 vert[ 2] = org1[2] + width * right1[2];
2218 vert[ 3] = org1[0] - width * right1[0];
2219 vert[ 4] = org1[1] - width * right1[1];
2220 vert[ 5] = org1[2] - width * right1[2];
2221 vert[ 6] = org2[0] - width * right2[0];
2222 vert[ 7] = org2[1] - width * right2[1];
2223 vert[ 8] = org2[2] - width * right2[2];
2224 vert[ 9] = org2[0] + width * right2[0];
2225 vert[10] = org2[1] + width * right2[1];
2226 vert[11] = org2[2] + width * right2[2];
2229 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
2231 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)
2233 float fog = 0.0f, ifog;
2238 fog = VERTEXFOGTABLE(VectorDistance(origin, r_vieworigin));
2241 R_Mesh_Matrix(&identitymatrix);
2242 GL_BlendFunc(blendfunc1, blendfunc2);
2243 GL_DepthMask(false);
2244 GL_DepthTest(!depthdisable);
2246 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
2247 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
2248 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
2249 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
2250 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
2251 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
2252 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
2253 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
2254 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
2255 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
2256 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
2257 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
2259 memset(&m, 0, sizeof(m));
2260 m.tex[0] = R_GetTexture(texture);
2261 m.pointer_texcoord[0] = spritetexcoord2f;
2262 m.pointer_vertex = vertex3f;
2264 GL_Color(cr * ifog, cg * ifog, cb * ifog, ca);
2265 R_Mesh_Draw(0, 4, 2, polygonelements);
2267 if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
2269 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
2270 GL_BlendFunc(blendfunc1, GL_ONE);
2271 GL_Color(fogcolor[0] * fog, fogcolor[1] * fog, fogcolor[2] * fog, ca);
2272 R_Mesh_Draw(0, 4, 2, polygonelements);
2276 int R_Mesh_AddVertex3f(rmesh_t *mesh, const float *v)
2280 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
2281 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
2283 if (i == mesh->numvertices)
2285 if (mesh->numvertices < mesh->maxvertices)
2287 VectorCopy(v, vertex3f);
2288 mesh->numvertices++;
2290 return mesh->numvertices;
2296 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
2300 element[0] = R_Mesh_AddVertex3f(mesh, vertex3f);vertex3f += 3;
2301 element[1] = R_Mesh_AddVertex3f(mesh, vertex3f);vertex3f += 3;
2302 e = mesh->element3i + mesh->numtriangles * 3;
2303 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
2305 element[2] = R_Mesh_AddVertex3f(mesh, vertex3f);
2306 if (mesh->numtriangles < mesh->maxtriangles)
2311 mesh->numtriangles++;
2313 element[1] = element[2];
2317 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
2319 int planenum, planenum2;
2322 mplane_t *plane, *plane2;
2323 float temppoints[2][256*3];
2324 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
2328 PolygonF_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->normal[3], 1024.0*1024.0*1024.0);
2329 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
2331 if (planenum2 == planenum)
2333 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);
2336 if (tempnumpoints < 3)
2338 // generate elements forming a triangle fan for this polygon
2339 R_Mesh_AddPolygon3f(mesh, tempnumpoints, temppoints[w]);
2343 static void R_DrawCollisionBrush(colbrushf_t *brush)
2347 memset(&m, 0, sizeof(m));
2348 m.pointer_vertex = brush->points->v;
2350 i = (int)(((size_t)brush) / sizeof(colbrushf_t));
2351 GL_Color((i & 31) * (1.0f / 32.0f), ((i >> 5) & 31) * (1.0f / 32.0f), ((i >> 10) & 31) * (1.0f / 32.0f), 0.2f);
2352 GL_LockArrays(0, brush->numpoints);
2353 R_Mesh_Draw(0, brush->numpoints, brush->numtriangles, brush->elements);
2354 GL_LockArrays(0, 0);
2357 static void R_DrawCollisionSurface(entity_render_t *ent, msurface_t *surface)
2361 if (!surface->num_collisiontriangles)
2363 memset(&m, 0, sizeof(m));
2364 m.pointer_vertex = surface->data_collisionvertex3f;
2366 i = (int)(((size_t)surface) / sizeof(msurface_t));
2367 GL_Color((i & 31) * (1.0f / 32.0f), ((i >> 5) & 31) * (1.0f / 32.0f), ((i >> 10) & 31) * (1.0f / 32.0f), 0.2f);
2368 GL_LockArrays(0, surface->num_collisionvertices);
2369 R_Mesh_Draw(0, surface->num_collisionvertices, surface->num_collisiontriangles, surface->data_collisionelement3i);
2370 GL_LockArrays(0, 0);
2373 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)
2375 texturelayer_t *layer;
2376 layer = t->currentlayers + t->currentnumlayers++;
2378 layer->depthmask = depthmask;
2379 layer->blendfunc1 = blendfunc1;
2380 layer->blendfunc2 = blendfunc2;
2381 layer->texture = texture;
2382 layer->texmatrix = *matrix;
2383 layer->color[0] = r;
2384 layer->color[1] = g;
2385 layer->color[2] = b;
2386 layer->color[3] = a;
2389 void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
2391 // FIXME: identify models using a better check than ent->model->brush.shadowmesh
2392 //int lightmode = ((ent->effects & EF_FULLBRIGHT) || ent->model->brush.shadowmesh) ? 0 : 2;
2395 texture_t *texture = t;
2396 model_t *model = ent->model;
2397 int s = ent->skinnum;
2398 if ((unsigned int)s >= (unsigned int)model->numskins)
2400 if (model->skinscenes)
2402 if (model->skinscenes[s].framecount > 1)
2403 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
2405 s = model->skinscenes[s].firstframe;
2408 t = t + s * model->num_surfaces;
2410 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];
2411 texture->currentframe = t;
2414 t->currentmaterialflags = t->basematerialflags;
2415 t->currentalpha = ent->alpha;
2416 if (t->basematerialflags & MATERIALFLAG_WATERALPHA)
2417 t->currentalpha *= r_wateralpha.value;
2418 if (!(ent->flags & RENDER_LIGHT))
2419 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
2420 if (ent->effects & EF_ADDITIVE)
2421 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_TRANSPARENT;
2422 else if (t->currentalpha < 1)
2423 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_TRANSPARENT;
2424 if (ent->effects & EF_NODEPTHTEST)
2425 t->currentmaterialflags |= MATERIALFLAG_NODEPTHTEST;
2426 if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
2427 t->currenttexmatrix = r_waterscrollmatrix;
2429 t->currenttexmatrix = identitymatrix;
2431 t->colormapping = VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f);
2432 t->basetexture = (!t->colormapping && t->skin.merged) ? t->skin.merged : t->skin.base;
2433 t->glosstexture = r_texture_white;
2434 t->specularpower = 8;
2435 t->specularscale = 0;
2436 if (r_shadow_gloss.integer > 0)
2440 if (r_shadow_glossintensity.value > 0)
2442 t->glosstexture = t->skin.gloss;
2443 t->specularscale = r_shadow_glossintensity.value;
2446 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
2447 t->specularscale = r_shadow_gloss2intensity.value;
2450 t->currentnumlayers = 0;
2451 if (!(t->currentmaterialflags & MATERIALFLAG_NODRAW))
2453 if (gl_lightmaps.integer)
2454 R_Texture_AddLayer(t, true, GL_ONE, GL_ZERO, TEXTURELAYERTYPE_LITTEXTURE_MULTIPASS, r_texture_white, &identitymatrix, 1, 1, 1, 1);
2455 else if (!(t->currentmaterialflags & MATERIALFLAG_SKY))
2457 int blendfunc1, blendfunc2, depthmask;
2458 if (t->currentmaterialflags & MATERIALFLAG_ADD)
2460 blendfunc1 = GL_SRC_ALPHA;
2461 blendfunc2 = GL_ONE;
2464 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
2466 blendfunc1 = GL_SRC_ALPHA;
2467 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
2472 blendfunc1 = GL_ONE;
2473 blendfunc2 = GL_ZERO;
2476 if (t->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL))
2478 rtexture_t *currentbasetexture;
2480 if (fogenabled && (t->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
2481 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
2482 currentbasetexture = (VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) < (1.0f / 1048576.0f) && t->skin.merged) ? t->skin.merged : t->skin.base;
2483 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2485 // fullbright is not affected by r_lightmapintensity
2486 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
2487 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->skin.pants)
2488 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);
2489 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->skin.shirt)
2490 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);
2496 // q3bsp has no lightmap updates, so the lightstylevalue that
2497 // would normally be baked into the lightmaptexture must be
2498 // applied to the color
2499 if (ent->model->type == mod_brushq3)
2500 colorscale *= r_refdef.lightstylevalue[0] * (1.0f / 256.0f);
2501 colorscale *= r_lightmapintensity;
2502 if (r_textureunits.integer >= 2 && gl_combine.integer)
2503 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);
2504 else if ((t->currentmaterialflags & MATERIALFLAG_TRANSPARENT) == 0)
2505 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);
2507 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);
2508 if (r_ambient.value >= (1.0f/64.0f))
2509 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);
2510 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->skin.pants)
2512 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);
2513 if (r_ambient.value >= (1.0f/64.0f))
2514 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);
2516 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->skin.shirt)
2518 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);
2519 if (r_ambient.value >= (1.0f/64.0f))
2520 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);
2523 if (t->skin.glow != NULL)
2524 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.glow, &t->currenttexmatrix, 1, 1, 1, t->currentalpha);
2525 if (fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
2527 // if this is opaque use alpha blend which will darken the earlier
2530 // if this is an alpha blended material, all the earlier passes
2531 // were darkened by fog already, so we only need to add the fog
2532 // color ontop through the fog mask texture
2534 // if this is an additive blended material, all the earlier passes
2535 // were darkened by fog already, and we should not add fog color
2536 // (because the background was not darkened, there is no fog color
2537 // that was lost behind it).
2538 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);
2545 void R_UpdateAllTextureInfo(entity_render_t *ent)
2549 for (i = 0;i < ent->model->num_textures;i++)
2550 R_UpdateTextureInfo(ent, ent->model->data_textures + i);
2553 int rsurface_array_size = 0;
2554 float *rsurface_array_vertex3f = NULL;
2555 float *rsurface_array_svector3f = NULL;
2556 float *rsurface_array_tvector3f = NULL;
2557 float *rsurface_array_normal3f = NULL;
2558 float *rsurface_array_color4f = NULL;
2559 float *rsurface_array_texcoord3f = NULL;
2561 void R_Mesh_ResizeArrays(int newvertices)
2563 if (rsurface_array_size >= newvertices)
2565 if (rsurface_array_vertex3f)
2566 Mem_Free(rsurface_array_vertex3f);
2567 rsurface_array_size = (newvertices + 1023) & ~1023;
2568 rsurface_array_vertex3f = Mem_Alloc(r_main_mempool, rsurface_array_size * sizeof(float[19]));
2569 rsurface_array_svector3f = rsurface_array_vertex3f + rsurface_array_size * 3;
2570 rsurface_array_tvector3f = rsurface_array_vertex3f + rsurface_array_size * 6;
2571 rsurface_array_normal3f = rsurface_array_vertex3f + rsurface_array_size * 9;
2572 rsurface_array_color4f = rsurface_array_vertex3f + rsurface_array_size * 12;
2573 rsurface_array_texcoord3f = rsurface_array_vertex3f + rsurface_array_size * 16;
2576 float *rsurface_vertex3f;
2577 float *rsurface_svector3f;
2578 float *rsurface_tvector3f;
2579 float *rsurface_normal3f;
2580 float *rsurface_lightmapcolor4f;
2582 void RSurf_SetVertexPointer(const entity_render_t *ent, const texture_t *texture, const msurface_t *surface, const vec3_t modelorg, qboolean generatenormals, qboolean generatetangents)
2584 if (rsurface_array_size < surface->groupmesh->num_vertices)
2585 R_Mesh_ResizeArrays(surface->groupmesh->num_vertices);
2586 if ((ent->frameblend[0].lerp != 1 || ent->frameblend[0].frame != 0) && (surface->groupmesh->data_morphvertex3f || surface->groupmesh->data_vertexboneweights))
2588 rsurface_vertex3f = rsurface_array_vertex3f;
2589 Mod_Alias_GetMesh_Vertex3f(ent->model, ent->frameblend, surface->groupmesh, rsurface_vertex3f);
2590 if (generatetangents || (texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2)))
2592 rsurface_svector3f = rsurface_array_svector3f;
2593 rsurface_tvector3f = rsurface_array_tvector3f;
2594 rsurface_normal3f = rsurface_array_normal3f;
2595 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);
2599 rsurface_svector3f = NULL;
2600 rsurface_tvector3f = NULL;
2601 if (generatenormals)
2603 rsurface_normal3f = rsurface_array_normal3f;
2604 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);
2607 rsurface_normal3f = NULL;
2612 rsurface_vertex3f = surface->groupmesh->data_vertex3f;
2613 rsurface_svector3f = surface->groupmesh->data_svector3f;
2614 rsurface_tvector3f = surface->groupmesh->data_tvector3f;
2615 rsurface_normal3f = surface->groupmesh->data_normal3f;
2617 if (texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
2620 float center[3], forward[3], right[3], up[3], v[4][3];
2621 matrix4x4_t matrix1, imatrix1;
2622 Matrix4x4_Transform(&ent->inversematrix, r_viewforward, forward);
2623 Matrix4x4_Transform(&ent->inversematrix, r_viewright, right);
2624 Matrix4x4_Transform(&ent->inversematrix, r_viewup, up);
2625 // a single autosprite surface can contain multiple sprites...
2626 for (j = 0;j < surface->num_vertices - 3;j += 4)
2628 VectorClear(center);
2629 for (i = 0;i < 4;i++)
2630 VectorAdd(center, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
2631 VectorScale(center, 0.25f, center);
2632 // FIXME: calculate vectors from triangle edges instead of using texture vectors as an easy way out?
2633 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);
2634 Matrix4x4_Invert_Simple(&imatrix1, &matrix1);
2635 for (i = 0;i < 4;i++)
2636 Matrix4x4_Transform(&imatrix1, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, v[i]);
2637 if (texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE2)
2639 forward[0] = modelorg[0] - center[0];
2640 forward[1] = modelorg[1] - center[1];
2642 VectorNormalize(forward);
2643 right[0] = forward[1];
2644 right[1] = -forward[0];
2646 VectorSet(up, 0, 0, 1);
2648 for (i = 0;i < 4;i++)
2649 VectorMAMAMAM(1, center, v[i][0], forward, v[i][1], right, v[i][2], up, rsurface_array_vertex3f + (surface->num_firstvertex+i+j) * 3);
2651 rsurface_vertex3f = rsurface_array_vertex3f;
2652 rsurface_svector3f = rsurface_array_svector3f;
2653 rsurface_tvector3f = rsurface_array_tvector3f;
2654 rsurface_normal3f = rsurface_array_normal3f;
2655 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);
2657 R_Mesh_VertexPointer(rsurface_vertex3f);
2660 static void RSurf_Draw(const msurface_t *surface)
2662 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2663 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2664 GL_LockArrays(0, 0);
2667 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)
2672 RSurf_SetVertexPointer(ent, texture, surface, modelorg, lightmode >= 2, false);
2676 vec3_t ambientcolor;
2677 vec3_t diffusecolor;
2679 VectorCopy(ent->modellight_lightdir, lightdir);
2680 ambientcolor[0] = ent->modellight_ambient[0] * r * 0.5f;
2681 ambientcolor[1] = ent->modellight_ambient[1] * g * 0.5f;
2682 ambientcolor[2] = ent->modellight_ambient[2] * b * 0.5f;
2683 diffusecolor[0] = ent->modellight_diffuse[0] * r * 0.5f;
2684 diffusecolor[1] = ent->modellight_diffuse[1] * g * 0.5f;
2685 diffusecolor[2] = ent->modellight_diffuse[2] * b * 0.5f;
2686 if (VectorLength2(diffusecolor) > 0)
2688 int numverts = surface->num_vertices;
2689 v = rsurface_vertex3f + 3 * surface->num_firstvertex;
2690 c2 = rsurface_normal3f + 3 * surface->num_firstvertex;
2691 c = rsurface_array_color4f + 4 * surface->num_firstvertex;
2692 // q3-style directional shading
2693 for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
2695 if ((f = DotProduct(c2, lightdir)) > 0)
2696 VectorMA(ambientcolor, f, diffusecolor, c);
2698 VectorCopy(ambientcolor, c);
2706 rsurface_lightmapcolor4f = rsurface_array_color4f;
2710 r = ambientcolor[0];
2711 g = ambientcolor[1];
2712 b = ambientcolor[2];
2713 rsurface_lightmapcolor4f = NULL;
2716 else if (lightmode >= 1)
2718 if (surface->lightmapinfo && surface->lightmapinfo->stainsamples)
2720 for (i = 0, c = rsurface_array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
2722 if (surface->lightmapinfo->samples)
2724 const unsigned char *lm = surface->lightmapinfo->samples + (surface->groupmesh->data_lightmapoffsets + surface->num_firstvertex)[i];
2725 float scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
2726 VectorScale(lm, scale, c);
2727 if (surface->lightmapinfo->styles[1] != 255)
2729 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
2731 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
2732 VectorMA(c, scale, lm, c);
2733 if (surface->lightmapinfo->styles[2] != 255)
2736 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
2737 VectorMA(c, scale, lm, c);
2738 if (surface->lightmapinfo->styles[3] != 255)
2741 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
2742 VectorMA(c, scale, lm, c);
2750 rsurface_lightmapcolor4f = rsurface_array_color4f;
2753 rsurface_lightmapcolor4f = surface->groupmesh->data_lightmapcolor4f;
2756 rsurface_lightmapcolor4f = NULL;
2759 if (rsurface_lightmapcolor4f)
2761 for (i = 0, v = (rsurface_vertex3f + 3 * surface->num_firstvertex), c = (rsurface_lightmapcolor4f + 4 * surface->num_firstvertex), c2 = (rsurface_array_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4, c2 += 4)
2763 f = 1 - VERTEXFOGTABLE(VectorDistance(v, modelorg));
2772 for (i = 0, v = (rsurface_vertex3f + 3 * surface->num_firstvertex), c2 = (rsurface_array_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c2 += 4)
2774 f = 1 - VERTEXFOGTABLE(VectorDistance(v, modelorg));
2781 rsurface_lightmapcolor4f = rsurface_array_color4f;
2783 if (applycolor && rsurface_lightmapcolor4f)
2785 for (i = 0, c = (rsurface_lightmapcolor4f + 4 * surface->num_firstvertex), c2 = (rsurface_array_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, c += 4, c2 += 4)
2792 rsurface_lightmapcolor4f = rsurface_array_color4f;
2794 R_Mesh_ColorPointer(rsurface_lightmapcolor4f);
2795 GL_Color(r, g, b, a);
2796 RSurf_Draw(surface);
2799 static void R_DrawTextureSurfaceList(const entity_render_t *ent, texture_t *texture, int texturenumsurfaces, const msurface_t **texturesurfacelist, const vec3_t modelorg)
2801 int texturesurfaceindex;
2803 const msurface_t *surface;
2804 qboolean applycolor;
2807 if (texture->currentmaterialflags & MATERIALFLAG_NODRAW)
2809 r_shadow_rtlight = NULL;
2810 renderstats.entities_surfaces += texturenumsurfaces;
2811 // FIXME: identify models using a better check than ent->model->brush.shadowmesh
2812 lightmode = ((ent->effects & EF_FULLBRIGHT) || ent->model->brush.shadowmesh) ? 0 : 2;
2813 GL_DepthTest(!(texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
2814 if ((texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (ent->flags & RENDER_NOCULLFACE))
2815 qglDisable(GL_CULL_FACE);
2816 if (texture->currentmaterialflags & MATERIALFLAG_SKY)
2818 // transparent sky would be ridiculous
2819 if (!(texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
2823 skyrendernow = false;
2825 // restore entity matrix
2826 R_Mesh_Matrix(&ent->matrix);
2829 // LordHavoc: HalfLife maps have freaky skypolys...
2830 // LordHavoc: Quake3 never did sky masking (unlike software Quake
2831 // and Quake2), so disable the sky masking in Quake3 maps as it
2832 // causes problems with q3map2 sky tricks
2833 if (!ent->model->brush.ishlbsp && ent->model->type != mod_brushq3)
2835 GL_Color(fogcolor[0], fogcolor[1], fogcolor[2], 1);
2836 memset(&m, 0, sizeof(m));
2838 if (skyrendermasked)
2840 // depth-only (masking)
2841 GL_ColorMask(0,0,0,0);
2842 // just to make sure that braindead drivers don't draw
2843 // anything despite that colormask...
2844 GL_BlendFunc(GL_ZERO, GL_ONE);
2849 GL_BlendFunc(GL_ONE, GL_ZERO);
2851 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2853 surface = texturesurfacelist[texturesurfaceindex];
2854 RSurf_SetVertexPointer(ent, texture, surface, modelorg, false, false);
2855 RSurf_Draw(surface);
2857 if (skyrendermasked)
2858 GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
2862 else if (r_glsl.integer && gl_support_fragment_shader)
2864 if (texture->currentmaterialflags & MATERIALFLAG_ADD)
2866 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2867 GL_DepthMask(false);
2869 else if (texture->currentmaterialflags & MATERIALFLAG_ALPHA)
2871 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2872 GL_DepthMask(false);
2876 GL_BlendFunc(GL_ONE, GL_ZERO);
2880 memset(&m, 0, sizeof(m));
2882 GL_Color(ent->colormod[0], ent->colormod[1], ent->colormod[2], texture->currentalpha);
2883 R_SetupSurfaceShader(ent, texture, modelorg, vec3_origin, lightmode == 2);
2884 if (!r_glsl_permutation)
2888 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2890 surface = texturesurfacelist[texturesurfaceindex];
2891 RSurf_SetVertexPointer(ent, texture, surface, modelorg, false, true);
2892 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2893 R_Mesh_TexCoordPointer(1, 3, rsurface_svector3f);
2894 R_Mesh_TexCoordPointer(2, 3, rsurface_tvector3f);
2895 R_Mesh_TexCoordPointer(3, 3, rsurface_normal3f);
2896 RSurf_Draw(surface);
2901 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2903 surface = texturesurfacelist[texturesurfaceindex];
2904 RSurf_SetVertexPointer(ent, texture, surface, modelorg, false, true);
2905 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2906 R_Mesh_TexCoordPointer(1, 3, rsurface_svector3f);
2907 R_Mesh_TexCoordPointer(2, 3, rsurface_tvector3f);
2908 R_Mesh_TexCoordPointer(3, 3, rsurface_normal3f);
2909 R_Mesh_TexCoordPointer(4, 2, surface->groupmesh->data_texcoordlightmap2f);
2910 if (surface->lightmaptexture)
2912 R_Mesh_TexBind(7, R_GetTexture(surface->lightmaptexture));
2913 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
2914 R_Mesh_TexBind(8, R_GetTexture(surface->deluxemaptexture));
2915 R_Mesh_ColorPointer(NULL);
2919 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
2920 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
2921 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
2922 R_Mesh_ColorPointer(surface->groupmesh->data_lightmapcolor4f);
2924 RSurf_Draw(surface);
2927 qglUseProgramObjectARB(0);
2929 else if (texture->currentnumlayers)
2932 texturelayer_t *layer;
2933 for (layerindex = 0, layer = texture->currentlayers;layerindex < texture->currentnumlayers;layerindex++, layer++)
2936 int layertexrgbscale;
2937 GL_DepthMask(layer->depthmask);
2938 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
2939 if ((layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2) && (gl_combine.integer || layer->depthmask))
2941 layertexrgbscale = 4;
2942 VectorScale(layer->color, 0.25f, layercolor);
2944 else if ((layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1) && (gl_combine.integer || layer->depthmask))
2946 layertexrgbscale = 2;
2947 VectorScale(layer->color, 0.5f, layercolor);
2951 layertexrgbscale = 1;
2952 VectorScale(layer->color, 1.0f, layercolor);
2954 layercolor[3] = layer->color[3];
2955 GL_Color(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
2956 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
2957 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
2958 switch (layer->type)
2960 case TEXTURELAYERTYPE_LITTEXTURE_COMBINE:
2961 memset(&m, 0, sizeof(m));
2962 m.tex[1] = R_GetTexture(layer->texture);
2963 m.texmatrix[1] = layer->texmatrix;
2964 m.texrgbscale[1] = layertexrgbscale;
2965 m.pointer_color = rsurface_array_color4f;
2969 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2971 surface = texturesurfacelist[texturesurfaceindex];
2972 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
2973 R_Mesh_TexCoordPointer(1, 2, surface->groupmesh->data_texcoordtexture2f);
2974 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2975 RSurf_DrawLightmap(ent, texture, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 2, applycolor, applyfog);
2980 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2982 surface = texturesurfacelist[texturesurfaceindex];
2983 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
2984 R_Mesh_TexCoordPointer(1, 2, surface->groupmesh->data_texcoordtexture2f);
2985 if (surface->lightmaptexture)
2987 R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
2988 RSurf_DrawLightmap(ent, texture, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, applyfog);
2992 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2993 RSurf_DrawLightmap(ent, texture, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 1, applycolor, applyfog);
2998 case TEXTURELAYERTYPE_LITTEXTURE_MULTIPASS:
2999 memset(&m, 0, sizeof(m));
3000 m.tex[0] = R_GetTexture(layer->texture);
3001 m.texmatrix[0] = layer->texmatrix;
3002 m.pointer_color = rsurface_array_color4f;
3003 m.texrgbscale[0] = layertexrgbscale;
3007 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3009 surface = texturesurfacelist[texturesurfaceindex];
3010 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
3011 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
3012 RSurf_DrawLightmap(ent, texture, surface, modelorg, 1, 1, 1, 1, 2, false, false);
3017 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3019 surface = texturesurfacelist[texturesurfaceindex];
3020 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
3021 if (surface->lightmaptexture)
3023 R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
3024 RSurf_DrawLightmap(ent, texture, surface, modelorg, 1, 1, 1, 1, 0, false, false);
3028 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
3029 RSurf_DrawLightmap(ent, texture, surface, modelorg, 1, 1, 1, 1, 1, false, false);
3033 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
3034 memset(&m, 0, sizeof(m));
3035 m.tex[0] = R_GetTexture(layer->texture);
3036 m.texmatrix[0] = layer->texmatrix;
3037 m.pointer_color = rsurface_array_color4f;
3038 m.texrgbscale[0] = layertexrgbscale;
3040 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3042 surface = texturesurfacelist[texturesurfaceindex];
3043 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
3044 RSurf_DrawLightmap(ent, texture, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, applyfog);
3047 case TEXTURELAYERTYPE_LITTEXTURE_VERTEX:
3048 memset(&m, 0, sizeof(m));
3049 m.tex[0] = R_GetTexture(layer->texture);
3050 m.texmatrix[0] = layer->texmatrix;
3051 m.texrgbscale[0] = layertexrgbscale;
3052 m.pointer_color = rsurface_array_color4f;
3056 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3058 surface = texturesurfacelist[texturesurfaceindex];
3059 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
3060 RSurf_DrawLightmap(ent, texture, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 2, applycolor, applyfog);
3065 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3067 surface = texturesurfacelist[texturesurfaceindex];
3068 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
3069 RSurf_DrawLightmap(ent, texture, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 1, applycolor, applyfog);
3073 case TEXTURELAYERTYPE_TEXTURE:
3074 memset(&m, 0, sizeof(m));
3075 m.tex[0] = R_GetTexture(layer->texture);
3076 m.texmatrix[0] = layer->texmatrix;
3077 m.pointer_color = rsurface_array_color4f;
3078 m.texrgbscale[0] = layertexrgbscale;
3080 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3082 surface = texturesurfacelist[texturesurfaceindex];
3083 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
3084 RSurf_DrawLightmap(ent, texture, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, applyfog);
3087 case TEXTURELAYERTYPE_FOG:
3088 memset(&m, 0, sizeof(m));
3091 m.tex[0] = R_GetTexture(layer->texture);
3092 m.texmatrix[0] = layer->texmatrix;
3095 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3099 surface = texturesurfacelist[texturesurfaceindex];
3100 RSurf_SetVertexPointer(ent, texture, surface, modelorg, false, false);
3102 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
3103 R_Mesh_ColorPointer(rsurface_array_color4f);
3104 for (i = 0, v = (rsurface_vertex3f + 3 * surface->num_firstvertex), c = (rsurface_array_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4)
3106 f = VERTEXFOGTABLE(VectorDistance(v, modelorg));
3107 c[0] = layercolor[0];
3108 c[1] = layercolor[1];
3109 c[2] = layercolor[2];
3110 c[3] = f * layercolor[3];
3112 RSurf_Draw(surface);
3116 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
3118 // if trying to do overbright on first pass of an opaque surface
3119 // when combine is not supported, brighten as a post process
3120 if (layertexrgbscale > 1 && !gl_combine.integer && layer->depthmask)
3123 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
3124 GL_Color(1, 1, 1, 1);
3125 memset(&m, 0, sizeof(m));
3127 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3129 surface = texturesurfacelist[texturesurfaceindex];
3130 RSurf_SetVertexPointer(ent, texture, surface, modelorg, false, false);
3131 for (scale = 1;scale < layertexrgbscale;scale <<= 1)
3132 RSurf_Draw(surface);
3137 if ((texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (ent->flags & RENDER_NOCULLFACE))
3138 qglEnable(GL_CULL_FACE);
3141 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight)
3143 const msurface_t *surface = ent->model->data_surfaces + surfacenumber;
3147 texture = surface->texture;
3148 if (texture->basematerialflags & MATERIALFLAG_SKY)
3149 return; // transparent sky is too difficult
3150 R_UpdateTextureInfo(ent, texture);
3152 R_Mesh_Matrix(&ent->matrix);
3153 Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
3154 R_DrawTextureSurfaceList(ent, texture->currentframe, 1, &surface, modelorg);
3157 void R_QueueTextureSurfaceList(entity_render_t *ent, texture_t *texture, int texturenumsurfaces, const msurface_t **texturesurfacelist, const vec3_t modelorg)
3159 int texturesurfaceindex;
3160 const msurface_t *surface;
3161 vec3_t tempcenter, center;
3162 if (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT)
3164 // drawing sky transparently would be too difficult
3165 if (!(texture->currentmaterialflags & MATERIALFLAG_SKY))
3167 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3169 surface = texturesurfacelist[texturesurfaceindex];
3170 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
3171 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
3172 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
3173 Matrix4x4_Transform(&ent->matrix, tempcenter, center);
3174 R_MeshQueue_AddTransparent(texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_vieworigin : center, R_DrawSurface_TransparentCallback, ent, surface - ent->model->data_surfaces, r_shadow_rtlight);
3179 R_DrawTextureSurfaceList(ent, texture, texturenumsurfaces, texturesurfacelist, modelorg);
3182 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
3183 void R_DrawSurfaces(entity_render_t *ent, qboolean skysurfaces)
3185 int i, j, f, flagsmask;
3186 int counttriangles = 0;
3187 msurface_t *surface, **surfacechain;
3188 texture_t *t, *texture;
3189 model_t *model = ent->model;
3191 const int maxsurfacelist = 1024;
3192 int numsurfacelist = 0;
3193 const msurface_t *surfacelist[1024];
3196 R_Mesh_Matrix(&ent->matrix);
3197 Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
3199 // update light styles
3200 if (!skysurfaces && model->brushq1.light_styleupdatechains)
3202 for (i = 0;i < model->brushq1.light_styles;i++)
3204 if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
3206 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
3207 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
3208 for (;(surface = *surfacechain);surfacechain++)
3209 surface->cached_dlight = true;
3214 R_UpdateAllTextureInfo(ent);
3215 flagsmask = skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL);
3220 if (r_showsurfaces.integer)
3225 GL_BlendFunc(GL_ONE, GL_ZERO);
3226 memset(&m, 0, sizeof(m));
3228 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
3230 if (ent == r_refdef.worldentity && !r_worldsurfacevisible[j])
3232 texture = surface->texture->currentframe;
3233 if ((texture->currentmaterialflags & flagsmask) && surface->num_triangles)
3235 int k = (int)(((size_t)surface) / sizeof(msurface_t));
3236 GL_Color((k & 15) * (1.0f / 16.0f), ((k >> 4) & 15) * (1.0f / 16.0f), ((k >> 8) & 15) * (1.0f / 16.0f), 0.2f);
3237 RSurf_SetVertexPointer(ent, texture, surface, modelorg, false, false);
3238 RSurf_Draw(surface);
3239 renderstats.entities_triangles += surface->num_triangles;
3241 renderstats.entities_surfaces++;
3244 else if (ent == r_refdef.worldentity)
3246 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
3248 if (!r_worldsurfacevisible[j])
3250 if (t != surface->texture)
3254 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
3257 t = surface->texture;
3258 texture = t->currentframe;
3259 f = texture->currentmaterialflags & flagsmask;
3261 if (f && surface->num_triangles)
3263 // if lightmap parameters changed, rebuild lightmap texture
3264 if (surface->cached_dlight)
3265 R_BuildLightMap(ent, surface);
3266 // add face to draw list
3267 surfacelist[numsurfacelist++] = surface;
3268 counttriangles += surface->num_triangles;
3269 if (numsurfacelist >= maxsurfacelist)
3271 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
3279 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
3281 if (t != surface->texture)
3285 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
3288 t = surface->texture;
3289 texture = t->currentframe;
3290 f = texture->currentmaterialflags & flagsmask;
3292 if (f && surface->num_triangles)
3294 // if lightmap parameters changed, rebuild lightmap texture
3295 if (surface->cached_dlight)
3296 R_BuildLightMap(ent, surface);
3297 // add face to draw list
3298 surfacelist[numsurfacelist++] = surface;
3299 counttriangles += surface->num_triangles;
3300 if (numsurfacelist >= maxsurfacelist)
3302 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
3309 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
3310 renderstats.entities_triangles += counttriangles;
3311 if (gl_support_fragment_shader)
3312 qglUseProgramObjectARB(0);
3314 if (r_showcollisionbrushes.integer && model->brush.num_brushes && !skysurfaces)
3317 msurface_t *surface;
3319 R_Mesh_Matrix(&ent->matrix);
3320 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
3321 GL_DepthMask(false);
3322 GL_DepthTest(!r_showdisabledepthtest.integer);
3323 qglPolygonOffset(r_polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_polygonoffset + r_showcollisionbrushes_polygonoffset.value);
3324 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
3325 if (brush->colbrushf && brush->colbrushf->numtriangles)
3326 R_DrawCollisionBrush(brush->colbrushf);
3327 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
3328 if (surface->num_collisiontriangles)
3329 R_DrawCollisionSurface(ent, surface);
3330 qglPolygonOffset(r_polygonfactor, r_polygonoffset);
3333 if (r_showtris.integer || r_shownormals.integer)
3336 const int *elements;
3341 if (r_showdisabledepthtest.integer)
3342 qglDepthFunc(GL_ALWAYS);
3343 GL_BlendFunc(GL_ONE, GL_ZERO);
3344 memset(&m, 0, sizeof(m));
3346 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
3348 if (ent == r_refdef.worldentity && !r_worldsurfacevisible[j])
3350 texture = surface->texture->currentframe;
3351 if ((texture->currentmaterialflags & flagsmask) && surface->num_triangles)
3353 RSurf_SetVertexPointer(ent, texture, surface, modelorg, false, r_shownormals.integer != 0);
3354 if (r_showtris.integer)
3356 if (!texture->currentlayers->depthmask)
3357 GL_Color(r_showtris.value, 0, 0, 1);
3358 else if (ent == r_refdef.worldentity)
3359 GL_Color(r_showtris.value, r_showtris.value, r_showtris.value, 1);
3361 GL_Color(0, r_showtris.value, 0, 1);
3362 elements = (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle);
3364 for (k = 0;k < surface->num_triangles;k++, elements += 3)
3366 qglArrayElement(elements[0]);qglArrayElement(elements[1]);
3367 qglArrayElement(elements[1]);qglArrayElement(elements[2]);
3368 qglArrayElement(elements[2]);qglArrayElement(elements[0]);
3372 if (r_shownormals.integer)
3374 GL_Color(r_shownormals.value, 0, 0, 1);
3376 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
3378 VectorCopy(rsurface_vertex3f + l * 3, v);
3379 qglVertex3f(v[0], v[1], v[2]);
3380 VectorMA(v, 8, rsurface_svector3f + l * 3, v);
3381 qglVertex3f(v[0], v[1], v[2]);
3384 GL_Color(0, 0, r_shownormals.value, 1);
3386 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
3388 VectorCopy(rsurface_vertex3f + l * 3, v);
3389 qglVertex3f(v[0], v[1], v[2]);
3390 VectorMA(v, 8, rsurface_tvector3f + l * 3, v);
3391 qglVertex3f(v[0], v[1], v[2]);
3394 GL_Color(0, r_shownormals.value, 0, 1);
3396 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
3398 VectorCopy(rsurface_vertex3f + l * 3, v);
3399 qglVertex3f(v[0], v[1], v[2]);
3400 VectorMA(v, 8, rsurface_normal3f + l * 3, v);
3401 qglVertex3f(v[0], v[1], v[2]);
3407 if (r_showdisabledepthtest.integer)
3408 qglDepthFunc(GL_LEQUAL);