2 Copyright (C) 1996-1997 Id Software, Inc.
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26 mempool_t *r_main_mempool;
27 rtexturepool_t *r_main_texturepool;
29 // used for dlight push checking and other things
34 renderstats_t renderstats;
36 // true during envmap command capture
39 // maximum visible distance (recalculated from world box each frame)
41 // brightness of world lightmaps and related lighting
42 // (often reduced when world rtlights are enabled)
43 float r_lightmapintensity;
44 // whether to draw world lights realtime, dlights realtime, and their shadows
46 qboolean r_rtworldshadows;
48 qboolean r_rtdlightshadows;
51 // forces all rendering to draw triangle outlines
66 matrix4x4_t r_view_matrix;
73 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
74 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
75 cvar_t r_showtris_polygonoffset = {0, "r_showtris_polygonoffset", "-10", "nudges triangle outlines in hardware depth units, used to make outlines appear infront of walls"};
76 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
77 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
78 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
79 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
80 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
81 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
82 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing\n"};
83 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
84 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
85 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
86 cvar_t r_fullbright = {0, "r_fullbright","0", "make everything bright cheat (not allowed in multiplayer)"};
87 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
88 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
89 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
91 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
92 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
93 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
94 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
95 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
96 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
97 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
99 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of hardware texture units reported by driver (note: setting this to 1 turns off gl_combine)"};
101 cvar_t r_glsl = {0, "r_glsl", "1", "enables use of OpenGL 2.0 pixel shaders for lighting"};
102 cvar_t r_glsl_offsetmapping = {0, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
103 cvar_t r_glsl_offsetmapping_reliefmapping = {0, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
104 cvar_t r_glsl_offsetmapping_scale = {0, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
105 cvar_t r_glsl_usehalffloat = {0, "r_glsl_usehalffloat", "0", "use half and hvec variables in GLSL shader for a speed gain (NVIDIA only)"};
106 cvar_t r_glsl_surfacenormalize = {0, "r_glsl_surfacenormalize", "1", "normalize bumpmap texels in GLSL shader, produces a more rounded look on small bumps and dents"};
107 cvar_t r_glsl_deluxemapping = {0, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"};
109 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1", "enables animation smoothing on sprites (requires r_lerpmodels 1)"};
110 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
111 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
113 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
114 cvar_t r_bloom_intensity = {CVAR_SAVE, "r_bloom_intensity", "1.5", "how bright the glow is"};
115 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
116 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
117 cvar_t r_bloom_power = {CVAR_SAVE, "r_bloom_power", "2", "how much to darken the image before blurring to make the bloom effect"};
119 cvar_t r_smoothnormals_areaweighting = {0, "r_smoothnormals_areaweighting", "1", "uses significantly faster (and supposedly higher quality) area-weighted vertex normals and tangent vectors rather than summing normalized triangle normals and tangents"};
121 cvar_t developer_texturelogging = {0, "developer_texturelogging", "0", "produces a textures.log file containing names of skins and map textures the engine tried to load"};
123 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
125 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"}; // used for testing renderer code changes, otherwise does nothing
127 rtexture_t *r_bloom_texture_screen;
128 rtexture_t *r_bloom_texture_bloom;
129 rtexture_t *r_texture_blanknormalmap;
130 rtexture_t *r_texture_white;
131 rtexture_t *r_texture_black;
132 rtexture_t *r_texture_notexture;
133 rtexture_t *r_texture_whitecube;
134 rtexture_t *r_texture_normalizationcube;
135 rtexture_t *r_texture_fogattenuation;
136 rtexture_t *r_texture_fogintensity;
138 // information about each possible shader permutation
139 r_glsl_permutation_t r_glsl_permutations[SHADERPERMUTATION_COUNT];
140 // currently selected permutation
141 r_glsl_permutation_t *r_glsl_permutation;
143 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
146 for (i = 0;i < verts;i++)
157 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
160 for (i = 0;i < verts;i++)
175 vec_t fogtabledistmultiplier;
176 float fogtable[FOGTABLEWIDTH];
177 float fog_density, fog_red, fog_green, fog_blue;
179 qboolean oldgl_fogenable;
180 void R_UpdateFog(void)
182 if (gamemode == GAME_NEHAHRA)
184 if (gl_fogenable.integer)
186 oldgl_fogenable = true;
187 fog_density = gl_fogdensity.value;
188 fog_red = gl_fogred.value;
189 fog_green = gl_foggreen.value;
190 fog_blue = gl_fogblue.value;
192 else if (oldgl_fogenable)
194 oldgl_fogenable = false;
203 fogcolor[0] = fog_red = bound(0.0f, fog_red , 1.0f);
204 fogcolor[1] = fog_green = bound(0.0f, fog_green, 1.0f);
205 fogcolor[2] = fog_blue = bound(0.0f, fog_blue , 1.0f);
210 fogdensity = -4000.0f / (fog_density * fog_density);
211 // this is the point where the fog reaches 0.9986 alpha, which we
212 // consider a good enough cutoff point for the texture
213 // (0.9986 * 256 == 255.6)
214 fogrange = 400 / fog_density;
215 fograngerecip = 1.0f / fogrange;
216 fogtabledistmultiplier = FOGTABLEWIDTH * fograngerecip;
217 // fog color was already set
223 // FIXME: move this to client?
226 if (gamemode == GAME_NEHAHRA)
228 Cvar_Set("gl_fogenable", "0");
229 Cvar_Set("gl_fogdensity", "0.2");
230 Cvar_Set("gl_fogred", "0.3");
231 Cvar_Set("gl_foggreen", "0.3");
232 Cvar_Set("gl_fogblue", "0.3");
234 fog_density = fog_red = fog_green = fog_blue = 0.0f;
237 // FIXME: move this to client?
238 void FOG_registercvars(void)
243 if (gamemode == GAME_NEHAHRA)
245 Cvar_RegisterVariable (&gl_fogenable);
246 Cvar_RegisterVariable (&gl_fogdensity);
247 Cvar_RegisterVariable (&gl_fogred);
248 Cvar_RegisterVariable (&gl_foggreen);
249 Cvar_RegisterVariable (&gl_fogblue);
250 Cvar_RegisterVariable (&gl_fogstart);
251 Cvar_RegisterVariable (&gl_fogend);
254 r = (-1.0/256.0) * (FOGTABLEWIDTH * FOGTABLEWIDTH);
255 for (x = 0;x < FOGTABLEWIDTH;x++)
257 alpha = exp(r / ((double)x*(double)x));
258 if (x == FOGTABLEWIDTH - 1)
260 fogtable[x] = bound(0, alpha, 1);
264 static void R_BuildBlankTextures(void)
266 unsigned char data[4];
267 data[0] = 128; // normal X
268 data[1] = 128; // normal Y
269 data[2] = 255; // normal Z
270 data[3] = 128; // height
271 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
276 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
281 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
284 static void R_BuildNoTexture(void)
287 unsigned char pix[16][16][4];
288 // this makes a light grey/dark grey checkerboard texture
289 for (y = 0;y < 16;y++)
291 for (x = 0;x < 16;x++)
293 if ((y < 8) ^ (x < 8))
309 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_RGBA, TEXF_MIPMAP, NULL);
312 static void R_BuildWhiteCube(void)
314 unsigned char data[6*1*1*4];
315 data[ 0] = 255;data[ 1] = 255;data[ 2] = 255;data[ 3] = 255;
316 data[ 4] = 255;data[ 5] = 255;data[ 6] = 255;data[ 7] = 255;
317 data[ 8] = 255;data[ 9] = 255;data[10] = 255;data[11] = 255;
318 data[12] = 255;data[13] = 255;data[14] = 255;data[15] = 255;
319 data[16] = 255;data[17] = 255;data[18] = 255;data[19] = 255;
320 data[20] = 255;data[21] = 255;data[22] = 255;data[23] = 255;
321 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
324 static void R_BuildNormalizationCube(void)
328 vec_t s, t, intensity;
330 unsigned char data[6][NORMSIZE][NORMSIZE][4];
331 for (side = 0;side < 6;side++)
333 for (y = 0;y < NORMSIZE;y++)
335 for (x = 0;x < NORMSIZE;x++)
337 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
338 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
373 intensity = 127.0f / sqrt(DotProduct(v, v));
374 data[side][y][x][0] = 128.0f + intensity * v[0];
375 data[side][y][x][1] = 128.0f + intensity * v[1];
376 data[side][y][x][2] = 128.0f + intensity * v[2];
377 data[side][y][x][3] = 255;
381 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, &data[0][0][0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
384 static void R_BuildFogTexture(void)
389 unsigned char data1[FOGWIDTH][4];
390 unsigned char data2[FOGWIDTH][4];
391 r = (-1.0/256.0) * (FOGWIDTH * FOGWIDTH);
392 for (x = 0;x < FOGWIDTH;x++)
394 alpha = exp(r / ((double)x*(double)x));
395 if (x == FOGWIDTH - 1)
397 b = (int)(256.0 * alpha);
398 b = bound(0, b, 255);
399 data1[x][0] = 255 - b;
400 data1[x][1] = 255 - b;
401 data1[x][2] = 255 - b;
408 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
409 r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
412 static const char *builtinshaderstring =
413 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
414 "// written by Forest 'LordHavoc' Hale\n"
416 "// common definitions between vertex shader and fragment shader:\n"
418 "// use half floats if available for math performance\n"
420 "#define myhalf half\n"
421 "#define myhvec2 hvec2\n"
422 "#define myhvec3 hvec3\n"
423 "#define myhvec4 hvec4\n"
425 "#define myhalf float\n"
426 "#define myhvec2 vec2\n"
427 "#define myhvec3 vec3\n"
428 "#define myhvec4 vec4\n"
431 "varying vec2 TexCoord;\n"
432 "#if !defined(MODE_LIGHTSOURCE) && !defined(MODE_LIGHTDIRECTION)\n"
433 "varying vec2 TexCoordLightmap;\n"
436 "#ifdef MODE_LIGHTSOURCE\n"
437 "varying myhvec3 CubeVector;\n"
440 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
441 "varying vec3 LightVector;\n"
444 "#if defined(USESPECULAR) || defined(USEFOG) || defined(USEOFFSETMAPPING)\n"
445 "varying vec3 EyeVector;\n"
448 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
449 "varying myhvec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
450 "varying myhvec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
451 "varying myhvec3 VectorR; // direction of R texcoord (surface normal)\n"
457 "// vertex shader specific:\n"
458 "#ifdef VERTEX_SHADER\n"
460 "#ifdef MODE_LIGHTSOURCE\n"
461 "uniform vec3 LightPosition;\n"
464 "#if defined(USESPECULAR) || defined(USEFOG) || defined(USEOFFSETMAPPING)\n"
465 "uniform vec3 EyePosition;\n"
468 "#ifdef MODE_LIGHTDIRECTION\n"
469 "uniform myhvec3 LightDir;\n"
472 "// TODO: get rid of tangentt (texcoord2) and use a crossproduct to regenerate it from tangents (texcoord1) and normal (texcoord3)\n"
476 " // copy the surface texcoord\n"
477 " TexCoord = vec2(gl_TextureMatrix[0] * gl_MultiTexCoord0);\n"
478 "#if !defined(MODE_LIGHTSOURCE) && !defined(MODE_LIGHTDIRECTION)\n"
479 " TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
481 " gl_FrontColor = gl_Color;\n"
483 "#ifdef MODE_LIGHTSOURCE\n"
484 " // transform vertex position into light attenuation/cubemap space\n"
485 " // (-1 to +1 across the light box)\n"
486 " CubeVector = vec3(gl_TextureMatrix[3] * gl_Vertex);\n"
488 " // transform unnormalized light direction into tangent space\n"
489 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
490 " // normalize it per pixel)\n"
491 " vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
492 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
493 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
494 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
497 "#ifdef MODE_LIGHTDIRECTION\n"
498 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
499 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
500 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
503 "#if defined(USESPECULAR) || defined(USEFOG) || defined(USEOFFSETMAPPING)\n"
504 " // transform unnormalized eye direction into tangent space\n"
505 " vec3 eyeminusvertex = EyePosition - gl_Vertex.xyz;\n"
506 " EyeVector.x = dot(eyeminusvertex, gl_MultiTexCoord1.xyz);\n"
507 " EyeVector.y = dot(eyeminusvertex, gl_MultiTexCoord2.xyz);\n"
508 " EyeVector.z = dot(eyeminusvertex, gl_MultiTexCoord3.xyz);\n"
511 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
512 " VectorS = gl_MultiTexCoord1.xyz;\n"
513 " VectorT = gl_MultiTexCoord2.xyz;\n"
514 " VectorR = gl_MultiTexCoord3.xyz;\n"
517 " // transform vertex to camera space, using ftransform to match non-VS\n"
519 " gl_Position = ftransform();\n"
527 "// fragment shader specific:\n"
528 "#ifdef FRAGMENT_SHADER\n"
530 "uniform myhvec3 LightColor;\n"
531 "#ifdef USEOFFSETMAPPING\n"
532 "uniform myhalf OffsetMapping_Scale;\n"
533 "uniform myhalf OffsetMapping_Bias;\n"
536 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE) || defined(MODE_LIGHTDIRECTION) || defined(USEOFFSETMAPPING)\n"
537 "uniform sampler2D Texture_Normal;\n"
540 "#ifdef MODE_LIGHTDIRECTION\n"
541 "uniform myhvec3 AmbientColor;\n"
542 "uniform myhvec3 DiffuseColor;\n"
543 "uniform myhvec3 SpecularColor;\n"
546 "uniform sampler2D Texture_Color;\n"
548 "#if !defined(MODE_LIGHTSOURCE) && !defined(MODE_LIGHTDIRECTION)\n"
549 "uniform sampler2D Texture_Lightmap;\n"
551 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
552 "uniform sampler2D Texture_Deluxemap;\n"
556 "uniform sampler2D Texture_Glow;\n"
559 "#ifdef USECOLORMAPPING\n"
560 "uniform sampler2D Texture_Pants;\n"
561 "uniform sampler2D Texture_Shirt;\n"
562 "uniform myhvec3 Color_Pants;\n"
563 "uniform myhvec3 Color_Shirt;\n"
566 "uniform myhalf AmbientScale;\n"
567 "uniform myhalf DiffuseScale;\n"
568 "#ifdef USESPECULAR\n"
569 "uniform myhalf SpecularScale;\n"
570 "uniform myhalf SpecularPower;\n"
571 "uniform sampler2D Texture_Gloss;\n"
574 "#ifdef USECUBEFILTER\n"
575 "uniform samplerCube Texture_Cube;\n"
579 "uniform myhvec3 FogColor;\n"
580 "uniform myhalf FogRangeRecip;\n"
581 "uniform sampler2D Texture_FogMask;\n"
584 "#ifdef USEEASTEREGG\n"
587 " gl_FragColor = myhvec4(0, 0, 0, 1);;\n"
590 " vec2 p = vec2(CubeVector.x * 16.0, CubeVector.y * 16.0);\n"
591 " vec2 c = vec2(CubeVector.x * 16.0, CubeVector.y * 16.0);\n"
592 " for (i = 0;i < 1000 && dot(p,p) < 4.0;i = i + 1)\n"
594 " o = p.x * p.x - p.y * p.y;\n"
595 " p.y = 2.0 * p.x * p.y;\n"
599 " o = float(i) * 0.314;\n"
601 " gl_FragColor = vec4(cos(o), sin(o), sin(o * 0.2), 1);\n"
603 "#else // USEEASTEREGG\n"
609 " // apply offsetmapping\n"
610 "#ifdef USEOFFSETMAPPING\n"
611 " myhvec2 TexCoordOffset = TexCoord;\n"
612 "#define TexCoord TexCoordOffset\n"
614 " myhvec3 eyedir = myhvec3(normalize(EyeVector));\n"
615 " myhalf depthbias = 1.0 - eyedir.z; // should this be a -?\n"
616 " depthbias = 1.0 - depthbias * depthbias;\n"
618 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
619 " // 14 sample relief mapping: linear search and then binary search\n"
620 " myhvec3 OffsetVector = myhvec3(EyeVector.xy * (1.0 / EyeVector.z) * depthbias * OffsetMapping_Scale * myhvec2(-0.1, 0.1), -0.1);\n"
621 " vec3 RT = vec3(TexCoord - OffsetVector.xy * 10.0, 1.0) + OffsetVector;\n"
622 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
623 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
624 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
625 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
626 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
627 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
628 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
629 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
630 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;OffsetVector *= 0.5;RT -= OffsetVector;\n"
631 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;OffsetVector *= 0.5;RT -= OffsetVector;\n"
632 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;OffsetVector *= 0.5;RT -= OffsetVector;\n"
633 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;OffsetVector *= 0.5;RT -= OffsetVector;\n"
634 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;OffsetVector *= 0.5;RT -= OffsetVector;\n"
635 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;OffsetVector *= 0.5;RT -= OffsetVector;\n"
636 " TexCoord = RT.xy;\n"
638 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
639 " myhvec2 OffsetVector = myhvec2((EyeVector.xy * (1.0 / EyeVector.z) * depthbias) * OffsetMapping_Scale * myhvec2(-0.333, 0.333));\n"
640 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
641 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
642 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
646 " // combine the diffuse textures (base, pants, shirt)\n"
647 " myhvec4 color = myhvec4(texture2D(Texture_Color, TexCoord));\n"
648 "#ifdef USECOLORMAPPING\n"
649 " color.rgb += myhvec3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhvec3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
655 "#ifdef MODE_LIGHTSOURCE\n"
658 " // get the surface normal and light normal\n"
659 "#ifdef SURFACENORMALIZE\n"
660 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - 0.5);\n"
662 " myhvec3 surfacenormal = -1.0 + 2.0 * myhvec3(texture2D(Texture_Normal, TexCoord));\n"
664 " myhvec3 diffusenormal = myhvec3(normalize(LightVector));\n"
666 " // calculate directional shading\n"
667 " color.rgb *= (AmbientScale + DiffuseScale * max(dot(surfacenormal, diffusenormal), 0.0));\n"
668 "#ifdef USESPECULAR\n"
669 " myhvec3 specularnormal = myhvec3(normalize(diffusenormal + myhvec3(normalize(EyeVector))));\n"
670 " color.rgb += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(max(dot(surfacenormal, specularnormal), 0.0), SpecularPower);\n"
673 "#ifdef USECUBEFILTER\n"
674 " // apply light cubemap filter\n"
675 " color.rgb *= myhvec3(textureCube(Texture_Cube, CubeVector));\n"
678 " // apply light color\n"
679 " color.rgb = color.rgb * LightColor;\n"
681 " // apply attenuation\n"
683 " // the attenuation is (1-(x*x+y*y+z*z)) which gives a large bright\n"
684 " // center and sharp falloff at the edge, this is about the most efficient\n"
685 " // we can get away with as far as providing illumination.\n"
687 " // pow(1-(x*x+y*y+z*z), 4) is far more realistic but needs large lights to\n"
688 " // provide significant illumination, large = slow = pain.\n"
689 " color.rgb *= max(1.0 - dot(CubeVector, CubeVector), 0.0);\n"
694 "#elif defined(MODE_LIGHTDIRECTION)\n"
695 " // directional model lighting\n"
697 " // get the surface normal and light normal\n"
698 "#ifdef SURFACENORMALIZE\n"
699 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - 0.5);\n"
701 " myhvec3 surfacenormal = -1.0 + 2.0 * myhvec3(texture2D(Texture_Normal, TexCoord));\n"
703 " myhvec3 diffusenormal = myhvec3(normalize(LightVector));\n"
706 " // calculate directional shading\n"
707 " color.rgb *= AmbientColor + DiffuseColor * max(dot(surfacenormal, diffusenormal), 0.0);\n"
708 "#ifdef USESPECULAR\n"
709 " myhvec3 specularnormal = myhvec3(normalize(diffusenormal + myhvec3(normalize(EyeVector))));\n"
710 " color.rgb += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(max(dot(surfacenormal, specularnormal), 0.0), SpecularPower);\n"
716 "#elif defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE)\n"
717 " // deluxemap lightmapping using light vectors in modelspace (evil q3map2)\n"
719 " // get the surface normal and light normal\n"
720 "#ifdef SURFACENORMALIZE\n"
721 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - 0.5);\n"
723 " myhvec3 surfacenormal = -1.0 + 2.0 * myhvec3(texture2D(Texture_Normal, TexCoord));\n"
725 " myhvec3 diffusenormal_modelspace = myhvec3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - 0.5;\n"
726 " myhvec3 diffusenormal = normalize(myhvec3(dot(diffusenormal_modelspace, VectorS), dot(diffusenormal_modelspace, VectorT), dot(diffusenormal_modelspace, VectorR)));\n"
728 " // calculate directional shading\n"
729 " myhvec3 tempcolor = color.rgb * (DiffuseScale * max(dot(surfacenormal, diffusenormal), 0.0));\n"
730 "#ifdef USESPECULAR\n"
731 " myhvec3 specularnormal = myhvec3(normalize(diffusenormal + myhvec3(normalize(EyeVector))));\n"
732 " tempcolor += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(max(dot(surfacenormal, specularnormal), 0.0), SpecularPower);\n"
735 " // apply lightmap color\n"
736 " color.rgb = tempcolor * myhvec3(texture2D(Texture_Lightmap, TexCoordLightmap)) + color.rgb * myhvec3(AmbientScale);\n"
741 "#elif defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
742 " // deluxemap lightmapping using light vectors in tangentspace\n"
744 " // get the surface normal and light normal\n"
745 "#ifdef SURFACENORMALIZE\n"
746 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - 0.5);\n"
747 " myhvec3 diffusenormal = normalize(myhvec3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - 0.5);\n"
749 " myhvec3 surfacenormal = -1.0 + 2.0 * myhvec3(texture2D(Texture_Normal, TexCoord));\n"
750 " myhvec3 diffusenormal = -1.0 + 2.0 * myhvec3(texture2D(Texture_Deluxemap, TexCoordLightmap));\n"
753 " // calculate directional shading\n"
754 " myhvec3 tempcolor = color.rgb * (DiffuseScale * max(dot(surfacenormal, diffusenormal), 0.0));\n"
755 "#ifdef USESPECULAR\n"
756 " myhvec3 specularnormal = myhvec3(normalize(diffusenormal + myhvec3(normalize(EyeVector))));\n"
757 " tempcolor += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(max(dot(surfacenormal, specularnormal), 0.0), SpecularPower);\n"
760 " // apply lightmap color\n"
761 " color.rgb = tempcolor * myhvec3(texture2D(Texture_Lightmap, TexCoordLightmap)) + color.rgb * myhvec3(AmbientScale);\n"
766 "#else // MODE none (lightmap)\n"
767 " // apply lightmap color\n"
768 " color.rgb *= myhvec3(texture2D(Texture_Lightmap, TexCoordLightmap)) * DiffuseScale + myhvec3(AmbientScale);\n"
772 " color.rgb += myhvec3(texture2D(Texture_Glow, TexCoord));\n"
777 " myhalf fog = texture2D(Texture_FogMask, myhvec2(length(EyeVector)*FogRangeRecip, 0.0)).x;\n"
778 " color.rgb = color.rgb * fog + FogColor * (1.0 - fog);\n"
781 " gl_FragColor = color * gl_Color;\n"
783 "#endif // !USEEASTEREGG\n"
788 void R_GLSL_CompilePermutation(int permutation)
790 r_glsl_permutation_t *p = r_glsl_permutations + permutation;
791 int vertstrings_count;
792 int fragstrings_count;
794 const char *vertstrings_list[SHADERPERMUTATION_COUNT+1];
795 const char *fragstrings_list[SHADERPERMUTATION_COUNT+1];
796 char permutationname[256];
800 vertstrings_list[0] = "#define VERTEX_SHADER\n";
801 fragstrings_list[0] = "#define FRAGMENT_SHADER\n";
802 vertstrings_count = 1;
803 fragstrings_count = 1;
804 permutationname[0] = 0;
805 if (permutation & SHADERPERMUTATION_MODE_LIGHTSOURCE)
807 vertstrings_list[vertstrings_count++] = "#define MODE_LIGHTSOURCE\n";
808 fragstrings_list[fragstrings_count++] = "#define MODE_LIGHTSOURCE\n";
809 strlcat(permutationname, " lightsource", sizeof(permutationname));
811 if (permutation & SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_MODELSPACE)
813 vertstrings_list[vertstrings_count++] = "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n";
814 fragstrings_list[fragstrings_count++] = "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n";
815 strlcat(permutationname, " lightdirectionmap_modelspace", sizeof(permutationname));
817 if (permutation & SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)
819 vertstrings_list[vertstrings_count++] = "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n";
820 fragstrings_list[fragstrings_count++] = "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n";
821 strlcat(permutationname, " lightdirectionmap_tangentspace", sizeof(permutationname));
823 if (permutation & SHADERPERMUTATION_MODE_LIGHTDIRECTION)
825 vertstrings_list[vertstrings_count++] = "#define MODE_LIGHTDIRECTION\n";
826 fragstrings_list[fragstrings_count++] = "#define MODE_LIGHTDIRECTION\n";
827 strlcat(permutationname, " lightdirection", sizeof(permutationname));
829 if (permutation & SHADERPERMUTATION_GLOW)
831 vertstrings_list[vertstrings_count++] = "#define USEGLOW\n";
832 fragstrings_list[fragstrings_count++] = "#define USEGLOW\n";
833 strlcat(permutationname, " glow", sizeof(permutationname));
835 if (permutation & SHADERPERMUTATION_COLORMAPPING)
837 vertstrings_list[vertstrings_count++] = "#define USECOLORMAPPING\n";
838 fragstrings_list[fragstrings_count++] = "#define USECOLORMAPPING\n";
839 strlcat(permutationname, " colormapping", sizeof(permutationname));
841 if (permutation & SHADERPERMUTATION_SPECULAR)
843 vertstrings_list[vertstrings_count++] = "#define USESPECULAR\n";
844 fragstrings_list[fragstrings_count++] = "#define USESPECULAR\n";
845 strlcat(permutationname, " specular", sizeof(permutationname));
847 if (permutation & SHADERPERMUTATION_FOG)
849 vertstrings_list[vertstrings_count++] = "#define USEFOG\n";
850 fragstrings_list[fragstrings_count++] = "#define USEFOG\n";
851 strlcat(permutationname, " fog", sizeof(permutationname));
853 if (permutation & SHADERPERMUTATION_CUBEFILTER)
855 vertstrings_list[vertstrings_count++] = "#define USECUBEFILTER\n";
856 fragstrings_list[fragstrings_count++] = "#define USECUBEFILTER\n";
857 strlcat(permutationname, " cubefilter", sizeof(permutationname));
859 if (permutation & SHADERPERMUTATION_OFFSETMAPPING)
861 vertstrings_list[vertstrings_count++] = "#define USEOFFSETMAPPING\n";
862 fragstrings_list[fragstrings_count++] = "#define USEOFFSETMAPPING\n";
863 strlcat(permutationname, " offsetmapping", sizeof(permutationname));
865 if (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING)
867 vertstrings_list[vertstrings_count++] = "#define USEOFFSETMAPPING_RELIEFMAPPING\n";
868 fragstrings_list[fragstrings_count++] = "#define USEOFFSETMAPPING_RELIEFMAPPING\n";
869 strlcat(permutationname, " OFFSETMAPPING_RELIEFMAPPING", sizeof(permutationname));
871 if (permutation & SHADERPERMUTATION_SURFACENORMALIZE)
873 vertstrings_list[vertstrings_count++] = "#define SURFACENORMALIZE\n";
874 fragstrings_list[fragstrings_count++] = "#define SURFACENORMALIZE\n";
875 strlcat(permutationname, " surfacenormalize", sizeof(permutationname));
877 if (permutation & SHADERPERMUTATION_GEFORCEFX)
879 vertstrings_list[vertstrings_count++] = "#define GEFORCEFX\n";
880 fragstrings_list[fragstrings_count++] = "#define GEFORCEFX\n";
881 strlcat(permutationname, " halffloat", sizeof(permutationname));
883 shaderstring = (char *)FS_LoadFile("glsl/default.glsl", r_main_mempool, false, NULL);
886 Con_DPrintf("GLSL shader text loaded from disk\n");
887 vertstrings_list[vertstrings_count++] = shaderstring;
888 fragstrings_list[fragstrings_count++] = shaderstring;
892 vertstrings_list[vertstrings_count++] = builtinshaderstring;
893 fragstrings_list[fragstrings_count++] = builtinshaderstring;
895 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, fragstrings_count, fragstrings_list);
899 qglUseProgramObjectARB(p->program);
900 p->loc_Texture_Normal = qglGetUniformLocationARB(p->program, "Texture_Normal");
901 p->loc_Texture_Color = qglGetUniformLocationARB(p->program, "Texture_Color");
902 p->loc_Texture_Gloss = qglGetUniformLocationARB(p->program, "Texture_Gloss");
903 p->loc_Texture_Cube = qglGetUniformLocationARB(p->program, "Texture_Cube");
904 p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
905 p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
906 p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
907 p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
908 p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
909 p->loc_Texture_Glow = qglGetUniformLocationARB(p->program, "Texture_Glow");
910 p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
911 p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
912 p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
913 p->loc_LightColor = qglGetUniformLocationARB(p->program, "LightColor");
914 p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants");
915 p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt");
916 p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip");
917 p->loc_AmbientScale = qglGetUniformLocationARB(p->program, "AmbientScale");
918 p->loc_DiffuseScale = qglGetUniformLocationARB(p->program, "DiffuseScale");
919 p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
920 p->loc_SpecularScale = qglGetUniformLocationARB(p->program, "SpecularScale");
921 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
922 p->loc_AmbientColor = qglGetUniformLocationARB(p->program, "AmbientColor");
923 p->loc_DiffuseColor = qglGetUniformLocationARB(p->program, "DiffuseColor");
924 p->loc_SpecularColor = qglGetUniformLocationARB(p->program, "SpecularColor");
925 p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
926 if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal, 0);
927 if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color, 1);
928 if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss, 2);
929 if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube, 3);
930 if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask, 4);
931 if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants, 5);
932 if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt, 6);
933 if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap, 7);
934 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap, 8);
935 if (p->loc_Texture_Glow >= 0) qglUniform1iARB(p->loc_Texture_Glow, 9);
936 qglUseProgramObjectARB(0);
940 Con_Printf("permutation%s failed for shader %s, some features may not work properly!\n", permutationname, "glsl/default.glsl");
942 Mem_Free(shaderstring);
945 void R_GLSL_Restart_f(void)
948 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
949 if (r_glsl_permutations[i].program)
950 GL_Backend_FreeProgram(r_glsl_permutations[i].program);
951 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
954 void R_SetupSurfaceShader(const entity_render_t *ent, const texture_t *texture, const vec3_t modelorg, const vec3_t lightcolorbase, qboolean modellighting)
956 // select a permutation of the lighting shader appropriate to this
957 // combination of texture, entity, light source, and fogging, only use the
958 // minimum features necessary to avoid wasting rendering time in the
959 // fragment shader on features that are not being used
961 float specularscale = texture->specularscale;
962 r_glsl_permutation = NULL;
963 if (r_shadow_rtlight)
965 permutation |= SHADERPERMUTATION_MODE_LIGHTSOURCE;
966 specularscale *= r_shadow_rtlight->specularscale;
967 if (r_shadow_rtlight->currentcubemap != r_texture_whitecube)
968 permutation |= SHADERPERMUTATION_CUBEFILTER;
973 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTION;
974 else if (r_glsl_deluxemapping.integer >= 1 && r_refdef.worldmodel && r_refdef.worldmodel->brushq3.deluxemapping)
976 if (r_refdef.worldmodel->brushq3.deluxemapping_modelspace)
977 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_MODELSPACE;
979 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
981 else if (r_glsl_deluxemapping.integer >= 2) // fake mode
982 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
983 if (texture->skin.glow)
984 permutation |= SHADERPERMUTATION_GLOW;
986 if (specularscale > 0)
987 permutation |= SHADERPERMUTATION_SPECULAR;
989 permutation |= SHADERPERMUTATION_FOG;
990 if (texture->colormapping)
991 permutation |= SHADERPERMUTATION_COLORMAPPING;
992 if (r_glsl_offsetmapping.integer)
994 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
995 if (r_glsl_offsetmapping_reliefmapping.integer)
996 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
998 if (r_glsl_surfacenormalize.integer)
999 permutation |= SHADERPERMUTATION_SURFACENORMALIZE;
1000 if (r_glsl_usehalffloat.integer)
1001 permutation |= SHADERPERMUTATION_GEFORCEFX;
1002 if (!r_glsl_permutations[permutation].program)
1004 if (!r_glsl_permutations[permutation].compiled)
1005 R_GLSL_CompilePermutation(permutation);
1006 if (!r_glsl_permutations[permutation].program)
1008 // remove features until we find a valid permutation
1010 for (i = SHADERPERMUTATION_COUNT-1;;i>>=1)
1012 // reduce i more quickly whenever it would not remove any bits
1013 if (permutation < i)
1016 if (!r_glsl_permutations[permutation].compiled)
1017 R_GLSL_CompilePermutation(permutation);
1018 if (r_glsl_permutations[permutation].program)
1021 return; // utterly failed
1025 r_glsl_permutation = r_glsl_permutations + permutation;
1027 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
1028 R_Mesh_TexMatrix(0, &texture->currenttexmatrix);
1029 if (permutation & SHADERPERMUTATION_MODE_LIGHTSOURCE)
1031 R_Mesh_TexMatrix(3, &r_shadow_entitytolight);
1032 if (r_glsl_permutation->loc_Texture_Cube >= 0) R_Mesh_TexBind(3, R_GetTexture(r_shadow_rtlight->currentcubemap));
1033 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, r_shadow_entitylightorigin[0], r_shadow_entitylightorigin[1], r_shadow_entitylightorigin[2]);
1034 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
1035 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_shadow_rtlight->ambientscale);
1036 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_shadow_rtlight->diffusescale);
1037 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, specularscale);
1039 else if (permutation & SHADERPERMUTATION_MODE_LIGHTDIRECTION)
1041 if (texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
1043 if (r_glsl_permutation->loc_AmbientColor >= 0)
1044 qglUniform3fARB(r_glsl_permutation->loc_AmbientColor, 1, 1, 1);
1045 if (r_glsl_permutation->loc_DiffuseColor >= 0)
1046 qglUniform3fARB(r_glsl_permutation->loc_DiffuseColor, 0, 0, 0);
1047 if (r_glsl_permutation->loc_SpecularColor >= 0)
1048 qglUniform3fARB(r_glsl_permutation->loc_SpecularColor, 0, 0, 0);
1049 if (r_glsl_permutation->loc_LightDir >= 0)
1050 qglUniform3fARB(r_glsl_permutation->loc_LightDir, 0, 0, -1);
1054 if (r_glsl_permutation->loc_AmbientColor >= 0)
1055 qglUniform3fARB(r_glsl_permutation->loc_AmbientColor, ent->modellight_ambient[0], ent->modellight_ambient[1], ent->modellight_ambient[2]);
1056 if (r_glsl_permutation->loc_DiffuseColor >= 0)
1057 qglUniform3fARB(r_glsl_permutation->loc_DiffuseColor, ent->modellight_diffuse[0], ent->modellight_diffuse[1], ent->modellight_diffuse[2]);
1058 if (r_glsl_permutation->loc_SpecularColor >= 0)
1059 qglUniform3fARB(r_glsl_permutation->loc_SpecularColor, ent->modellight_diffuse[0] * texture->specularscale, ent->modellight_diffuse[1] * texture->specularscale, ent->modellight_diffuse[2] * texture->specularscale);
1060 if (r_glsl_permutation->loc_LightDir >= 0)
1061 qglUniform3fARB(r_glsl_permutation->loc_LightDir, ent->modellight_lightdir[0], ent->modellight_lightdir[1], ent->modellight_lightdir[2]);
1066 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_ambient.value * 2.0f / 128.0f);
1067 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_lightmapintensity * 2.0f);
1068 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, specularscale * 2.0f);
1070 if (r_glsl_permutation->loc_Texture_Normal >= 0) R_Mesh_TexBind(0, R_GetTexture(texture->skin.nmap));
1071 if (r_glsl_permutation->loc_Texture_Color >= 0) R_Mesh_TexBind(1, R_GetTexture(texture->basetexture));
1072 if (r_glsl_permutation->loc_Texture_Gloss >= 0) R_Mesh_TexBind(2, R_GetTexture(texture->glosstexture));
1073 if (r_glsl_permutation->loc_Texture_FogMask >= 0) R_Mesh_TexBind(4, R_GetTexture(r_texture_fogattenuation));
1074 if (r_glsl_permutation->loc_Texture_Pants >= 0) R_Mesh_TexBind(5, R_GetTexture(texture->skin.pants));
1075 if (r_glsl_permutation->loc_Texture_Shirt >= 0) R_Mesh_TexBind(6, R_GetTexture(texture->skin.shirt));
1076 if (r_glsl_permutation->loc_Texture_Glow >= 0) R_Mesh_TexBind(9, R_GetTexture(texture->skin.glow));
1077 if (r_glsl_permutation->loc_FogColor >= 0)
1079 // additive passes are only darkened by fog, not tinted
1080 if (r_shadow_rtlight || (texture->currentmaterialflags & MATERIALFLAG_ADD))
1081 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
1083 qglUniform3fARB(r_glsl_permutation->loc_FogColor, fogcolor[0], fogcolor[1], fogcolor[2]);
1085 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, modelorg[0], modelorg[1], modelorg[2]);
1086 if (r_glsl_permutation->loc_Color_Pants >= 0)
1088 if (texture->skin.pants)
1089 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, ent->colormap_pantscolor[0], ent->colormap_pantscolor[1], ent->colormap_pantscolor[2]);
1091 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
1093 if (r_glsl_permutation->loc_Color_Shirt >= 0)
1095 if (texture->skin.shirt)
1096 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, ent->colormap_shirtcolor[0], ent->colormap_shirtcolor[1], ent->colormap_shirtcolor[2]);
1098 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
1100 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, fograngerecip);
1101 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, texture->specularpower);
1102 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
1106 void gl_main_start(void)
1108 // use half float math where available (speed gain on NVIDIA GFFX and GF6)
1109 if (gl_support_half_float)
1110 Cvar_SetValue("r_glsl_usehalffloat", 1);
1111 r_main_texturepool = R_AllocTexturePool();
1112 r_bloom_texture_screen = NULL;
1113 r_bloom_texture_bloom = NULL;
1114 R_BuildBlankTextures();
1116 if (gl_texturecubemap)
1119 R_BuildNormalizationCube();
1121 R_BuildFogTexture();
1122 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
1125 void gl_main_shutdown(void)
1127 R_FreeTexturePool(&r_main_texturepool);
1128 r_bloom_texture_screen = NULL;
1129 r_bloom_texture_bloom = NULL;
1130 r_texture_blanknormalmap = NULL;
1131 r_texture_white = NULL;
1132 r_texture_black = NULL;
1133 r_texture_whitecube = NULL;
1134 r_texture_normalizationcube = NULL;
1138 extern void CL_ParseEntityLump(char *entitystring);
1139 void gl_main_newmap(void)
1141 // FIXME: move this code to client
1143 char *entities, entname[MAX_QPATH];
1147 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
1148 l = (int)strlen(entname) - 4;
1149 if (l >= 0 && !strcmp(entname + l, ".bsp"))
1151 strcpy(entname + l, ".ent");
1152 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
1154 CL_ParseEntityLump(entities);
1159 if (cl.worldmodel->brush.entities)
1160 CL_ParseEntityLump(cl.worldmodel->brush.entities);
1164 void GL_Main_Init(void)
1166 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
1168 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed\n");
1169 FOG_registercvars(); // FIXME: move this fog stuff to client?
1170 Cvar_RegisterVariable(&r_nearclip);
1171 Cvar_RegisterVariable(&r_showtris);
1172 Cvar_RegisterVariable(&r_showtris_polygonoffset);
1173 Cvar_RegisterVariable(&r_shownormals);
1174 Cvar_RegisterVariable(&r_showlighting);
1175 Cvar_RegisterVariable(&r_showshadowvolumes);
1176 Cvar_RegisterVariable(&r_showcollisionbrushes);
1177 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
1178 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
1179 Cvar_RegisterVariable(&r_showdisabledepthtest);
1180 Cvar_RegisterVariable(&r_drawentities);
1181 Cvar_RegisterVariable(&r_drawviewmodel);
1182 Cvar_RegisterVariable(&r_speeds);
1183 Cvar_RegisterVariable(&r_fullbrights);
1184 Cvar_RegisterVariable(&r_wateralpha);
1185 Cvar_RegisterVariable(&r_dynamic);
1186 Cvar_RegisterVariable(&r_fullbright);
1187 Cvar_RegisterVariable(&r_textureunits);
1188 Cvar_RegisterVariable(&r_glsl);
1189 Cvar_RegisterVariable(&r_glsl_offsetmapping);
1190 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
1191 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
1192 Cvar_RegisterVariable(&r_glsl_usehalffloat);
1193 Cvar_RegisterVariable(&r_glsl_surfacenormalize);
1194 Cvar_RegisterVariable(&r_glsl_deluxemapping);
1195 Cvar_RegisterVariable(&r_lerpsprites);
1196 Cvar_RegisterVariable(&r_lerpmodels);
1197 Cvar_RegisterVariable(&r_waterscroll);
1198 Cvar_RegisterVariable(&r_bloom);
1199 Cvar_RegisterVariable(&r_bloom_intensity);
1200 Cvar_RegisterVariable(&r_bloom_blur);
1201 Cvar_RegisterVariable(&r_bloom_resolution);
1202 Cvar_RegisterVariable(&r_bloom_power);
1203 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
1204 Cvar_RegisterVariable(&developer_texturelogging);
1205 Cvar_RegisterVariable(&gl_lightmaps);
1206 Cvar_RegisterVariable(&r_test);
1207 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
1208 Cvar_SetValue("r_fullbrights", 0);
1209 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
1212 static vec3_t r_farclip_origin;
1213 static vec3_t r_farclip_direction;
1214 static vec_t r_farclip_directiondist;
1215 static vec_t r_farclip_meshfarclip;
1216 static int r_farclip_directionbit0;
1217 static int r_farclip_directionbit1;
1218 static int r_farclip_directionbit2;
1220 // enlarge farclip to accomodate box
1221 static void R_FarClip_Box(vec3_t mins, vec3_t maxs)
1224 d = (r_farclip_directionbit0 ? mins[0] : maxs[0]) * r_farclip_direction[0]
1225 + (r_farclip_directionbit1 ? mins[1] : maxs[1]) * r_farclip_direction[1]
1226 + (r_farclip_directionbit2 ? mins[2] : maxs[2]) * r_farclip_direction[2];
1227 if (r_farclip_meshfarclip < d)
1228 r_farclip_meshfarclip = d;
1231 // return farclip value
1232 static float R_FarClip(vec3_t origin, vec3_t direction, vec_t startfarclip)
1236 VectorCopy(origin, r_farclip_origin);
1237 VectorCopy(direction, r_farclip_direction);
1238 r_farclip_directiondist = DotProduct(r_farclip_origin, r_farclip_direction);
1239 r_farclip_directionbit0 = r_farclip_direction[0] < 0;
1240 r_farclip_directionbit1 = r_farclip_direction[1] < 0;
1241 r_farclip_directionbit2 = r_farclip_direction[2] < 0;
1242 r_farclip_meshfarclip = r_farclip_directiondist + startfarclip;
1244 if (r_refdef.worldmodel)
1245 R_FarClip_Box(r_refdef.worldmodel->normalmins, r_refdef.worldmodel->normalmaxs);
1246 for (i = 0;i < r_refdef.numentities;i++)
1247 R_FarClip_Box(r_refdef.entities[i]->mins, r_refdef.entities[i]->maxs);
1249 return r_farclip_meshfarclip - r_farclip_directiondist;
1252 extern void R_Textures_Init(void);
1253 extern void GL_Draw_Init(void);
1254 extern void GL_Main_Init(void);
1255 extern void R_Shadow_Init(void);
1256 extern void R_Sky_Init(void);
1257 extern void GL_Surf_Init(void);
1258 extern void R_Crosshairs_Init(void);
1259 extern void R_Light_Init(void);
1260 extern void R_Particles_Init(void);
1261 extern void R_Explosion_Init(void);
1262 extern void gl_backend_init(void);
1263 extern void Sbar_Init(void);
1264 extern void R_LightningBeams_Init(void);
1265 extern void Mod_RenderInit(void);
1267 void Render_Init(void)
1277 R_Crosshairs_Init();
1282 R_LightningBeams_Init();
1291 extern char *ENGINE_EXTENSIONS;
1294 VID_CheckExtensions();
1296 // LordHavoc: report supported extensions
1297 Con_DPrintf("\nengine extensions: %s\n", vm_sv_extensions );
1299 // clear to black (loading plaque will be seen over this)
1300 qglClearColor(0,0,0,1);
1301 qglClear(GL_COLOR_BUFFER_BIT);
1304 int R_CullBox(const vec3_t mins, const vec3_t maxs)
1308 for (i = 0;i < 4;i++)
1315 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1319 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1323 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1327 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1331 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1335 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1339 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1343 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1351 //==================================================================================
1353 static void R_UpdateEntityLighting(entity_render_t *ent)
1355 vec3_t tempdiffusenormal;
1356 VectorSet(ent->modellight_ambient, r_ambient.value * (2.0f / 128.0f), r_ambient.value * (2.0f / 128.0f), r_ambient.value * (2.0f / 128.0f));
1357 VectorClear(ent->modellight_diffuse);
1358 VectorClear(ent->modellight_lightdir);
1359 if ((ent->flags & RENDER_LIGHT) && r_refdef.worldmodel && r_refdef.worldmodel->brush.LightPoint)
1360 r_refdef.worldmodel->brush.LightPoint(r_refdef.worldmodel, ent->origin, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
1362 VectorSet(ent->modellight_ambient, 1, 1, 1);
1363 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
1364 VectorNormalize(ent->modellight_lightdir);
1365 ent->modellight_ambient[0] *= ent->colormod[0] * r_lightmapintensity;
1366 ent->modellight_ambient[1] *= ent->colormod[1] * r_lightmapintensity;
1367 ent->modellight_ambient[2] *= ent->colormod[2] * r_lightmapintensity;
1368 ent->modellight_diffuse[0] *= ent->colormod[0] * r_lightmapintensity;
1369 ent->modellight_diffuse[1] *= ent->colormod[1] * r_lightmapintensity;
1370 ent->modellight_diffuse[2] *= ent->colormod[2] * r_lightmapintensity;
1373 static void R_MarkEntities (void)
1376 entity_render_t *ent;
1378 if (!r_drawentities.integer)
1381 r_refdef.worldentity->visframe = r_framecount;
1382 renderimask = envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : (chase_active.integer ? 0 : RENDER_EXTERIORMODEL);
1383 if (r_refdef.worldmodel && r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs)
1385 // worldmodel can check visibility
1386 for (i = 0;i < r_refdef.numentities;i++)
1388 ent = r_refdef.entities[i];
1389 // some of the renderer still relies on origin...
1390 Matrix4x4_OriginFromMatrix(&ent->matrix, ent->origin);
1391 // some of the renderer still relies on scale...
1392 ent->scale = Matrix4x4_ScaleFromMatrix(&ent->matrix);
1393 if (!(ent->flags & renderimask) && !R_CullBox(ent->mins, ent->maxs) && ((ent->effects & EF_NODEPTHTEST) || r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs(r_refdef.worldmodel, r_worldleafvisible, ent->mins, ent->maxs)))
1395 ent->visframe = r_framecount;
1396 R_UpdateEntityLighting(ent);
1402 // no worldmodel or it can't check visibility
1403 for (i = 0;i < r_refdef.numentities;i++)
1405 ent = r_refdef.entities[i];
1406 // some of the renderer still relies on origin...
1407 Matrix4x4_OriginFromMatrix(&ent->matrix, ent->origin);
1408 // some of the renderer still relies on scale...
1409 ent->scale = Matrix4x4_ScaleFromMatrix(&ent->matrix);
1410 if (!(ent->flags & renderimask) && !R_CullBox(ent->mins, ent->maxs) && (ent->effects & EF_NODEPTHTEST))
1412 ent->visframe = r_framecount;
1413 R_UpdateEntityLighting(ent);
1419 // only used if skyrendermasked, and normally returns false
1420 int R_DrawBrushModelsSky (void)
1423 entity_render_t *ent;
1425 if (!r_drawentities.integer)
1429 for (i = 0;i < r_refdef.numentities;i++)
1431 ent = r_refdef.entities[i];
1432 if (ent->visframe == r_framecount && ent->model && ent->model->DrawSky)
1434 ent->model->DrawSky(ent);
1441 void R_DrawNoModel(entity_render_t *ent);
1442 void R_DrawModels(void)
1445 entity_render_t *ent;
1447 if (!r_drawentities.integer)
1450 for (i = 0;i < r_refdef.numentities;i++)
1452 ent = r_refdef.entities[i];
1453 if (ent->visframe == r_framecount)
1455 renderstats.entities++;
1456 if (ent->model && ent->model->Draw != NULL)
1457 ent->model->Draw(ent);
1464 static void R_SetFrustum(void)
1466 // break apart the view matrix into vectors for various purposes
1467 Matrix4x4_ToVectors(&r_view_matrix, r_viewforward, r_viewleft, r_viewup, r_vieworigin);
1468 VectorNegate(r_viewleft, r_viewright);
1471 frustum[0].normal[0] = 0 - 1.0 / r_refdef.frustum_x;
1472 frustum[0].normal[1] = 0 - 0;
1473 frustum[0].normal[2] = -1 - 0;
1474 frustum[1].normal[0] = 0 + 1.0 / r_refdef.frustum_x;
1475 frustum[1].normal[1] = 0 + 0;
1476 frustum[1].normal[2] = -1 + 0;
1477 frustum[2].normal[0] = 0 - 0;
1478 frustum[2].normal[1] = 0 - 1.0 / r_refdef.frustum_y;
1479 frustum[2].normal[2] = -1 - 0;
1480 frustum[3].normal[0] = 0 + 0;
1481 frustum[3].normal[1] = 0 + 1.0 / r_refdef.frustum_y;
1482 frustum[3].normal[2] = -1 + 0;
1486 zNear = r_nearclip.value;
1487 nudge = 1.0 - 1.0 / (1<<23);
1488 frustum[4].normal[0] = 0 - 0;
1489 frustum[4].normal[1] = 0 - 0;
1490 frustum[4].normal[2] = -1 - -nudge;
1491 frustum[4].dist = 0 - -2 * zNear * nudge;
1492 frustum[5].normal[0] = 0 + 0;
1493 frustum[5].normal[1] = 0 + 0;
1494 frustum[5].normal[2] = -1 + -nudge;
1495 frustum[5].dist = 0 + -2 * zNear * nudge;
1501 frustum[0].normal[0] = m[3] - m[0];
1502 frustum[0].normal[1] = m[7] - m[4];
1503 frustum[0].normal[2] = m[11] - m[8];
1504 frustum[0].dist = m[15] - m[12];
1506 frustum[1].normal[0] = m[3] + m[0];
1507 frustum[1].normal[1] = m[7] + m[4];
1508 frustum[1].normal[2] = m[11] + m[8];
1509 frustum[1].dist = m[15] + m[12];
1511 frustum[2].normal[0] = m[3] - m[1];
1512 frustum[2].normal[1] = m[7] - m[5];
1513 frustum[2].normal[2] = m[11] - m[9];
1514 frustum[2].dist = m[15] - m[13];
1516 frustum[3].normal[0] = m[3] + m[1];
1517 frustum[3].normal[1] = m[7] + m[5];
1518 frustum[3].normal[2] = m[11] + m[9];
1519 frustum[3].dist = m[15] + m[13];
1521 frustum[4].normal[0] = m[3] - m[2];
1522 frustum[4].normal[1] = m[7] - m[6];
1523 frustum[4].normal[2] = m[11] - m[10];
1524 frustum[4].dist = m[15] - m[14];
1526 frustum[5].normal[0] = m[3] + m[2];
1527 frustum[5].normal[1] = m[7] + m[6];
1528 frustum[5].normal[2] = m[11] + m[10];
1529 frustum[5].dist = m[15] + m[14];
1534 VectorMAM(1, r_viewforward, 1.0 / -r_refdef.frustum_x, r_viewleft, frustum[0].normal);
1535 VectorMAM(1, r_viewforward, 1.0 / r_refdef.frustum_x, r_viewleft, frustum[1].normal);
1536 VectorMAM(1, r_viewforward, 1.0 / -r_refdef.frustum_y, r_viewup, frustum[2].normal);
1537 VectorMAM(1, r_viewforward, 1.0 / r_refdef.frustum_y, r_viewup, frustum[3].normal);
1538 VectorCopy(r_viewforward, frustum[4].normal);
1539 VectorNormalize(frustum[0].normal);
1540 VectorNormalize(frustum[1].normal);
1541 VectorNormalize(frustum[2].normal);
1542 VectorNormalize(frustum[3].normal);
1543 frustum[0].dist = DotProduct (r_vieworigin, frustum[0].normal);
1544 frustum[1].dist = DotProduct (r_vieworigin, frustum[1].normal);
1545 frustum[2].dist = DotProduct (r_vieworigin, frustum[2].normal);
1546 frustum[3].dist = DotProduct (r_vieworigin, frustum[3].normal);
1547 frustum[4].dist = DotProduct (r_vieworigin, frustum[4].normal) + r_nearclip.value;
1548 PlaneClassify(&frustum[0]);
1549 PlaneClassify(&frustum[1]);
1550 PlaneClassify(&frustum[2]);
1551 PlaneClassify(&frustum[3]);
1552 PlaneClassify(&frustum[4]);
1554 // LordHavoc: note to all quake engine coders, Quake had a special case
1555 // for 90 degrees which assumed a square view (wrong), so I removed it,
1556 // Quake2 has it disabled as well.
1558 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
1559 //RotatePointAroundVector( frustum[0].normal, r_viewup, r_viewforward, -(90 - r_refdef.fov_x / 2));
1560 //frustum[0].dist = DotProduct (r_vieworigin, frustum[0].normal);
1561 //PlaneClassify(&frustum[0]);
1563 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
1564 //RotatePointAroundVector( frustum[1].normal, r_viewup, r_viewforward, (90 - r_refdef.fov_x / 2));
1565 //frustum[1].dist = DotProduct (r_vieworigin, frustum[1].normal);
1566 //PlaneClassify(&frustum[1]);
1568 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
1569 //RotatePointAroundVector( frustum[2].normal, r_viewleft, r_viewforward, -(90 - r_refdef.fov_y / 2));
1570 //frustum[2].dist = DotProduct (r_vieworigin, frustum[2].normal);
1571 //PlaneClassify(&frustum[2]);
1573 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
1574 //RotatePointAroundVector( frustum[3].normal, r_viewleft, r_viewforward, (90 - r_refdef.fov_y / 2));
1575 //frustum[3].dist = DotProduct (r_vieworigin, frustum[3].normal);
1576 //PlaneClassify(&frustum[3]);
1579 //VectorCopy(r_viewforward, frustum[4].normal);
1580 //frustum[4].dist = DotProduct (r_vieworigin, frustum[4].normal) + r_nearclip.value;
1581 //PlaneClassify(&frustum[4]);
1584 static void R_BlendView(void)
1586 int screenwidth, screenheight;
1591 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;
1829 // GL is weird because it's bottom to top, r_view_y is top to bottom
1830 qglViewport(r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
1831 GL_Scissor(r_view_x, r_view_y, r_view_width, r_view_height);
1832 GL_ScissorTest(true);
1837 if (r_timereport_active)
1838 R_TimeReport("setup");
1840 qglDepthFunc(GL_LEQUAL);
1841 qglPolygonOffset(0, 0);
1842 qglEnable(GL_POLYGON_OFFSET_FILL);
1846 qglPolygonOffset(0, 0);
1847 qglDisable(GL_POLYGON_OFFSET_FILL);
1850 if (r_timereport_active)
1851 R_TimeReport("blendview");
1853 GL_Scissor(0, 0, vid.width, vid.height);
1854 GL_ScissorTest(false);
1858 void CSQC_R_ClearScreen (void)
1860 if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
1861 return; //Host_Error ("R_RenderView: NULL worldmodel");
1863 r_view_width = bound(0, r_refdef.width, vid.width);
1864 r_view_height = bound(0, r_refdef.height, vid.height);
1866 r_view_x = bound(0, r_refdef.x, vid.width - r_refdef.width);
1867 r_view_y = bound(0, r_refdef.y, vid.height - r_refdef.height);
1869 r_view_matrix = r_refdef.viewentitymatrix;
1870 GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
1871 r_rtworld = r_shadow_realtime_world.integer;
1872 r_rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
1873 r_rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer;
1874 r_rtdlightshadows = r_rtdlight && (r_rtworld ? r_shadow_realtime_world_dlightshadows.integer : r_shadow_realtime_dlight_shadows.integer) && gl_stencil;
1875 r_lightmapintensity = r_rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
1877 // GL is weird because it's bottom to top, r_view_y is top to bottom
1878 qglViewport(r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
1879 GL_Scissor(r_view_x, r_view_y, r_view_width, r_view_height);
1880 GL_ScissorTest(true);
1885 if (r_timereport_active)
1886 R_TimeReport("setup");
1890 void CSQC_R_RenderScene (void)
1892 qglDepthFunc(GL_LEQUAL);
1893 qglPolygonOffset(0, 0);
1894 qglEnable(GL_POLYGON_OFFSET_FILL);
1898 qglPolygonOffset(0, 0);
1899 qglDisable(GL_POLYGON_OFFSET_FILL);
1902 if (r_timereport_active)
1903 R_TimeReport("blendview");
1905 GL_Scissor(0, 0, vid.width, vid.height);
1906 GL_ScissorTest(false);
1909 extern void R_DrawLightningBeams (void);
1910 extern void VM_AddPolygonsToMeshQueue (void);
1911 void R_RenderScene(void)
1915 // don't let sound skip if going slow
1916 if (r_refdef.extraupdate)
1921 if (gl_support_fragment_shader)
1922 qglUseProgramObjectARB(0);
1924 R_MeshQueue_BeginScene();
1928 r_farclip = R_FarClip(r_vieworigin, r_viewforward, 768.0f) + 256.0f;
1929 nearclip = bound (0.001f, r_nearclip.value, r_farclip - 1.0f);
1931 if (r_rtworldshadows || r_rtdlightshadows)
1932 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_refdef.frustum_x, r_refdef.frustum_y, nearclip);
1934 GL_SetupView_Mode_Perspective(r_refdef.frustum_x, r_refdef.frustum_y, nearclip, r_farclip);
1936 GL_SetupView_Orientation_FromEntity(&r_view_matrix);
1938 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);
1942 R_WorldVisibility();
1943 if (r_timereport_active)
1944 R_TimeReport("worldvis");
1947 if (r_timereport_active)
1948 R_TimeReport("markentity");
1950 R_Shadow_UpdateWorldLightSelection();
1952 for (r_showtrispass = 0;r_showtrispass <= (r_showtris.value > 0);r_showtrispass++)
1958 GL_BlendFunc(GL_ONE, GL_ONE);
1959 GL_DepthTest(!r_showdisabledepthtest.integer);
1960 GL_DepthMask(GL_FALSE);
1961 memset(&m, 0, sizeof(m));
1963 //qglEnable(GL_LINE_SMOOTH);
1964 qglEnable(GL_POLYGON_OFFSET_LINE);
1965 qglPolygonOffset(0, r_showtris_polygonoffset.value);
1969 if (cl.csqc_vidvars.drawworld)
1971 // don't let sound skip if going slow
1972 if (r_refdef.extraupdate)
1976 GL_ShowTrisColor(0.025, 0.025, 0, 1);
1977 if (r_refdef.worldmodel && r_refdef.worldmodel->DrawSky)
1979 r_refdef.worldmodel->DrawSky(r_refdef.worldentity);
1980 if (r_timereport_active)
1981 R_TimeReport("worldsky");
1984 if (R_DrawBrushModelsSky() && r_timereport_active)
1985 R_TimeReport("bmodelsky");
1988 GL_ShowTrisColor(0.05, 0.05, 0.05, 1);
1989 if (r_refdef.worldmodel && r_refdef.worldmodel->Draw)
1991 r_refdef.worldmodel->Draw(r_refdef.worldentity);
1992 if (r_timereport_active)
1993 R_TimeReport("world");
1997 // don't let sound skip if going slow
1998 if (r_refdef.extraupdate)
2002 GL_ShowTrisColor(0, 0.015, 0, 1);
2005 if (r_timereport_active)
2006 R_TimeReport("models");
2008 // don't let sound skip if going slow
2009 if (r_refdef.extraupdate)
2013 GL_ShowTrisColor(0, 0, 0.033, 1);
2014 R_ShadowVolumeLighting(false);
2015 if (r_timereport_active)
2016 R_TimeReport("rtlights");
2018 // don't let sound skip if going slow
2019 if (r_refdef.extraupdate)
2023 GL_ShowTrisColor(0.1, 0, 0, 1);
2025 if (cl.csqc_vidvars.drawworld)
2027 R_DrawLightningBeams();
2028 if (r_timereport_active)
2029 R_TimeReport("lightning");
2032 if (r_timereport_active)
2033 R_TimeReport("particles");
2036 if (r_timereport_active)
2037 R_TimeReport("explosions");
2040 R_MeshQueue_RenderTransparent();
2041 if (r_timereport_active)
2042 R_TimeReport("drawtrans");
2044 if (cl.csqc_vidvars.drawworld)
2047 if (r_timereport_active)
2048 R_TimeReport("coronas");
2050 if(cl.csqc_vidvars.drawcrosshair)
2052 R_DrawWorldCrosshair();
2053 if (r_timereport_active)
2054 R_TimeReport("crosshair");
2057 VM_AddPolygonsToMeshQueue();
2059 R_MeshQueue_Render();
2063 //qglDisable(GL_LINE_SMOOTH);
2064 qglDisable(GL_POLYGON_OFFSET_LINE);
2070 R_MeshQueue_EndScene();
2072 // don't let sound skip if going slow
2073 if (r_refdef.extraupdate)
2076 if (gl_support_fragment_shader)
2077 qglUseProgramObjectARB(0);
2081 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
2084 float *v, *c, f1, f2, diff[3], vertex3f[8*3], color4f[8*4];
2086 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2087 GL_DepthMask(false);
2089 R_Mesh_Matrix(&identitymatrix);
2091 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2];
2092 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
2093 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
2094 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
2095 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
2096 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
2097 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
2098 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
2099 R_FillColors(color, 8, cr, cg, cb, ca);
2102 for (i = 0, v = vertex, c = color;i < 8;i++, v += 4, c += 4)
2104 f2 = VERTEXFOGTABLE(VectorDistance(v, r_vieworigin));
2106 c[0] = c[0] * f1 + fogcolor[0] * f2;
2107 c[1] = c[1] * f1 + fogcolor[1] * f2;
2108 c[2] = c[2] * f1 + fogcolor[2] * f2;
2111 memset(&m, 0, sizeof(m));
2112 m.pointer_vertex = vertex3f;
2113 m.pointer_color = color;
2119 int nomodelelements[24] =
2131 float nomodelvertex3f[6*3] =
2141 float nomodelcolor4f[6*4] =
2143 0.0f, 0.0f, 0.5f, 1.0f,
2144 0.0f, 0.0f, 0.5f, 1.0f,
2145 0.0f, 0.5f, 0.0f, 1.0f,
2146 0.0f, 0.5f, 0.0f, 1.0f,
2147 0.5f, 0.0f, 0.0f, 1.0f,
2148 0.5f, 0.0f, 0.0f, 1.0f
2151 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight)
2157 R_Mesh_Matrix(&ent->matrix);
2159 memset(&m, 0, sizeof(m));
2160 m.pointer_vertex = nomodelvertex3f;
2162 if (ent->flags & EF_ADDITIVE)
2164 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2165 GL_DepthMask(false);
2167 else if (ent->alpha < 1)
2169 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2170 GL_DepthMask(false);
2174 GL_BlendFunc(GL_ONE, GL_ZERO);
2177 GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
2180 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
2181 m.pointer_color = color4f;
2182 f2 = VERTEXFOGTABLE(VectorDistance(ent->origin, r_vieworigin));
2184 for (i = 0, c = color4f;i < 6;i++, c += 4)
2186 c[0] = (c[0] * f1 + fogcolor[0] * f2);
2187 c[1] = (c[1] * f1 + fogcolor[1] * f2);
2188 c[2] = (c[2] * f1 + fogcolor[2] * f2);
2192 else if (ent->alpha != 1)
2194 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
2195 m.pointer_color = color4f;
2196 for (i = 0, c = color4f;i < 6;i++, c += 4)
2200 m.pointer_color = nomodelcolor4f;
2202 R_Mesh_Draw(0, 6, 8, nomodelelements);
2205 void R_DrawNoModel(entity_render_t *ent)
2207 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
2208 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_vieworigin : ent->origin, R_DrawNoModel_TransparentCallback, ent, 0, r_shadow_rtlight);
2210 // R_DrawNoModelCallback(ent, 0);
2213 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
2215 vec3_t right1, right2, diff, normal;
2217 VectorSubtract (org2, org1, normal);
2219 // calculate 'right' vector for start
2220 VectorSubtract (r_vieworigin, org1, diff);
2221 CrossProduct (normal, diff, right1);
2222 VectorNormalize (right1);
2224 // calculate 'right' vector for end
2225 VectorSubtract (r_vieworigin, org2, diff);
2226 CrossProduct (normal, diff, right2);
2227 VectorNormalize (right2);
2229 vert[ 0] = org1[0] + width * right1[0];
2230 vert[ 1] = org1[1] + width * right1[1];
2231 vert[ 2] = org1[2] + width * right1[2];
2232 vert[ 3] = org1[0] - width * right1[0];
2233 vert[ 4] = org1[1] - width * right1[1];
2234 vert[ 5] = org1[2] - width * right1[2];
2235 vert[ 6] = org2[0] - width * right2[0];
2236 vert[ 7] = org2[1] - width * right2[1];
2237 vert[ 8] = org2[2] - width * right2[2];
2238 vert[ 9] = org2[0] + width * right2[0];
2239 vert[10] = org2[1] + width * right2[1];
2240 vert[11] = org2[2] + width * right2[2];
2243 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
2245 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)
2247 float fog = 0.0f, ifog;
2252 fog = VERTEXFOGTABLE(VectorDistance(origin, r_vieworigin));
2255 R_Mesh_Matrix(&identitymatrix);
2256 GL_BlendFunc(blendfunc1, blendfunc2);
2257 GL_DepthMask(false);
2258 GL_DepthTest(!depthdisable);
2260 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
2261 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
2262 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
2263 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
2264 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
2265 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
2266 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
2267 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
2268 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
2269 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
2270 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
2271 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
2273 memset(&m, 0, sizeof(m));
2274 m.tex[0] = R_GetTexture(texture);
2275 m.pointer_texcoord[0] = spritetexcoord2f;
2276 m.pointer_vertex = vertex3f;
2278 GL_Color(cr * ifog, cg * ifog, cb * ifog, ca);
2279 R_Mesh_Draw(0, 4, 2, polygonelements);
2281 if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
2283 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
2284 GL_BlendFunc(blendfunc1, GL_ONE);
2285 GL_Color(fogcolor[0] * fog, fogcolor[1] * fog, fogcolor[2] * fog, ca);
2286 R_Mesh_Draw(0, 4, 2, polygonelements);
2290 int R_Mesh_AddVertex3f(rmesh_t *mesh, const float *v)
2294 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
2295 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
2297 if (i == mesh->numvertices)
2299 if (mesh->numvertices < mesh->maxvertices)
2301 VectorCopy(v, vertex3f);
2302 mesh->numvertices++;
2304 return mesh->numvertices;
2310 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
2314 element[0] = R_Mesh_AddVertex3f(mesh, vertex3f);vertex3f += 3;
2315 element[1] = R_Mesh_AddVertex3f(mesh, vertex3f);vertex3f += 3;
2316 e = mesh->element3i + mesh->numtriangles * 3;
2317 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
2319 element[2] = R_Mesh_AddVertex3f(mesh, vertex3f);
2320 if (mesh->numtriangles < mesh->maxtriangles)
2325 mesh->numtriangles++;
2327 element[1] = element[2];
2331 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
2333 int planenum, planenum2;
2336 mplane_t *plane, *plane2;
2337 float temppoints[2][256*3];
2338 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
2342 PolygonF_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->normal[3], 1024.0*1024.0*1024.0);
2343 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
2345 if (planenum2 == planenum)
2347 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);
2350 if (tempnumpoints < 3)
2352 // generate elements forming a triangle fan for this polygon
2353 R_Mesh_AddPolygon3f(mesh, tempnumpoints, temppoints[w]);
2357 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)
2359 texturelayer_t *layer;
2360 layer = t->currentlayers + t->currentnumlayers++;
2362 layer->depthmask = depthmask;
2363 layer->blendfunc1 = blendfunc1;
2364 layer->blendfunc2 = blendfunc2;
2365 layer->texture = texture;
2366 layer->texmatrix = *matrix;
2367 layer->color[0] = r;
2368 layer->color[1] = g;
2369 layer->color[2] = b;
2370 layer->color[3] = a;
2373 void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
2375 // FIXME: identify models using a better check than ent->model->brush.shadowmesh
2376 //int lightmode = ((ent->effects & EF_FULLBRIGHT) || ent->model->brush.shadowmesh) ? 0 : 2;
2379 texture_t *texture = t;
2380 model_t *model = ent->model;
2381 int s = ent->skinnum;
2382 if ((unsigned int)s >= (unsigned int)model->numskins)
2384 if (model->skinscenes)
2386 if (model->skinscenes[s].framecount > 1)
2387 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
2389 s = model->skinscenes[s].firstframe;
2392 t = t + s * model->num_surfaces;
2394 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];
2395 texture->currentframe = t;
2398 t->currentmaterialflags = t->basematerialflags;
2399 t->currentalpha = ent->alpha;
2400 if (t->basematerialflags & MATERIALFLAG_WATERALPHA)
2401 t->currentalpha *= r_wateralpha.value;
2402 if (!(ent->flags & RENDER_LIGHT))
2403 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
2404 if (ent->effects & EF_ADDITIVE)
2405 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_TRANSPARENT;
2406 else if (t->currentalpha < 1)
2407 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_TRANSPARENT;
2408 if (ent->effects & EF_NODEPTHTEST)
2409 t->currentmaterialflags |= MATERIALFLAG_NODEPTHTEST;
2410 if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
2411 t->currenttexmatrix = r_waterscrollmatrix;
2413 t->currenttexmatrix = identitymatrix;
2415 t->colormapping = VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f);
2416 t->basetexture = (!t->colormapping && t->skin.merged) ? t->skin.merged : t->skin.base;
2417 t->glosstexture = r_texture_white;
2418 t->specularpower = 8;
2419 t->specularscale = 0;
2420 if (r_shadow_gloss.integer > 0)
2424 if (r_shadow_glossintensity.value > 0)
2426 t->glosstexture = t->skin.gloss;
2427 t->specularscale = r_shadow_glossintensity.value;
2430 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
2431 t->specularscale = r_shadow_gloss2intensity.value;
2434 t->currentnumlayers = 0;
2435 if (!(t->currentmaterialflags & MATERIALFLAG_NODRAW))
2437 if (gl_lightmaps.integer)
2438 R_Texture_AddLayer(t, true, GL_ONE, GL_ZERO, TEXTURELAYERTYPE_LITTEXTURE_MULTIPASS, r_texture_white, &identitymatrix, 1, 1, 1, 1);
2439 else if (!(t->currentmaterialflags & MATERIALFLAG_SKY))
2441 int blendfunc1, blendfunc2, depthmask;
2442 if (t->currentmaterialflags & MATERIALFLAG_ADD)
2444 blendfunc1 = GL_SRC_ALPHA;
2445 blendfunc2 = GL_ONE;
2448 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
2450 blendfunc1 = GL_SRC_ALPHA;
2451 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
2456 blendfunc1 = GL_ONE;
2457 blendfunc2 = GL_ZERO;
2460 if (t->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL))
2462 rtexture_t *currentbasetexture;
2464 if (fogenabled && (t->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
2465 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
2466 currentbasetexture = (VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) < (1.0f / 1048576.0f) && t->skin.merged) ? t->skin.merged : t->skin.base;
2467 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2469 // fullbright is not affected by r_lightmapintensity
2470 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
2471 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->skin.pants)
2472 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);
2473 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->skin.shirt)
2474 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);
2480 // q3bsp has no lightmap updates, so the lightstylevalue that
2481 // would normally be baked into the lightmaptexture must be
2482 // applied to the color
2483 if (ent->model->type == mod_brushq3)
2484 colorscale *= r_refdef.lightstylevalue[0] * (1.0f / 256.0f);
2485 colorscale *= r_lightmapintensity;
2486 if (r_textureunits.integer >= 2 && gl_combine.integer)
2487 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);
2488 else if ((t->currentmaterialflags & MATERIALFLAG_TRANSPARENT) == 0)
2489 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);
2491 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);
2492 if (r_ambient.value >= (1.0f/64.0f))
2493 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);
2494 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->skin.pants)
2496 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);
2497 if (r_ambient.value >= (1.0f/64.0f))
2498 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);
2500 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->skin.shirt)
2502 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);
2503 if (r_ambient.value >= (1.0f/64.0f))
2504 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);
2507 if (t->skin.glow != NULL)
2508 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.glow, &t->currenttexmatrix, 1, 1, 1, t->currentalpha);
2509 if (fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
2511 // if this is opaque use alpha blend which will darken the earlier
2514 // if this is an alpha blended material, all the earlier passes
2515 // were darkened by fog already, so we only need to add the fog
2516 // color ontop through the fog mask texture
2518 // if this is an additive blended material, all the earlier passes
2519 // were darkened by fog already, and we should not add fog color
2520 // (because the background was not darkened, there is no fog color
2521 // that was lost behind it).
2522 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);
2529 void R_UpdateAllTextureInfo(entity_render_t *ent)
2533 for (i = 0;i < ent->model->num_textures;i++)
2534 R_UpdateTextureInfo(ent, ent->model->data_textures + i);
2537 float *rsurface_vertex3f;
2538 float *rsurface_svector3f;
2539 float *rsurface_tvector3f;
2540 float *rsurface_normal3f;
2541 float *rsurface_lightmapcolor4f;
2543 void RSurf_SetVertexPointer(const entity_render_t *ent, const texture_t *texture, const msurface_t *surface, const vec3_t modelorg, qboolean generatenormals, qboolean generatetangents)
2545 if ((ent->frameblend[0].lerp != 1 || ent->frameblend[0].frame != 0) && (surface->groupmesh->data_morphvertex3f || surface->groupmesh->data_vertexboneweights))
2547 rsurface_vertex3f = varray_vertex3f;
2548 Mod_Alias_GetMesh_Vertex3f(ent->model, ent->frameblend, surface->groupmesh, rsurface_vertex3f);
2549 if (generatetangents || (texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2)))
2551 rsurface_svector3f = varray_svector3f;
2552 rsurface_tvector3f = varray_tvector3f;
2553 rsurface_normal3f = varray_normal3f;
2554 Mod_BuildTextureVectorsAndNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface_vertex3f, surface->groupmesh->data_texcoordtexture2f, surface->groupmesh->data_element3i + surface->num_firsttriangle * 3, rsurface_svector3f, rsurface_tvector3f, rsurface_normal3f, r_smoothnormals_areaweighting.integer);
2558 rsurface_svector3f = NULL;
2559 rsurface_tvector3f = NULL;
2560 if (generatenormals)
2562 rsurface_normal3f = varray_normal3f;
2563 Mod_BuildNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface_vertex3f, surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle, rsurface_normal3f, r_smoothnormals_areaweighting.integer);
2566 rsurface_normal3f = NULL;
2571 rsurface_vertex3f = surface->groupmesh->data_vertex3f;
2572 rsurface_svector3f = surface->groupmesh->data_svector3f;
2573 rsurface_tvector3f = surface->groupmesh->data_tvector3f;
2574 rsurface_normal3f = surface->groupmesh->data_normal3f;
2576 if (texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
2579 float center[3], forward[3], right[3], up[3], v[4][3];
2580 matrix4x4_t matrix1, imatrix1;
2581 Matrix4x4_Transform(&ent->inversematrix, r_viewforward, forward);
2582 Matrix4x4_Transform(&ent->inversematrix, r_viewright, right);
2583 Matrix4x4_Transform(&ent->inversematrix, r_viewup, up);
2584 // a single autosprite surface can contain multiple sprites...
2585 for (j = 0;j < surface->num_vertices - 3;j += 4)
2587 VectorClear(center);
2588 for (i = 0;i < 4;i++)
2589 VectorAdd(center, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
2590 VectorScale(center, 0.25f, center);
2591 // FIXME: calculate vectors from triangle edges instead of using texture vectors as an easy way out?
2592 Matrix4x4_FromVectors(&matrix1, (rsurface_normal3f + 3 * surface->num_firstvertex) + j*3, (rsurface_svector3f + 3 * surface->num_firstvertex) + j*3, (rsurface_tvector3f + 3 * surface->num_firstvertex) + j*3, center);
2593 Matrix4x4_Invert_Simple(&imatrix1, &matrix1);
2594 for (i = 0;i < 4;i++)
2595 Matrix4x4_Transform(&imatrix1, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, v[i]);
2596 if (texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE2)
2598 forward[0] = modelorg[0] - center[0];
2599 forward[1] = modelorg[1] - center[1];
2601 VectorNormalize(forward);
2602 right[0] = forward[1];
2603 right[1] = -forward[0];
2605 VectorSet(up, 0, 0, 1);
2607 for (i = 0;i < 4;i++)
2608 VectorMAMAMAM(1, center, v[i][0], forward, v[i][1], right, v[i][2], up, varray_vertex3f + (surface->num_firstvertex+i+j) * 3);
2610 rsurface_vertex3f = varray_vertex3f;
2611 rsurface_svector3f = varray_svector3f;
2612 rsurface_tvector3f = varray_tvector3f;
2613 rsurface_normal3f = varray_normal3f;
2614 Mod_BuildTextureVectorsAndNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface_vertex3f, surface->groupmesh->data_texcoordtexture2f, surface->groupmesh->data_element3i + surface->num_firsttriangle * 3, rsurface_svector3f, rsurface_tvector3f, rsurface_normal3f, r_smoothnormals_areaweighting.integer);
2616 R_Mesh_VertexPointer(rsurface_vertex3f);
2619 static void RSurf_Draw(const msurface_t *surface)
2621 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2622 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2623 GL_LockArrays(0, 0);
2626 static void RSurf_DrawLightmap(const entity_render_t *ent, const texture_t *texture, const msurface_t *surface, const vec3_t modelorg, float r, float g, float b, float a, int lightmode, qboolean applycolor, qboolean applyfog)
2631 RSurf_SetVertexPointer(ent, texture, surface, modelorg, lightmode >= 2, false);
2635 vec3_t ambientcolor;
2636 vec3_t diffusecolor;
2638 VectorCopy(ent->modellight_lightdir, lightdir);
2639 ambientcolor[0] = ent->modellight_ambient[0] * r * 0.5f;
2640 ambientcolor[1] = ent->modellight_ambient[1] * g * 0.5f;
2641 ambientcolor[2] = ent->modellight_ambient[2] * b * 0.5f;
2642 diffusecolor[0] = ent->modellight_diffuse[0] * r * 0.5f;
2643 diffusecolor[1] = ent->modellight_diffuse[1] * g * 0.5f;
2644 diffusecolor[2] = ent->modellight_diffuse[2] * b * 0.5f;
2645 if (VectorLength2(diffusecolor) > 0)
2647 int numverts = surface->num_vertices;
2648 v = rsurface_vertex3f + 3 * surface->num_firstvertex;
2649 c2 = rsurface_normal3f + 3 * surface->num_firstvertex;
2650 c = varray_color4f + 4 * surface->num_firstvertex;
2651 // q3-style directional shading
2652 for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
2654 if ((f = DotProduct(c2, lightdir)) > 0)
2655 VectorMA(ambientcolor, f, diffusecolor, c);
2657 VectorCopy(ambientcolor, c);
2665 rsurface_lightmapcolor4f = varray_color4f;
2669 r = ambientcolor[0];
2670 g = ambientcolor[1];
2671 b = ambientcolor[2];
2672 rsurface_lightmapcolor4f = NULL;
2675 else if (lightmode >= 1)
2677 if (surface->lightmapinfo && surface->lightmapinfo->stainsamples)
2679 for (i = 0, c = varray_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
2681 if (surface->lightmapinfo->samples)
2683 const unsigned char *lm = surface->lightmapinfo->samples + (surface->groupmesh->data_lightmapoffsets + surface->num_firstvertex)[i];
2684 float scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
2685 VectorScale(lm, scale, c);
2686 if (surface->lightmapinfo->styles[1] != 255)
2688 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
2690 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
2691 VectorMA(c, scale, lm, c);
2692 if (surface->lightmapinfo->styles[2] != 255)
2695 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
2696 VectorMA(c, scale, lm, c);
2697 if (surface->lightmapinfo->styles[3] != 255)
2700 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
2701 VectorMA(c, scale, lm, c);
2709 rsurface_lightmapcolor4f = varray_color4f;
2712 rsurface_lightmapcolor4f = surface->groupmesh->data_lightmapcolor4f;
2715 rsurface_lightmapcolor4f = NULL;
2718 if (rsurface_lightmapcolor4f)
2720 for (i = 0, v = (rsurface_vertex3f + 3 * surface->num_firstvertex), c = (rsurface_lightmapcolor4f + 4 * surface->num_firstvertex), c2 = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4, c2 += 4)
2722 f = 1 - VERTEXFOGTABLE(VectorDistance(v, modelorg));
2731 for (i = 0, v = (rsurface_vertex3f + 3 * surface->num_firstvertex), c2 = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c2 += 4)
2733 f = 1 - VERTEXFOGTABLE(VectorDistance(v, modelorg));
2740 rsurface_lightmapcolor4f = varray_color4f;
2742 if (applycolor && rsurface_lightmapcolor4f)
2744 for (i = 0, c = (rsurface_lightmapcolor4f + 4 * surface->num_firstvertex), c2 = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, c += 4, c2 += 4)
2751 rsurface_lightmapcolor4f = varray_color4f;
2753 R_Mesh_ColorPointer(rsurface_lightmapcolor4f);
2754 GL_Color(r, g, b, a);
2755 RSurf_Draw(surface);
2758 static void R_DrawTextureSurfaceList(const entity_render_t *ent, texture_t *texture, int texturenumsurfaces, const msurface_t **texturesurfacelist, const vec3_t modelorg)
2760 int texturesurfaceindex;
2762 const msurface_t *surface;
2763 qboolean applycolor;
2766 if (texture->currentmaterialflags & MATERIALFLAG_NODRAW)
2768 r_shadow_rtlight = NULL;
2769 renderstats.entities_surfaces += texturenumsurfaces;
2770 // FIXME: identify models using a better check than ent->model->brush.shadowmesh
2771 lightmode = ((ent->effects & EF_FULLBRIGHT) || ent->model->brush.shadowmesh) ? 0 : 2;
2772 GL_DepthTest(!(texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
2773 if ((texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (ent->flags & RENDER_NOCULLFACE))
2774 qglDisable(GL_CULL_FACE);
2775 if (texture->currentmaterialflags & MATERIALFLAG_SKY)
2777 // transparent sky would be ridiculous
2778 if (!(texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
2783 skyrendernow = false;
2784 if (skyrendermasked)
2787 // restore entity matrix and GL_Color
2788 R_Mesh_Matrix(&ent->matrix);
2792 // LordHavoc: HalfLife maps have freaky skypolys...
2793 //if (!ent->model->brush.ishlbsp)
2795 if (skyrendermasked)
2797 // depth-only (masking)
2798 GL_ColorMask(0,0,0,0);
2799 // just to make sure that braindead drivers don't draw anything
2800 // despite that colormask...
2801 GL_BlendFunc(GL_ZERO, GL_ONE);
2806 GL_BlendFunc(GL_ONE, GL_ZERO);
2808 GL_Color(fogcolor[0], fogcolor[1], fogcolor[2], 1);
2809 memset(&m, 0, sizeof(m));
2811 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2813 surface = texturesurfacelist[texturesurfaceindex];
2814 RSurf_SetVertexPointer(ent, texture, surface, modelorg, false, false);
2815 RSurf_Draw(surface);
2817 if (skyrendermasked)
2818 GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
2822 else if (r_glsl.integer && gl_support_fragment_shader)
2824 if (texture->currentmaterialflags & MATERIALFLAG_ADD)
2826 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2827 GL_DepthMask(false);
2829 else if (texture->currentmaterialflags & MATERIALFLAG_ALPHA)
2831 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2832 GL_DepthMask(false);
2836 GL_BlendFunc(GL_ONE, GL_ZERO);
2840 memset(&m, 0, sizeof(m));
2842 GL_Color(ent->colormod[0], ent->colormod[1], ent->colormod[2], texture->currentalpha);
2843 R_SetupSurfaceShader(ent, texture, modelorg, vec3_origin, lightmode == 2);
2844 if (!r_glsl_permutation)
2848 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2850 surface = texturesurfacelist[texturesurfaceindex];
2851 RSurf_SetVertexPointer(ent, texture, surface, modelorg, false, true);
2852 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2853 R_Mesh_TexCoordPointer(1, 3, rsurface_svector3f);
2854 R_Mesh_TexCoordPointer(2, 3, rsurface_tvector3f);
2855 R_Mesh_TexCoordPointer(3, 3, rsurface_normal3f);
2856 RSurf_Draw(surface);
2861 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2863 surface = texturesurfacelist[texturesurfaceindex];
2864 RSurf_SetVertexPointer(ent, texture, surface, modelorg, false, true);
2865 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2866 R_Mesh_TexCoordPointer(1, 3, rsurface_svector3f);
2867 R_Mesh_TexCoordPointer(2, 3, rsurface_tvector3f);
2868 R_Mesh_TexCoordPointer(3, 3, rsurface_normal3f);
2869 R_Mesh_TexCoordPointer(4, 2, surface->groupmesh->data_texcoordlightmap2f);
2870 if (surface->lightmaptexture)
2872 R_Mesh_TexBind(7, R_GetTexture(surface->lightmaptexture));
2873 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
2874 R_Mesh_TexBind(8, R_GetTexture(surface->deluxemaptexture));
2875 R_Mesh_ColorPointer(NULL);
2879 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
2880 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
2881 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
2882 R_Mesh_ColorPointer(surface->groupmesh->data_lightmapcolor4f);
2884 RSurf_Draw(surface);
2887 qglUseProgramObjectARB(0);
2889 else if (texture->currentnumlayers)
2892 texturelayer_t *layer;
2893 for (layerindex = 0, layer = texture->currentlayers;layerindex < texture->currentnumlayers;layerindex++, layer++)
2896 int layertexrgbscale;
2897 GL_DepthMask(layer->depthmask);
2898 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
2899 if ((layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2) && (gl_combine.integer || layer->depthmask))
2901 layertexrgbscale = 4;
2902 VectorScale(layer->color, 0.25f, layercolor);
2904 else if ((layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1) && (gl_combine.integer || layer->depthmask))
2906 layertexrgbscale = 2;
2907 VectorScale(layer->color, 0.5f, layercolor);
2911 layertexrgbscale = 1;
2912 VectorScale(layer->color, 1.0f, layercolor);
2914 layercolor[3] = layer->color[3];
2915 GL_Color(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
2916 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
2917 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
2918 switch (layer->type)
2920 case TEXTURELAYERTYPE_LITTEXTURE_COMBINE:
2921 memset(&m, 0, sizeof(m));
2922 m.tex[1] = R_GetTexture(layer->texture);
2923 m.texmatrix[1] = layer->texmatrix;
2924 m.texrgbscale[1] = layertexrgbscale;
2925 m.pointer_color = varray_color4f;
2929 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2931 surface = texturesurfacelist[texturesurfaceindex];
2932 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
2933 R_Mesh_TexCoordPointer(1, 2, surface->groupmesh->data_texcoordtexture2f);
2934 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2935 RSurf_DrawLightmap(ent, texture, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 2, applycolor, applyfog);
2940 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2942 surface = texturesurfacelist[texturesurfaceindex];
2943 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
2944 R_Mesh_TexCoordPointer(1, 2, surface->groupmesh->data_texcoordtexture2f);
2945 if (surface->lightmaptexture)
2947 R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
2948 RSurf_DrawLightmap(ent, texture, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, applyfog);
2952 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2953 RSurf_DrawLightmap(ent, texture, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 1, applycolor, applyfog);
2958 case TEXTURELAYERTYPE_LITTEXTURE_MULTIPASS:
2959 memset(&m, 0, sizeof(m));
2960 m.tex[0] = R_GetTexture(layer->texture);
2961 m.texmatrix[0] = layer->texmatrix;
2962 m.pointer_color = varray_color4f;
2963 m.texrgbscale[0] = layertexrgbscale;
2967 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2969 surface = texturesurfacelist[texturesurfaceindex];
2970 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
2971 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2972 RSurf_DrawLightmap(ent, texture, surface, modelorg, 1, 1, 1, 1, 2, false, false);
2977 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2979 surface = texturesurfacelist[texturesurfaceindex];
2980 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
2981 if (surface->lightmaptexture)
2983 R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
2984 RSurf_DrawLightmap(ent, texture, surface, modelorg, 1, 1, 1, 1, 0, false, false);
2988 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2989 RSurf_DrawLightmap(ent, texture, surface, modelorg, 1, 1, 1, 1, 1, false, false);
2993 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
2994 memset(&m, 0, sizeof(m));
2995 m.tex[0] = R_GetTexture(layer->texture);
2996 m.texmatrix[0] = layer->texmatrix;
2997 m.pointer_color = varray_color4f;
2998 m.texrgbscale[0] = layertexrgbscale;
3000 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3002 surface = texturesurfacelist[texturesurfaceindex];
3003 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
3004 RSurf_DrawLightmap(ent, texture, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, applyfog);
3007 case TEXTURELAYERTYPE_LITTEXTURE_VERTEX:
3008 memset(&m, 0, sizeof(m));
3009 m.tex[0] = R_GetTexture(layer->texture);
3010 m.texmatrix[0] = layer->texmatrix;
3011 m.texrgbscale[0] = layertexrgbscale;
3012 m.pointer_color = varray_color4f;
3016 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3018 surface = texturesurfacelist[texturesurfaceindex];
3019 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
3020 RSurf_DrawLightmap(ent, texture, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 2, applycolor, applyfog);
3025 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3027 surface = texturesurfacelist[texturesurfaceindex];
3028 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
3029 RSurf_DrawLightmap(ent, texture, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 1, applycolor, applyfog);
3033 case TEXTURELAYERTYPE_TEXTURE:
3034 memset(&m, 0, sizeof(m));
3035 m.tex[0] = R_GetTexture(layer->texture);
3036 m.texmatrix[0] = layer->texmatrix;
3037 m.pointer_color = varray_color4f;
3038 m.texrgbscale[0] = layertexrgbscale;
3040 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3042 surface = texturesurfacelist[texturesurfaceindex];
3043 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
3044 RSurf_DrawLightmap(ent, texture, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, applyfog);
3047 case TEXTURELAYERTYPE_FOG:
3048 memset(&m, 0, sizeof(m));
3051 m.tex[0] = R_GetTexture(layer->texture);
3052 m.texmatrix[0] = layer->texmatrix;
3055 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3059 surface = texturesurfacelist[texturesurfaceindex];
3060 RSurf_SetVertexPointer(ent, texture, surface, modelorg, false, false);
3062 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
3063 R_Mesh_ColorPointer(varray_color4f);
3064 for (i = 0, v = (rsurface_vertex3f + 3 * surface->num_firstvertex), c = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4)
3066 f = VERTEXFOGTABLE(VectorDistance(v, modelorg));
3067 c[0] = layercolor[0];
3068 c[1] = layercolor[1];
3069 c[2] = layercolor[2];
3070 c[3] = f * layercolor[3];
3072 RSurf_Draw(surface);
3076 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
3078 // if trying to do overbright on first pass of an opaque surface
3079 // when combine is not supported, brighten as a post process
3080 if (layertexrgbscale > 1 && !gl_combine.integer && layer->depthmask)
3083 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
3084 GL_Color(1, 1, 1, 1);
3085 memset(&m, 0, sizeof(m));
3087 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3089 surface = texturesurfacelist[texturesurfaceindex];
3090 RSurf_SetVertexPointer(ent, texture, surface, modelorg, false, false);
3091 for (scale = 1;scale < layertexrgbscale;scale <<= 1)
3092 RSurf_Draw(surface);
3096 if (r_shownormals.integer && !r_showtrispass)
3100 GL_DepthTest(!r_showdisabledepthtest.integer);
3101 GL_DepthMask(texture->currentlayers->depthmask);
3102 GL_BlendFunc(texture->currentlayers->blendfunc1, texture->currentlayers->blendfunc2);
3103 memset(&m, 0, sizeof(m));
3105 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3107 surface = texturesurfacelist[texturesurfaceindex];
3108 RSurf_SetVertexPointer(ent, texture, surface, modelorg, false, true);
3109 GL_Color(1, 0, 0, 1);
3111 for (j = 0, k = surface->num_firstvertex;j < surface->num_vertices;j++, k++)
3113 VectorCopy(rsurface_vertex3f + k * 3, v);
3114 qglVertex3f(v[0], v[1], v[2]);
3115 VectorMA(v, 8, rsurface_svector3f + k * 3, v);
3116 qglVertex3f(v[0], v[1], v[2]);
3118 GL_Color(0, 0, 1, 1);
3119 for (j = 0, k = surface->num_firstvertex;j < surface->num_vertices;j++, k++)
3121 VectorCopy(rsurface_vertex3f + k * 3, v);
3122 qglVertex3f(v[0], v[1], v[2]);
3123 VectorMA(v, 8, rsurface_tvector3f + k * 3, v);
3124 qglVertex3f(v[0], v[1], v[2]);
3126 GL_Color(0, 1, 0, 1);
3127 for (j = 0, k = surface->num_firstvertex;j < surface->num_vertices;j++, k++)
3129 VectorCopy(rsurface_vertex3f + k * 3, v);
3130 qglVertex3f(v[0], v[1], v[2]);
3131 VectorMA(v, 8, rsurface_normal3f + k * 3, v);
3132 qglVertex3f(v[0], v[1], v[2]);
3138 if ((texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (ent->flags & RENDER_NOCULLFACE))
3139 qglEnable(GL_CULL_FACE);
3142 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight)
3144 const msurface_t *surface = ent->model->data_surfaces + surfacenumber;
3148 texture = surface->texture;
3149 if (texture->basematerialflags & MATERIALFLAG_SKY)
3150 return; // transparent sky is too difficult
3151 R_UpdateTextureInfo(ent, texture);
3153 R_Mesh_Matrix(&ent->matrix);
3154 Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
3155 R_DrawTextureSurfaceList(ent, texture->currentframe, 1, &surface, modelorg);
3158 void R_QueueTextureSurfaceList(entity_render_t *ent, texture_t *texture, int texturenumsurfaces, const msurface_t **texturesurfacelist, const vec3_t modelorg)
3160 int texturesurfaceindex;
3161 const msurface_t *surface;
3162 vec3_t tempcenter, center;
3163 if (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT)
3165 // drawing sky transparently would be too difficult
3166 if (!(texture->currentmaterialflags & MATERIALFLAG_SKY))
3168 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3170 surface = texturesurfacelist[texturesurfaceindex];
3171 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
3172 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
3173 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
3174 Matrix4x4_Transform(&ent->matrix, tempcenter, center);
3175 R_MeshQueue_AddTransparent(texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_vieworigin : center, R_DrawSurface_TransparentCallback, ent, surface - ent->model->data_surfaces, r_shadow_rtlight);
3180 R_DrawTextureSurfaceList(ent, texture, texturenumsurfaces, texturesurfacelist, modelorg);
3183 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
3184 void R_DrawSurfaces(entity_render_t *ent, qboolean skysurfaces)
3186 int i, j, f, flagsmask;
3187 int counttriangles = 0;
3188 msurface_t *surface, **surfacechain;
3189 texture_t *t, *texture;
3190 model_t *model = ent->model;
3192 const int maxsurfacelist = 1024;
3193 int numsurfacelist = 0;
3194 const msurface_t *surfacelist[1024];
3197 R_Mesh_Matrix(&ent->matrix);
3198 Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
3200 // update light styles
3201 if (!skysurfaces && model->brushq1.light_styleupdatechains)
3203 for (i = 0;i < model->brushq1.light_styles;i++)
3205 if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
3207 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
3208 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
3209 for (;(surface = *surfacechain);surfacechain++)
3210 surface->cached_dlight = true;
3215 R_UpdateAllTextureInfo(ent);
3216 flagsmask = skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL);
3221 if (ent == r_refdef.worldentity)
3223 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
3225 if (!r_worldsurfacevisible[j])
3227 if (t != surface->texture)
3231 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
3234 t = surface->texture;
3235 texture = t->currentframe;
3236 f = texture->currentmaterialflags & flagsmask;
3238 if (f && surface->num_triangles)
3240 // if lightmap parameters changed, rebuild lightmap texture
3241 if (surface->cached_dlight)
3242 R_BuildLightMap(ent, surface);
3243 // add face to draw list
3244 surfacelist[numsurfacelist++] = surface;
3245 counttriangles += surface->num_triangles;
3246 if (numsurfacelist >= maxsurfacelist)
3248 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
3256 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
3258 if (t != surface->texture)
3262 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
3265 t = surface->texture;
3266 texture = t->currentframe;
3267 f = texture->currentmaterialflags & flagsmask;
3269 if (f && surface->num_triangles)
3271 // if lightmap parameters changed, rebuild lightmap texture
3272 if (surface->cached_dlight)
3273 R_BuildLightMap(ent, surface);
3274 // add face to draw list
3275 surfacelist[numsurfacelist++] = surface;
3276 counttriangles += surface->num_triangles;
3277 if (numsurfacelist >= maxsurfacelist)
3279 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
3286 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
3287 if (!r_showtrispass)
3288 renderstats.entities_triangles += counttriangles;
3289 if (gl_support_fragment_shader)
3290 qglUseProgramObjectARB(0);