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;
2581 qboolean rsurface_generatevertex;
2582 qboolean rsurface_generatetangents;
2583 qboolean rsurface_generatenormals;
2584 qboolean rsurface_deformvertex;
2585 qboolean rsurface_dynamicvertex;
2586 vec3_t rsurface_modelorg;
2587 const entity_render_t *rsurface_entity;
2588 const model_t *rsurface_model;
2589 const texture_t *rsurface_texture;
2591 void RSurf_PrepareForBatch(const entity_render_t *ent, const texture_t *texture, const vec3_t modelorg)
2593 VectorCopy(modelorg, rsurface_modelorg);
2594 rsurface_entity = ent;
2595 rsurface_model = ent->model;
2596 rsurface_texture = texture;
2599 void RSurf_SetPointersForPass(qboolean generatenormals, qboolean generatetangents)
2601 if (rsurface_array_size < rsurface_model->surfmesh.num_vertices)
2602 R_Mesh_ResizeArrays(rsurface_model->surfmesh.num_vertices);
2603 if ((rsurface_entity->frameblend[0].lerp != 1 || rsurface_entity->frameblend[0].frame != 0) && (rsurface_model->surfmesh.data_morphvertex3f || rsurface_model->surfmesh.data_vertexboneweights))
2605 rsurface_generatevertex = true;
2606 rsurface_generatetangents = false;
2607 rsurface_generatenormals = false;
2608 rsurface_vertex3f = rsurface_array_vertex3f;
2609 if (generatetangents || (rsurface_texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2)))
2611 rsurface_generatetangents = true;
2612 rsurface_svector3f = rsurface_array_svector3f;
2613 rsurface_tvector3f = rsurface_array_tvector3f;
2614 rsurface_normal3f = rsurface_array_normal3f;
2618 rsurface_svector3f = NULL;
2619 rsurface_tvector3f = NULL;
2620 if (generatenormals)
2622 rsurface_generatenormals = true;
2623 rsurface_normal3f = rsurface_array_normal3f;
2626 rsurface_normal3f = NULL;
2631 rsurface_generatevertex = false;
2632 rsurface_generatetangents = false;
2633 rsurface_generatenormals = false;
2634 rsurface_vertex3f = rsurface_model->surfmesh.data_vertex3f;
2635 rsurface_svector3f = rsurface_model->surfmesh.data_svector3f;
2636 rsurface_tvector3f = rsurface_model->surfmesh.data_tvector3f;
2637 rsurface_normal3f = rsurface_model->surfmesh.data_normal3f;
2639 if (rsurface_texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
2641 rsurface_deformvertex = true;
2642 rsurface_vertex3f = rsurface_array_vertex3f;
2643 rsurface_svector3f = rsurface_array_svector3f;
2644 rsurface_tvector3f = rsurface_array_tvector3f;
2645 rsurface_normal3f = rsurface_array_normal3f;
2648 rsurface_deformvertex = false;
2649 R_Mesh_VertexPointer(rsurface_vertex3f);
2650 rsurface_dynamicvertex = rsurface_generatevertex || rsurface_deformvertex;
2653 void RSurf_PrepareDynamicSurfaceVertices(const msurface_t *surface)
2655 float *vertex3f, *svector3f, *tvector3f, *normal3f;
2656 model_t *model = rsurface_entity->model;
2657 if (!rsurface_dynamicvertex)
2659 if (rsurface_generatevertex)
2661 Mod_Alias_GetMesh_Vertex3f(model, rsurface_entity->frameblend, rsurface_array_vertex3f);
2662 if (rsurface_generatetangents)
2663 Mod_BuildTextureVectorsAndNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface_vertex3f, model->surfmesh.data_texcoordtexture2f, model->surfmesh.data_element3i + surface->num_firsttriangle * 3, rsurface_array_svector3f, rsurface_array_tvector3f, rsurface_array_normal3f, r_smoothnormals_areaweighting.integer);
2664 else if (rsurface_generatenormals)
2665 Mod_BuildNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface_array_vertex3f, model->surfmesh.data_element3i + 3 * surface->num_firsttriangle, rsurface_array_normal3f, r_smoothnormals_areaweighting.integer);
2667 if (rsurface_deformvertex)
2670 float center[3], forward[3], right[3], up[3], v[4][3];
2671 matrix4x4_t matrix1, imatrix1;
2672 if (rsurface_generatevertex)
2674 vertex3f = rsurface_array_vertex3f;
2675 svector3f = rsurface_array_svector3f;
2676 tvector3f = rsurface_array_tvector3f;
2677 normal3f = rsurface_array_normal3f;
2681 vertex3f = rsurface_vertex3f;
2682 svector3f = rsurface_svector3f;
2683 tvector3f = rsurface_tvector3f;
2684 normal3f = rsurface_normal3f;
2686 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_viewforward, forward);
2687 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_viewright, right);
2688 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_viewup, up);
2689 // a single autosprite surface can contain multiple sprites...
2690 for (j = 0;j < surface->num_vertices - 3;j += 4)
2692 VectorClear(center);
2693 for (i = 0;i < 4;i++)
2694 VectorAdd(center, (vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
2695 VectorScale(center, 0.25f, center);
2696 // FIXME: calculate vectors from triangle edges instead of using texture vectors as an easy way out?
2697 Matrix4x4_FromVectors(&matrix1, (normal3f + 3 * surface->num_firstvertex) + j*3, (svector3f + 3 * surface->num_firstvertex) + j*3, (tvector3f + 3 * surface->num_firstvertex) + j*3, center);
2698 Matrix4x4_Invert_Simple(&imatrix1, &matrix1);
2699 for (i = 0;i < 4;i++)
2700 Matrix4x4_Transform(&imatrix1, (vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, v[i]);
2701 if (rsurface_texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE2)
2703 forward[0] = rsurface_modelorg[0] - center[0];
2704 forward[1] = rsurface_modelorg[1] - center[1];
2706 VectorNormalize(forward);
2707 right[0] = forward[1];
2708 right[1] = -forward[0];
2710 VectorSet(up, 0, 0, 1);
2712 for (i = 0;i < 4;i++)
2713 VectorMAMAMAM(1, center, v[i][0], forward, v[i][1], right, v[i][2], up, rsurface_array_vertex3f + (surface->num_firstvertex+i+j) * 3);
2715 Mod_BuildTextureVectorsAndNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface_array_vertex3f, model->surfmesh.data_texcoordtexture2f, model->surfmesh.data_element3i + surface->num_firsttriangle * 3, rsurface_array_svector3f, rsurface_array_tvector3f, rsurface_array_normal3f, r_smoothnormals_areaweighting.integer);
2719 static void RSurf_Draw(const msurface_t *surface)
2721 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2722 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
2723 GL_LockArrays(0, 0);
2726 static void RSurf_DrawLightmap(const msurface_t *surface, float r, float g, float b, float a, int lightmode, qboolean applycolor, qboolean applyfog)
2734 vec3_t ambientcolor;
2735 vec3_t diffusecolor;
2737 VectorCopy(rsurface_entity->modellight_lightdir, lightdir);
2738 ambientcolor[0] = rsurface_entity->modellight_ambient[0] * r * 0.5f;
2739 ambientcolor[1] = rsurface_entity->modellight_ambient[1] * g * 0.5f;
2740 ambientcolor[2] = rsurface_entity->modellight_ambient[2] * b * 0.5f;
2741 diffusecolor[0] = rsurface_entity->modellight_diffuse[0] * r * 0.5f;
2742 diffusecolor[1] = rsurface_entity->modellight_diffuse[1] * g * 0.5f;
2743 diffusecolor[2] = rsurface_entity->modellight_diffuse[2] * b * 0.5f;
2744 if (VectorLength2(diffusecolor) > 0)
2746 int numverts = surface->num_vertices;
2747 v = rsurface_vertex3f + 3 * surface->num_firstvertex;
2748 c2 = rsurface_normal3f + 3 * surface->num_firstvertex;
2749 c = rsurface_array_color4f + 4 * surface->num_firstvertex;
2750 // q3-style directional shading
2751 for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
2753 if ((f = DotProduct(c2, lightdir)) > 0)
2754 VectorMA(ambientcolor, f, diffusecolor, c);
2756 VectorCopy(ambientcolor, c);
2764 rsurface_lightmapcolor4f = rsurface_array_color4f;
2768 r = ambientcolor[0];
2769 g = ambientcolor[1];
2770 b = ambientcolor[2];
2771 rsurface_lightmapcolor4f = NULL;
2774 else if (lightmode >= 1)
2776 if (surface->lightmapinfo && surface->lightmapinfo->stainsamples)
2778 for (i = 0, c = rsurface_array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
2780 if (surface->lightmapinfo->samples)
2782 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface_model->surfmesh.data_lightmapoffsets + surface->num_firstvertex)[i];
2783 float scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
2784 VectorScale(lm, scale, c);
2785 if (surface->lightmapinfo->styles[1] != 255)
2787 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
2789 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
2790 VectorMA(c, scale, lm, c);
2791 if (surface->lightmapinfo->styles[2] != 255)
2794 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
2795 VectorMA(c, scale, lm, c);
2796 if (surface->lightmapinfo->styles[3] != 255)
2799 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
2800 VectorMA(c, scale, lm, c);
2808 rsurface_lightmapcolor4f = rsurface_array_color4f;
2811 rsurface_lightmapcolor4f = rsurface_model->surfmesh.data_lightmapcolor4f;
2814 rsurface_lightmapcolor4f = NULL;
2817 if (rsurface_lightmapcolor4f)
2819 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)
2821 f = 1 - VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
2830 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)
2832 f = 1 - VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
2839 rsurface_lightmapcolor4f = rsurface_array_color4f;
2841 if (applycolor && rsurface_lightmapcolor4f)
2843 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)
2850 rsurface_lightmapcolor4f = rsurface_array_color4f;
2852 R_Mesh_ColorPointer(rsurface_lightmapcolor4f);
2853 GL_Color(r, g, b, a);
2854 RSurf_Draw(surface);
2857 static void R_DrawTextureSurfaceList(const entity_render_t *ent, texture_t *texture, int texturenumsurfaces, const msurface_t **texturesurfacelist, const vec3_t modelorg)
2859 int texturesurfaceindex;
2861 const msurface_t *surface;
2862 model_t *model = ent->model;
2863 qboolean applycolor;
2866 if (texture->currentmaterialflags & MATERIALFLAG_NODRAW)
2868 r_shadow_rtlight = NULL;
2869 renderstats.entities_surfaces += texturenumsurfaces;
2870 // FIXME: identify models using a better check than model->brush.shadowmesh
2871 lightmode = ((ent->effects & EF_FULLBRIGHT) || model->brush.shadowmesh) ? 0 : 2;
2872 GL_DepthTest(!(texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
2873 if ((texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (ent->flags & RENDER_NOCULLFACE))
2874 qglDisable(GL_CULL_FACE);
2875 RSurf_PrepareForBatch(ent, texture, modelorg);
2876 if (texture->currentmaterialflags & MATERIALFLAG_SKY)
2878 // transparent sky would be ridiculous
2879 if (!(texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
2883 skyrendernow = false;
2885 // restore entity matrix
2886 R_Mesh_Matrix(&ent->matrix);
2889 // LordHavoc: HalfLife maps have freaky skypolys...
2890 // LordHavoc: Quake3 never did sky masking (unlike software Quake
2891 // and Quake2), so disable the sky masking in Quake3 maps as it
2892 // causes problems with q3map2 sky tricks
2893 if (!model->brush.ishlbsp && model->type != mod_brushq3)
2895 GL_Color(fogcolor[0], fogcolor[1], fogcolor[2], 1);
2896 memset(&m, 0, sizeof(m));
2898 if (skyrendermasked)
2900 // depth-only (masking)
2901 GL_ColorMask(0,0,0,0);
2902 // just to make sure that braindead drivers don't draw
2903 // anything despite that colormask...
2904 GL_BlendFunc(GL_ZERO, GL_ONE);
2909 GL_BlendFunc(GL_ONE, GL_ZERO);
2911 RSurf_SetPointersForPass(false, false);
2912 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2914 surface = texturesurfacelist[texturesurfaceindex];
2915 if (rsurface_dynamicvertex)
2916 RSurf_PrepareDynamicSurfaceVertices(surface);
2917 RSurf_Draw(surface);
2919 if (skyrendermasked)
2920 GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
2924 else if (r_glsl.integer && gl_support_fragment_shader)
2926 if (texture->currentmaterialflags & MATERIALFLAG_ADD)
2928 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2929 GL_DepthMask(false);
2931 else if (texture->currentmaterialflags & MATERIALFLAG_ALPHA)
2933 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2934 GL_DepthMask(false);
2938 GL_BlendFunc(GL_ONE, GL_ZERO);
2942 memset(&m, 0, sizeof(m));
2944 GL_Color(ent->colormod[0], ent->colormod[1], ent->colormod[2], texture->currentalpha);
2945 R_SetupSurfaceShader(ent, texture, modelorg, vec3_origin, lightmode == 2);
2946 if (!r_glsl_permutation)
2948 RSurf_SetPointersForPass(false, true);
2951 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2953 surface = texturesurfacelist[texturesurfaceindex];
2954 if (rsurface_dynamicvertex)
2955 RSurf_PrepareDynamicSurfaceVertices(surface);
2956 R_Mesh_TexCoordPointer(0, 2, model->surfmesh.data_texcoordtexture2f);
2957 R_Mesh_TexCoordPointer(1, 3, rsurface_svector3f);
2958 R_Mesh_TexCoordPointer(2, 3, rsurface_tvector3f);
2959 R_Mesh_TexCoordPointer(3, 3, rsurface_normal3f);
2960 RSurf_Draw(surface);
2965 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2967 surface = texturesurfacelist[texturesurfaceindex];
2968 if (rsurface_dynamicvertex)
2969 RSurf_PrepareDynamicSurfaceVertices(surface);
2970 R_Mesh_TexCoordPointer(0, 2, model->surfmesh.data_texcoordtexture2f);
2971 R_Mesh_TexCoordPointer(1, 3, rsurface_svector3f);
2972 R_Mesh_TexCoordPointer(2, 3, rsurface_tvector3f);
2973 R_Mesh_TexCoordPointer(3, 3, rsurface_normal3f);
2974 R_Mesh_TexCoordPointer(4, 2, model->surfmesh.data_texcoordlightmap2f);
2975 if (surface->lightmaptexture)
2977 R_Mesh_TexBind(7, R_GetTexture(surface->lightmaptexture));
2978 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
2979 R_Mesh_TexBind(8, R_GetTexture(surface->deluxemaptexture));
2980 R_Mesh_ColorPointer(NULL);
2984 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
2985 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
2986 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
2987 R_Mesh_ColorPointer(model->surfmesh.data_lightmapcolor4f);
2989 RSurf_Draw(surface);
2992 qglUseProgramObjectARB(0);
2994 else if (texture->currentnumlayers)
2997 texturelayer_t *layer;
2998 for (layerindex = 0, layer = texture->currentlayers;layerindex < texture->currentnumlayers;layerindex++, layer++)
3001 int layertexrgbscale;
3002 GL_DepthMask(layer->depthmask);
3003 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
3004 if ((layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2) && (gl_combine.integer || layer->depthmask))
3006 layertexrgbscale = 4;
3007 VectorScale(layer->color, 0.25f, layercolor);
3009 else if ((layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1) && (gl_combine.integer || layer->depthmask))
3011 layertexrgbscale = 2;
3012 VectorScale(layer->color, 0.5f, layercolor);
3016 layertexrgbscale = 1;
3017 VectorScale(layer->color, 1.0f, layercolor);
3019 layercolor[3] = layer->color[3];
3020 GL_Color(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
3021 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
3022 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
3023 switch (layer->type)
3025 case TEXTURELAYERTYPE_LITTEXTURE_COMBINE:
3026 memset(&m, 0, sizeof(m));
3027 m.tex[1] = R_GetTexture(layer->texture);
3028 m.texmatrix[1] = layer->texmatrix;
3029 m.texrgbscale[1] = layertexrgbscale;
3030 m.pointer_color = rsurface_array_color4f;
3032 RSurf_SetPointersForPass(lightmode == 2, false);
3035 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3037 surface = texturesurfacelist[texturesurfaceindex];
3038 R_Mesh_TexCoordPointer(0, 2, model->surfmesh.data_texcoordlightmap2f);
3039 R_Mesh_TexCoordPointer(1, 2, model->surfmesh.data_texcoordtexture2f);
3040 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
3041 if (rsurface_dynamicvertex)
3042 RSurf_PrepareDynamicSurfaceVertices(surface);
3043 RSurf_DrawLightmap(surface, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 2, applycolor, applyfog);
3048 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3050 surface = texturesurfacelist[texturesurfaceindex];
3051 R_Mesh_TexCoordPointer(0, 2, model->surfmesh.data_texcoordlightmap2f);
3052 R_Mesh_TexCoordPointer(1, 2, model->surfmesh.data_texcoordtexture2f);
3053 if (rsurface_dynamicvertex)
3054 RSurf_PrepareDynamicSurfaceVertices(surface);
3055 if (surface->lightmaptexture)
3057 R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
3058 RSurf_DrawLightmap(surface, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, applyfog);
3062 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
3063 RSurf_DrawLightmap(surface, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 1, applycolor, applyfog);
3068 case TEXTURELAYERTYPE_LITTEXTURE_MULTIPASS:
3069 memset(&m, 0, sizeof(m));
3070 m.tex[0] = R_GetTexture(layer->texture);
3071 m.texmatrix[0] = layer->texmatrix;
3072 m.pointer_color = rsurface_array_color4f;
3073 m.texrgbscale[0] = layertexrgbscale;
3075 RSurf_SetPointersForPass(lightmode == 2, false);
3078 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3080 surface = texturesurfacelist[texturesurfaceindex];
3081 R_Mesh_TexCoordPointer(0, 2, model->surfmesh.data_texcoordlightmap2f);
3082 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
3083 if (rsurface_dynamicvertex)
3084 RSurf_PrepareDynamicSurfaceVertices(surface);
3085 RSurf_DrawLightmap(surface, 1, 1, 1, 1, 2, false, false);
3090 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3092 surface = texturesurfacelist[texturesurfaceindex];
3093 R_Mesh_TexCoordPointer(0, 2, model->surfmesh.data_texcoordlightmap2f);
3094 if (rsurface_dynamicvertex)
3095 RSurf_PrepareDynamicSurfaceVertices(surface);
3096 if (surface->lightmaptexture)
3098 R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
3099 RSurf_DrawLightmap(surface, 1, 1, 1, 1, 0, false, false);
3103 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
3104 RSurf_DrawLightmap(surface, 1, 1, 1, 1, 1, false, false);
3108 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
3109 memset(&m, 0, sizeof(m));
3110 m.tex[0] = R_GetTexture(layer->texture);
3111 m.texmatrix[0] = layer->texmatrix;
3112 m.pointer_color = rsurface_array_color4f;
3113 m.texrgbscale[0] = layertexrgbscale;
3115 RSurf_SetPointersForPass(false, false);
3116 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3118 surface = texturesurfacelist[texturesurfaceindex];
3119 R_Mesh_TexCoordPointer(0, 2, model->surfmesh.data_texcoordtexture2f);
3120 if (rsurface_dynamicvertex)
3121 RSurf_PrepareDynamicSurfaceVertices(surface);
3122 RSurf_DrawLightmap(surface, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, false);
3125 case TEXTURELAYERTYPE_LITTEXTURE_VERTEX:
3126 memset(&m, 0, sizeof(m));
3127 m.tex[0] = R_GetTexture(layer->texture);
3128 m.texmatrix[0] = layer->texmatrix;
3129 m.texrgbscale[0] = layertexrgbscale;
3130 m.pointer_color = rsurface_array_color4f;
3132 RSurf_SetPointersForPass(lightmode == 2, false);
3135 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3137 surface = texturesurfacelist[texturesurfaceindex];
3138 R_Mesh_TexCoordPointer(0, 2, model->surfmesh.data_texcoordtexture2f);
3139 if (rsurface_dynamicvertex)
3140 RSurf_PrepareDynamicSurfaceVertices(surface);
3141 RSurf_DrawLightmap(surface, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 2, applycolor, applyfog);
3146 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3148 surface = texturesurfacelist[texturesurfaceindex];
3149 R_Mesh_TexCoordPointer(0, 2, model->surfmesh.data_texcoordtexture2f);
3150 if (rsurface_dynamicvertex)
3151 RSurf_PrepareDynamicSurfaceVertices(surface);
3152 RSurf_DrawLightmap(surface, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 1, applycolor, applyfog);
3156 case TEXTURELAYERTYPE_TEXTURE:
3157 memset(&m, 0, sizeof(m));
3158 m.tex[0] = R_GetTexture(layer->texture);
3159 m.texmatrix[0] = layer->texmatrix;
3160 m.pointer_color = rsurface_array_color4f;
3161 m.texrgbscale[0] = layertexrgbscale;
3163 RSurf_SetPointersForPass(false, false);
3164 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3166 surface = texturesurfacelist[texturesurfaceindex];
3167 R_Mesh_TexCoordPointer(0, 2, model->surfmesh.data_texcoordtexture2f);
3168 if (rsurface_dynamicvertex)
3169 RSurf_PrepareDynamicSurfaceVertices(surface);
3170 RSurf_DrawLightmap(surface, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, applyfog);
3173 case TEXTURELAYERTYPE_FOG:
3174 memset(&m, 0, sizeof(m));
3177 m.tex[0] = R_GetTexture(layer->texture);
3178 m.texmatrix[0] = layer->texmatrix;
3181 RSurf_SetPointersForPass(false, false);
3182 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3186 surface = texturesurfacelist[texturesurfaceindex];
3188 R_Mesh_TexCoordPointer(0, 2, model->surfmesh.data_texcoordtexture2f);
3189 R_Mesh_ColorPointer(rsurface_array_color4f);
3190 if (rsurface_dynamicvertex)
3191 RSurf_PrepareDynamicSurfaceVertices(surface);
3192 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)
3194 f = VERTEXFOGTABLE(VectorDistance(v, modelorg));
3195 c[0] = layercolor[0];
3196 c[1] = layercolor[1];
3197 c[2] = layercolor[2];
3198 c[3] = f * layercolor[3];
3200 RSurf_Draw(surface);
3204 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
3206 // if trying to do overbright on first pass of an opaque surface
3207 // when combine is not supported, brighten as a post process
3208 if (layertexrgbscale > 1 && !gl_combine.integer && layer->depthmask)
3211 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
3212 GL_Color(1, 1, 1, 1);
3213 memset(&m, 0, sizeof(m));
3215 RSurf_SetPointersForPass(false, false);
3216 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3218 surface = texturesurfacelist[texturesurfaceindex];
3219 if (rsurface_dynamicvertex)
3220 RSurf_PrepareDynamicSurfaceVertices(surface);
3221 for (scale = 1;scale < layertexrgbscale;scale <<= 1)
3222 RSurf_Draw(surface);
3227 if ((texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (ent->flags & RENDER_NOCULLFACE))
3228 qglEnable(GL_CULL_FACE);
3231 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight)
3233 const msurface_t *surface = ent->model->data_surfaces + surfacenumber;
3237 texture = surface->texture;
3238 if (texture->basematerialflags & MATERIALFLAG_SKY)
3239 return; // transparent sky is too difficult
3240 R_UpdateTextureInfo(ent, texture);
3242 R_Mesh_Matrix(&ent->matrix);
3243 Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
3244 R_DrawTextureSurfaceList(ent, texture->currentframe, 1, &surface, modelorg);
3247 void R_QueueTextureSurfaceList(entity_render_t *ent, texture_t *texture, int texturenumsurfaces, const msurface_t **texturesurfacelist, const vec3_t modelorg)
3249 int texturesurfaceindex;
3250 const msurface_t *surface;
3251 vec3_t tempcenter, center;
3252 if (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT)
3254 // drawing sky transparently would be too difficult
3255 if (!(texture->currentmaterialflags & MATERIALFLAG_SKY))
3257 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3259 surface = texturesurfacelist[texturesurfaceindex];
3260 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
3261 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
3262 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
3263 Matrix4x4_Transform(&ent->matrix, tempcenter, center);
3264 R_MeshQueue_AddTransparent(texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_vieworigin : center, R_DrawSurface_TransparentCallback, ent, surface - ent->model->data_surfaces, r_shadow_rtlight);
3269 R_DrawTextureSurfaceList(ent, texture, texturenumsurfaces, texturesurfacelist, modelorg);
3272 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
3273 void R_DrawSurfaces(entity_render_t *ent, qboolean skysurfaces)
3275 int i, j, f, flagsmask;
3276 int counttriangles = 0;
3277 msurface_t *surface, **surfacechain;
3278 texture_t *t, *texture;
3279 model_t *model = ent->model;
3281 const int maxsurfacelist = 1024;
3282 int numsurfacelist = 0;
3283 const msurface_t *surfacelist[1024];
3286 R_Mesh_Matrix(&ent->matrix);
3287 Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
3289 // update light styles
3290 if (!skysurfaces && model->brushq1.light_styleupdatechains)
3292 for (i = 0;i < model->brushq1.light_styles;i++)
3294 if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
3296 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
3297 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
3298 for (;(surface = *surfacechain);surfacechain++)
3299 surface->cached_dlight = true;
3304 R_UpdateAllTextureInfo(ent);
3305 flagsmask = skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL);
3310 if (r_showsurfaces.integer)
3315 GL_BlendFunc(GL_ONE, GL_ZERO);
3316 memset(&m, 0, sizeof(m));
3319 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
3321 if (ent == r_refdef.worldentity && !r_worldsurfacevisible[j])
3323 if (t != surface->texture)
3325 t = surface->texture;
3326 texture = t->currentframe;
3327 RSurf_PrepareForBatch(ent, texture, modelorg);
3328 RSurf_SetPointersForPass(false, false);
3330 if ((texture->currentmaterialflags & flagsmask) && surface->num_triangles)
3332 int k = (int)(((size_t)surface) / sizeof(msurface_t));
3333 GL_Color((k & 15) * (1.0f / 16.0f), ((k >> 4) & 15) * (1.0f / 16.0f), ((k >> 8) & 15) * (1.0f / 16.0f), 0.2f);
3334 if (rsurface_dynamicvertex)
3335 RSurf_PrepareDynamicSurfaceVertices(surface);
3336 RSurf_Draw(surface);
3337 renderstats.entities_triangles += surface->num_triangles;
3339 renderstats.entities_surfaces++;
3342 else if (ent == r_refdef.worldentity)
3344 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
3346 if (!r_worldsurfacevisible[j])
3348 if (t != surface->texture)
3352 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
3355 t = surface->texture;
3356 texture = t->currentframe;
3357 f = texture->currentmaterialflags & flagsmask;
3359 if (f && surface->num_triangles)
3361 // if lightmap parameters changed, rebuild lightmap texture
3362 if (surface->cached_dlight)
3363 R_BuildLightMap(ent, surface);
3364 // add face to draw list
3365 surfacelist[numsurfacelist++] = surface;
3366 counttriangles += surface->num_triangles;
3367 if (numsurfacelist >= maxsurfacelist)
3369 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
3377 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
3379 if (t != surface->texture)
3383 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
3386 t = surface->texture;
3387 texture = t->currentframe;
3388 f = texture->currentmaterialflags & flagsmask;
3390 if (f && surface->num_triangles)
3392 // if lightmap parameters changed, rebuild lightmap texture
3393 if (surface->cached_dlight)
3394 R_BuildLightMap(ent, surface);
3395 // add face to draw list
3396 surfacelist[numsurfacelist++] = surface;
3397 counttriangles += surface->num_triangles;
3398 if (numsurfacelist >= maxsurfacelist)
3400 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
3407 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
3408 renderstats.entities_triangles += counttriangles;
3409 if (gl_support_fragment_shader)
3410 qglUseProgramObjectARB(0);
3412 if (r_showcollisionbrushes.integer && model->brush.num_brushes && !skysurfaces)
3415 msurface_t *surface;
3417 R_Mesh_Matrix(&ent->matrix);
3418 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
3419 GL_DepthMask(false);
3420 GL_DepthTest(!r_showdisabledepthtest.integer);
3421 qglPolygonOffset(r_polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_polygonoffset + r_showcollisionbrushes_polygonoffset.value);
3422 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
3423 if (brush->colbrushf && brush->colbrushf->numtriangles)
3424 R_DrawCollisionBrush(brush->colbrushf);
3425 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
3426 if (surface->num_collisiontriangles)
3427 R_DrawCollisionSurface(ent, surface);
3428 qglPolygonOffset(r_polygonfactor, r_polygonoffset);
3431 if (r_showtris.integer || r_shownormals.integer)
3434 const int *elements;
3439 if (r_showdisabledepthtest.integer)
3440 qglDepthFunc(GL_ALWAYS);
3441 GL_BlendFunc(GL_ONE, GL_ZERO);
3442 memset(&m, 0, sizeof(m));
3444 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
3446 if (ent == r_refdef.worldentity && !r_worldsurfacevisible[j])
3448 texture = surface->texture->currentframe;
3449 if ((texture->currentmaterialflags & flagsmask) && surface->num_triangles)
3451 RSurf_PrepareForBatch(ent, texture, modelorg);
3452 RSurf_SetPointersForPass(false, r_shownormals.integer != 0);
3453 if (rsurface_dynamicvertex)
3454 RSurf_PrepareDynamicSurfaceVertices(surface);
3455 if (r_showtris.integer)
3457 if (!texture->currentlayers->depthmask)
3458 GL_Color(r_showtris.value, 0, 0, 1);
3459 else if (ent == r_refdef.worldentity)
3460 GL_Color(r_showtris.value, r_showtris.value, r_showtris.value, 1);
3462 GL_Color(0, r_showtris.value, 0, 1);
3463 elements = (ent->model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
3465 for (k = 0;k < surface->num_triangles;k++, elements += 3)
3467 qglArrayElement(elements[0]);qglArrayElement(elements[1]);
3468 qglArrayElement(elements[1]);qglArrayElement(elements[2]);
3469 qglArrayElement(elements[2]);qglArrayElement(elements[0]);
3473 if (r_shownormals.integer)
3475 GL_Color(r_shownormals.value, 0, 0, 1);
3477 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
3479 VectorCopy(rsurface_vertex3f + l * 3, v);
3480 qglVertex3f(v[0], v[1], v[2]);
3481 VectorMA(v, 8, rsurface_svector3f + l * 3, v);
3482 qglVertex3f(v[0], v[1], v[2]);
3485 GL_Color(0, 0, r_shownormals.value, 1);
3487 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
3489 VectorCopy(rsurface_vertex3f + l * 3, v);
3490 qglVertex3f(v[0], v[1], v[2]);
3491 VectorMA(v, 8, rsurface_tvector3f + l * 3, v);
3492 qglVertex3f(v[0], v[1], v[2]);
3495 GL_Color(0, r_shownormals.value, 0, 1);
3497 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
3499 VectorCopy(rsurface_vertex3f + l * 3, v);
3500 qglVertex3f(v[0], v[1], v[2]);
3501 VectorMA(v, 8, rsurface_normal3f + l * 3, v);
3502 qglVertex3f(v[0], v[1], v[2]);
3508 if (r_showdisabledepthtest.integer)
3509 qglDepthFunc(GL_LEQUAL);