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.
27 mempool_t *r_main_mempool;
28 rtexturepool_t *r_main_texturepool;
35 r_viewcache_t r_viewcache;
37 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "1", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
38 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
39 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%, 10 = 100%)"};
40 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
41 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
42 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
43 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"};
44 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"};
45 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
46 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"};
47 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"};
48 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"};
49 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
50 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
51 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
52 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
53 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling"};
54 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
55 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
56 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
57 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
58 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
59 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
60 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
61 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this)"};
62 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
63 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
64 cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
65 cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "2", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
67 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
68 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
69 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
70 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
71 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
72 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
73 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
75 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)"};
77 cvar_t r_glsl = {CVAR_SAVE, "r_glsl", "1", "enables use of OpenGL 2.0 pixel shaders for lighting"};
78 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
79 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
80 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
81 cvar_t r_glsl_deluxemapping = {CVAR_SAVE, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"};
82 cvar_t r_glsl_contrastboost = {CVAR_SAVE, "r_glsl_contrastboost", "1", "by how much to multiply the contrast in dark areas (1 is no change)"};
84 cvar_t r_water = {CVAR_SAVE, "r_water", "0", "whether to use reflections and refraction on water surfaces (note: r_wateralpha must be set below 1)"};
85 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
86 cvar_t r_water_resolutionmultiplier = {CVAR_SAVE, "r_water_resolutionmultiplier", "0.5", "multiplier for screen resolution when rendering refracted/reflected scenes, 1 is full quality, lower values are faster"};
87 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
88 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
90 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1", "enables animation smoothing on sprites (requires r_lerpmodels 1)"};
91 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
92 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
94 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
95 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
96 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
97 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
98 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
99 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
100 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
102 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
103 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
104 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
105 cvar_t r_hdr_range = {CVAR_SAVE, "r_hdr_range", "4", "how much dynamic range to render bloom with (equivilant to multiplying r_bloom_brighten by this value and dividing r_bloom_colorscale by this value)"};
107 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"};
109 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"};
111 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
113 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
114 cvar_t r_batchmode = {0, "r_batchmode", "1", "selects method of rendering multiple surfaces with one driver call (values are 0, 1, 2, etc...)"};
116 extern qboolean v_flipped_state;
118 typedef struct r_glsl_bloomshader_s
121 int loc_Texture_Bloom;
123 r_glsl_bloomshader_t;
125 static struct r_bloomstate_s
130 int bloomwidth, bloomheight;
132 int screentexturewidth, screentextureheight;
133 rtexture_t *texture_screen;
135 int bloomtexturewidth, bloomtextureheight;
136 rtexture_t *texture_bloom;
138 r_glsl_bloomshader_t *shader;
140 // arrays for rendering the screen passes
141 float screentexcoord2f[8];
142 float bloomtexcoord2f[8];
143 float offsettexcoord2f[8];
147 typedef struct r_waterstate_waterplane_s
149 rtexture_t *texture_refraction;
150 rtexture_t *texture_reflection;
152 int materialflags; // combined flags of all water surfaces on this plane
153 unsigned char pvsbits[(32768+7)>>3]; // FIXME: buffer overflow on huge maps
156 r_waterstate_waterplane_t;
158 #define MAX_WATERPLANES 16
160 static struct r_waterstate_s
164 qboolean renderingscene; // true while rendering a refraction or reflection texture, disables water surfaces
166 int waterwidth, waterheight;
167 int texturewidth, textureheight;
169 int maxwaterplanes; // same as MAX_WATERPLANES
171 r_waterstate_waterplane_t waterplanes[MAX_WATERPLANES];
173 float screenscale[2];
174 float screencenter[2];
178 // shadow volume bsp struct with automatically growing nodes buffer
181 rtexture_t *r_texture_blanknormalmap;
182 rtexture_t *r_texture_white;
183 rtexture_t *r_texture_grey128;
184 rtexture_t *r_texture_black;
185 rtexture_t *r_texture_notexture;
186 rtexture_t *r_texture_whitecube;
187 rtexture_t *r_texture_normalizationcube;
188 rtexture_t *r_texture_fogattenuation;
189 //rtexture_t *r_texture_fogintensity;
191 char r_qwskincache[MAX_SCOREBOARD][MAX_QPATH];
192 skinframe_t *r_qwskincache_skinframe[MAX_SCOREBOARD];
194 // vertex coordinates for a quad that covers the screen exactly
195 const static float r_screenvertex3f[12] =
203 extern void R_DrawModelShadows(void);
205 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
208 for (i = 0;i < verts;i++)
219 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
222 for (i = 0;i < verts;i++)
232 // FIXME: move this to client?
235 if (gamemode == GAME_NEHAHRA)
237 Cvar_Set("gl_fogenable", "0");
238 Cvar_Set("gl_fogdensity", "0.2");
239 Cvar_Set("gl_fogred", "0.3");
240 Cvar_Set("gl_foggreen", "0.3");
241 Cvar_Set("gl_fogblue", "0.3");
243 r_refdef.fog_density = r_refdef.fog_red = r_refdef.fog_green = r_refdef.fog_blue = 0.0f;
246 float FogPoint_World(const vec3_t p)
248 int fogmasktableindex = (int)(VectorDistance((p), r_view.origin) * r_refdef.fogmasktabledistmultiplier);
249 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
252 float FogPoint_Model(const vec3_t p)
254 int fogmasktableindex = (int)(VectorDistance((p), rsurface.modelorg) * r_refdef.fogmasktabledistmultiplier);
255 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
258 static void R_BuildBlankTextures(void)
260 unsigned char data[4];
261 data[0] = 128; // normal X
262 data[1] = 128; // normal Y
263 data[2] = 255; // normal Z
264 data[3] = 128; // height
265 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
270 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
275 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
280 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
283 static void R_BuildNoTexture(void)
286 unsigned char pix[16][16][4];
287 // this makes a light grey/dark grey checkerboard texture
288 for (y = 0;y < 16;y++)
290 for (x = 0;x < 16;x++)
292 if ((y < 8) ^ (x < 8))
308 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_RGBA, TEXF_MIPMAP, NULL);
311 static void R_BuildWhiteCube(void)
313 unsigned char data[6*1*1*4];
314 data[ 0] = 255;data[ 1] = 255;data[ 2] = 255;data[ 3] = 255;
315 data[ 4] = 255;data[ 5] = 255;data[ 6] = 255;data[ 7] = 255;
316 data[ 8] = 255;data[ 9] = 255;data[10] = 255;data[11] = 255;
317 data[12] = 255;data[13] = 255;data[14] = 255;data[15] = 255;
318 data[16] = 255;data[17] = 255;data[18] = 255;data[19] = 255;
319 data[20] = 255;data[21] = 255;data[22] = 255;data[23] = 255;
320 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
323 static void R_BuildNormalizationCube(void)
327 vec_t s, t, intensity;
329 unsigned char data[6][NORMSIZE][NORMSIZE][4];
330 for (side = 0;side < 6;side++)
332 for (y = 0;y < NORMSIZE;y++)
334 for (x = 0;x < NORMSIZE;x++)
336 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
337 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
372 intensity = 127.0f / sqrt(DotProduct(v, v));
373 data[side][y][x][0] = (unsigned char)(128.0f + intensity * v[0]);
374 data[side][y][x][1] = (unsigned char)(128.0f + intensity * v[1]);
375 data[side][y][x][2] = (unsigned char)(128.0f + intensity * v[2]);
376 data[side][y][x][3] = 255;
380 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, &data[0][0][0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
383 static void R_BuildFogTexture(void)
387 unsigned char data1[FOGWIDTH][4];
388 //unsigned char data2[FOGWIDTH][4];
389 for (x = 0;x < FOGWIDTH;x++)
391 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
396 //data2[x][0] = 255 - b;
397 //data2[x][1] = 255 - b;
398 //data2[x][2] = 255 - b;
401 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
402 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
405 static const char *builtinshaderstring =
406 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
407 "// written by Forest 'LordHavoc' Hale\n"
409 "// common definitions between vertex shader and fragment shader:\n"
411 "#ifdef __GLSL_CG_DATA_TYPES\n"
412 "# define myhalf half\n"
413 "# define myhvec2 hvec2\n"
414 "# define myhvec3 hvec3\n"
415 "# define myhvec4 hvec4\n"
417 "# define myhalf float\n"
418 "# define myhvec2 vec2\n"
419 "# define myhvec3 vec3\n"
420 "# define myhvec4 vec4\n"
423 "varying vec2 TexCoord;\n"
424 "varying vec2 TexCoordLightmap;\n"
426 "//#ifdef MODE_LIGHTSOURCE\n"
427 "varying vec3 CubeVector;\n"
430 "//#ifdef MODE_LIGHTSOURCE\n"
431 "varying vec3 LightVector;\n"
433 "//# ifdef MODE_LIGHTDIRECTION\n"
434 "//varying vec3 LightVector;\n"
438 "varying vec3 EyeVector;\n"
440 "varying vec3 EyeVectorModelSpace;\n"
443 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
444 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
445 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
447 "//#ifdef MODE_WATER\n"
448 "varying vec4 ModelViewProjectionPosition;\n"
450 "//# ifdef MODE_REFRACTION\n"
451 "//varying vec4 ModelViewProjectionPosition;\n"
453 "//# ifdef USEREFLECTION\n"
454 "//varying vec4 ModelViewProjectionPosition;\n"
463 "// vertex shader specific:\n"
464 "#ifdef VERTEX_SHADER\n"
466 "uniform vec3 LightPosition;\n"
467 "uniform vec3 EyePosition;\n"
468 "uniform vec3 LightDir;\n"
470 "// TODO: get rid of tangentt (texcoord2) and use a crossproduct to regenerate it from tangents (texcoord1) and normal (texcoord3)\n"
474 " gl_FrontColor = gl_Color;\n"
475 " // copy the surface texcoord\n"
476 " TexCoord = vec2(gl_TextureMatrix[0] * gl_MultiTexCoord0);\n"
477 "#ifndef MODE_LIGHTSOURCE\n"
478 "# ifndef MODE_LIGHTDIRECTION\n"
479 " TexCoordLightmap = vec2(gl_MultiTexCoord4);\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 " // transform unnormalized eye direction into tangent space\n"
505 " vec3 EyeVectorModelSpace;\n"
507 " EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
508 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
509 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
510 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
512 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
513 " VectorS = gl_MultiTexCoord1.xyz;\n"
514 " VectorT = gl_MultiTexCoord2.xyz;\n"
515 " VectorR = gl_MultiTexCoord3.xyz;\n"
518 "//#if defined(MODE_WATER) || defined(MODE_REFRACTION) || defined(USEREFLECTION)\n"
519 "// ModelViewProjectionPosition = gl_Vertex * gl_ModelViewProjectionMatrix;\n"
520 "// //ModelViewProjectionPosition_svector = (gl_Vertex + vec4(gl_MultiTexCoord1.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
521 "// //ModelViewProjectionPosition_tvector = (gl_Vertex + vec4(gl_MultiTexCoord2.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
524 "// transform vertex to camera space, using ftransform to match non-VS\n"
526 " gl_Position = ftransform();\n"
528 "#ifdef MODE_WATER\n"
529 " ModelViewProjectionPosition = gl_Position;\n"
531 "#ifdef MODE_REFRACTION\n"
532 " ModelViewProjectionPosition = gl_Position;\n"
534 "#ifdef USEREFLECTION\n"
535 " ModelViewProjectionPosition = gl_Position;\n"
539 "#endif // VERTEX_SHADER\n"
544 "// fragment shader specific:\n"
545 "#ifdef FRAGMENT_SHADER\n"
547 "// 13 textures, we can only use up to 16 on DX9-class hardware\n"
548 "uniform sampler2D Texture_Normal;\n"
549 "uniform sampler2D Texture_Color;\n"
550 "uniform sampler2D Texture_Gloss;\n"
551 "uniform samplerCube Texture_Cube;\n"
552 "uniform sampler2D Texture_Attenuation;\n"
553 "uniform sampler2D Texture_FogMask;\n"
554 "uniform sampler2D Texture_Pants;\n"
555 "uniform sampler2D Texture_Shirt;\n"
556 "uniform sampler2D Texture_Lightmap;\n"
557 "uniform sampler2D Texture_Deluxemap;\n"
558 "uniform sampler2D Texture_Glow;\n"
559 "uniform sampler2D Texture_Reflection;\n"
560 "uniform sampler2D Texture_Refraction;\n"
562 "uniform myhvec3 LightColor;\n"
563 "uniform myhvec3 AmbientColor;\n"
564 "uniform myhvec3 DiffuseColor;\n"
565 "uniform myhvec3 SpecularColor;\n"
566 "uniform myhvec3 Color_Pants;\n"
567 "uniform myhvec3 Color_Shirt;\n"
568 "uniform myhvec3 FogColor;\n"
570 "//#ifdef MODE_WATER\n"
571 "uniform vec4 DistortScaleRefractReflect;\n"
572 "uniform vec4 ScreenScaleRefractReflect;\n"
573 "uniform vec4 ScreenCenterRefractReflect;\n"
574 "uniform myhvec4 RefractColor;\n"
575 "uniform myhvec4 ReflectColor;\n"
576 "uniform myhalf ReflectFactor;\n"
577 "uniform myhalf ReflectOffset;\n"
579 "//# ifdef MODE_REFRACTION\n"
580 "//uniform vec4 DistortScaleRefractReflect;\n"
581 "//uniform vec4 ScreenScaleRefractReflect;\n"
582 "//uniform vec4 ScreenCenterRefractReflect;\n"
583 "//uniform myhvec4 RefractColor;\n"
584 "//# ifdef USEREFLECTION\n"
585 "//uniform myhvec4 ReflectColor;\n"
588 "//# ifdef USEREFLECTION\n"
589 "//uniform vec4 DistortScaleRefractReflect;\n"
590 "//uniform vec4 ScreenScaleRefractReflect;\n"
591 "//uniform vec4 ScreenCenterRefractReflect;\n"
592 "//uniform myhvec4 ReflectColor;\n"
597 "uniform myhalf GlowScale;\n"
598 "uniform myhalf SceneBrightness;\n"
599 "#ifdef USECONTRASTBOOST\n"
600 "uniform myhalf ContrastBoostCoeff;\n"
603 "uniform float OffsetMapping_Scale;\n"
604 "uniform float OffsetMapping_Bias;\n"
605 "uniform float FogRangeRecip;\n"
607 "uniform myhalf AmbientScale;\n"
608 "uniform myhalf DiffuseScale;\n"
609 "uniform myhalf SpecularScale;\n"
610 "uniform myhalf SpecularPower;\n"
612 "#ifdef USEOFFSETMAPPING\n"
613 "vec2 OffsetMapping(vec2 TexCoord)\n"
615 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
616 " // 14 sample relief mapping: linear search and then binary search\n"
617 " // this basically steps forward a small amount repeatedly until it finds\n"
618 " // itself inside solid, then jitters forward and back using decreasing\n"
619 " // amounts to find the impact\n"
620 " //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
621 " //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
622 " vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
623 " vec3 RT = vec3(TexCoord, 1);\n"
624 " OffsetVector *= 0.1;\n"
625 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
626 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
627 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
628 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
629 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
630 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
631 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
632 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
633 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
634 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) - 0.5);\n"
635 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5 - 0.25);\n"
636 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25 - 0.125);\n"
637 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125 - 0.0625);\n"
638 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
641 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
642 " // this basically moves forward the full distance, and then backs up based\n"
643 " // on height of samples\n"
644 " //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
645 " //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
646 " vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
647 " TexCoord += OffsetVector;\n"
648 " OffsetVector *= 0.333;\n"
649 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
650 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
651 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
652 " return TexCoord;\n"
655 "#endif // USEOFFSETMAPPING\n"
657 "#ifdef MODE_WATER\n"
662 "#ifdef USEOFFSETMAPPING\n"
663 " // apply offsetmapping\n"
664 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
665 "#define TexCoord TexCoordOffset\n"
668 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
669 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
670 " vec4 ScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect + vec2(normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5))).xyxy * DistortScaleRefractReflect;\n"
671 " float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 5.0) * ReflectFactor + ReflectOffset;\n"
672 " gl_FragColor = mix(texture2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, texture2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
675 "#else // MODE_WATER\n"
676 "#ifdef MODE_REFRACTION\n"
678 "// refraction pass\n"
681 "#ifdef USEOFFSETMAPPING\n"
682 " // apply offsetmapping\n"
683 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
684 "#define TexCoord TexCoordOffset\n"
687 " vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
688 " //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
689 " vec2 ScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy + vec2(normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
690 " gl_FragColor = texture2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
693 "#else // MODE_REFRACTION\n"
696 "#ifdef USEOFFSETMAPPING\n"
697 " // apply offsetmapping\n"
698 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
699 "#define TexCoord TexCoordOffset\n"
702 " // combine the diffuse textures (base, pants, shirt)\n"
703 " myhvec4 color = myhvec4(texture2D(Texture_Color, TexCoord));\n"
704 "#ifdef USECOLORMAPPING\n"
705 " color.rgb += myhvec3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhvec3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
711 "#ifdef MODE_LIGHTSOURCE\n"
714 " // calculate surface normal, light normal, and specular normal\n"
715 " // compute color intensity for the two textures (colormap and glossmap)\n"
716 " // scale by light color and attenuation as efficiently as possible\n"
717 " // (do as much scalar math as possible rather than vector math)\n"
718 "# ifdef USESPECULAR\n"
719 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
720 " myhvec3 diffusenormal = myhvec3(normalize(LightVector));\n"
721 " myhvec3 specularnormal = normalize(diffusenormal + myhvec3(normalize(EyeVector)));\n"
723 " // calculate directional shading\n"
724 " color.rgb = LightColor * myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0))) * (color.rgb * (AmbientScale + DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0))) + (SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower)) * myhvec3(texture2D(Texture_Gloss, TexCoord)));\n"
726 "# ifdef USEDIFFUSE\n"
727 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
728 " myhvec3 diffusenormal = myhvec3(normalize(LightVector));\n"
730 " // calculate directional shading\n"
731 " color.rgb = color.rgb * LightColor * (myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0))) * (AmbientScale + DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0))));\n"
733 " // calculate directionless shading\n"
734 " color.rgb = color.rgb * LightColor * myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
738 "# ifdef USECUBEFILTER\n"
739 " // apply light cubemap filter\n"
740 " //color.rgb *= normalize(CubeVector) * 0.5 + 0.5;//vec3(textureCube(Texture_Cube, CubeVector));\n"
741 " color.rgb *= myhvec3(textureCube(Texture_Cube, CubeVector));\n"
743 " color *= myhvec4(gl_Color);\n"
744 "#endif // MODE_LIGHTSOURCE\n"
749 "#ifdef MODE_LIGHTDIRECTION\n"
750 " // directional model lighting\n"
752 " // get the surface normal and light normal\n"
753 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
754 " myhvec3 diffusenormal = myhvec3(LightVector);\n"
756 " // calculate directional shading\n"
757 " color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
758 "# ifdef USESPECULAR\n"
759 " myhvec3 specularnormal = normalize(diffusenormal + myhvec3(normalize(EyeVector)));\n"
760 " color.rgb += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
762 " color *= myhvec4(gl_Color);\n"
763 "#endif // MODE_LIGHTDIRECTION\n"
768 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
769 " // deluxemap lightmapping using light vectors in modelspace (evil q3map2)\n"
771 " // get the surface normal and light normal\n"
772 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
774 " myhvec3 diffusenormal_modelspace = myhvec3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - myhvec3(0.5);\n"
775 " myhvec3 diffusenormal = normalize(myhvec3(dot(diffusenormal_modelspace, myhvec3(VectorS)), dot(diffusenormal_modelspace, myhvec3(VectorT)), dot(diffusenormal_modelspace, myhvec3(VectorR))));\n"
776 " // calculate directional shading\n"
777 " myhvec3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0)));\n"
778 "# ifdef USESPECULAR\n"
779 " myhvec3 specularnormal = myhvec3(normalize(diffusenormal + myhvec3(normalize(EyeVector))));\n"
780 " tempcolor += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
783 " // apply lightmap color\n"
784 " color.rgb = myhvec4(tempcolor,1) * myhvec4(texture2D(Texture_Lightmap, TexCoordLightmap)) * myhvec4(gl_Color) + myhvec4(color.rgb * AmbientScale, 0);\n"
785 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
790 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
791 " // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
793 " // get the surface normal and light normal\n"
794 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
796 " myhvec3 diffusenormal = normalize(myhvec3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - myhvec3(0.5));\n"
797 " // calculate directional shading\n"
798 " myhvec3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0)));\n"
799 "# ifdef USESPECULAR\n"
800 " myhvec3 specularnormal = myhvec3(normalize(diffusenormal + myhvec3(normalize(EyeVector))));\n"
801 " tempcolor += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
804 " // apply lightmap color\n"
805 " color = myhvec4(tempcolor, 1) * myhvec4(texture2D(Texture_Lightmap, TexCoordLightmap)) * myhvec4(gl_Color) + myhvec4(color.rgb * AmbientScale, 0);\n"
806 "#endif // MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
811 "#ifdef MODE_LIGHTMAP\n"
812 " // apply lightmap color\n"
813 " color *= myhvec4(texture2D(Texture_Lightmap, TexCoordLightmap)) * myhvec4(gl_Color) * myhvec4(myhvec3(DiffuseScale), 1) + myhvec4(myhvec3(AmbientScale), 0);\n"
814 "#endif // MODE_LIGHTMAP\n"
824 " color.rgb += myhvec3(texture2D(Texture_Glow, TexCoord)) * GlowScale;\n"
827 "#ifndef MODE_LIGHTSOURCE\n"
828 "# ifdef USEREFLECTION\n"
829 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
830 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
831 " vec4 ScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect + vec3(normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5))).xyxy * DistortScaleRefractReflect;\n"
832 " color.rgb = mix(color.rgb, myhvec3(texture2D(Texture_Reflection, ScreenTexCoord.zw)) * ReflectColor.rgb, ReflectColor.a);\n"
838 " color.rgb = mix(FogColor, color.rgb, myhalf(texture2D(Texture_FogMask, myhvec2(length(EyeVectorModelSpace)*FogRangeRecip, 0.0))));\n"
841 "#ifdef USECONTRASTBOOST\n"
842 " color.rgb = color.rgb / (ContrastBoostCoeff * color.rgb + myhvec3(1, 1, 1));\n"
845 " color.rgb *= SceneBrightness;\n"
847 " gl_FragColor = vec4(color);\n"
849 "#endif // MODE_REFRACTION\n"
850 "#endif // MODE_WATER\n"
852 "#endif // FRAGMENT_SHADER\n"
855 #define SHADERPERMUTATION_COLORMAPPING (1<<0) // indicates this is a colormapped skin
856 #define SHADERPERMUTATION_CONTRASTBOOST (1<<1) // r_glsl_contrastboost boosts the contrast at low color levels (similar to gamma)
857 #define SHADERPERMUTATION_FOG (1<<2) // tint the color by fog color or black if using additive blend mode
858 #define SHADERPERMUTATION_CUBEFILTER (1<<3) // (lightsource) use cubemap light filter
859 #define SHADERPERMUTATION_GLOW (1<<4) // (lightmap) blend in an additive glow texture
860 #define SHADERPERMUTATION_DIFFUSE (1<<5) // (lightsource) whether to use directional shading
861 #define SHADERPERMUTATION_SPECULAR (1<<6) // (lightsource or deluxemapping) render specular effects
862 #define SHADERPERMUTATION_REFLECTION (1<<7) // normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
863 #define SHADERPERMUTATION_OFFSETMAPPING (1<<8) // adjust texcoords to roughly simulate a displacement mapped surface
864 #define SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING (1<<9) // adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
865 #define SHADERPERMUTATION_MODEBASE (1<<10) // multiplier for the SHADERMODE_ values to get a valid index
867 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
868 const char *shaderpermutationinfo[][2] =
870 {"#define USECOLORMAPPING\n", " colormapping"},
871 {"#define USECONTRASTBOOST\n", " contrastboost"},
872 {"#define USEFOG\n", " fog"},
873 {"#define USECUBEFILTER\n", " cubefilter"},
874 {"#define USEGLOW\n", " glow"},
875 {"#define USEDIFFUSE\n", " diffuse"},
876 {"#define USESPECULAR\n", " specular"},
877 {"#define USEREFLECTION\n", " reflection"},
878 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
879 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
883 // this enum is multiplied by SHADERPERMUTATION_MODEBASE
884 typedef enum shadermode_e
886 SHADERMODE_LIGHTMAP, // (lightmap) use directional pixel shading from fixed light direction (q3bsp)
887 SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, // (lightmap) use directional pixel shading from texture containing modelspace light directions (deluxemap)
888 SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, // (lightmap) use directional pixel shading from texture containing tangentspace light directions (deluxemap)
889 SHADERMODE_LIGHTDIRECTION, // (lightmap) use directional pixel shading from fixed light direction (q3bsp)
890 SHADERMODE_LIGHTSOURCE, // (lightsource) use directional pixel shading from light source (rtlight)
891 SHADERMODE_REFRACTION, // refract background (the material is rendered normally after this pass)
892 SHADERMODE_WATER, // refract background and reflection (the material is rendered normally after this pass)
897 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
898 const char *shadermodeinfo[][2] =
900 {"#define MODE_LIGHTMAP\n", " lightmap"},
901 {"#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
902 {"#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
903 {"#define MODE_LIGHTDIRECTION\n", " lightdirection"},
904 {"#define MODE_LIGHTSOURCE\n", " lightsource"},
905 {"#define MODE_REFRACTION\n", " refraction"},
906 {"#define MODE_WATER\n", " water"},
910 #define SHADERPERMUTATION_INDICES (SHADERPERMUTATION_MODEBASE * SHADERMODE_COUNT)
912 typedef struct r_glsl_permutation_s
914 // indicates if we have tried compiling this permutation already
916 // 0 if compilation failed
918 // locations of detected uniforms in program object, or -1 if not found
919 int loc_Texture_Normal;
920 int loc_Texture_Color;
921 int loc_Texture_Gloss;
922 int loc_Texture_Cube;
923 int loc_Texture_Attenuation;
924 int loc_Texture_FogMask;
925 int loc_Texture_Pants;
926 int loc_Texture_Shirt;
927 int loc_Texture_Lightmap;
928 int loc_Texture_Deluxemap;
929 int loc_Texture_Glow;
930 int loc_Texture_Refraction;
931 int loc_Texture_Reflection;
933 int loc_LightPosition;
938 int loc_FogRangeRecip;
939 int loc_AmbientScale;
940 int loc_DiffuseScale;
941 int loc_SpecularScale;
942 int loc_SpecularPower;
944 int loc_SceneBrightness; // or: Scenebrightness * ContrastBoost
945 int loc_OffsetMapping_Scale;
946 int loc_AmbientColor;
947 int loc_DiffuseColor;
948 int loc_SpecularColor;
950 int loc_ContrastBoostCoeff; // 1 - 1/ContrastBoost
951 int loc_DistortScaleRefractReflect;
952 int loc_ScreenScaleRefractReflect;
953 int loc_ScreenCenterRefractReflect;
954 int loc_RefractColor;
955 int loc_ReflectColor;
956 int loc_ReflectFactor;
957 int loc_ReflectOffset;
959 r_glsl_permutation_t;
961 // information about each possible shader permutation
962 r_glsl_permutation_t r_glsl_permutations[SHADERPERMUTATION_INDICES];
963 // currently selected permutation
964 r_glsl_permutation_t *r_glsl_permutation;
966 // these are additional flags used only by R_GLSL_CompilePermutation
967 #define SHADERTYPE_USES_VERTEXSHADER (1<<0)
968 #define SHADERTYPE_USES_GEOMETRYSHADER (1<<1)
969 #define SHADERTYPE_USES_FRAGMENTSHADER (1<<2)
971 static void R_GLSL_CompilePermutation(const char *filename, int permutation, int shadertype)
974 qboolean shaderfound;
975 r_glsl_permutation_t *p = r_glsl_permutations + permutation;
976 int vertstrings_count;
977 int geomstrings_count;
978 int fragstrings_count;
980 const char *vertstrings_list[32+1];
981 const char *geomstrings_list[32+1];
982 const char *fragstrings_list[32+1];
983 char permutationname[256];
988 vertstrings_list[0] = "#define VERTEX_SHADER\n";
989 geomstrings_list[0] = "#define GEOMETRY_SHADER\n";
990 fragstrings_list[0] = "#define FRAGMENT_SHADER\n";
991 vertstrings_count = 1;
992 geomstrings_count = 1;
993 fragstrings_count = 1;
994 permutationname[0] = 0;
995 i = permutation / SHADERPERMUTATION_MODEBASE;
996 vertstrings_list[vertstrings_count++] = shadermodeinfo[i][0];
997 geomstrings_list[geomstrings_count++] = shadermodeinfo[i][0];
998 fragstrings_list[fragstrings_count++] = shadermodeinfo[i][0];
999 strlcat(permutationname, shadermodeinfo[i][1], sizeof(permutationname));
1000 for (i = 0;shaderpermutationinfo[i][0];i++)
1002 if (permutation & (1<<i))
1004 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i][0];
1005 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i][0];
1006 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i][0];
1007 strlcat(permutationname, shaderpermutationinfo[i][1], sizeof(permutationname));
1011 // keep line numbers correct
1012 vertstrings_list[vertstrings_count++] = "\n";
1013 geomstrings_list[geomstrings_count++] = "\n";
1014 fragstrings_list[fragstrings_count++] = "\n";
1017 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1018 shaderfound = false;
1021 Con_DPrint("from disk... ");
1022 vertstrings_list[vertstrings_count++] = shaderstring;
1023 geomstrings_list[geomstrings_count++] = shaderstring;
1024 fragstrings_list[fragstrings_count++] = shaderstring;
1027 else if (!strcmp(filename, "glsl/default.glsl"))
1029 vertstrings_list[vertstrings_count++] = builtinshaderstring;
1030 geomstrings_list[geomstrings_count++] = builtinshaderstring;
1031 fragstrings_list[fragstrings_count++] = builtinshaderstring;
1034 // clear any lists that are not needed by this shader
1035 if (!(shadertype & SHADERTYPE_USES_VERTEXSHADER))
1036 vertstrings_count = 0;
1037 if (!(shadertype & SHADERTYPE_USES_GEOMETRYSHADER))
1038 geomstrings_count = 0;
1039 if (!(shadertype & SHADERTYPE_USES_FRAGMENTSHADER))
1040 fragstrings_count = 0;
1041 // compile the shader program
1042 if (shaderfound && vertstrings_count + geomstrings_count + fragstrings_count)
1043 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1047 qglUseProgramObjectARB(p->program);CHECKGLERROR
1048 // look up all the uniform variable names we care about, so we don't
1049 // have to look them up every time we set them
1050 p->loc_Texture_Normal = qglGetUniformLocationARB(p->program, "Texture_Normal");
1051 p->loc_Texture_Color = qglGetUniformLocationARB(p->program, "Texture_Color");
1052 p->loc_Texture_Gloss = qglGetUniformLocationARB(p->program, "Texture_Gloss");
1053 p->loc_Texture_Cube = qglGetUniformLocationARB(p->program, "Texture_Cube");
1054 p->loc_Texture_Attenuation = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
1055 p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
1056 p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
1057 p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
1058 p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
1059 p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
1060 p->loc_Texture_Glow = qglGetUniformLocationARB(p->program, "Texture_Glow");
1061 p->loc_Texture_Refraction = qglGetUniformLocationARB(p->program, "Texture_Refraction");
1062 p->loc_Texture_Reflection = qglGetUniformLocationARB(p->program, "Texture_Reflection");
1063 p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
1064 p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
1065 p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
1066 p->loc_LightColor = qglGetUniformLocationARB(p->program, "LightColor");
1067 p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants");
1068 p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt");
1069 p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip");
1070 p->loc_AmbientScale = qglGetUniformLocationARB(p->program, "AmbientScale");
1071 p->loc_DiffuseScale = qglGetUniformLocationARB(p->program, "DiffuseScale");
1072 p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
1073 p->loc_SpecularScale = qglGetUniformLocationARB(p->program, "SpecularScale");
1074 p->loc_GlowScale = qglGetUniformLocationARB(p->program, "GlowScale");
1075 p->loc_SceneBrightness = qglGetUniformLocationARB(p->program, "SceneBrightness");
1076 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
1077 p->loc_AmbientColor = qglGetUniformLocationARB(p->program, "AmbientColor");
1078 p->loc_DiffuseColor = qglGetUniformLocationARB(p->program, "DiffuseColor");
1079 p->loc_SpecularColor = qglGetUniformLocationARB(p->program, "SpecularColor");
1080 p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
1081 p->loc_ContrastBoostCoeff = qglGetUniformLocationARB(p->program, "ContrastBoostCoeff");
1082 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
1083 p->loc_ScreenScaleRefractReflect = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
1084 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
1085 p->loc_RefractColor = qglGetUniformLocationARB(p->program, "RefractColor");
1086 p->loc_ReflectColor = qglGetUniformLocationARB(p->program, "ReflectColor");
1087 p->loc_ReflectFactor = qglGetUniformLocationARB(p->program, "ReflectFactor");
1088 p->loc_ReflectOffset = qglGetUniformLocationARB(p->program, "ReflectOffset");
1089 // initialize the samplers to refer to the texture units we use
1090 if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal, 0);
1091 if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color, 1);
1092 if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss, 2);
1093 if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube, 3);
1094 if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask, 4);
1095 if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants, 5);
1096 if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt, 6);
1097 if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap, 7);
1098 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap, 8);
1099 if (p->loc_Texture_Glow >= 0) qglUniform1iARB(p->loc_Texture_Glow, 9);
1100 if (p->loc_Texture_Attenuation >= 0) qglUniform1iARB(p->loc_Texture_Attenuation, 10);
1101 if (p->loc_Texture_Refraction >= 0) qglUniform1iARB(p->loc_Texture_Refraction, 11);
1102 if (p->loc_Texture_Reflection >= 0) qglUniform1iARB(p->loc_Texture_Reflection, 12);
1104 qglUseProgramObjectARB(0);CHECKGLERROR
1105 if (developer.integer)
1106 Con_Printf("GLSL shader %s :%s compiled.\n", filename, permutationname);
1110 if (developer.integer)
1111 Con_Printf("GLSL shader %s :%s failed! source code line offset for above errors is %i.\n", permutationname, filename, -(vertstrings_count - 1));
1113 Con_Printf("GLSL shader %s :%s failed! some features may not work properly.\n", permutationname, filename);
1116 Mem_Free(shaderstring);
1119 void R_GLSL_Restart_f(void)
1122 for (i = 0;i < SHADERPERMUTATION_INDICES;i++)
1123 if (r_glsl_permutations[i].program)
1124 GL_Backend_FreeProgram(r_glsl_permutations[i].program);
1125 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
1128 void R_GLSL_DumpShader_f(void)
1132 qfile_t *file = FS_Open("glsl/default.glsl", "w", false, false);
1135 Con_Printf("failed to write to glsl/default.glsl\n");
1139 FS_Print(file, "// The engine may define the following macros:\n");
1140 FS_Print(file, "// #define VERTEX_SHADER\n// #define GEOMETRY_SHADER\n// #define FRAGMENT_SHADER\n");
1141 for (i = 0;shadermodeinfo[i][0];i++)
1142 FS_Printf(file, "// %s", shadermodeinfo[i][0]);
1143 for (i = 0;shaderpermutationinfo[i][0];i++)
1144 FS_Printf(file, "// %s", shaderpermutationinfo[i][0]);
1145 FS_Print(file, "\n");
1146 FS_Print(file, builtinshaderstring);
1149 Con_Printf("glsl/default.glsl written\n");
1152 extern rtexture_t *r_shadow_attenuationgradienttexture;
1153 extern rtexture_t *r_shadow_attenuation2dtexture;
1154 extern rtexture_t *r_shadow_attenuation3dtexture;
1155 int R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass)
1157 // select a permutation of the lighting shader appropriate to this
1158 // combination of texture, entity, light source, and fogging, only use the
1159 // minimum features necessary to avoid wasting rendering time in the
1160 // fragment shader on features that are not being used
1161 const char *shaderfilename = NULL;
1162 unsigned int permutation = 0;
1163 unsigned int shadertype = 0;
1164 shadermode_t mode = 0;
1165 r_glsl_permutation = NULL;
1166 shaderfilename = "glsl/default.glsl";
1167 shadertype = SHADERTYPE_USES_VERTEXSHADER | SHADERTYPE_USES_FRAGMENTSHADER;
1168 // TODO: implement geometry-shader based shadow volumes someday
1169 if (r_glsl_offsetmapping.integer)
1171 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
1172 if (r_glsl_offsetmapping_reliefmapping.integer)
1173 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
1175 if (rsurfacepass == RSURFPASS_BACKGROUND)
1177 // distorted background
1178 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
1179 mode = SHADERMODE_WATER;
1181 mode = SHADERMODE_REFRACTION;
1183 else if (rsurfacepass == RSURFPASS_RTLIGHT)
1186 mode = SHADERMODE_LIGHTSOURCE;
1187 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
1188 permutation |= SHADERPERMUTATION_CUBEFILTER;
1189 if (diffusescale > 0)
1190 permutation |= SHADERPERMUTATION_DIFFUSE;
1191 if (specularscale > 0)
1192 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
1193 if (r_refdef.fogenabled)
1194 permutation |= SHADERPERMUTATION_FOG;
1195 if (rsurface.texture->colormapping)
1196 permutation |= SHADERPERMUTATION_COLORMAPPING;
1197 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1198 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1199 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1200 permutation |= SHADERPERMUTATION_REFLECTION;
1202 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
1204 // bright unshaded geometry
1205 mode = SHADERMODE_LIGHTMAP;
1206 if (rsurface.texture->currentskinframe->glow)
1207 permutation |= SHADERPERMUTATION_GLOW;
1208 if (r_refdef.fogenabled)
1209 permutation |= SHADERPERMUTATION_FOG;
1210 if (rsurface.texture->colormapping)
1211 permutation |= SHADERPERMUTATION_COLORMAPPING;
1212 if (r_glsl_offsetmapping.integer)
1214 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
1215 if (r_glsl_offsetmapping_reliefmapping.integer)
1216 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
1218 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1219 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1220 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1221 permutation |= SHADERPERMUTATION_REFLECTION;
1223 else if (modellighting)
1225 // directional model lighting
1226 mode = SHADERMODE_LIGHTDIRECTION;
1227 if (rsurface.texture->currentskinframe->glow)
1228 permutation |= SHADERPERMUTATION_GLOW;
1229 if (specularscale > 0)
1230 permutation |= SHADERPERMUTATION_SPECULAR;
1231 if (r_refdef.fogenabled)
1232 permutation |= SHADERPERMUTATION_FOG;
1233 if (rsurface.texture->colormapping)
1234 permutation |= SHADERPERMUTATION_COLORMAPPING;
1235 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1236 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1237 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1238 permutation |= SHADERPERMUTATION_REFLECTION;
1243 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.worldmodel && r_refdef.worldmodel->brushq3.deluxemapping)
1245 // deluxemapping (light direction texture)
1246 if (rsurface.uselightmaptexture && r_refdef.worldmodel && r_refdef.worldmodel->brushq3.deluxemapping && r_refdef.worldmodel->brushq3.deluxemapping_modelspace)
1247 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
1249 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
1250 if (specularscale > 0)
1251 permutation |= SHADERPERMUTATION_SPECULAR;
1253 else if (r_glsl_deluxemapping.integer >= 2)
1255 // fake deluxemapping (uniform light direction in tangentspace)
1256 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
1257 if (specularscale > 0)
1258 permutation |= SHADERPERMUTATION_SPECULAR;
1262 // ordinary lightmapping
1263 mode = SHADERMODE_LIGHTMAP;
1265 if (rsurface.texture->currentskinframe->glow)
1266 permutation |= SHADERPERMUTATION_GLOW;
1267 if (r_refdef.fogenabled)
1268 permutation |= SHADERPERMUTATION_FOG;
1269 if (rsurface.texture->colormapping)
1270 permutation |= SHADERPERMUTATION_COLORMAPPING;
1271 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1272 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1273 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1274 permutation |= SHADERPERMUTATION_REFLECTION;
1276 permutation |= mode * SHADERPERMUTATION_MODEBASE;
1277 if (!r_glsl_permutations[permutation].program)
1279 if (!r_glsl_permutations[permutation].compiled)
1280 R_GLSL_CompilePermutation(shaderfilename, permutation, shadertype);
1281 if (!r_glsl_permutations[permutation].program)
1283 // remove features until we find a valid permutation
1285 for (i = (SHADERPERMUTATION_MODEBASE >> 1);;i>>=1)
1289 Con_Printf("OpenGL 2.0 shaders disabled - unable to find a working shader permutation fallback on this driver (set r_glsl 1 if you want to try again)\n");
1290 Cvar_SetValueQuick(&r_glsl, 0);
1291 return 0; // no bit left to clear
1293 // reduce i more quickly whenever it would not remove any bits
1294 if (!(permutation & i))
1297 if (!r_glsl_permutations[permutation].compiled)
1298 R_GLSL_CompilePermutation(shaderfilename, permutation, shadertype);
1299 if (r_glsl_permutations[permutation].program)
1304 r_glsl_permutation = r_glsl_permutations + permutation;
1306 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
1307 if (mode == SHADERMODE_LIGHTSOURCE)
1309 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
1310 if (permutation & SHADERPERMUTATION_DIFFUSE)
1312 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
1313 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, ambientscale);
1314 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, diffusescale);
1315 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, specularscale);
1319 // ambient only is simpler
1320 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0] * ambientscale, lightcolorbase[1] * ambientscale, lightcolorbase[2] * ambientscale);
1321 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, 1);
1322 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, 0);
1323 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, 0);
1326 else if (mode == SHADERMODE_LIGHTDIRECTION)
1328 if (r_glsl_permutation->loc_AmbientColor >= 0)
1329 qglUniform3fARB(r_glsl_permutation->loc_AmbientColor, rsurface.modellight_ambient[0] * ambientscale, rsurface.modellight_ambient[1] * ambientscale, rsurface.modellight_ambient[2] * ambientscale);
1330 if (r_glsl_permutation->loc_DiffuseColor >= 0)
1331 qglUniform3fARB(r_glsl_permutation->loc_DiffuseColor, rsurface.modellight_diffuse[0] * diffusescale, rsurface.modellight_diffuse[1] * diffusescale, rsurface.modellight_diffuse[2] * diffusescale);
1332 if (r_glsl_permutation->loc_SpecularColor >= 0)
1333 qglUniform3fARB(r_glsl_permutation->loc_SpecularColor, rsurface.modellight_diffuse[0] * specularscale, rsurface.modellight_diffuse[1] * specularscale, rsurface.modellight_diffuse[2] * specularscale);
1334 if (r_glsl_permutation->loc_LightDir >= 0)
1335 qglUniform3fARB(r_glsl_permutation->loc_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
1339 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_ambient.value * 2.0f / 128.0f);
1340 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_refdef.lightmapintensity * 2.0f);
1341 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, r_refdef.lightmapintensity * specularscale * 2.0f);
1343 if (r_glsl_permutation->loc_GlowScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_GlowScale, r_hdr_glowintensity.value);
1344 if (r_glsl_permutation->loc_ContrastBoostCoeff >= 0)
1346 // The formula used is actually:
1347 // color.rgb *= SceneBrightness;
1348 // color.rgb *= ContrastBoost / ((ContrastBoost - 1) * color.rgb + 1);
1349 // I simplify that to
1350 // color.rgb *= [[SceneBrightness * ContrastBoost]];
1351 // color.rgb /= [[(ContrastBoost - 1) / ContrastBoost]] * color.rgb + 1;
1353 // color.rgb = [[SceneBrightness * ContrastBoost]] / ([[(ContrastBoost - 1) * SceneBrightness]] + 1 / color.rgb);
1354 // and do [[calculations]] here in the engine
1355 qglUniform1fARB(r_glsl_permutation->loc_ContrastBoostCoeff, (r_glsl_contrastboost.value - 1) * r_view.colorscale);
1356 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_view.colorscale * r_glsl_contrastboost.value);
1359 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_view.colorscale);
1360 if (r_glsl_permutation->loc_FogColor >= 0)
1362 // additive passes are only darkened by fog, not tinted
1363 if (rsurface.rtlight || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD))
1364 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
1366 qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
1368 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.modelorg[0], rsurface.modelorg[1], rsurface.modelorg[2]);
1369 if (r_glsl_permutation->loc_Color_Pants >= 0)
1371 if (rsurface.texture->currentskinframe->pants)
1372 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
1374 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
1376 if (r_glsl_permutation->loc_Color_Shirt >= 0)
1378 if (rsurface.texture->currentskinframe->shirt)
1379 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
1381 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
1383 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, r_refdef.fograngerecip);
1384 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower);
1385 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
1386 if (r_glsl_permutation->loc_DistortScaleRefractReflect >= 0) qglUniform4fARB(r_glsl_permutation->loc_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);
1387 if (r_glsl_permutation->loc_ScreenScaleRefractReflect >= 0) qglUniform4fARB(r_glsl_permutation->loc_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
1388 if (r_glsl_permutation->loc_ScreenCenterRefractReflect >= 0) qglUniform4fARB(r_glsl_permutation->loc_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
1389 if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f);
1390 if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f);
1391 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
1392 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
1397 #define SKINFRAME_HASH 1024
1401 int loadsequence; // incremented each level change
1402 memexpandablearray_t array;
1403 skinframe_t *hash[SKINFRAME_HASH];
1407 void R_SkinFrame_PrepareForPurge(void)
1409 r_skinframe.loadsequence++;
1410 // wrap it without hitting zero
1411 if (r_skinframe.loadsequence >= 200)
1412 r_skinframe.loadsequence = 1;
1415 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
1419 // mark the skinframe as used for the purging code
1420 skinframe->loadsequence = r_skinframe.loadsequence;
1423 void R_SkinFrame_Purge(void)
1427 for (i = 0;i < SKINFRAME_HASH;i++)
1429 for (s = r_skinframe.hash[i];s;s = s->next)
1431 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
1433 if (s->base == r_texture_notexture) s->base = NULL;
1434 if (s->nmap == r_texture_blanknormalmap)s->nmap = NULL;
1435 if (s->merged == s->base) s->merged = NULL;
1436 if (s->stain ) R_FreeTexture(s->stain );s->stain = NULL;
1437 if (s->merged) R_FreeTexture(s->merged);s->merged = NULL;
1438 if (s->base ) R_FreeTexture(s->base );s->base = NULL;
1439 if (s->pants ) R_FreeTexture(s->pants );s->pants = NULL;
1440 if (s->shirt ) R_FreeTexture(s->shirt );s->shirt = NULL;
1441 if (s->nmap ) R_FreeTexture(s->nmap );s->nmap = NULL;
1442 if (s->gloss ) R_FreeTexture(s->gloss );s->gloss = NULL;
1443 if (s->glow ) R_FreeTexture(s->glow );s->glow = NULL;
1444 if (s->fog ) R_FreeTexture(s->fog );s->fog = NULL;
1445 s->loadsequence = 0;
1451 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
1455 char basename[MAX_QPATH];
1457 Image_StripImageExtension(name, basename, sizeof(basename));
1459 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
1460 for (item = r_skinframe.hash[hashindex];item;item = item->next)
1461 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
1467 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
1468 memset(item, 0, sizeof(*item));
1469 strlcpy(item->basename, basename, sizeof(item->basename));
1470 item->textureflags = textureflags;
1471 item->comparewidth = comparewidth;
1472 item->compareheight = compareheight;
1473 item->comparecrc = comparecrc;
1474 item->next = r_skinframe.hash[hashindex];
1475 r_skinframe.hash[hashindex] = item;
1477 R_SkinFrame_MarkUsed(item);
1481 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
1483 // FIXME: it should be possible to disable loading various layers using
1484 // cvars, to prevent wasted loading time and memory usage if the user does
1486 qboolean loadnormalmap = true;
1487 qboolean loadgloss = true;
1488 qboolean loadpantsandshirt = true;
1489 qboolean loadglow = true;
1491 unsigned char *pixels;
1492 unsigned char *bumppixels;
1493 unsigned char *basepixels = NULL;
1494 int basepixels_width;
1495 int basepixels_height;
1496 skinframe_t *skinframe;
1498 if (cls.state == ca_dedicated)
1501 // return an existing skinframe if already loaded
1502 // if loading of the first image fails, don't make a new skinframe as it
1503 // would cause all future lookups of this to be missing
1504 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
1505 if (skinframe && skinframe->base)
1508 basepixels = loadimagepixels(name, complain, 0, 0);
1509 if (basepixels == NULL)
1512 // we've got some pixels to store, so really allocate this new texture now
1514 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
1515 skinframe->stain = NULL;
1516 skinframe->merged = NULL;
1517 skinframe->base = r_texture_notexture;
1518 skinframe->pants = NULL;
1519 skinframe->shirt = NULL;
1520 skinframe->nmap = r_texture_blanknormalmap;
1521 skinframe->gloss = NULL;
1522 skinframe->glow = NULL;
1523 skinframe->fog = NULL;
1525 basepixels_width = image_width;
1526 basepixels_height = image_height;
1527 skinframe->base = R_LoadTexture2D (r_main_texturepool, skinframe->basename, basepixels_width, basepixels_height, basepixels, TEXTYPE_RGBA, skinframe->textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), NULL);
1529 if (textureflags & TEXF_ALPHA)
1531 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
1532 if (basepixels[j] < 255)
1534 if (j < basepixels_width * basepixels_height * 4)
1536 // has transparent pixels
1537 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
1538 for (j = 0;j < image_width * image_height * 4;j += 4)
1543 pixels[j+3] = basepixels[j+3];
1545 skinframe->fog = R_LoadTexture2D (r_main_texturepool, va("%s_mask", skinframe->basename), image_width, image_height, pixels, TEXTYPE_RGBA, skinframe->textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), NULL);
1550 // _norm is the name used by tenebrae and has been adopted as standard
1553 if ((pixels = loadimagepixels(va("%s_norm", skinframe->basename), false, 0, 0)) != NULL)
1555 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_RGBA, skinframe->textureflags & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), NULL);
1559 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixels(va("%s_bump", skinframe->basename), false, 0, 0)) != NULL)
1561 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
1562 Image_HeightmapToNormalmap(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
1563 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_RGBA, skinframe->textureflags & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), NULL);
1565 Mem_Free(bumppixels);
1567 else if (r_shadow_bumpscale_basetexture.value > 0)
1569 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
1570 Image_HeightmapToNormalmap(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
1571 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), basepixels_width, basepixels_height, pixels, TEXTYPE_RGBA, skinframe->textureflags & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), NULL);
1575 // _luma is supported for tenebrae compatibility
1576 // (I think it's a very stupid name, but oh well)
1577 // _glow is the preferred name
1578 if (loadglow && ((pixels = loadimagepixels(va("%s_glow", skinframe->basename), false, 0, 0)) != NULL || (pixels = loadimagepixels(va("%s_luma", skinframe->basename), false, 0, 0)) != NULL)) {skinframe->glow = R_LoadTexture2D (r_main_texturepool, va("%s_glow", skinframe->basename), image_width, image_height, pixels, TEXTYPE_RGBA, skinframe->textureflags & (gl_texturecompression_glow.integer ? ~0 : ~TEXF_COMPRESS), NULL);Mem_Free(pixels);pixels = NULL;}
1579 if (loadgloss && (pixels = loadimagepixels(va("%s_gloss", skinframe->basename), false, 0, 0)) != NULL) {skinframe->gloss = R_LoadTexture2D (r_main_texturepool, va("%s_gloss", skinframe->basename), image_width, image_height, pixels, TEXTYPE_RGBA, skinframe->textureflags & (gl_texturecompression_gloss.integer ? ~0 : ~TEXF_COMPRESS), NULL);Mem_Free(pixels);pixels = NULL;}
1580 if (loadpantsandshirt && (pixels = loadimagepixels(va("%s_pants", skinframe->basename), false, 0, 0)) != NULL) {skinframe->pants = R_LoadTexture2D (r_main_texturepool, va("%s_pants", skinframe->basename), image_width, image_height, pixels, TEXTYPE_RGBA, skinframe->textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), NULL);Mem_Free(pixels);pixels = NULL;}
1581 if (loadpantsandshirt && (pixels = loadimagepixels(va("%s_shirt", skinframe->basename), false, 0, 0)) != NULL) {skinframe->shirt = R_LoadTexture2D (r_main_texturepool, va("%s_shirt", skinframe->basename), image_width, image_height, pixels, TEXTYPE_RGBA, skinframe->textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), NULL);Mem_Free(pixels);pixels = NULL;}
1584 Mem_Free(basepixels);
1589 static rtexture_t *R_SkinFrame_TextureForSkinLayer(const unsigned char *in, int width, int height, const char *name, const unsigned int *palette, int textureflags, qboolean force)
1594 for (i = 0;i < width*height;i++)
1595 if (((unsigned char *)&palette[in[i]])[3] > 0)
1597 if (i == width*height)
1600 return R_LoadTexture2D (r_main_texturepool, name, width, height, in, TEXTYPE_PALETTE, textureflags, palette);
1603 skinframe_t *R_SkinFrame_LoadInternal(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height, int bitsperpixel, const unsigned int *palette, const unsigned int *alphapalette)
1606 unsigned char *temp1, *temp2;
1607 skinframe_t *skinframe;
1609 if (cls.state == ca_dedicated)
1612 // if already loaded just return it, otherwise make a new skinframe
1613 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*bitsperpixel/8) : 0, true);
1614 if (skinframe && skinframe->base)
1617 skinframe->stain = NULL;
1618 skinframe->merged = NULL;
1619 skinframe->base = r_texture_notexture;
1620 skinframe->pants = NULL;
1621 skinframe->shirt = NULL;
1622 skinframe->nmap = r_texture_blanknormalmap;
1623 skinframe->gloss = NULL;
1624 skinframe->glow = NULL;
1625 skinframe->fog = NULL;
1627 // if no data was provided, then clearly the caller wanted to get a blank skinframe
1631 if (bitsperpixel == 32)
1633 if (r_shadow_bumpscale_basetexture.value > 0)
1635 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
1636 temp2 = temp1 + width * height * 4;
1637 Image_HeightmapToNormalmap(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
1638 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_RGBA, skinframe->textureflags | TEXF_ALPHA, NULL);
1641 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_RGBA, skinframe->textureflags, NULL);
1642 if (textureflags & TEXF_ALPHA)
1644 for (i = 3;i < width * height * 4;i += 4)
1645 if (skindata[i] < 255)
1647 if (i < width * height * 4)
1649 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
1650 memcpy(fogpixels, skindata, width * height * 4);
1651 for (i = 0;i < width * height * 4;i += 4)
1652 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
1653 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_RGBA, skinframe->textureflags, NULL);
1654 Mem_Free(fogpixels);
1658 else if (bitsperpixel == 8)
1660 if (r_shadow_bumpscale_basetexture.value > 0)
1662 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
1663 temp2 = temp1 + width * height * 4;
1664 if (bitsperpixel == 32)
1665 Image_HeightmapToNormalmap(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
1668 // use either a custom palette or the quake palette
1669 Image_Copy8bitRGBA(skindata, temp1, width * height, palette ? palette : palette_complete);
1670 Image_HeightmapToNormalmap(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
1672 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_RGBA, skinframe->textureflags | TEXF_ALPHA, NULL);
1675 // use either a custom palette, or the quake palette
1676 skinframe->base = skinframe->merged = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_merged", skinframe->basename), palette ? palette : (loadglowtexture ? palette_nofullbrights : ((skinframe->textureflags & TEXF_ALPHA) ? palette_transparent : palette_complete)), skinframe->textureflags, true); // all
1677 if (!palette && loadglowtexture)
1678 skinframe->glow = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_glow", skinframe->basename), palette_onlyfullbrights, skinframe->textureflags, false); // glow
1679 if (!palette && loadpantsandshirt)
1681 skinframe->pants = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_pants", skinframe->basename), palette_pantsaswhite, skinframe->textureflags, false); // pants
1682 skinframe->shirt = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_shirt", skinframe->basename), palette_shirtaswhite, skinframe->textureflags, false); // shirt
1684 if (skinframe->pants || skinframe->shirt)
1685 skinframe->base = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_nospecial", skinframe->basename),loadglowtexture ? palette_nocolormapnofullbrights : palette_nocolormap, skinframe->textureflags, false); // no special colors
1686 if (textureflags & TEXF_ALPHA)
1688 // if not using a custom alphapalette, use the quake one
1690 alphapalette = palette_alpha;
1691 for (i = 0;i < width * height;i++)
1692 if (((unsigned char *)alphapalette)[skindata[i]*4+3] < 255)
1694 if (i < width * height)
1695 skinframe->fog = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_fog", skinframe->basename), alphapalette, skinframe->textureflags, true); // fog mask
1702 skinframe_t *R_SkinFrame_LoadMissing(void)
1704 skinframe_t *skinframe;
1706 if (cls.state == ca_dedicated)
1709 skinframe = R_SkinFrame_Find("missing", TEXF_PRECACHE, 0, 0, 0, true);
1710 skinframe->stain = NULL;
1711 skinframe->merged = NULL;
1712 skinframe->base = r_texture_notexture;
1713 skinframe->pants = NULL;
1714 skinframe->shirt = NULL;
1715 skinframe->nmap = r_texture_blanknormalmap;
1716 skinframe->gloss = NULL;
1717 skinframe->glow = NULL;
1718 skinframe->fog = NULL;
1723 void gl_main_start(void)
1728 r = (-1.0/256.0) * (FOGMASKTABLEWIDTH * FOGMASKTABLEWIDTH);
1729 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
1731 alpha = 1 - exp(r / ((double)x*(double)x));
1732 if (x == FOGMASKTABLEWIDTH - 1)
1734 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
1737 memset(r_qwskincache, 0, sizeof(r_qwskincache));
1738 memset(r_qwskincache_skinframe, 0, sizeof(r_qwskincache_skinframe));
1740 // set up r_skinframe loading system for textures
1741 memset(&r_skinframe, 0, sizeof(r_skinframe));
1742 r_skinframe.loadsequence = 1;
1743 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
1745 r_main_texturepool = R_AllocTexturePool();
1746 R_BuildBlankTextures();
1748 if (gl_texturecubemap)
1751 R_BuildNormalizationCube();
1753 R_BuildFogTexture();
1754 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
1755 memset(&r_waterstate, 0, sizeof(r_waterstate));
1756 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
1757 memset(&r_svbsp, 0, sizeof (r_svbsp));
1760 void gl_main_shutdown(void)
1762 memset(r_qwskincache, 0, sizeof(r_qwskincache));
1763 memset(r_qwskincache_skinframe, 0, sizeof(r_qwskincache_skinframe));
1765 // clear out the r_skinframe state
1766 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
1767 memset(&r_skinframe, 0, sizeof(r_skinframe));
1770 Mem_Free(r_svbsp.nodes);
1771 memset(&r_svbsp, 0, sizeof (r_svbsp));
1772 R_FreeTexturePool(&r_main_texturepool);
1773 r_texture_blanknormalmap = NULL;
1774 r_texture_white = NULL;
1775 r_texture_grey128 = NULL;
1776 r_texture_black = NULL;
1777 r_texture_whitecube = NULL;
1778 r_texture_normalizationcube = NULL;
1779 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
1780 memset(&r_waterstate, 0, sizeof(r_waterstate));
1784 extern void CL_ParseEntityLump(char *entitystring);
1785 void gl_main_newmap(void)
1787 // FIXME: move this code to client
1789 char *entities, entname[MAX_QPATH];
1792 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
1793 l = (int)strlen(entname) - 4;
1794 if (l >= 0 && !strcmp(entname + l, ".bsp"))
1796 memcpy(entname + l, ".ent", 5);
1797 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
1799 CL_ParseEntityLump(entities);
1804 if (cl.worldmodel->brush.entities)
1805 CL_ParseEntityLump(cl.worldmodel->brush.entities);
1809 void GL_Main_Init(void)
1811 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
1813 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
1814 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
1815 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
1816 if (gamemode == GAME_NEHAHRA)
1818 Cvar_RegisterVariable (&gl_fogenable);
1819 Cvar_RegisterVariable (&gl_fogdensity);
1820 Cvar_RegisterVariable (&gl_fogred);
1821 Cvar_RegisterVariable (&gl_foggreen);
1822 Cvar_RegisterVariable (&gl_fogblue);
1823 Cvar_RegisterVariable (&gl_fogstart);
1824 Cvar_RegisterVariable (&gl_fogend);
1826 Cvar_RegisterVariable(&r_depthfirst);
1827 Cvar_RegisterVariable(&r_nearclip);
1828 Cvar_RegisterVariable(&r_showbboxes);
1829 Cvar_RegisterVariable(&r_showsurfaces);
1830 Cvar_RegisterVariable(&r_showtris);
1831 Cvar_RegisterVariable(&r_shownormals);
1832 Cvar_RegisterVariable(&r_showlighting);
1833 Cvar_RegisterVariable(&r_showshadowvolumes);
1834 Cvar_RegisterVariable(&r_showcollisionbrushes);
1835 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
1836 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
1837 Cvar_RegisterVariable(&r_showdisabledepthtest);
1838 Cvar_RegisterVariable(&r_drawportals);
1839 Cvar_RegisterVariable(&r_drawentities);
1840 Cvar_RegisterVariable(&r_cullentities_trace);
1841 Cvar_RegisterVariable(&r_cullentities_trace_samples);
1842 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
1843 Cvar_RegisterVariable(&r_cullentities_trace_delay);
1844 Cvar_RegisterVariable(&r_drawviewmodel);
1845 Cvar_RegisterVariable(&r_speeds);
1846 Cvar_RegisterVariable(&r_fullbrights);
1847 Cvar_RegisterVariable(&r_wateralpha);
1848 Cvar_RegisterVariable(&r_dynamic);
1849 Cvar_RegisterVariable(&r_fullbright);
1850 Cvar_RegisterVariable(&r_shadows);
1851 Cvar_RegisterVariable(&r_shadows_throwdistance);
1852 Cvar_RegisterVariable(&r_q1bsp_skymasking);
1853 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
1854 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
1855 Cvar_RegisterVariable(&r_textureunits);
1856 Cvar_RegisterVariable(&r_glsl);
1857 Cvar_RegisterVariable(&r_glsl_offsetmapping);
1858 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
1859 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
1860 Cvar_RegisterVariable(&r_glsl_deluxemapping);
1861 Cvar_RegisterVariable(&r_water);
1862 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
1863 Cvar_RegisterVariable(&r_water_clippingplanebias);
1864 Cvar_RegisterVariable(&r_water_refractdistort);
1865 Cvar_RegisterVariable(&r_water_reflectdistort);
1866 Cvar_RegisterVariable(&r_lerpsprites);
1867 Cvar_RegisterVariable(&r_lerpmodels);
1868 Cvar_RegisterVariable(&r_waterscroll);
1869 Cvar_RegisterVariable(&r_bloom);
1870 Cvar_RegisterVariable(&r_bloom_colorscale);
1871 Cvar_RegisterVariable(&r_bloom_brighten);
1872 Cvar_RegisterVariable(&r_bloom_blur);
1873 Cvar_RegisterVariable(&r_bloom_resolution);
1874 Cvar_RegisterVariable(&r_bloom_colorexponent);
1875 Cvar_RegisterVariable(&r_bloom_colorsubtract);
1876 Cvar_RegisterVariable(&r_hdr);
1877 Cvar_RegisterVariable(&r_hdr_scenebrightness);
1878 Cvar_RegisterVariable(&r_glsl_contrastboost);
1879 Cvar_RegisterVariable(&r_hdr_glowintensity);
1880 Cvar_RegisterVariable(&r_hdr_range);
1881 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
1882 Cvar_RegisterVariable(&developer_texturelogging);
1883 Cvar_RegisterVariable(&gl_lightmaps);
1884 Cvar_RegisterVariable(&r_test);
1885 Cvar_RegisterVariable(&r_batchmode);
1886 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
1887 Cvar_SetValue("r_fullbrights", 0);
1888 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
1891 extern void R_Textures_Init(void);
1892 extern void GL_Draw_Init(void);
1893 extern void GL_Main_Init(void);
1894 extern void R_Shadow_Init(void);
1895 extern void R_Sky_Init(void);
1896 extern void GL_Surf_Init(void);
1897 extern void R_Light_Init(void);
1898 extern void R_Particles_Init(void);
1899 extern void R_Explosion_Init(void);
1900 extern void gl_backend_init(void);
1901 extern void Sbar_Init(void);
1902 extern void R_LightningBeams_Init(void);
1903 extern void Mod_RenderInit(void);
1905 void Render_Init(void)
1918 R_LightningBeams_Init();
1927 extern char *ENGINE_EXTENSIONS;
1930 VID_CheckExtensions();
1932 // LordHavoc: report supported extensions
1933 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
1935 // clear to black (loading plaque will be seen over this)
1937 qglClearColor(0,0,0,1);CHECKGLERROR
1938 qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
1941 int R_CullBox(const vec3_t mins, const vec3_t maxs)
1945 for (i = 0;i < r_view.numfrustumplanes;i++)
1947 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
1950 p = r_view.frustum + i;
1955 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1959 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1963 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1967 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1971 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1975 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1979 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1983 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1991 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
1995 for (i = 0;i < numplanes;i++)
2002 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2006 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2010 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2014 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2018 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2022 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2026 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2030 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2038 //==================================================================================
2040 static void R_UpdateEntityLighting(entity_render_t *ent)
2042 vec3_t tempdiffusenormal;
2044 // fetch the lighting from the worldmodel data
2045 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));
2046 VectorClear(ent->modellight_diffuse);
2047 VectorClear(tempdiffusenormal);
2048 if ((ent->flags & RENDER_LIGHT) && r_refdef.worldmodel && r_refdef.worldmodel->brush.LightPoint)
2051 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
2052 r_refdef.worldmodel->brush.LightPoint(r_refdef.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
2055 VectorSet(ent->modellight_ambient, 1, 1, 1);
2057 // move the light direction into modelspace coordinates for lighting code
2058 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
2059 if(VectorLength2(ent->modellight_lightdir) > 0)
2061 VectorNormalize(ent->modellight_lightdir);
2065 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
2068 // scale ambient and directional light contributions according to rendering variables
2069 ent->modellight_ambient[0] *= ent->colormod[0] * r_refdef.lightmapintensity;
2070 ent->modellight_ambient[1] *= ent->colormod[1] * r_refdef.lightmapintensity;
2071 ent->modellight_ambient[2] *= ent->colormod[2] * r_refdef.lightmapintensity;
2072 ent->modellight_diffuse[0] *= ent->colormod[0] * r_refdef.lightmapintensity;
2073 ent->modellight_diffuse[1] *= ent->colormod[1] * r_refdef.lightmapintensity;
2074 ent->modellight_diffuse[2] *= ent->colormod[2] * r_refdef.lightmapintensity;
2077 static void R_View_UpdateEntityVisible (void)
2080 entity_render_t *ent;
2082 if (!r_drawentities.integer)
2085 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : ((chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL : RENDER_EXTERIORMODEL);
2086 if (r_refdef.worldmodel && r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs)
2088 // worldmodel can check visibility
2089 for (i = 0;i < r_refdef.numentities;i++)
2091 ent = r_refdef.entities[i];
2092 r_viewcache.entityvisible[i] = !(ent->flags & renderimask) && !R_CullBox(ent->mins, ent->maxs) && ((ent->effects & EF_NODEPTHTEST) || (ent->flags & RENDER_VIEWMODEL) || r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs(r_refdef.worldmodel, r_viewcache.world_leafvisible, ent->mins, ent->maxs));
2094 if(r_cullentities_trace.integer)
2096 for (i = 0;i < r_refdef.numentities;i++)
2098 ent = r_refdef.entities[i];
2099 if(r_viewcache.entityvisible[i] && !(ent->effects & EF_NODEPTHTEST) && !(ent->flags & RENDER_VIEWMODEL) && !(ent->model && (ent->model->name[0] == '*')))
2101 if(Mod_CanSeeBox_Trace(r_cullentities_trace_samples.integer, r_cullentities_trace_enlarge.value, r_refdef.worldmodel, r_view.origin, ent->mins, ent->maxs))
2102 ent->last_trace_visibility = realtime;
2103 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
2104 r_viewcache.entityvisible[i] = 0;
2111 // no worldmodel or it can't check visibility
2112 for (i = 0;i < r_refdef.numentities;i++)
2114 ent = r_refdef.entities[i];
2115 r_viewcache.entityvisible[i] = !(ent->flags & renderimask) && !R_CullBox(ent->mins, ent->maxs);
2119 // update entity lighting (even on hidden entities for r_shadows)
2120 for (i = 0;i < r_refdef.numentities;i++)
2121 R_UpdateEntityLighting(r_refdef.entities[i]);
2124 // only used if skyrendermasked, and normally returns false
2125 int R_DrawBrushModelsSky (void)
2128 entity_render_t *ent;
2130 if (!r_drawentities.integer)
2134 for (i = 0;i < r_refdef.numentities;i++)
2136 if (!r_viewcache.entityvisible[i])
2138 ent = r_refdef.entities[i];
2139 if (!ent->model || !ent->model->DrawSky)
2141 ent->model->DrawSky(ent);
2147 static void R_DrawNoModel(entity_render_t *ent);
2148 static void R_DrawModels(void)
2151 entity_render_t *ent;
2153 if (!r_drawentities.integer)
2156 for (i = 0;i < r_refdef.numentities;i++)
2158 if (!r_viewcache.entityvisible[i])
2160 ent = r_refdef.entities[i];
2161 r_refdef.stats.entities++;
2162 if (ent->model && ent->model->Draw != NULL)
2163 ent->model->Draw(ent);
2169 static void R_DrawModelsDepth(void)
2172 entity_render_t *ent;
2174 if (!r_drawentities.integer)
2177 for (i = 0;i < r_refdef.numentities;i++)
2179 if (!r_viewcache.entityvisible[i])
2181 ent = r_refdef.entities[i];
2182 r_refdef.stats.entities++;
2183 if (ent->model && ent->model->DrawDepth != NULL)
2184 ent->model->DrawDepth(ent);
2188 static void R_DrawModelsDebug(void)
2191 entity_render_t *ent;
2193 if (!r_drawentities.integer)
2196 for (i = 0;i < r_refdef.numentities;i++)
2198 if (!r_viewcache.entityvisible[i])
2200 ent = r_refdef.entities[i];
2201 r_refdef.stats.entities++;
2202 if (ent->model && ent->model->DrawDebug != NULL)
2203 ent->model->DrawDebug(ent);
2207 static void R_DrawModelsAddWaterPlanes(void)
2210 entity_render_t *ent;
2212 if (!r_drawentities.integer)
2215 for (i = 0;i < r_refdef.numentities;i++)
2217 if (!r_viewcache.entityvisible[i])
2219 ent = r_refdef.entities[i];
2220 r_refdef.stats.entities++;
2221 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
2222 ent->model->DrawAddWaterPlanes(ent);
2226 static void R_View_SetFrustum(void)
2229 double slopex, slopey;
2231 // break apart the view matrix into vectors for various purposes
2232 Matrix4x4_ToVectors(&r_view.matrix, r_view.forward, r_view.left, r_view.up, r_view.origin);
2233 VectorNegate(r_view.left, r_view.right);
2236 r_view.frustum[0].normal[0] = 0 - 1.0 / r_view.frustum_x;
2237 r_view.frustum[0].normal[1] = 0 - 0;
2238 r_view.frustum[0].normal[2] = -1 - 0;
2239 r_view.frustum[1].normal[0] = 0 + 1.0 / r_view.frustum_x;
2240 r_view.frustum[1].normal[1] = 0 + 0;
2241 r_view.frustum[1].normal[2] = -1 + 0;
2242 r_view.frustum[2].normal[0] = 0 - 0;
2243 r_view.frustum[2].normal[1] = 0 - 1.0 / r_view.frustum_y;
2244 r_view.frustum[2].normal[2] = -1 - 0;
2245 r_view.frustum[3].normal[0] = 0 + 0;
2246 r_view.frustum[3].normal[1] = 0 + 1.0 / r_view.frustum_y;
2247 r_view.frustum[3].normal[2] = -1 + 0;
2251 zNear = r_refdef.nearclip;
2252 nudge = 1.0 - 1.0 / (1<<23);
2253 r_view.frustum[4].normal[0] = 0 - 0;
2254 r_view.frustum[4].normal[1] = 0 - 0;
2255 r_view.frustum[4].normal[2] = -1 - -nudge;
2256 r_view.frustum[4].dist = 0 - -2 * zNear * nudge;
2257 r_view.frustum[5].normal[0] = 0 + 0;
2258 r_view.frustum[5].normal[1] = 0 + 0;
2259 r_view.frustum[5].normal[2] = -1 + -nudge;
2260 r_view.frustum[5].dist = 0 + -2 * zNear * nudge;
2266 r_view.frustum[0].normal[0] = m[3] - m[0];
2267 r_view.frustum[0].normal[1] = m[7] - m[4];
2268 r_view.frustum[0].normal[2] = m[11] - m[8];
2269 r_view.frustum[0].dist = m[15] - m[12];
2271 r_view.frustum[1].normal[0] = m[3] + m[0];
2272 r_view.frustum[1].normal[1] = m[7] + m[4];
2273 r_view.frustum[1].normal[2] = m[11] + m[8];
2274 r_view.frustum[1].dist = m[15] + m[12];
2276 r_view.frustum[2].normal[0] = m[3] - m[1];
2277 r_view.frustum[2].normal[1] = m[7] - m[5];
2278 r_view.frustum[2].normal[2] = m[11] - m[9];
2279 r_view.frustum[2].dist = m[15] - m[13];
2281 r_view.frustum[3].normal[0] = m[3] + m[1];
2282 r_view.frustum[3].normal[1] = m[7] + m[5];
2283 r_view.frustum[3].normal[2] = m[11] + m[9];
2284 r_view.frustum[3].dist = m[15] + m[13];
2286 r_view.frustum[4].normal[0] = m[3] - m[2];
2287 r_view.frustum[4].normal[1] = m[7] - m[6];
2288 r_view.frustum[4].normal[2] = m[11] - m[10];
2289 r_view.frustum[4].dist = m[15] - m[14];
2291 r_view.frustum[5].normal[0] = m[3] + m[2];
2292 r_view.frustum[5].normal[1] = m[7] + m[6];
2293 r_view.frustum[5].normal[2] = m[11] + m[10];
2294 r_view.frustum[5].dist = m[15] + m[14];
2299 if (r_view.useperspective)
2301 slopex = 1.0 / r_view.frustum_x;
2302 slopey = 1.0 / r_view.frustum_y;
2303 VectorMA(r_view.forward, -slopex, r_view.left, r_view.frustum[0].normal);
2304 VectorMA(r_view.forward, slopex, r_view.left, r_view.frustum[1].normal);
2305 VectorMA(r_view.forward, -slopey, r_view.up , r_view.frustum[2].normal);
2306 VectorMA(r_view.forward, slopey, r_view.up , r_view.frustum[3].normal);
2307 VectorCopy(r_view.forward, r_view.frustum[4].normal);
2309 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
2310 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, -1024 * slopex, r_view.left, -1024 * slopey, r_view.up, r_view.frustumcorner[0]);
2311 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, 1024 * slopex, r_view.left, -1024 * slopey, r_view.up, r_view.frustumcorner[1]);
2312 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, -1024 * slopex, r_view.left, 1024 * slopey, r_view.up, r_view.frustumcorner[2]);
2313 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, 1024 * slopex, r_view.left, 1024 * slopey, r_view.up, r_view.frustumcorner[3]);
2315 r_view.frustum[0].dist = DotProduct (r_view.origin, r_view.frustum[0].normal);
2316 r_view.frustum[1].dist = DotProduct (r_view.origin, r_view.frustum[1].normal);
2317 r_view.frustum[2].dist = DotProduct (r_view.origin, r_view.frustum[2].normal);
2318 r_view.frustum[3].dist = DotProduct (r_view.origin, r_view.frustum[3].normal);
2319 r_view.frustum[4].dist = DotProduct (r_view.origin, r_view.frustum[4].normal) + r_refdef.nearclip;
2323 VectorScale(r_view.left, -r_view.ortho_x, r_view.frustum[0].normal);
2324 VectorScale(r_view.left, r_view.ortho_x, r_view.frustum[1].normal);
2325 VectorScale(r_view.up, -r_view.ortho_y, r_view.frustum[2].normal);
2326 VectorScale(r_view.up, r_view.ortho_y, r_view.frustum[3].normal);
2327 VectorCopy(r_view.forward, r_view.frustum[4].normal);
2328 r_view.frustum[0].dist = DotProduct (r_view.origin, r_view.frustum[0].normal) + r_view.ortho_x;
2329 r_view.frustum[1].dist = DotProduct (r_view.origin, r_view.frustum[1].normal) + r_view.ortho_x;
2330 r_view.frustum[2].dist = DotProduct (r_view.origin, r_view.frustum[2].normal) + r_view.ortho_y;
2331 r_view.frustum[3].dist = DotProduct (r_view.origin, r_view.frustum[3].normal) + r_view.ortho_y;
2332 r_view.frustum[4].dist = DotProduct (r_view.origin, r_view.frustum[4].normal) + r_refdef.nearclip;
2334 r_view.numfrustumplanes = 5;
2336 if (r_view.useclipplane)
2338 r_view.numfrustumplanes = 6;
2339 r_view.frustum[5] = r_view.clipplane;
2342 for (i = 0;i < r_view.numfrustumplanes;i++)
2343 PlaneClassify(r_view.frustum + i);
2345 // LordHavoc: note to all quake engine coders, Quake had a special case
2346 // for 90 degrees which assumed a square view (wrong), so I removed it,
2347 // Quake2 has it disabled as well.
2349 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
2350 //RotatePointAroundVector( r_view.frustum[0].normal, r_view.up, r_view.forward, -(90 - r_refdef.fov_x / 2));
2351 //r_view.frustum[0].dist = DotProduct (r_view.origin, frustum[0].normal);
2352 //PlaneClassify(&frustum[0]);
2354 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
2355 //RotatePointAroundVector( r_view.frustum[1].normal, r_view.up, r_view.forward, (90 - r_refdef.fov_x / 2));
2356 //r_view.frustum[1].dist = DotProduct (r_view.origin, frustum[1].normal);
2357 //PlaneClassify(&frustum[1]);
2359 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
2360 //RotatePointAroundVector( r_view.frustum[2].normal, r_view.left, r_view.forward, -(90 - r_refdef.fov_y / 2));
2361 //r_view.frustum[2].dist = DotProduct (r_view.origin, frustum[2].normal);
2362 //PlaneClassify(&frustum[2]);
2364 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
2365 //RotatePointAroundVector( r_view.frustum[3].normal, r_view.left, r_view.forward, (90 - r_refdef.fov_y / 2));
2366 //r_view.frustum[3].dist = DotProduct (r_view.origin, frustum[3].normal);
2367 //PlaneClassify(&frustum[3]);
2370 //VectorCopy(r_view.forward, r_view.frustum[4].normal);
2371 //r_view.frustum[4].dist = DotProduct (r_view.origin, frustum[4].normal) + r_nearclip.value;
2372 //PlaneClassify(&frustum[4]);
2375 void R_View_Update(void)
2377 R_View_SetFrustum();
2378 R_View_WorldVisibility(r_view.useclipplane);
2379 R_View_UpdateEntityVisible();
2382 void R_SetupView(void)
2384 if (!r_view.useperspective)
2385 GL_SetupView_Mode_Ortho(-r_view.ortho_x, -r_view.ortho_y, r_view.ortho_x, r_view.ortho_y, -r_refdef.farclip, r_refdef.farclip);
2386 else if (r_refdef.rtworldshadows || r_refdef.rtdlightshadows)
2387 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_view.frustum_x, r_view.frustum_y, r_refdef.nearclip);
2389 GL_SetupView_Mode_Perspective(r_view.frustum_x, r_view.frustum_y, r_refdef.nearclip, r_refdef.farclip);
2391 GL_SetupView_Orientation_FromEntity(&r_view.matrix);
2393 if (r_view.useclipplane)
2395 // LordHavoc: couldn't figure out how to make this approach the
2396 vec_t dist = r_view.clipplane.dist - r_water_clippingplanebias.value;
2397 vec_t viewdist = DotProduct(r_view.origin, r_view.clipplane.normal);
2398 if (viewdist < r_view.clipplane.dist + r_water_clippingplanebias.value)
2399 dist = r_view.clipplane.dist;
2400 GL_SetupView_ApplyCustomNearClipPlane(r_view.clipplane.normal[0], r_view.clipplane.normal[1], r_view.clipplane.normal[2], dist);
2404 void R_ResetViewRendering2D(void)
2406 if (gl_support_fragment_shader)
2408 qglUseProgramObjectARB(0);CHECKGLERROR
2413 // GL is weird because it's bottom to top, r_view.y is top to bottom
2414 qglViewport(r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
2415 GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
2416 GL_Scissor(r_view.x, r_view.y, r_view.width, r_view.height);
2417 GL_Color(1, 1, 1, 1);
2418 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
2419 GL_BlendFunc(GL_ONE, GL_ZERO);
2420 GL_AlphaTest(false);
2421 GL_ScissorTest(false);
2422 GL_DepthMask(false);
2423 GL_DepthRange(0, 1);
2424 GL_DepthTest(false);
2425 R_Mesh_Matrix(&identitymatrix);
2426 R_Mesh_ResetTextureState();
2427 GL_PolygonOffset(0, 0);
2428 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
2429 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
2430 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
2431 qglStencilMask(~0);CHECKGLERROR
2432 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
2433 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
2434 GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
2437 void R_ResetViewRendering3D(void)
2439 if (gl_support_fragment_shader)
2441 qglUseProgramObjectARB(0);CHECKGLERROR
2446 // GL is weird because it's bottom to top, r_view.y is top to bottom
2447 qglViewport(r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
2449 GL_Scissor(r_view.x, r_view.y, r_view.width, r_view.height);
2450 GL_Color(1, 1, 1, 1);
2451 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
2452 GL_BlendFunc(GL_ONE, GL_ZERO);
2453 GL_AlphaTest(false);
2454 GL_ScissorTest(true);
2456 GL_DepthRange(0, 1);
2458 R_Mesh_Matrix(&identitymatrix);
2459 R_Mesh_ResetTextureState();
2460 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
2461 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
2462 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
2463 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
2464 qglStencilMask(~0);CHECKGLERROR
2465 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
2466 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
2467 GL_CullFace(r_view.cullface_back);
2471 R_Bloom_SetupShader(
2473 "// written by Forest 'LordHavoc' Hale\n"
2475 "// common definitions between vertex shader and fragment shader:\n"
2477 "#ifdef __GLSL_CG_DATA_TYPES\n"
2478 "#define myhalf half\n"
2479 "#define myhvec2 hvec2\n"
2480 "#define myhvec3 hvec3\n"
2481 "#define myhvec4 hvec4\n"
2483 "#define myhalf float\n"
2484 "#define myhvec2 vec2\n"
2485 "#define myhvec3 vec3\n"
2486 "#define myhvec4 vec4\n"
2489 "varying vec2 ScreenTexCoord;\n"
2490 "varying vec2 BloomTexCoord;\n"
2495 "// vertex shader specific:\n"
2496 "#ifdef VERTEX_SHADER\n"
2500 " ScreenTexCoord = vec2(gl_MultiTexCoord0);\n"
2501 " BloomTexCoord = vec2(gl_MultiTexCoord1);\n"
2502 " // transform vertex to camera space, using ftransform to match non-VS\n"
2504 " gl_Position = ftransform();\n"
2507 "#endif // VERTEX_SHADER\n"
2512 "// fragment shader specific:\n"
2513 "#ifdef FRAGMENT_SHADER\n"
2518 " myhvec3 color = myhvec3(texture2D(Texture_Screen, ScreenTexCoord));\n"
2519 " for (x = -BLUR_X;x <= BLUR_X;x++)
2520 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2521 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2522 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2523 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2525 " gl_FragColor = vec4(color);\n"
2528 "#endif // FRAGMENT_SHADER\n"
2531 void R_RenderScene(qboolean addwaterplanes);
2533 static void R_Water_StartFrame(void)
2536 int waterwidth, waterheight, texturewidth, textureheight;
2537 r_waterstate_waterplane_t *p;
2539 // set waterwidth and waterheight to the water resolution that will be
2540 // used (often less than the screen resolution for faster rendering)
2541 waterwidth = (int)bound(1, r_view.width * r_water_resolutionmultiplier.value, r_view.width);
2542 waterheight = (int)bound(1, r_view.height * r_water_resolutionmultiplier.value, r_view.height);
2544 // calculate desired texture sizes
2545 // can't use water if the card does not support the texture size
2546 if (!r_water.integer || !r_glsl.integer || !gl_support_fragment_shader || waterwidth > gl_max_texture_size || waterheight > gl_max_texture_size)
2547 texturewidth = textureheight = waterwidth = waterheight = 0;
2548 else if (gl_support_arb_texture_non_power_of_two)
2550 texturewidth = waterwidth;
2551 textureheight = waterheight;
2555 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
2556 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
2559 // allocate textures as needed
2560 if (r_waterstate.waterwidth != waterwidth || r_waterstate.waterheight != waterheight || r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight)
2562 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
2563 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
2565 if (p->texture_refraction)
2566 R_FreeTexture(p->texture_refraction);
2567 p->texture_refraction = NULL;
2568 if (p->texture_reflection)
2569 R_FreeTexture(p->texture_reflection);
2570 p->texture_reflection = NULL;
2572 memset(&r_waterstate, 0, sizeof(r_waterstate));
2573 r_waterstate.waterwidth = waterwidth;
2574 r_waterstate.waterheight = waterheight;
2575 r_waterstate.texturewidth = texturewidth;
2576 r_waterstate.textureheight = textureheight;
2579 if (r_waterstate.waterwidth)
2581 r_waterstate.enabled = true;
2583 // set up variables that will be used in shader setup
2584 r_waterstate.screenscale[0] = 0.5f * (float)waterwidth / (float)texturewidth;
2585 r_waterstate.screenscale[1] = 0.5f * (float)waterheight / (float)textureheight;
2586 r_waterstate.screencenter[0] = 0.5f * (float)waterwidth / (float)texturewidth;
2587 r_waterstate.screencenter[1] = 0.5f * (float)waterheight / (float)textureheight;
2590 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
2591 r_waterstate.numwaterplanes = 0;
2594 static void R_Water_AddWaterPlane(msurface_t *surface)
2596 int triangleindex, planeindex;
2602 r_waterstate_waterplane_t *p;
2603 // just use the first triangle with a valid normal for any decisions
2604 VectorClear(normal);
2605 VectorClear(center);
2606 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
2608 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
2609 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
2610 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
2611 TriangleNormal(vert[0], vert[1], vert[2], normal);
2612 if (VectorLength2(normal) >= 0.001)
2615 // now find the center of this surface
2616 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles*3;triangleindex++, e++)
2618 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
2619 VectorAdd(center, vert[0], center);
2621 f = 1.0 / surface->num_triangles*3;
2622 VectorScale(center, f, center);
2624 // find a matching plane if there is one
2625 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
2626 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
2628 if (planeindex >= r_waterstate.maxwaterplanes)
2629 return; // nothing we can do, out of planes
2631 // if this triangle does not fit any known plane rendered this frame, add one
2632 if (planeindex >= r_waterstate.numwaterplanes)
2634 // store the new plane
2635 r_waterstate.numwaterplanes++;
2636 VectorCopy(normal, p->plane.normal);
2637 VectorNormalize(p->plane.normal);
2638 p->plane.dist = DotProduct(vert[0], p->plane.normal);
2639 PlaneClassify(&p->plane);
2640 // flip the plane if it does not face the viewer
2641 if (PlaneDiff(r_view.origin, &p->plane) < 0)
2643 VectorNegate(p->plane.normal, p->plane.normal);
2644 p->plane.dist *= -1;
2645 PlaneClassify(&p->plane);
2647 // clear materialflags and pvs
2648 p->materialflags = 0;
2649 p->pvsvalid = false;
2651 // merge this surface's materialflags into the waterplane
2652 p->materialflags |= surface->texture->currentframe->currentmaterialflags;
2653 // merge this surface's PVS into the waterplane
2654 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.worldmodel && r_refdef.worldmodel->brush.FatPVS)
2656 r_refdef.worldmodel->brush.FatPVS(r_refdef.worldmodel, r_view.origin, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
2661 static void R_Water_ProcessPlanes(void)
2663 r_view_t originalview;
2665 r_waterstate_waterplane_t *p;
2667 originalview = r_view;
2669 // make sure enough textures are allocated
2670 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
2672 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
2674 if (!p->texture_refraction)
2675 p->texture_refraction = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_refraction", planeindex), r_waterstate.texturewidth, r_waterstate.textureheight, NULL, TEXTYPE_RGBA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
2676 if (!p->texture_refraction)
2680 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
2682 if (!p->texture_reflection)
2683 p->texture_reflection = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_reflection", planeindex), r_waterstate.texturewidth, r_waterstate.textureheight, NULL, TEXTYPE_RGBA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
2684 if (!p->texture_reflection)
2690 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
2692 r_view.showdebug = false;
2693 r_view.width = r_waterstate.waterwidth;
2694 r_view.height = r_waterstate.waterheight;
2695 r_view.useclipplane = true;
2696 r_waterstate.renderingscene = true;
2698 // render the normal view scene and copy into texture
2699 // (except that a clipping plane should be used to hide everything on one side of the water, and the viewer's weapon model should be omitted)
2700 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
2702 r_view.clipplane = p->plane;
2703 VectorNegate(r_view.clipplane.normal, r_view.clipplane.normal);
2704 r_view.clipplane.dist = -r_view.clipplane.dist;
2705 PlaneClassify(&r_view.clipplane);
2707 R_RenderScene(false);
2709 // copy view into the screen texture
2710 R_Mesh_TexBind(0, R_GetTexture(p->texture_refraction));
2711 GL_ActiveTexture(0);
2713 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
2716 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
2718 // render reflected scene and copy into texture
2719 Matrix4x4_Reflect(&r_view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
2720 r_view.clipplane = p->plane;
2721 // reverse the cullface settings for this render
2722 r_view.cullface_front = GL_FRONT;
2723 r_view.cullface_back = GL_BACK;
2724 if (r_refdef.worldmodel && r_refdef.worldmodel->brush.num_pvsclusterbytes)
2726 r_view.usecustompvs = true;
2728 memcpy(r_viewcache.world_pvsbits, p->pvsbits, r_refdef.worldmodel->brush.num_pvsclusterbytes);
2730 memset(r_viewcache.world_pvsbits, 0xFF, r_refdef.worldmodel->brush.num_pvsclusterbytes);
2733 R_ResetViewRendering3D();
2736 R_RenderScene(false);
2738 R_Mesh_TexBind(0, R_GetTexture(p->texture_reflection));
2739 GL_ActiveTexture(0);
2741 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
2743 R_ResetViewRendering3D();
2747 r_view = originalview;
2748 r_waterstate.renderingscene = false;
2752 r_view = originalview;
2753 r_waterstate.renderingscene = false;
2754 Cvar_SetValueQuick(&r_water, 0);
2755 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
2759 void R_Bloom_StartFrame(void)
2761 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
2763 // set bloomwidth and bloomheight to the bloom resolution that will be
2764 // used (often less than the screen resolution for faster rendering)
2765 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_view.width);
2766 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_view.height / r_view.width;
2767 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_view.height);
2769 // calculate desired texture sizes
2770 if (gl_support_arb_texture_non_power_of_two)
2772 screentexturewidth = r_view.width;
2773 screentextureheight = r_view.height;
2774 bloomtexturewidth = r_bloomstate.bloomwidth;
2775 bloomtextureheight = r_bloomstate.bloomheight;
2779 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
2780 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
2781 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
2782 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
2787 screentexturewidth = screentextureheight = 0;
2789 else if (r_bloom.integer)
2794 screentexturewidth = screentextureheight = 0;
2795 bloomtexturewidth = bloomtextureheight = 0;
2798 if ((!bloomtexturewidth && !bloomtextureheight) || r_bloom_resolution.integer < 4 || r_bloom_blur.value < 1 || r_bloom_blur.value >= 512 || screentexturewidth > gl_max_texture_size || screentextureheight > gl_max_texture_size || bloomtexturewidth > gl_max_texture_size || bloomtextureheight > gl_max_texture_size)
2800 // can't use bloom if the parameters are too weird
2801 // can't use bloom if the card does not support the texture size
2802 if (r_bloomstate.texture_screen)
2803 R_FreeTexture(r_bloomstate.texture_screen);
2804 if (r_bloomstate.texture_bloom)
2805 R_FreeTexture(r_bloomstate.texture_bloom);
2806 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
2810 r_bloomstate.enabled = true;
2811 r_bloomstate.hdr = r_hdr.integer != 0;
2813 // allocate textures as needed
2814 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
2816 if (r_bloomstate.texture_screen)
2817 R_FreeTexture(r_bloomstate.texture_screen);
2818 r_bloomstate.texture_screen = NULL;
2819 r_bloomstate.screentexturewidth = screentexturewidth;
2820 r_bloomstate.screentextureheight = screentextureheight;
2821 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
2822 r_bloomstate.texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, TEXTYPE_RGBA, TEXF_FORCENEAREST | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
2824 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
2826 if (r_bloomstate.texture_bloom)
2827 R_FreeTexture(r_bloomstate.texture_bloom);
2828 r_bloomstate.texture_bloom = NULL;
2829 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
2830 r_bloomstate.bloomtextureheight = bloomtextureheight;
2831 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
2832 r_bloomstate.texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", r_bloomstate.bloomtexturewidth, r_bloomstate.bloomtextureheight, NULL, TEXTYPE_RGBA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
2835 // set up a texcoord array for the full resolution screen image
2836 // (we have to keep this around to copy back during final render)
2837 r_bloomstate.screentexcoord2f[0] = 0;
2838 r_bloomstate.screentexcoord2f[1] = (float)r_view.height / (float)r_bloomstate.screentextureheight;
2839 r_bloomstate.screentexcoord2f[2] = (float)r_view.width / (float)r_bloomstate.screentexturewidth;
2840 r_bloomstate.screentexcoord2f[3] = (float)r_view.height / (float)r_bloomstate.screentextureheight;
2841 r_bloomstate.screentexcoord2f[4] = (float)r_view.width / (float)r_bloomstate.screentexturewidth;
2842 r_bloomstate.screentexcoord2f[5] = 0;
2843 r_bloomstate.screentexcoord2f[6] = 0;
2844 r_bloomstate.screentexcoord2f[7] = 0;
2846 // set up a texcoord array for the reduced resolution bloom image
2847 // (which will be additive blended over the screen image)
2848 r_bloomstate.bloomtexcoord2f[0] = 0;
2849 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
2850 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
2851 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
2852 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
2853 r_bloomstate.bloomtexcoord2f[5] = 0;
2854 r_bloomstate.bloomtexcoord2f[6] = 0;
2855 r_bloomstate.bloomtexcoord2f[7] = 0;
2858 void R_Bloom_CopyScreenTexture(float colorscale)
2860 r_refdef.stats.bloom++;
2862 R_ResetViewRendering2D();
2863 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
2864 R_Mesh_ColorPointer(NULL, 0, 0);
2865 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
2866 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
2868 // copy view into the screen texture
2869 GL_ActiveTexture(0);
2871 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
2872 r_refdef.stats.bloom_copypixels += r_view.width * r_view.height;
2874 // now scale it down to the bloom texture size
2876 qglViewport(r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
2877 GL_BlendFunc(GL_ONE, GL_ZERO);
2878 GL_Color(colorscale, colorscale, colorscale, 1);
2879 // TODO: optimize with multitexture or GLSL
2880 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2881 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2883 // we now have a bloom image in the framebuffer
2884 // copy it into the bloom image texture for later processing
2885 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2886 GL_ActiveTexture(0);
2888 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
2889 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2892 void R_Bloom_CopyHDRTexture(void)
2894 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2895 GL_ActiveTexture(0);
2897 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
2898 r_refdef.stats.bloom_copypixels += r_view.width * r_view.height;
2901 void R_Bloom_MakeTexture(void)
2904 float xoffset, yoffset, r, brighten;
2906 r_refdef.stats.bloom++;
2908 R_ResetViewRendering2D();
2909 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
2910 R_Mesh_ColorPointer(NULL, 0, 0);
2912 // we have a bloom image in the framebuffer
2914 qglViewport(r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
2916 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
2919 r = bound(0, r_bloom_colorexponent.value / x, 1);
2920 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
2921 GL_Color(r, r, r, 1);
2922 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2923 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
2924 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2925 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2927 // copy the vertically blurred bloom view to a texture
2928 GL_ActiveTexture(0);
2930 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
2931 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2934 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
2935 brighten = r_bloom_brighten.value;
2937 brighten *= r_hdr_range.value;
2938 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2939 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
2941 for (dir = 0;dir < 2;dir++)
2943 // blend on at multiple vertical offsets to achieve a vertical blur
2944 // TODO: do offset blends using GLSL
2945 GL_BlendFunc(GL_ONE, GL_ZERO);
2946 for (x = -range;x <= range;x++)
2948 if (!dir){xoffset = 0;yoffset = x;}
2949 else {xoffset = x;yoffset = 0;}
2950 xoffset /= (float)r_bloomstate.bloomtexturewidth;
2951 yoffset /= (float)r_bloomstate.bloomtextureheight;
2952 // compute a texcoord array with the specified x and y offset
2953 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
2954 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
2955 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
2956 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
2957 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
2958 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
2959 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
2960 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
2961 // this r value looks like a 'dot' particle, fading sharply to
2962 // black at the edges
2963 // (probably not realistic but looks good enough)
2964 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
2965 //r = (dir ? 1.0f : brighten)/(range*2+1);
2966 r = (dir ? 1.0f : brighten)/(range*2+1)*(1 - x*x/(float)(range*range));
2967 GL_Color(r, r, r, 1);
2968 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2969 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2970 GL_BlendFunc(GL_ONE, GL_ONE);
2973 // copy the vertically blurred bloom view to a texture
2974 GL_ActiveTexture(0);
2976 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
2977 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2980 // apply subtract last
2981 // (just like it would be in a GLSL shader)
2982 if (r_bloom_colorsubtract.value > 0 && gl_support_ext_blend_subtract)
2984 GL_BlendFunc(GL_ONE, GL_ZERO);
2985 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2986 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
2987 GL_Color(1, 1, 1, 1);
2988 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2989 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2991 GL_BlendFunc(GL_ONE, GL_ONE);
2992 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
2993 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2994 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
2995 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
2996 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2997 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2998 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
3000 // copy the darkened bloom view to a texture
3001 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3002 GL_ActiveTexture(0);
3004 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
3005 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3009 void R_HDR_RenderBloomTexture(void)
3011 int oldwidth, oldheight;
3013 oldwidth = r_view.width;
3014 oldheight = r_view.height;
3015 r_view.width = r_bloomstate.bloomwidth;
3016 r_view.height = r_bloomstate.bloomheight;
3018 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
3019 // TODO: add exposure compensation features
3020 // TODO: add fp16 framebuffer support
3022 r_view.showdebug = false;
3023 r_view.colorscale = r_bloom_colorscale.value * r_hdr_scenebrightness.value;
3025 r_view.colorscale /= r_hdr_range.value;
3026 r_waterstate.numwaterplanes = 0;
3027 R_RenderScene(r_waterstate.enabled);
3028 r_view.showdebug = true;
3030 R_ResetViewRendering2D();
3032 R_Bloom_CopyHDRTexture();
3033 R_Bloom_MakeTexture();
3035 R_ResetViewRendering3D();
3038 if (r_timereport_active)
3039 R_TimeReport("clear");
3042 // restore the view settings
3043 r_view.width = oldwidth;
3044 r_view.height = oldheight;
3047 static void R_BlendView(void)
3049 if (r_bloomstate.enabled && r_bloomstate.hdr)
3051 // render high dynamic range bloom effect
3052 // the bloom texture was made earlier this render, so we just need to
3053 // blend it onto the screen...
3054 R_ResetViewRendering2D();
3055 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3056 R_Mesh_ColorPointer(NULL, 0, 0);
3057 GL_Color(1, 1, 1, 1);
3058 GL_BlendFunc(GL_ONE, GL_ONE);
3059 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3060 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3061 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3062 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
3064 else if (r_bloomstate.enabled)
3066 // render simple bloom effect
3067 // copy the screen and shrink it and darken it for the bloom process
3068 R_Bloom_CopyScreenTexture(r_bloom_colorscale.value);
3069 // make the bloom texture
3070 R_Bloom_MakeTexture();
3071 // put the original screen image back in place and blend the bloom
3073 R_ResetViewRendering2D();
3074 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3075 R_Mesh_ColorPointer(NULL, 0, 0);
3076 GL_Color(1, 1, 1, 1);
3077 GL_BlendFunc(GL_ONE, GL_ZERO);
3078 // do both in one pass if possible
3079 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3080 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3081 if (r_textureunits.integer >= 2 && gl_combine.integer)
3083 R_Mesh_TexCombine(1, GL_ADD, GL_ADD, 1, 1);
3084 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_screen));
3085 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.screentexcoord2f, 0, 0);
3089 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3090 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
3091 // now blend on the bloom texture
3092 GL_BlendFunc(GL_ONE, GL_ONE);
3093 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
3094 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
3096 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3097 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
3099 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
3101 // apply a color tint to the whole view
3102 R_ResetViewRendering2D();
3103 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3104 R_Mesh_ColorPointer(NULL, 0, 0);
3105 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3106 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
3107 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3111 void R_RenderScene(qboolean addwaterplanes);
3113 matrix4x4_t r_waterscrollmatrix;
3115 void R_UpdateVariables(void)
3119 r_refdef.farclip = 4096;
3120 if (r_refdef.worldmodel)
3121 r_refdef.farclip += VectorDistance(r_refdef.worldmodel->normalmins, r_refdef.worldmodel->normalmaxs);
3122 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
3124 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
3125 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
3126 r_refdef.polygonfactor = 0;
3127 r_refdef.polygonoffset = 0;
3128 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
3129 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
3131 r_refdef.rtworld = r_shadow_realtime_world.integer;
3132 r_refdef.rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
3133 r_refdef.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
3134 r_refdef.rtdlightshadows = r_refdef.rtdlight && r_shadow_realtime_dlight_shadows.integer && gl_stencil;
3135 r_refdef.lightmapintensity = r_refdef.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
3136 if (r_showsurfaces.integer)
3138 r_refdef.rtworld = false;
3139 r_refdef.rtworldshadows = false;
3140 r_refdef.rtdlight = false;
3141 r_refdef.rtdlightshadows = false;
3142 r_refdef.lightmapintensity = 0;
3145 if (gamemode == GAME_NEHAHRA)
3147 if (gl_fogenable.integer)
3149 r_refdef.oldgl_fogenable = true;
3150 r_refdef.fog_density = gl_fogdensity.value;
3151 r_refdef.fog_red = gl_fogred.value;
3152 r_refdef.fog_green = gl_foggreen.value;
3153 r_refdef.fog_blue = gl_fogblue.value;
3155 else if (r_refdef.oldgl_fogenable)
3157 r_refdef.oldgl_fogenable = false;
3158 r_refdef.fog_density = 0;
3159 r_refdef.fog_red = 0;
3160 r_refdef.fog_green = 0;
3161 r_refdef.fog_blue = 0;
3164 if (r_refdef.fog_density)
3166 r_refdef.fogcolor[0] = bound(0.0f, r_refdef.fog_red , 1.0f);
3167 r_refdef.fogcolor[1] = bound(0.0f, r_refdef.fog_green, 1.0f);
3168 r_refdef.fogcolor[2] = bound(0.0f, r_refdef.fog_blue , 1.0f);
3170 if (r_refdef.fog_density)
3172 r_refdef.fogenabled = true;
3173 // this is the point where the fog reaches 0.9986 alpha, which we
3174 // consider a good enough cutoff point for the texture
3175 // (0.9986 * 256 == 255.6)
3176 r_refdef.fogrange = 400 / r_refdef.fog_density;
3177 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
3178 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
3179 // fog color was already set
3182 r_refdef.fogenabled = false;
3190 void R_RenderView(void)
3192 if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
3193 return; //Host_Error ("R_RenderView: NULL worldmodel");
3195 R_Shadow_UpdateWorldLightSelection();
3197 R_Bloom_StartFrame();
3198 R_Water_StartFrame();
3201 if (r_timereport_active)
3202 R_TimeReport("setup");
3204 R_ResetViewRendering3D();
3207 if (r_timereport_active)
3208 R_TimeReport("clear");
3210 r_view.showdebug = true;
3212 // this produces a bloom texture to be used in R_BlendView() later
3214 R_HDR_RenderBloomTexture();
3216 r_view.colorscale = r_hdr_scenebrightness.value;
3217 r_waterstate.numwaterplanes = 0;
3218 R_RenderScene(r_waterstate.enabled);
3221 if (r_timereport_active)
3222 R_TimeReport("blendview");
3224 GL_Scissor(0, 0, vid.width, vid.height);
3225 GL_ScissorTest(false);
3229 extern void R_DrawLightningBeams (void);
3230 extern void VM_CL_AddPolygonsToMeshQueue (void);
3231 extern void R_DrawPortals (void);
3232 extern cvar_t cl_locs_show;
3233 static void R_DrawLocs(void);
3234 static void R_DrawEntityBBoxes(void);
3235 void R_RenderScene(qboolean addwaterplanes)
3239 R_ResetViewRendering3D();
3242 if (r_timereport_active)
3243 R_TimeReport("watervisibility");
3245 if (cl.csqc_vidvars.drawworld && r_refdef.worldmodel && r_refdef.worldmodel->DrawAddWaterPlanes)
3247 r_refdef.worldmodel->DrawAddWaterPlanes(r_refdef.worldentity);
3248 if (r_timereport_active)
3249 R_TimeReport("waterworld");
3252 // don't let sound skip if going slow
3253 if (r_refdef.extraupdate)
3256 R_DrawModelsAddWaterPlanes();
3257 if (r_timereport_active)
3258 R_TimeReport("watermodels");
3260 R_Water_ProcessPlanes();
3261 if (r_timereport_active)
3262 R_TimeReport("waterscenes");
3265 R_ResetViewRendering3D();
3267 // don't let sound skip if going slow
3268 if (r_refdef.extraupdate)
3271 R_MeshQueue_BeginScene();
3276 if (r_timereport_active)
3277 R_TimeReport("visibility");
3279 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);
3281 if (cl.csqc_vidvars.drawworld)
3283 // don't let sound skip if going slow
3284 if (r_refdef.extraupdate)
3287 if (r_refdef.worldmodel && r_refdef.worldmodel->DrawSky)
3289 r_refdef.worldmodel->DrawSky(r_refdef.worldentity);
3290 if (r_timereport_active)
3291 R_TimeReport("worldsky");
3294 if (R_DrawBrushModelsSky() && r_timereport_active)
3295 R_TimeReport("bmodelsky");
3298 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.worldmodel && r_refdef.worldmodel->DrawDepth)
3300 r_refdef.worldmodel->DrawDepth(r_refdef.worldentity);
3301 if (r_timereport_active)
3302 R_TimeReport("worlddepth");
3304 if (r_depthfirst.integer >= 2)
3306 R_DrawModelsDepth();
3307 if (r_timereport_active)
3308 R_TimeReport("modeldepth");
3311 if (cl.csqc_vidvars.drawworld && r_refdef.worldmodel && r_refdef.worldmodel->Draw)
3313 r_refdef.worldmodel->Draw(r_refdef.worldentity);
3314 if (r_timereport_active)
3315 R_TimeReport("world");
3318 // don't let sound skip if going slow
3319 if (r_refdef.extraupdate)
3323 if (r_timereport_active)
3324 R_TimeReport("models");
3326 // don't let sound skip if going slow
3327 if (r_refdef.extraupdate)
3330 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
3332 R_DrawModelShadows();
3334 R_ResetViewRendering3D();
3336 // don't let sound skip if going slow
3337 if (r_refdef.extraupdate)
3341 R_ShadowVolumeLighting(false);
3342 if (r_timereport_active)
3343 R_TimeReport("rtlights");
3345 // don't let sound skip if going slow
3346 if (r_refdef.extraupdate)
3349 if (cl.csqc_vidvars.drawworld)
3351 R_DrawLightningBeams();
3352 if (r_timereport_active)
3353 R_TimeReport("lightning");
3356 if (r_timereport_active)
3357 R_TimeReport("particles");
3360 if (r_timereport_active)
3361 R_TimeReport("explosions");
3364 if (gl_support_fragment_shader)
3366 qglUseProgramObjectARB(0);CHECKGLERROR
3368 VM_CL_AddPolygonsToMeshQueue();
3370 if (r_view.showdebug)
3372 if (cl_locs_show.integer)
3375 if (r_timereport_active)
3376 R_TimeReport("showlocs");
3379 if (r_drawportals.integer)
3382 if (r_timereport_active)
3383 R_TimeReport("portals");
3386 if (r_showbboxes.value > 0)
3388 R_DrawEntityBBoxes();
3389 if (r_timereport_active)
3390 R_TimeReport("bboxes");
3394 if (gl_support_fragment_shader)
3396 qglUseProgramObjectARB(0);CHECKGLERROR
3398 R_MeshQueue_RenderTransparent();
3399 if (r_timereport_active)
3400 R_TimeReport("drawtrans");
3402 if (gl_support_fragment_shader)
3404 qglUseProgramObjectARB(0);CHECKGLERROR
3407 if (r_view.showdebug && r_refdef.worldmodel && r_refdef.worldmodel->DrawDebug && (r_showtris.value > 0 || r_shownormals.value > 0 || r_showcollisionbrushes.value > 0))
3409 r_refdef.worldmodel->DrawDebug(r_refdef.worldentity);
3410 if (r_timereport_active)
3411 R_TimeReport("worlddebug");
3412 R_DrawModelsDebug();
3413 if (r_timereport_active)
3414 R_TimeReport("modeldebug");
3417 if (gl_support_fragment_shader)
3419 qglUseProgramObjectARB(0);CHECKGLERROR
3422 if (cl.csqc_vidvars.drawworld)
3425 if (r_timereport_active)
3426 R_TimeReport("coronas");
3429 // don't let sound skip if going slow
3430 if (r_refdef.extraupdate)
3433 R_ResetViewRendering2D();
3436 static const int bboxelements[36] =
3446 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
3449 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
3450 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3451 GL_DepthMask(false);
3452 GL_DepthRange(0, 1);
3453 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3454 R_Mesh_Matrix(&identitymatrix);
3455 R_Mesh_ResetTextureState();
3457 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
3458 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
3459 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
3460 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
3461 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
3462 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
3463 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
3464 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
3465 R_FillColors(color4f, 8, cr, cg, cb, ca);
3466 if (r_refdef.fogenabled)
3468 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
3470 f1 = FogPoint_World(v);
3472 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
3473 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
3474 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
3477 R_Mesh_VertexPointer(vertex3f, 0, 0);
3478 R_Mesh_ColorPointer(color4f, 0, 0);
3479 R_Mesh_ResetTextureState();
3480 R_Mesh_Draw(0, 8, 12, bboxelements, 0, 0);
3483 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
3487 prvm_edict_t *edict;
3488 // this function draws bounding boxes of server entities
3492 for (i = 0;i < numsurfaces;i++)
3494 edict = PRVM_EDICT_NUM(surfacelist[i]);
3495 switch ((int)edict->fields.server->solid)
3497 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
3498 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
3499 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
3500 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
3501 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
3502 default: Vector4Set(color, 0, 0, 0, 0.50);break;
3504 color[3] *= r_showbboxes.value;
3505 color[3] = bound(0, color[3], 1);
3506 GL_DepthTest(!r_showdisabledepthtest.integer);
3507 GL_CullFace(r_view.cullface_front);
3508 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
3513 static void R_DrawEntityBBoxes(void)
3516 prvm_edict_t *edict;
3518 // this function draws bounding boxes of server entities
3522 for (i = 0;i < prog->num_edicts;i++)
3524 edict = PRVM_EDICT_NUM(i);
3525 if (edict->priv.server->free)
3527 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
3528 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
3533 int nomodelelements[24] =
3545 float nomodelvertex3f[6*3] =
3555 float nomodelcolor4f[6*4] =
3557 0.0f, 0.0f, 0.5f, 1.0f,
3558 0.0f, 0.0f, 0.5f, 1.0f,
3559 0.0f, 0.5f, 0.0f, 1.0f,
3560 0.0f, 0.5f, 0.0f, 1.0f,
3561 0.5f, 0.0f, 0.0f, 1.0f,
3562 0.5f, 0.0f, 0.0f, 1.0f
3565 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
3570 // this is only called once per entity so numsurfaces is always 1, and
3571 // surfacelist is always {0}, so this code does not handle batches
3572 R_Mesh_Matrix(&ent->matrix);
3574 if (ent->flags & EF_ADDITIVE)
3576 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
3577 GL_DepthMask(false);
3579 else if (ent->alpha < 1)
3581 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3582 GL_DepthMask(false);
3586 GL_BlendFunc(GL_ONE, GL_ZERO);
3589 GL_DepthRange(0, (ent->flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
3590 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3591 GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
3592 GL_CullFace((ent->effects & EF_DOUBLESIDED) ? GL_NONE : r_view.cullface_back);
3593 R_Mesh_VertexPointer(nomodelvertex3f, 0, 0);
3594 if (r_refdef.fogenabled)
3597 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
3598 R_Mesh_ColorPointer(color4f, 0, 0);
3599 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
3600 f1 = FogPoint_World(org);
3602 for (i = 0, c = color4f;i < 6;i++, c += 4)
3604 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
3605 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
3606 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
3610 else if (ent->alpha != 1)
3612 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
3613 R_Mesh_ColorPointer(color4f, 0, 0);
3614 for (i = 0, c = color4f;i < 6;i++, c += 4)
3618 R_Mesh_ColorPointer(nomodelcolor4f, 0, 0);
3619 R_Mesh_ResetTextureState();
3620 R_Mesh_Draw(0, 6, 8, nomodelelements, 0, 0);
3623 void R_DrawNoModel(entity_render_t *ent)
3626 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
3627 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
3628 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
3630 // R_DrawNoModelCallback(ent, 0);
3633 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
3635 vec3_t right1, right2, diff, normal;
3637 VectorSubtract (org2, org1, normal);
3639 // calculate 'right' vector for start
3640 VectorSubtract (r_view.origin, org1, diff);
3641 CrossProduct (normal, diff, right1);
3642 VectorNormalize (right1);
3644 // calculate 'right' vector for end
3645 VectorSubtract (r_view.origin, org2, diff);
3646 CrossProduct (normal, diff, right2);
3647 VectorNormalize (right2);
3649 vert[ 0] = org1[0] + width * right1[0];
3650 vert[ 1] = org1[1] + width * right1[1];
3651 vert[ 2] = org1[2] + width * right1[2];
3652 vert[ 3] = org1[0] - width * right1[0];
3653 vert[ 4] = org1[1] - width * right1[1];
3654 vert[ 5] = org1[2] - width * right1[2];
3655 vert[ 6] = org2[0] - width * right2[0];
3656 vert[ 7] = org2[1] - width * right2[1];
3657 vert[ 8] = org2[2] - width * right2[2];
3658 vert[ 9] = org2[0] + width * right2[0];
3659 vert[10] = org2[1] + width * right2[1];
3660 vert[11] = org2[2] + width * right2[2];
3663 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
3665 void R_DrawSprite(int blendfunc1, int blendfunc2, rtexture_t *texture, rtexture_t *fogtexture, qboolean depthdisable, qboolean depthshort, 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)
3670 if (r_refdef.fogenabled)
3671 fog = FogPoint_World(origin);
3673 R_Mesh_Matrix(&identitymatrix);
3674 GL_BlendFunc(blendfunc1, blendfunc2);
3680 GL_CullFace(r_view.cullface_front);
3683 GL_CullFace(r_view.cullface_back);
3685 GL_DepthMask(false);
3686 GL_DepthRange(0, depthshort ? 0.0625 : 1);
3687 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3688 GL_DepthTest(!depthdisable);
3690 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
3691 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
3692 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
3693 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
3694 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
3695 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
3696 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
3697 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
3698 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
3699 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
3700 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
3701 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
3703 R_Mesh_VertexPointer(vertex3f, 0, 0);
3704 R_Mesh_ColorPointer(NULL, 0, 0);
3705 R_Mesh_ResetTextureState();
3706 R_Mesh_TexBind(0, R_GetTexture(texture));
3707 R_Mesh_TexCoordPointer(0, 2, spritetexcoord2f, 0, 0);
3708 // FIXME: fixed function path can't properly handle r_view.colorscale > 1
3709 GL_Color(cr * fog * r_view.colorscale, cg * fog * r_view.colorscale, cb * fog * r_view.colorscale, ca);
3710 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3712 if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
3714 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
3715 GL_BlendFunc(blendfunc1, GL_ONE);
3717 GL_Color(r_refdef.fogcolor[0] * fog * r_view.colorscale, r_refdef.fogcolor[1] * fog * r_view.colorscale, r_refdef.fogcolor[2] * fog * r_view.colorscale, ca);
3718 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3722 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
3727 VectorSet(v, x, y, z);
3728 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
3729 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
3731 if (i == mesh->numvertices)
3733 if (mesh->numvertices < mesh->maxvertices)
3735 VectorCopy(v, vertex3f);
3736 mesh->numvertices++;
3738 return mesh->numvertices;
3744 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
3748 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
3749 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
3750 e = mesh->element3i + mesh->numtriangles * 3;
3751 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
3753 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
3754 if (mesh->numtriangles < mesh->maxtriangles)
3759 mesh->numtriangles++;
3761 element[1] = element[2];
3765 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
3769 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
3770 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
3771 e = mesh->element3i + mesh->numtriangles * 3;
3772 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
3774 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
3775 if (mesh->numtriangles < mesh->maxtriangles)
3780 mesh->numtriangles++;
3782 element[1] = element[2];
3786 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
3787 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
3789 int planenum, planenum2;
3792 mplane_t *plane, *plane2;
3794 double temppoints[2][256*3];
3795 // figure out how large a bounding box we need to properly compute this brush
3797 for (w = 0;w < numplanes;w++)
3798 maxdist = max(maxdist, planes[w].dist);
3799 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
3800 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
3801 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
3805 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
3806 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
3808 if (planenum2 == planenum)
3810 PolygonD_Divide(tempnumpoints, temppoints[w], plane2->normal[0], plane2->normal[1], plane2->normal[2], plane2->dist, R_MESH_PLANE_DIST_EPSILON, 0, NULL, NULL, 256, temppoints[!w], &tempnumpoints, NULL);
3813 if (tempnumpoints < 3)
3815 // generate elements forming a triangle fan for this polygon
3816 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
3820 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)
3822 texturelayer_t *layer;
3823 layer = t->currentlayers + t->currentnumlayers++;
3825 layer->depthmask = depthmask;
3826 layer->blendfunc1 = blendfunc1;
3827 layer->blendfunc2 = blendfunc2;
3828 layer->texture = texture;
3829 layer->texmatrix = *matrix;
3830 layer->color[0] = r * r_view.colorscale;
3831 layer->color[1] = g * r_view.colorscale;
3832 layer->color[2] = b * r_view.colorscale;
3833 layer->color[3] = a;
3836 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
3839 index = parms[2] + r_refdef.time * parms[3];
3840 index -= floor(index);
3844 case Q3WAVEFUNC_NONE:
3845 case Q3WAVEFUNC_NOISE:
3846 case Q3WAVEFUNC_COUNT:
3849 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
3850 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
3851 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
3852 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
3853 case Q3WAVEFUNC_TRIANGLE:
3855 f = index - floor(index);
3866 return (float)(parms[0] + parms[1] * f);
3869 void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
3872 model_t *model = ent->model;
3875 q3shaderinfo_layer_tcmod_t *tcmod;
3877 // switch to an alternate material if this is a q1bsp animated material
3879 texture_t *texture = t;
3880 int s = ent->skinnum;
3881 if ((unsigned int)s >= (unsigned int)model->numskins)
3883 if (model->skinscenes)
3885 if (model->skinscenes[s].framecount > 1)
3886 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
3888 s = model->skinscenes[s].firstframe;
3891 t = t + s * model->num_surfaces;
3894 // use an alternate animation if the entity's frame is not 0,
3895 // and only if the texture has an alternate animation
3896 if (ent->frame2 != 0 && t->anim_total[1])
3897 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.time * 5.0f) % t->anim_total[1]) : 0];
3899 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.time * 5.0f) % t->anim_total[0]) : 0];
3901 texture->currentframe = t;
3904 // update currentskinframe to be a qw skin or animation frame
3905 if ((i = ent->entitynumber - 1) >= 0 && i < cl.maxclients)
3907 if (strcmp(r_qwskincache[i], cl.scores[i].qw_skin))
3909 strlcpy(r_qwskincache[i], cl.scores[i].qw_skin, sizeof(r_qwskincache[i]));
3910 Con_DPrintf("loading skins/%s\n", r_qwskincache[i]);
3911 r_qwskincache_skinframe[i] = R_SkinFrame_LoadExternal(va("skins/%s", r_qwskincache[i]), TEXF_PRECACHE | (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS, developer.integer > 0);
3913 t->currentskinframe = r_qwskincache_skinframe[i];
3914 if (t->currentskinframe == NULL)
3915 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->frame2time)) % t->numskinframes];
3917 else if (t->numskinframes >= 2)
3918 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->frame2time)) % t->numskinframes];
3919 if (t->backgroundnumskinframes >= 2)
3920 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - ent->frame2time)) % t->backgroundnumskinframes];
3922 t->currentmaterialflags = t->basematerialflags;
3923 t->currentalpha = ent->alpha;
3924 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
3926 t->currentalpha *= r_wateralpha.value;
3928 * FIXME what is this supposed to do?
3929 // if rendering refraction/reflection, disable transparency
3930 if (r_waterstate.enabled && (t->currentalpha < 1 || (t->currentmaterialflags & MATERIALFLAG_ALPHA)))
3931 t->currentmaterialflags |= MATERIALFLAG_WATERSHADER;
3934 if(!r_waterstate.enabled)
3935 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION);
3936 if (!(ent->flags & RENDER_LIGHT))
3937 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
3938 if (ent->effects & EF_ADDITIVE)
3939 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
3940 else if (t->currentalpha < 1)
3941 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
3942 if (ent->effects & EF_DOUBLESIDED)
3943 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
3944 if (ent->effects & EF_NODEPTHTEST)
3945 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
3946 if (ent->flags & RENDER_VIEWMODEL)
3947 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
3948 if (t->backgroundnumskinframes && !(t->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED))
3949 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
3951 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && (tcmod->tcmod || i < 1);i++, tcmod++)
3954 switch(tcmod->tcmod)
3958 if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
3959 matrix = r_waterscrollmatrix;
3961 matrix = identitymatrix;
3963 case Q3TCMOD_ENTITYTRANSLATE:
3964 // this is used in Q3 to allow the gamecode to control texcoord
3965 // scrolling on the entity, which is not supported in darkplaces yet.
3966 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
3968 case Q3TCMOD_ROTATE:
3969 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
3970 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.time, 0, 0, 1);
3971 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
3974 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
3976 case Q3TCMOD_SCROLL:
3977 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.time, tcmod->parms[1] * r_refdef.time, 0);
3979 case Q3TCMOD_STRETCH:
3980 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
3981 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
3983 case Q3TCMOD_TRANSFORM:
3984 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
3985 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
3986 VectorSet(tcmat + 6, 0 , 0 , 1);
3987 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
3988 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
3990 case Q3TCMOD_TURBULENT:
3991 // this is handled in the RSurf_PrepareVertices function
3992 matrix = identitymatrix;
3995 // either replace or concatenate the transformation
3997 t->currenttexmatrix = matrix;
4000 matrix4x4_t temp = t->currenttexmatrix;
4001 Matrix4x4_Concat(&t->currenttexmatrix, &matrix, &temp);
4005 t->colormapping = VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f);
4006 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
4007 t->glosstexture = r_texture_black;
4008 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
4009 t->backgroundglosstexture = r_texture_black;
4010 t->specularpower = r_shadow_glossexponent.value;
4011 // TODO: store reference values for these in the texture?
4012 t->specularscale = 0;
4013 if (r_shadow_gloss.integer > 0)
4015 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
4017 if (r_shadow_glossintensity.value > 0)
4019 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
4020 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
4021 t->specularscale = r_shadow_glossintensity.value;
4024 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
4026 t->glosstexture = r_texture_white;
4027 t->backgroundglosstexture = r_texture_white;
4028 t->specularscale = r_shadow_gloss2intensity.value;
4032 // lightmaps mode looks bad with dlights using actual texturing, so turn
4033 // off the colormap and glossmap, but leave the normalmap on as it still
4034 // accurately represents the shading involved
4035 if (gl_lightmaps.integer && !(t->currentmaterialflags & MATERIALFLAG_BLENDED))
4037 t->basetexture = r_texture_white;
4038 t->specularscale = 0;
4041 t->currentpolygonfactor = r_refdef.polygonfactor + t->basepolygonfactor;
4042 t->currentpolygonoffset = r_refdef.polygonoffset + t->basepolygonoffset;
4043 // submodels are biased to avoid z-fighting with world surfaces that they
4044 // may be exactly overlapping (avoids z-fighting artifacts on certain
4045 // doors and things in Quake maps)
4046 if (ent->model->brush.submodel)
4048 t->currentpolygonfactor += r_polygonoffset_submodel_factor.value;
4049 t->currentpolygonoffset += r_polygonoffset_submodel_offset.value;
4052 VectorClear(t->dlightcolor);
4053 t->currentnumlayers = 0;
4054 if (!(t->currentmaterialflags & MATERIALFLAG_NODRAW))
4056 if (!(t->currentmaterialflags & MATERIALFLAG_SKY))
4058 int blendfunc1, blendfunc2, depthmask;
4059 if (t->currentmaterialflags & MATERIALFLAG_ADD)
4061 blendfunc1 = GL_SRC_ALPHA;
4062 blendfunc2 = GL_ONE;
4064 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
4066 blendfunc1 = GL_SRC_ALPHA;
4067 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
4069 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
4071 blendfunc1 = t->customblendfunc[0];
4072 blendfunc2 = t->customblendfunc[1];
4076 blendfunc1 = GL_ONE;
4077 blendfunc2 = GL_ZERO;
4079 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
4080 if (t->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL))
4082 rtexture_t *currentbasetexture;
4084 if (r_refdef.fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED))
4085 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
4086 currentbasetexture = (VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) < (1.0f / 1048576.0f) && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
4087 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
4089 // fullbright is not affected by r_refdef.lightmapintensity
4090 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
4091 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
4092 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->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);
4093 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
4094 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->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);
4099 // set the color tint used for lights affecting this surface
4100 VectorSet(t->dlightcolor, ent->colormod[0] * t->currentalpha, ent->colormod[1] * t->currentalpha, ent->colormod[2] * t->currentalpha);
4102 // q3bsp has no lightmap updates, so the lightstylevalue that
4103 // would normally be baked into the lightmap must be
4104 // applied to the color
4105 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
4106 if (ent->model->type == mod_brushq3)
4107 colorscale *= r_refdef.lightstylevalue[0] * (1.0f / 256.0f);
4108 colorscale *= r_refdef.lightmapintensity;
4109 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_LITTEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0] * colorscale, ent->colormod[1] * colorscale, ent->colormod[2] * colorscale, t->currentalpha);
4110 if (r_ambient.value >= (1.0f/64.0f))
4111 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);
4112 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
4114 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->currentskinframe->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);
4115 if (r_ambient.value >= (1.0f/64.0f))
4116 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->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);
4118 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
4120 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->currentskinframe->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);
4121 if (r_ambient.value >= (1.0f/64.0f))
4122 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->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);
4125 if (t->currentskinframe->glow != NULL)
4126 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->glow, &t->currenttexmatrix, r_hdr_glowintensity.value, r_hdr_glowintensity.value, r_hdr_glowintensity.value, t->currentalpha);
4127 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
4129 // if this is opaque use alpha blend which will darken the earlier
4132 // if this is an alpha blended material, all the earlier passes
4133 // were darkened by fog already, so we only need to add the fog
4134 // color ontop through the fog mask texture
4136 // if this is an additive blended material, all the earlier passes
4137 // were darkened by fog already, and we should not add fog color
4138 // (because the background was not darkened, there is no fog color
4139 // that was lost behind it).
4140 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, (t->currentmaterialflags & MATERIALFLAG_BLENDED) ? GL_ONE : GL_ONE_MINUS_SRC_ALPHA, TEXTURELAYERTYPE_FOG, t->currentskinframe->fog, &identitymatrix, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], t->currentalpha);
4147 void R_UpdateAllTextureInfo(entity_render_t *ent)
4151 for (i = 0;i < ent->model->num_texturesperskin;i++)
4152 R_UpdateTextureInfo(ent, ent->model->data_textures + i);
4155 rsurfacestate_t rsurface;
4157 void R_Mesh_ResizeArrays(int newvertices)
4160 if (rsurface.array_size >= newvertices)
4162 if (rsurface.array_modelvertex3f)
4163 Mem_Free(rsurface.array_modelvertex3f);
4164 rsurface.array_size = (newvertices + 1023) & ~1023;
4165 base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
4166 rsurface.array_modelvertex3f = base + rsurface.array_size * 0;
4167 rsurface.array_modelsvector3f = base + rsurface.array_size * 3;
4168 rsurface.array_modeltvector3f = base + rsurface.array_size * 6;
4169 rsurface.array_modelnormal3f = base + rsurface.array_size * 9;
4170 rsurface.array_deformedvertex3f = base + rsurface.array_size * 12;
4171 rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
4172 rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
4173 rsurface.array_deformednormal3f = base + rsurface.array_size * 21;
4174 rsurface.array_texcoord3f = base + rsurface.array_size * 24;
4175 rsurface.array_color4f = base + rsurface.array_size * 27;
4176 rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
4179 void RSurf_CleanUp(void)
4182 if (rsurface.mode == RSURFMODE_GLSL)
4184 qglUseProgramObjectARB(0);CHECKGLERROR
4186 GL_AlphaTest(false);
4187 rsurface.mode = RSURFMODE_NONE;
4188 rsurface.uselightmaptexture = false;
4189 rsurface.texture = NULL;
4192 void RSurf_ActiveWorldEntity(void)
4194 model_t *model = r_refdef.worldmodel;
4196 if (rsurface.array_size < model->surfmesh.num_vertices)
4197 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
4198 rsurface.matrix = identitymatrix;
4199 rsurface.inversematrix = identitymatrix;
4200 R_Mesh_Matrix(&identitymatrix);
4201 VectorCopy(r_view.origin, rsurface.modelorg);
4202 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
4203 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
4204 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
4205 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
4206 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
4207 rsurface.frameblend[0].frame = 0;
4208 rsurface.frameblend[0].lerp = 1;
4209 rsurface.frameblend[1].frame = 0;
4210 rsurface.frameblend[1].lerp = 0;
4211 rsurface.frameblend[2].frame = 0;
4212 rsurface.frameblend[2].lerp = 0;
4213 rsurface.frameblend[3].frame = 0;
4214 rsurface.frameblend[3].lerp = 0;
4215 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
4216 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
4217 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
4218 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
4219 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
4220 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
4221 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
4222 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
4223 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
4224 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
4225 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
4226 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
4227 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
4228 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
4229 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
4230 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
4231 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
4232 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
4233 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
4234 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
4235 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
4236 rsurface.modelelement3i = model->surfmesh.data_element3i;
4237 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo;
4238 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
4239 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
4240 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
4241 rsurface.modelsurfaces = model->data_surfaces;
4242 rsurface.generatedvertex = false;
4243 rsurface.vertex3f = rsurface.modelvertex3f;
4244 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
4245 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
4246 rsurface.svector3f = rsurface.modelsvector3f;
4247 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
4248 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
4249 rsurface.tvector3f = rsurface.modeltvector3f;
4250 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
4251 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
4252 rsurface.normal3f = rsurface.modelnormal3f;
4253 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
4254 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
4255 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
4258 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4260 model_t *model = ent->model;
4262 if (rsurface.array_size < model->surfmesh.num_vertices)
4263 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
4264 rsurface.matrix = ent->matrix;
4265 rsurface.inversematrix = ent->inversematrix;
4266 R_Mesh_Matrix(&rsurface.matrix);
4267 Matrix4x4_Transform(&rsurface.inversematrix, r_view.origin, rsurface.modelorg);
4268 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
4269 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
4270 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
4271 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
4272 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
4273 rsurface.frameblend[0] = ent->frameblend[0];
4274 rsurface.frameblend[1] = ent->frameblend[1];
4275 rsurface.frameblend[2] = ent->frameblend[2];
4276 rsurface.frameblend[3] = ent->frameblend[3];
4277 if (model->surfmesh.isanimated && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].frame != 0))
4281 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
4282 rsurface.modelsvector3f = rsurface.array_modelsvector3f;
4283 rsurface.modeltvector3f = rsurface.array_modeltvector3f;
4284 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
4285 Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
4287 else if (wantnormals)
4289 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
4290 rsurface.modelsvector3f = NULL;
4291 rsurface.modeltvector3f = NULL;
4292 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
4293 Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
4297 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
4298 rsurface.modelsvector3f = NULL;
4299 rsurface.modeltvector3f = NULL;
4300 rsurface.modelnormal3f = NULL;
4301 Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, NULL, NULL, NULL);
4303 rsurface.modelvertex3f_bufferobject = 0;
4304 rsurface.modelvertex3f_bufferoffset = 0;
4305 rsurface.modelsvector3f_bufferobject = 0;
4306 rsurface.modelsvector3f_bufferoffset = 0;
4307 rsurface.modeltvector3f_bufferobject = 0;
4308 rsurface.modeltvector3f_bufferoffset = 0;
4309 rsurface.modelnormal3f_bufferobject = 0;
4310 rsurface.modelnormal3f_bufferoffset = 0;
4311 rsurface.generatedvertex = true;
4315 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
4316 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
4317 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
4318 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
4319 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
4320 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
4321 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
4322 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
4323 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
4324 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
4325 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
4326 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
4327 rsurface.generatedvertex = false;
4329 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
4330 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
4331 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
4332 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
4333 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
4334 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
4335 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
4336 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
4337 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
4338 rsurface.modelelement3i = model->surfmesh.data_element3i;
4339 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo;
4340 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
4341 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
4342 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
4343 rsurface.modelsurfaces = model->data_surfaces;
4344 rsurface.vertex3f = rsurface.modelvertex3f;
4345 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
4346 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
4347 rsurface.svector3f = rsurface.modelsvector3f;
4348 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
4349 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
4350 rsurface.tvector3f = rsurface.modeltvector3f;
4351 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
4352 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
4353 rsurface.normal3f = rsurface.modelnormal3f;
4354 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
4355 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
4356 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
4359 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
4360 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, msurface_t **texturesurfacelist)
4363 int texturesurfaceindex;
4368 const float *v1, *in_tc;
4370 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
4372 q3shaderinfo_deform_t *deform;
4373 // if vertices are dynamic (animated models), generate them into the temporary rsurface.array_model* arrays and point rsurface.model* at them instead of the static data from the model itself
4374 if (rsurface.generatedvertex)
4376 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
4377 generatenormals = true;
4378 for (i = 0;i < Q3MAXDEFORMS;i++)
4380 if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
4382 generatetangents = true;
4383 generatenormals = true;
4385 if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
4386 generatenormals = true;
4388 if (generatenormals && !rsurface.modelnormal3f)
4390 rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
4391 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
4392 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
4393 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer);
4395 if (generatetangents && !rsurface.modelsvector3f)
4397 rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
4398 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
4399 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
4400 rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
4401 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
4402 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
4403 Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f, r_smoothnormals_areaweighting.integer);
4406 rsurface.vertex3f = rsurface.modelvertex3f;
4407 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
4408 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
4409 rsurface.svector3f = rsurface.modelsvector3f;
4410 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
4411 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
4412 rsurface.tvector3f = rsurface.modeltvector3f;
4413 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
4414 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
4415 rsurface.normal3f = rsurface.modelnormal3f;
4416 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
4417 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
4418 // if vertices are deformed (sprite flares and things in maps, possibly
4419 // water waves, bulges and other deformations), generate them into
4420 // rsurface.deform* arrays from whatever the rsurface.* arrays point to
4421 // (may be static model data or generated data for an animated model, or
4422 // the previous deform pass)
4423 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
4425 switch (deform->deform)
4428 case Q3DEFORM_PROJECTIONSHADOW:
4429 case Q3DEFORM_TEXT0:
4430 case Q3DEFORM_TEXT1:
4431 case Q3DEFORM_TEXT2:
4432 case Q3DEFORM_TEXT3:
4433 case Q3DEFORM_TEXT4:
4434 case Q3DEFORM_TEXT5:
4435 case Q3DEFORM_TEXT6:
4436 case Q3DEFORM_TEXT7:
4439 case Q3DEFORM_AUTOSPRITE:
4440 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.forward, newforward);
4441 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.right, newright);
4442 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.up, newup);
4443 VectorNormalize(newforward);
4444 VectorNormalize(newright);
4445 VectorNormalize(newup);
4446 // make deformed versions of only the model vertices used by the specified surfaces
4447 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4449 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4450 // a single autosprite surface can contain multiple sprites...
4451 for (j = 0;j < surface->num_vertices - 3;j += 4)
4453 VectorClear(center);
4454 for (i = 0;i < 4;i++)
4455 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
4456 VectorScale(center, 0.25f, center);
4457 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, forward);
4458 VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
4459 VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
4460 for (i = 0;i < 4;i++)
4462 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
4463 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
4466 Mod_BuildNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface.vertex3f, rsurface.modelelement3i + surface->num_firsttriangle * 3, rsurface.array_deformednormal3f, r_smoothnormals_areaweighting.integer);
4467 Mod_BuildTextureVectorsFromNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface.vertex3f, rsurface.modeltexcoordtexture2f, rsurface.array_deformednormal3f, rsurface.modelelement3i + surface->num_firsttriangle * 3, rsurface.array_deformedsvector3f, rsurface.array_deformedtvector3f, r_smoothnormals_areaweighting.integer);
4469 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4470 rsurface.vertex3f_bufferobject = 0;
4471 rsurface.vertex3f_bufferoffset = 0;
4472 rsurface.svector3f = rsurface.array_deformedsvector3f;
4473 rsurface.svector3f_bufferobject = 0;
4474 rsurface.svector3f_bufferoffset = 0;
4475 rsurface.tvector3f = rsurface.array_deformedtvector3f;
4476 rsurface.tvector3f_bufferobject = 0;
4477 rsurface.tvector3f_bufferoffset = 0;
4478 rsurface.normal3f = rsurface.array_deformednormal3f;
4479 rsurface.normal3f_bufferobject = 0;
4480 rsurface.normal3f_bufferoffset = 0;
4482 case Q3DEFORM_AUTOSPRITE2:
4483 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.forward, newforward);
4484 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.right, newright);
4485 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.up, newup);
4486 VectorNormalize(newforward);
4487 VectorNormalize(newright);
4488 VectorNormalize(newup);
4489 // make deformed versions of only the model vertices used by the specified surfaces
4490 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4492 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4493 const float *v1, *v2;
4503 memset(shortest, 0, sizeof(shortest));
4504 // a single autosprite surface can contain multiple sprites...
4505 for (j = 0;j < surface->num_vertices - 3;j += 4)
4507 VectorClear(center);
4508 for (i = 0;i < 4;i++)
4509 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
4510 VectorScale(center, 0.25f, center);
4511 // find the two shortest edges, then use them to define the
4512 // axis vectors for rotating around the central axis
4513 for (i = 0;i < 6;i++)
4515 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
4516 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
4518 Debug_PolygonBegin(NULL, 0, false, 0);
4519 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
4520 Debug_PolygonVertex((v1[0] + v2[0]) * 0.5f + rsurface.normal3f[3 * (surface->num_firstvertex + j)+0] * 4, (v1[1] + v2[1]) * 0.5f + rsurface.normal3f[3 * (surface->num_firstvertex + j)+1], (v1[2] + v2[2]) * 0.5f + rsurface.normal3f[3 * (surface->num_firstvertex + j)+2], 0, 0, 1, 1, 0, 1);
4521 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
4524 l = VectorDistance2(v1, v2);
4525 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
4527 l += (1.0f / 1024.0f);
4528 if (shortest[0].length2 > l || i == 0)
4530 shortest[1] = shortest[0];
4531 shortest[0].length2 = l;
4532 shortest[0].v1 = v1;
4533 shortest[0].v2 = v2;
4535 else if (shortest[1].length2 > l || i == 1)
4537 shortest[1].length2 = l;
4538 shortest[1].v1 = v1;
4539 shortest[1].v2 = v2;
4542 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
4543 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
4545 Debug_PolygonBegin(NULL, 0, false, 0);
4546 Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
4547 Debug_PolygonVertex(center[0] + rsurface.normal3f[3 * (surface->num_firstvertex + j)+0] * 4, center[1] + rsurface.normal3f[3 * (surface->num_firstvertex + j)+1] * 4, center[2] + rsurface.normal3f[3 * (surface->num_firstvertex + j)+2] * 4, 0, 0, 0, 1, 0, 1);
4548 Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
4551 // this calculates the right vector from the shortest edge
4552 // and the up vector from the edge midpoints
4553 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
4554 VectorNormalize(right);
4555 VectorSubtract(end, start, up);
4556 VectorNormalize(up);
4557 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
4558 //VectorSubtract(rsurface.modelorg, center, forward);
4559 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.forward, forward);
4560 VectorNegate(forward, forward);
4561 VectorReflect(forward, 0, up, forward);
4562 VectorNormalize(forward);
4563 CrossProduct(up, forward, newright);
4564 VectorNormalize(newright);
4566 Debug_PolygonBegin(NULL, 0, false, 0);
4567 Debug_PolygonVertex(center[0] + rsurface.normal3f[3 * (surface->num_firstvertex + j)+0] * 8, center[1] + rsurface.normal3f[3 * (surface->num_firstvertex + j)+1] * 8, center[2] + rsurface.normal3f[3 * (surface->num_firstvertex + j)+2] * 8, 0, 0, 1, 0, 0, 1);
4568 Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
4569 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
4573 Debug_PolygonBegin(NULL, 0, false, 0);
4574 Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
4575 Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
4576 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
4579 // rotate the quad around the up axis vector, this is made
4580 // especially easy by the fact we know the quad is flat,
4581 // so we only have to subtract the center position and
4582 // measure distance along the right vector, and then
4583 // multiply that by the newright vector and add back the
4585 // we also need to subtract the old position to undo the
4586 // displacement from the center, which we do with a
4587 // DotProduct, the subtraction/addition of center is also
4588 // optimized into DotProducts here
4589 l = DotProduct(right, center);
4590 for (i = 0;i < 4;i++)
4592 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
4593 f = DotProduct(right, v1) - l;
4594 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
4597 Mod_BuildNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface.vertex3f, rsurface.modelelement3i + surface->num_firsttriangle * 3, rsurface.array_deformednormal3f, r_smoothnormals_areaweighting.integer);
4598 Mod_BuildTextureVectorsFromNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface.vertex3f, rsurface.modeltexcoordtexture2f, rsurface.array_deformednormal3f, rsurface.modelelement3i + surface->num_firsttriangle * 3, rsurface.array_deformedsvector3f, rsurface.array_deformedtvector3f, r_smoothnormals_areaweighting.integer);
4600 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4601 rsurface.vertex3f_bufferobject = 0;
4602 rsurface.vertex3f_bufferoffset = 0;
4603 rsurface.svector3f = rsurface.array_deformedsvector3f;
4604 rsurface.svector3f_bufferobject = 0;
4605 rsurface.svector3f_bufferoffset = 0;
4606 rsurface.tvector3f = rsurface.array_deformedtvector3f;
4607 rsurface.tvector3f_bufferobject = 0;
4608 rsurface.tvector3f_bufferoffset = 0;
4609 rsurface.normal3f = rsurface.array_deformednormal3f;
4610 rsurface.normal3f_bufferobject = 0;
4611 rsurface.normal3f_bufferoffset = 0;
4613 case Q3DEFORM_NORMAL:
4614 // deform the normals to make reflections wavey
4615 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4617 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4618 for (j = 0;j < surface->num_vertices;j++)
4621 float *normal = (rsurface.array_deformednormal3f + 3 * surface->num_firstvertex) + j*3;
4622 VectorScale((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
4623 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, normal);
4624 normal[0] += deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.time * deform->parms[1]);
4625 normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.time * deform->parms[1]);
4626 normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.time * deform->parms[1]);
4627 VectorNormalize(normal);
4629 Mod_BuildTextureVectorsFromNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface.vertex3f, rsurface.modeltexcoordtexture2f, rsurface.array_deformednormal3f, rsurface.modelelement3i + surface->num_firsttriangle * 3, rsurface.array_deformedsvector3f, rsurface.array_deformedtvector3f, r_smoothnormals_areaweighting.integer);
4631 rsurface.svector3f = rsurface.array_deformedsvector3f;
4632 rsurface.svector3f_bufferobject = 0;
4633 rsurface.svector3f_bufferoffset = 0;
4634 rsurface.tvector3f = rsurface.array_deformedtvector3f;
4635 rsurface.tvector3f_bufferobject = 0;
4636 rsurface.tvector3f_bufferoffset = 0;
4637 rsurface.normal3f = rsurface.array_deformednormal3f;
4638 rsurface.normal3f_bufferobject = 0;
4639 rsurface.normal3f_bufferoffset = 0;
4642 // deform vertex array to make wavey water and flags and such
4643 waveparms[0] = deform->waveparms[0];
4644 waveparms[1] = deform->waveparms[1];
4645 waveparms[2] = deform->waveparms[2];
4646 waveparms[3] = deform->waveparms[3];
4647 // this is how a divisor of vertex influence on deformation
4648 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
4649 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
4650 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4652 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4653 for (j = 0;j < surface->num_vertices;j++)
4655 float *vertex = (rsurface.array_deformedvertex3f + 3 * surface->num_firstvertex) + j*3;
4656 VectorCopy((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, vertex);
4657 // if the wavefunc depends on time, evaluate it per-vertex
4660 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
4661 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
4663 VectorMA(vertex, scale, (rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, vertex);
4666 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4667 rsurface.vertex3f_bufferobject = 0;
4668 rsurface.vertex3f_bufferoffset = 0;
4670 case Q3DEFORM_BULGE:
4671 // deform vertex array to make the surface have moving bulges
4672 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4674 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4675 for (j = 0;j < surface->num_vertices;j++)
4677 scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.time * deform->parms[2])) * deform->parms[1];
4678 VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
4681 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4682 rsurface.vertex3f_bufferobject = 0;
4683 rsurface.vertex3f_bufferoffset = 0;
4686 // deform vertex array
4687 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
4688 VectorScale(deform->parms, scale, waveparms);
4689 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4691 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4692 for (j = 0;j < surface->num_vertices;j++)
4693 VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
4695 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4696 rsurface.vertex3f_bufferobject = 0;
4697 rsurface.vertex3f_bufferoffset = 0;
4701 // generate texcoords based on the chosen texcoord source
4702 switch(rsurface.texture->tcgen.tcgen)
4705 case Q3TCGEN_TEXTURE:
4706 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
4707 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordtexture2f_bufferobject;
4708 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
4710 case Q3TCGEN_LIGHTMAP:
4711 rsurface.texcoordtexture2f = rsurface.modeltexcoordlightmap2f;
4712 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
4713 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
4715 case Q3TCGEN_VECTOR:
4716 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4718 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4719 for (j = 0, v1 = rsurface.modelvertex3f + 3 * surface->num_firstvertex, out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;j < surface->num_vertices;j++, v1 += 3, out_tc += 2)
4721 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
4722 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
4725 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
4726 rsurface.texcoordtexture2f_bufferobject = 0;
4727 rsurface.texcoordtexture2f_bufferoffset = 0;
4729 case Q3TCGEN_ENVIRONMENT:
4730 // make environment reflections using a spheremap
4731 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4733 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4734 const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
4735 const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
4736 float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
4737 for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
4739 float l, d, eyedir[3];
4740 VectorSubtract(rsurface.modelorg, vertex, eyedir);
4741 l = 0.5f / VectorLength(eyedir);
4742 d = DotProduct(normal, eyedir)*2;
4743 out_tc[0] = 0.5f + (normal[1]*d - eyedir[1])*l;
4744 out_tc[1] = 0.5f - (normal[2]*d - eyedir[2])*l;
4747 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
4748 rsurface.texcoordtexture2f_bufferobject = 0;
4749 rsurface.texcoordtexture2f_bufferoffset = 0;
4752 // the only tcmod that needs software vertex processing is turbulent, so
4753 // check for it here and apply the changes if needed
4754 // and we only support that as the first one
4755 // (handling a mixture of turbulent and other tcmods would be problematic
4756 // without punting it entirely to a software path)
4757 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
4759 amplitude = rsurface.texture->tcmods[0].parms[1];
4760 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.time * rsurface.texture->tcmods[0].parms[3];
4761 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4763 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4764 for (j = 0, v1 = rsurface.modelvertex3f + 3 * surface->num_firstvertex, in_tc = rsurface.texcoordtexture2f + 2 * surface->num_firstvertex, out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;j < surface->num_vertices;j++, v1 += 3, in_tc += 2, out_tc += 2)
4766 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
4767 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
4770 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
4771 rsurface.texcoordtexture2f_bufferobject = 0;
4772 rsurface.texcoordtexture2f_bufferoffset = 0;
4774 rsurface.texcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
4775 rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
4776 rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
4777 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
4780 void RSurf_DrawBatch_Simple(int texturenumsurfaces, msurface_t **texturesurfacelist)
4783 const msurface_t *surface = texturesurfacelist[0];
4784 const msurface_t *surface2;
4789 // TODO: lock all array ranges before render, rather than on each surface
4790 if (texturenumsurfaces == 1)
4792 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
4793 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
4795 else if (r_batchmode.integer == 2)
4797 #define MAXBATCHTRIANGLES 4096
4798 int batchtriangles = 0;
4799 int batchelements[MAXBATCHTRIANGLES*3];
4800 for (i = 0;i < texturenumsurfaces;i = j)
4802 surface = texturesurfacelist[i];
4804 if (surface->num_triangles > MAXBATCHTRIANGLES)
4806 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
4809 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
4810 batchtriangles = surface->num_triangles;
4811 firstvertex = surface->num_firstvertex;
4812 endvertex = surface->num_firstvertex + surface->num_vertices;
4813 for (;j < texturenumsurfaces;j++)
4815 surface2 = texturesurfacelist[j];
4816 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
4818 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
4819 batchtriangles += surface2->num_triangles;
4820 firstvertex = min(firstvertex, surface2->num_firstvertex);
4821 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
4823 surface2 = texturesurfacelist[j-1];
4824 numvertices = endvertex - firstvertex;
4825 R_Mesh_Draw(firstvertex, numvertices, batchtriangles, batchelements, 0, 0);
4828 else if (r_batchmode.integer == 1)
4830 for (i = 0;i < texturenumsurfaces;i = j)
4832 surface = texturesurfacelist[i];
4833 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
4834 if (texturesurfacelist[j] != surface2)
4836 surface2 = texturesurfacelist[j-1];
4837 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
4838 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
4839 GL_LockArrays(surface->num_firstvertex, numvertices);
4840 R_Mesh_Draw(surface->num_firstvertex, numvertices, numtriangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
4845 for (i = 0;i < texturenumsurfaces;i++)
4847 surface = texturesurfacelist[i];
4848 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
4849 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
4854 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit, int refractiontexunit, int reflectiontexunit)
4856 int i, planeindex, vertexindex;
4860 r_waterstate_waterplane_t *p, *bestp;
4861 msurface_t *surface;
4862 if (r_waterstate.renderingscene)
4864 for (i = 0;i < texturenumsurfaces;i++)
4866 surface = texturesurfacelist[i];
4867 if (lightmaptexunit >= 0)
4868 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
4869 if (deluxemaptexunit >= 0)
4870 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
4871 // pick the closest matching water plane
4874 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
4877 for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
4879 Matrix4x4_Transform(&rsurface.matrix, v, vert);
4880 d += fabs(PlaneDiff(vert, &p->plane));
4882 if (bestd > d || !bestp)
4890 if (refractiontexunit >= 0)
4891 R_Mesh_TexBind(refractiontexunit, R_GetTexture(bestp->texture_refraction));
4892 if (reflectiontexunit >= 0)
4893 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(bestp->texture_reflection));
4897 if (refractiontexunit >= 0)
4898 R_Mesh_TexBind(refractiontexunit, R_GetTexture(r_texture_black));
4899 if (reflectiontexunit >= 0)
4900 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(r_texture_black));
4902 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
4903 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
4907 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit)
4911 const msurface_t *surface = texturesurfacelist[0];
4912 const msurface_t *surface2;
4917 // TODO: lock all array ranges before render, rather than on each surface
4918 if (texturenumsurfaces == 1)
4920 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
4921 if (deluxemaptexunit >= 0)
4922 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
4923 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
4924 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
4926 else if (r_batchmode.integer == 2)
4928 #define MAXBATCHTRIANGLES 4096
4929 int batchtriangles = 0;
4930 int batchelements[MAXBATCHTRIANGLES*3];
4931 for (i = 0;i < texturenumsurfaces;i = j)
4933 surface = texturesurfacelist[i];
4934 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
4935 if (deluxemaptexunit >= 0)
4936 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
4938 if (surface->num_triangles > MAXBATCHTRIANGLES)
4940 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
4943 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
4944 batchtriangles = surface->num_triangles;
4945 firstvertex = surface->num_firstvertex;
4946 endvertex = surface->num_firstvertex + surface->num_vertices;
4947 for (;j < texturenumsurfaces;j++)
4949 surface2 = texturesurfacelist[j];
4950 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
4952 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
4953 batchtriangles += surface2->num_triangles;
4954 firstvertex = min(firstvertex, surface2->num_firstvertex);
4955 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
4957 surface2 = texturesurfacelist[j-1];
4958 numvertices = endvertex - firstvertex;
4959 R_Mesh_Draw(firstvertex, numvertices, batchtriangles, batchelements, 0, 0);
4962 else if (r_batchmode.integer == 1)
4965 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
4966 for (i = 0;i < texturenumsurfaces;i = j)
4968 surface = texturesurfacelist[i];
4969 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
4970 if (texturesurfacelist[j] != surface2)
4972 Con_Printf(" %i", j - i);
4975 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
4977 for (i = 0;i < texturenumsurfaces;i = j)
4979 surface = texturesurfacelist[i];
4980 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
4981 if (deluxemaptexunit >= 0)
4982 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
4983 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
4984 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
4987 Con_Printf(" %i", j - i);
4989 surface2 = texturesurfacelist[j-1];
4990 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
4991 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
4992 GL_LockArrays(surface->num_firstvertex, numvertices);
4993 R_Mesh_Draw(surface->num_firstvertex, numvertices, numtriangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
5001 for (i = 0;i < texturenumsurfaces;i++)
5003 surface = texturesurfacelist[i];
5004 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5005 if (deluxemaptexunit >= 0)
5006 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5007 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5008 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
5013 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
5016 int texturesurfaceindex;
5017 if (r_showsurfaces.integer == 2)
5019 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5021 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5022 for (j = 0;j < surface->num_triangles;j++)
5024 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_view.colorscale;
5025 GL_Color(f, f, f, 1);
5026 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, 1, (rsurface.modelelement3i + 3 * (j + surface->num_firsttriangle)), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * (j + surface->num_firsttriangle)));
5032 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5034 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5035 int k = (int)(((size_t)surface) / sizeof(msurface_t));
5036 GL_Color((k & 15) * (1.0f / 16.0f) * r_view.colorscale, ((k >> 4) & 15) * (1.0f / 16.0f) * r_view.colorscale, ((k >> 8) & 15) * (1.0f / 16.0f) * r_view.colorscale, 1);
5037 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5038 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
5043 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, msurface_t **texturesurfacelist)
5045 int texturesurfaceindex;
5049 if (rsurface.lightmapcolor4f)
5051 // generate color arrays for the surfaces in this list
5052 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5054 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5055 for (i = 0, v = (rsurface.vertex3f + 3 * surface->num_firstvertex), c = (rsurface.lightmapcolor4f + 4 * surface->num_firstvertex), c2 = (rsurface.array_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4, c2 += 4)
5057 f = FogPoint_Model(v);
5067 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5069 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5070 for (i = 0, v = (rsurface.vertex3f + 3 * surface->num_firstvertex), c2 = (rsurface.array_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c2 += 4)
5072 f = FogPoint_Model(v);
5080 rsurface.lightmapcolor4f = rsurface.array_color4f;
5081 rsurface.lightmapcolor4f_bufferobject = 0;
5082 rsurface.lightmapcolor4f_bufferoffset = 0;
5085 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a)
5087 int texturesurfaceindex;
5090 if (!rsurface.lightmapcolor4f)
5092 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5094 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5095 for (i = 0, c = (rsurface.lightmapcolor4f + 4 * surface->num_firstvertex), c2 = (rsurface.array_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, c += 4, c2 += 4)
5103 rsurface.lightmapcolor4f = rsurface.array_color4f;
5104 rsurface.lightmapcolor4f_bufferobject = 0;
5105 rsurface.lightmapcolor4f_bufferoffset = 0;
5108 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5111 rsurface.lightmapcolor4f = NULL;
5112 rsurface.lightmapcolor4f_bufferobject = 0;
5113 rsurface.lightmapcolor4f_bufferoffset = 0;
5114 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5115 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5116 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5117 GL_Color(r, g, b, a);
5118 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 0, -1);
5121 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5123 // TODO: optimize applyfog && applycolor case
5124 // just apply fog if necessary, and tint the fog color array if necessary
5125 rsurface.lightmapcolor4f = NULL;
5126 rsurface.lightmapcolor4f_bufferobject = 0;
5127 rsurface.lightmapcolor4f_bufferoffset = 0;
5128 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5129 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5130 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5131 GL_Color(r, g, b, a);
5132 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5135 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5137 int texturesurfaceindex;
5141 if (texturesurfacelist[0]->lightmapinfo && texturesurfacelist[0]->lightmapinfo->stainsamples)
5143 // generate color arrays for the surfaces in this list
5144 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5146 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5147 for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
5149 if (surface->lightmapinfo->samples)
5151 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
5152 float scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
5153 VectorScale(lm, scale, c);
5154 if (surface->lightmapinfo->styles[1] != 255)
5156 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
5158 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
5159 VectorMA(c, scale, lm, c);
5160 if (surface->lightmapinfo->styles[2] != 255)
5163 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
5164 VectorMA(c, scale, lm, c);
5165 if (surface->lightmapinfo->styles[3] != 255)
5168 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
5169 VectorMA(c, scale, lm, c);
5179 rsurface.lightmapcolor4f = rsurface.array_color4f;
5180 rsurface.lightmapcolor4f_bufferobject = 0;
5181 rsurface.lightmapcolor4f_bufferoffset = 0;
5185 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
5186 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
5187 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
5189 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5190 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5191 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5192 GL_Color(r, g, b, a);
5193 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5196 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5198 int texturesurfaceindex;
5202 vec3_t ambientcolor;
5203 vec3_t diffusecolor;
5207 VectorCopy(rsurface.modellight_lightdir, lightdir);
5208 ambientcolor[0] = rsurface.modellight_ambient[0] * r * 0.5f;
5209 ambientcolor[1] = rsurface.modellight_ambient[1] * g * 0.5f;
5210 ambientcolor[2] = rsurface.modellight_ambient[2] * b * 0.5f;
5211 diffusecolor[0] = rsurface.modellight_diffuse[0] * r * 0.5f;
5212 diffusecolor[1] = rsurface.modellight_diffuse[1] * g * 0.5f;
5213 diffusecolor[2] = rsurface.modellight_diffuse[2] * b * 0.5f;
5214 if (VectorLength2(diffusecolor) > 0)
5216 // generate color arrays for the surfaces in this list
5217 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5219 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5220 int numverts = surface->num_vertices;
5221 v = rsurface.vertex3f + 3 * surface->num_firstvertex;
5222 c2 = rsurface.normal3f + 3 * surface->num_firstvertex;
5223 c = rsurface.array_color4f + 4 * surface->num_firstvertex;
5224 // q3-style directional shading
5225 for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
5227 if ((f = DotProduct(c2, lightdir)) > 0)
5228 VectorMA(ambientcolor, f, diffusecolor, c);
5230 VectorCopy(ambientcolor, c);
5239 rsurface.lightmapcolor4f = rsurface.array_color4f;
5240 rsurface.lightmapcolor4f_bufferobject = 0;
5241 rsurface.lightmapcolor4f_bufferoffset = 0;
5245 r = ambientcolor[0];
5246 g = ambientcolor[1];
5247 b = ambientcolor[2];
5248 rsurface.lightmapcolor4f = NULL;
5249 rsurface.lightmapcolor4f_bufferobject = 0;
5250 rsurface.lightmapcolor4f_bufferoffset = 0;
5252 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5253 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5254 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5255 GL_Color(r, g, b, a);
5256 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5259 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
5261 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5262 GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset);
5263 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
5264 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_view.cullface_back);
5265 if (rsurface.mode != RSURFMODE_SHOWSURFACES)
5267 rsurface.mode = RSURFMODE_SHOWSURFACES;
5269 GL_BlendFunc(GL_ONE, GL_ZERO);
5270 R_Mesh_ColorPointer(NULL, 0, 0);
5271 R_Mesh_ResetTextureState();
5273 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
5274 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
5277 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, msurface_t **texturesurfacelist)
5279 // transparent sky would be ridiculous
5280 if ((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED))
5282 if (rsurface.mode != RSURFMODE_SKY)
5284 if (rsurface.mode == RSURFMODE_GLSL)
5286 qglUseProgramObjectARB(0);CHECKGLERROR
5288 rsurface.mode = RSURFMODE_SKY;
5292 skyrendernow = false;
5294 // restore entity matrix
5295 R_Mesh_Matrix(&rsurface.matrix);
5297 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5298 GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset);
5299 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
5300 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_view.cullface_back);
5302 // LordHavoc: HalfLife maps have freaky skypolys so don't use
5303 // skymasking on them, and Quake3 never did sky masking (unlike
5304 // software Quake and software Quake2), so disable the sky masking
5305 // in Quake3 maps as it causes problems with q3map2 sky tricks,
5306 // and skymasking also looks very bad when noclipping outside the
5307 // level, so don't use it then either.
5308 if (r_refdef.worldmodel && r_refdef.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_viewcache.world_novis)
5310 GL_Color(r_refdef.fogcolor[0] * r_view.colorscale, r_refdef.fogcolor[1] * r_view.colorscale, r_refdef.fogcolor[2] * r_view.colorscale, 1);
5311 R_Mesh_ColorPointer(NULL, 0, 0);
5312 R_Mesh_ResetTextureState();
5313 if (skyrendermasked)
5315 // depth-only (masking)
5316 GL_ColorMask(0,0,0,0);
5317 // just to make sure that braindead drivers don't draw
5318 // anything despite that colormask...
5319 GL_BlendFunc(GL_ZERO, GL_ONE);
5324 GL_BlendFunc(GL_ONE, GL_ZERO);
5326 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
5327 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5328 if (skyrendermasked)
5329 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
5333 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, msurface_t **texturesurfacelist)
5335 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION)))
5338 if (rsurface.mode != RSURFMODE_GLSL)
5340 rsurface.mode = RSURFMODE_GLSL;
5341 R_Mesh_ResetTextureState();
5344 R_Mesh_TexMatrix(0, &rsurface.texture->currenttexmatrix);
5345 R_Mesh_TexBind(0, R_GetTexture(rsurface.texture->currentskinframe->nmap));
5346 R_Mesh_TexBind(1, R_GetTexture(rsurface.texture->basetexture));
5347 R_Mesh_TexBind(2, R_GetTexture(rsurface.texture->glosstexture));
5348 R_Mesh_TexBind(4, R_GetTexture(r_texture_fogattenuation));
5349 R_Mesh_TexBind(5, R_GetTexture(rsurface.texture->currentskinframe->pants));
5350 R_Mesh_TexBind(6, R_GetTexture(rsurface.texture->currentskinframe->shirt));
5351 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
5353 R_Mesh_TexBind(7, R_GetTexture(r_texture_grey128));
5354 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
5355 R_Mesh_ColorPointer(NULL, 0, 0);
5357 else if (rsurface.uselightmaptexture)
5359 R_Mesh_TexBind(7, R_GetTexture(texturesurfacelist[0]->lightmaptexture));
5360 R_Mesh_TexBind(8, R_GetTexture(texturesurfacelist[0]->deluxemaptexture));
5361 R_Mesh_ColorPointer(NULL, 0, 0);
5365 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
5366 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
5367 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
5369 R_Mesh_TexBind(9, R_GetTexture(rsurface.texture->currentskinframe->glow));
5370 R_Mesh_TexBind(11, R_GetTexture(r_texture_white)); // changed per surface
5371 R_Mesh_TexBind(12, R_GetTexture(r_texture_white)); // changed per surface
5373 if (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5375 // render background
5376 GL_BlendFunc(GL_ONE, GL_ZERO);
5378 GL_AlphaTest(false);
5380 GL_Color(1, 1, 1, 1);
5381 R_Mesh_ColorPointer(NULL, 0, 0);
5383 R_SetupSurfaceShader(vec3_origin, rsurface.lightmode == 2, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
5384 if (r_glsl_permutation)
5386 RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
5387 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
5388 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
5389 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
5390 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
5391 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
5392 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist, -1, -1, r_glsl_permutation->loc_Texture_Refraction ? 11 : -1, r_glsl_permutation->loc_Texture_Reflection ? 12 : -1);
5395 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5396 GL_DepthMask(false);
5397 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5398 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
5400 R_Mesh_TexBind(7, R_GetTexture(r_texture_grey128));
5401 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
5402 R_Mesh_ColorPointer(NULL, 0, 0);
5404 else if (rsurface.uselightmaptexture)
5406 R_Mesh_TexBind(7, R_GetTexture(texturesurfacelist[0]->lightmaptexture));
5407 R_Mesh_TexBind(8, R_GetTexture(texturesurfacelist[0]->deluxemaptexture));
5408 R_Mesh_ColorPointer(NULL, 0, 0);
5412 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
5413 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
5414 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
5416 R_Mesh_TexBind(11, R_GetTexture(r_texture_white)); // changed per surface
5417 R_Mesh_TexBind(12, R_GetTexture(r_texture_white)); // changed per surface
5420 R_SetupSurfaceShader(vec3_origin, rsurface.lightmode == 2, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE);
5421 if (!r_glsl_permutation)
5424 if (rsurface.lightmode == 2)
5425 RSurf_PrepareVerticesForBatch(true, r_glsl_permutation->loc_Texture_Normal >= 0, texturenumsurfaces, texturesurfacelist);
5427 RSurf_PrepareVerticesForBatch(r_glsl_permutation->loc_Texture_Normal >= 0, r_glsl_permutation->loc_Texture_Normal >= 0, texturenumsurfaces, texturesurfacelist);
5428 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
5429 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
5430 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
5431 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
5432 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
5433 GL_Color(rsurface.texture->currentlayers[0].color[0], rsurface.texture->currentlayers[0].color[1], rsurface.texture->currentlayers[0].color[2], rsurface.texture->currentlayers[0].color[3]);
5435 if (r_glsl_permutation->loc_Texture_Refraction >= 0)
5437 GL_BlendFunc(GL_ONE, GL_ZERO);
5439 GL_AlphaTest(false);
5442 if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
5444 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
5445 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist, 7, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? 8 : -1, r_glsl_permutation->loc_Texture_Refraction >= 0 ? 11 : -1, r_glsl_permutation->loc_Texture_Reflection >= 0 ? 12 : -1);
5447 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 7, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? 8 : -1);
5451 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
5452 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist, -1, -1, r_glsl_permutation->loc_Texture_Refraction >= 0 ? 11 : -1, r_glsl_permutation->loc_Texture_Reflection >= 0 ? 12 : -1);
5454 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5456 if (rsurface.texture->backgroundnumskinframes && !(rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED))
5461 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, msurface_t **texturesurfacelist)
5463 // OpenGL 1.3 path - anything not completely ancient
5464 int texturesurfaceindex;
5465 qboolean applycolor;
5469 const texturelayer_t *layer;
5470 if (rsurface.mode != RSURFMODE_MULTIPASS)
5471 rsurface.mode = RSURFMODE_MULTIPASS;
5472 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
5474 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
5477 int layertexrgbscale;
5478 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5480 if (layerindex == 0)
5484 GL_AlphaTest(false);
5485 qglDepthFunc(GL_EQUAL);CHECKGLERROR
5488 GL_DepthMask(layer->depthmask);
5489 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
5490 if ((layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2) && (gl_combine.integer || layer->depthmask))
5492 layertexrgbscale = 4;
5493 VectorScale(layer->color, 0.25f, layercolor);
5495 else if ((layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1) && (gl_combine.integer || layer->depthmask))
5497 layertexrgbscale = 2;
5498 VectorScale(layer->color, 0.5f, layercolor);
5502 layertexrgbscale = 1;
5503 VectorScale(layer->color, 1.0f, layercolor);
5505 layercolor[3] = layer->color[3];
5506 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
5507 R_Mesh_ColorPointer(NULL, 0, 0);
5508 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
5509 switch (layer->type)
5511 case TEXTURELAYERTYPE_LITTEXTURE:
5512 memset(&m, 0, sizeof(m));
5513 m.tex[0] = R_GetTexture(r_texture_white);
5514 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
5515 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
5516 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
5517 m.tex[1] = R_GetTexture(layer->texture);
5518 m.texmatrix[1] = layer->texmatrix;
5519 m.texrgbscale[1] = layertexrgbscale;
5520 m.pointer_texcoord[1] = rsurface.texcoordtexture2f;
5521 m.pointer_texcoord_bufferobject[1] = rsurface.texcoordtexture2f_bufferobject;
5522 m.pointer_texcoord_bufferoffset[1] = rsurface.texcoordtexture2f_bufferoffset;
5523 R_Mesh_TextureState(&m);
5524 if (rsurface.lightmode == 2)
5525 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
5526 else if (rsurface.uselightmaptexture)
5527 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
5529 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
5531 case TEXTURELAYERTYPE_TEXTURE:
5532 memset(&m, 0, sizeof(m));
5533 m.tex[0] = R_GetTexture(layer->texture);
5534 m.texmatrix[0] = layer->texmatrix;
5535 m.texrgbscale[0] = layertexrgbscale;
5536 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5537 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5538 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5539 R_Mesh_TextureState(&m);
5540 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
5542 case TEXTURELAYERTYPE_FOG:
5543 memset(&m, 0, sizeof(m));
5544 m.texrgbscale[0] = layertexrgbscale;
5547 m.tex[0] = R_GetTexture(layer->texture);
5548 m.texmatrix[0] = layer->texmatrix;
5549 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5550 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5551 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5553 R_Mesh_TextureState(&m);
5554 // generate a color array for the fog pass
5555 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
5556 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5560 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5561 for (i = 0, v = (rsurface.vertex3f + 3 * surface->num_firstvertex), c = (rsurface.array_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4)
5563 f = 1 - FogPoint_Model(v);
5564 c[0] = layercolor[0];
5565 c[1] = layercolor[1];
5566 c[2] = layercolor[2];
5567 c[3] = f * layercolor[3];
5570 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5573 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
5575 GL_LockArrays(0, 0);
5578 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5580 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
5581 GL_AlphaTest(false);
5585 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, msurface_t **texturesurfacelist)
5587 // OpenGL 1.1 - crusty old voodoo path
5588 int texturesurfaceindex;
5592 const texturelayer_t *layer;
5593 if (rsurface.mode != RSURFMODE_MULTIPASS)
5594 rsurface.mode = RSURFMODE_MULTIPASS;
5595 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
5597 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
5599 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5601 if (layerindex == 0)
5605 GL_AlphaTest(false);
5606 qglDepthFunc(GL_EQUAL);CHECKGLERROR
5609 GL_DepthMask(layer->depthmask);
5610 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
5611 R_Mesh_ColorPointer(NULL, 0, 0);
5612 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
5613 switch (layer->type)
5615 case TEXTURELAYERTYPE_LITTEXTURE:
5616 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
5618 // two-pass lit texture with 2x rgbscale
5619 // first the lightmap pass
5620 memset(&m, 0, sizeof(m));
5621 m.tex[0] = R_GetTexture(r_texture_white);
5622 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
5623 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
5624 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
5625 R_Mesh_TextureState(&m);
5626 if (rsurface.lightmode == 2)
5627 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5628 else if (rsurface.uselightmaptexture)
5629 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5631 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5632 GL_LockArrays(0, 0);
5633 // then apply the texture to it
5634 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
5635 memset(&m, 0, sizeof(m));
5636 m.tex[0] = R_GetTexture(layer->texture);
5637 m.texmatrix[0] = layer->texmatrix;
5638 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5639 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5640 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5641 R_Mesh_TextureState(&m);
5642 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layer->color[0] * 0.5f, layer->color[1] * 0.5f, layer->color[2] * 0.5f, layer->color[3], layer->color[0] != 2 || layer->color[1] != 2 || layer->color[2] != 2 || layer->color[3] != 1, false);
5646 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
5647 memset(&m, 0, sizeof(m));
5648 m.tex[0] = R_GetTexture(layer->texture);
5649 m.texmatrix[0] = layer->texmatrix;
5650 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5651 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5652 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5653 R_Mesh_TextureState(&m);
5654 if (rsurface.lightmode == 2)
5655 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layer->color[0], layer->color[1], layer->color[2], layer->color[3], layer->color[0] != 1 || layer->color[1] != 1 || layer->color[2] != 1 || layer->color[3] != 1, applyfog);
5657 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layer->color[0], layer->color[1], layer->color[2], layer->color[3], layer->color[0] != 1 || layer->color[1] != 1 || layer->color[2] != 1 || layer->color[3] != 1, applyfog);
5660 case TEXTURELAYERTYPE_TEXTURE:
5661 // singletexture unlit texture with transparency support
5662 memset(&m, 0, sizeof(m));
5663 m.tex[0] = R_GetTexture(layer->texture);
5664 m.texmatrix[0] = layer->texmatrix;
5665 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5666 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5667 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5668 R_Mesh_TextureState(&m);
5669 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layer->color[0], layer->color[1], layer->color[2], layer->color[3], layer->color[0] != 1 || layer->color[1] != 1 || layer->color[2] != 1 || layer->color[3] != 1, applyfog);
5671 case TEXTURELAYERTYPE_FOG:
5672 // singletexture fogging
5673 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
5676 memset(&m, 0, sizeof(m));
5677 m.tex[0] = R_GetTexture(layer->texture);
5678 m.texmatrix[0] = layer->texmatrix;
5679 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5680 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5681 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5682 R_Mesh_TextureState(&m);
5685 R_Mesh_ResetTextureState();
5686 // generate a color array for the fog pass
5687 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5691 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5692 for (i = 0, v = (rsurface.vertex3f + 3 * surface->num_firstvertex), c = (rsurface.array_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4)
5694 f = 1 - FogPoint_Model(v);
5695 c[0] = layer->color[0];
5696 c[1] = layer->color[1];
5697 c[2] = layer->color[2];
5698 c[3] = f * layer->color[3];
5701 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5704 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
5706 GL_LockArrays(0, 0);
5709 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5711 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
5712 GL_AlphaTest(false);
5716 static void R_DrawTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly)
5718 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW)
5720 rsurface.rtlight = NULL;
5724 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
5726 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
5728 if (rsurface.mode != RSURFMODE_MULTIPASS)
5729 rsurface.mode = RSURFMODE_MULTIPASS;
5730 if (r_depthfirst.integer == 3)
5732 int i = (int)(texturesurfacelist[0] - rsurface.modelsurfaces);
5733 if (!r_view.showdebug)
5734 GL_Color(0, 0, 0, 1);
5736 GL_Color(((i >> 6) & 7) / 7.0f, ((i >> 3) & 7) / 7.0f, (i & 7) / 7.0f,1);
5740 GL_ColorMask(0,0,0,0);
5743 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5744 GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset);
5745 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_view.cullface_back);
5747 GL_BlendFunc(GL_ONE, GL_ZERO);
5749 GL_AlphaTest(false);
5750 R_Mesh_ColorPointer(NULL, 0, 0);
5751 R_Mesh_ResetTextureState();
5752 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
5753 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5754 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
5755 r_refdef.stats.entities_surfaces += texturenumsurfaces;
5757 else if (r_depthfirst.integer == 3)
5759 else if (!r_view.showdebug && (r_showsurfaces.integer || gl_lightmaps.integer))
5761 GL_Color(0, 0, 0, 1);
5762 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5764 else if (r_showsurfaces.integer)
5766 if (rsurface.mode != RSURFMODE_MULTIPASS)
5767 rsurface.mode = RSURFMODE_MULTIPASS;
5768 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5769 GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset);
5771 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_view.cullface_back);
5772 GL_BlendFunc(GL_ONE, GL_ZERO);
5773 GL_DepthMask(writedepth);
5775 GL_AlphaTest(false);
5776 R_Mesh_ColorPointer(NULL, 0, 0);
5777 R_Mesh_ResetTextureState();
5778 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
5779 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
5780 r_refdef.stats.entities_surfaces += texturenumsurfaces;
5782 else if (gl_lightmaps.integer)
5785 if (rsurface.mode != RSURFMODE_MULTIPASS)
5786 rsurface.mode = RSURFMODE_MULTIPASS;
5787 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5789 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_view.cullface_back);
5790 GL_BlendFunc(GL_ONE, GL_ZERO);
5791 GL_DepthMask(writedepth);
5793 GL_AlphaTest(false);
5794 // use lightmode 0 (fullbright or lightmap) or 2 (model lighting)
5795 rsurface.lightmode = ((rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT) || rsurface.modeltexcoordlightmap2f != NULL) ? 0 : 2;
5796 R_Mesh_ColorPointer(NULL, 0, 0);
5797 memset(&m, 0, sizeof(m));
5798 m.tex[0] = R_GetTexture(r_texture_white);
5799 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
5800 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
5801 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
5802 R_Mesh_TextureState(&m);
5803 RSurf_PrepareVerticesForBatch(rsurface.lightmode == 2, false, texturenumsurfaces, texturesurfacelist);
5804 if (rsurface.lightmode == 2)
5805 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5806 else if (rsurface.uselightmaptexture)
5807 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5809 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5810 r_refdef.stats.entities_surfaces += texturenumsurfaces;
5812 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
5814 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
5815 r_refdef.stats.entities_surfaces += texturenumsurfaces;
5817 else if (rsurface.texture->currentnumlayers)
5819 // write depth for anything we skipped on the depth-only pass earlier
5820 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5822 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5823 GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset);
5824 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
5825 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_view.cullface_back);
5826 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5827 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
5828 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5829 // use lightmode 0 (fullbright or lightmap) or 2 (model lighting)
5830 rsurface.lightmode = ((rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT) || rsurface.modeltexcoordlightmap2f != NULL) ? 0 : 2;
5831 if (r_glsl.integer && gl_support_fragment_shader)
5832 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist);
5833 else if (gl_combine.integer && r_textureunits.integer >= 2)
5834 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist);
5836 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist);
5837 r_refdef.stats.entities_surfaces += texturenumsurfaces;
5840 GL_LockArrays(0, 0);
5843 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
5846 int texturenumsurfaces, endsurface;
5848 msurface_t *surface;
5849 msurface_t *texturesurfacelist[1024];
5851 // if the model is static it doesn't matter what value we give for
5852 // wantnormals and wanttangents, so this logic uses only rules applicable
5853 // to a model, knowing that they are meaningless otherwise
5854 if (ent == r_refdef.worldentity)
5855 RSurf_ActiveWorldEntity();
5856 else if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
5857 RSurf_ActiveModelEntity(ent, false, false);
5859 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
5861 for (i = 0;i < numsurfaces;i = j)
5864 surface = rsurface.modelsurfaces + surfacelist[i];
5865 texture = surface->texture;
5866 R_UpdateTextureInfo(ent, texture);
5867 rsurface.texture = texture->currentframe;
5868 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
5869 // scan ahead until we find a different texture
5870 endsurface = min(i + 1024, numsurfaces);
5871 texturenumsurfaces = 0;
5872 texturesurfacelist[texturenumsurfaces++] = surface;
5873 for (;j < endsurface;j++)
5875 surface = rsurface.modelsurfaces + surfacelist[j];
5876 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
5878 texturesurfacelist[texturenumsurfaces++] = surface;
5880 // render the range of surfaces
5881 R_DrawTextureSurfaceList(texturenumsurfaces, texturesurfacelist, true, false);
5887 void R_QueueSurfaceList(entity_render_t *ent, int numsurfaces, msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes)
5890 vec3_t tempcenter, center;
5892 // if we're rendering water textures (extra scene renders), use a separate loop to avoid burdening the main one
5895 for (i = 0;i < numsurfaces;i++)
5896 if (surfacelist[i]->texture->currentframe->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION))
5897 R_Water_AddWaterPlane(surfacelist[i]);
5900 // break the surface list down into batches by texture and use of lightmapping
5901 for (i = 0;i < numsurfaces;i = j)
5904 // texture is the base texture pointer, rsurface.texture is the
5905 // current frame/skin the texture is directing us to use (for example
5906 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
5907 // use skin 1 instead)
5908 texture = surfacelist[i]->texture;
5909 rsurface.texture = texture->currentframe;
5910 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
5911 if (!(rsurface.texture->currentmaterialflags & flagsmask))
5913 // if this texture is not the kind we want, skip ahead to the next one
5914 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
5918 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
5920 // transparent surfaces get pushed off into the transparent queue
5921 const msurface_t *surface = surfacelist[i];
5924 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
5925 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
5926 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
5927 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
5928 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_view.origin : center, R_DrawSurface_TransparentCallback, ent, surface - rsurface.modelsurfaces, rsurface.rtlight);
5932 // simply scan ahead until we find a different texture or lightmap state
5933 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
5935 // render the range of surfaces
5936 R_DrawTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly);
5941 float locboxvertex3f[6*4*3] =
5943 1,0,1, 1,0,0, 1,1,0, 1,1,1,
5944 0,1,1, 0,1,0, 0,0,0, 0,0,1,
5945 1,1,1, 1,1,0, 0,1,0, 0,1,1,
5946 0,0,1, 0,0,0, 1,0,0, 1,0,1,
5947 0,0,1, 1,0,1, 1,1,1, 0,1,1,
5948 1,0,0, 0,0,0, 0,1,0, 1,1,0
5951 int locboxelement3i[6*2*3] =
5961 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
5964 cl_locnode_t *loc = (cl_locnode_t *)ent;
5966 float vertex3f[6*4*3];
5968 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5969 GL_DepthMask(false);
5970 GL_DepthRange(0, 1);
5971 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5973 GL_CullFace(GL_NONE);
5974 R_Mesh_Matrix(&identitymatrix);
5976 R_Mesh_VertexPointer(vertex3f, 0, 0);
5977 R_Mesh_ColorPointer(NULL, 0, 0);
5978 R_Mesh_ResetTextureState();
5981 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_view.colorscale,
5982 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_view.colorscale,
5983 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_view.colorscale,
5984 surfacelist[0] < 0 ? 0.5f : 0.125f);
5986 if (VectorCompare(loc->mins, loc->maxs))
5988 VectorSet(size, 2, 2, 2);
5989 VectorMA(loc->mins, -0.5f, size, mins);
5993 VectorCopy(loc->mins, mins);
5994 VectorSubtract(loc->maxs, loc->mins, size);
5997 for (i = 0;i < 6*4*3;)
5998 for (j = 0;j < 3;j++, i++)
5999 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
6001 R_Mesh_Draw(0, 6*4, 6*2, locboxelement3i, 0, 0);
6004 void R_DrawLocs(void)
6007 cl_locnode_t *loc, *nearestloc;
6009 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
6010 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
6012 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
6013 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
6017 void R_DrawDebugModel(entity_render_t *ent)
6019 int i, j, k, l, flagsmask;
6020 const int *elements;
6022 msurface_t *surface;
6023 model_t *model = ent->model;
6026 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WATER | MATERIALFLAG_WALL;
6028 R_Mesh_ColorPointer(NULL, 0, 0);
6029 R_Mesh_ResetTextureState();
6030 GL_DepthRange(0, 1);
6031 GL_DepthTest(!r_showdisabledepthtest.integer);
6032 GL_DepthMask(false);
6033 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6035 if (r_showcollisionbrushes.value > 0 && model->brush.num_brushes)
6037 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
6038 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
6040 if (brush->colbrushf && brush->colbrushf->numtriangles)
6042 R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
6043 GL_Color((i & 31) * (1.0f / 32.0f) * r_view.colorscale, ((i >> 5) & 31) * (1.0f / 32.0f) * r_view.colorscale, ((i >> 10) & 31) * (1.0f / 32.0f) * r_view.colorscale, r_showcollisionbrushes.value);
6044 R_Mesh_Draw(0, brush->colbrushf->numpoints, brush->colbrushf->numtriangles, brush->colbrushf->elements, 0, 0);
6047 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
6049 if (surface->num_collisiontriangles)
6051 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
6052 GL_Color((i & 31) * (1.0f / 32.0f) * r_view.colorscale, ((i >> 5) & 31) * (1.0f / 32.0f) * r_view.colorscale, ((i >> 10) & 31) * (1.0f / 32.0f) * r_view.colorscale, r_showcollisionbrushes.value);
6053 R_Mesh_Draw(0, surface->num_collisionvertices, surface->num_collisiontriangles, surface->data_collisionelement3i, 0, 0);
6058 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6060 if (r_showtris.integer || r_shownormals.integer)
6062 if (r_showdisabledepthtest.integer)
6064 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6065 GL_DepthMask(false);
6069 GL_BlendFunc(GL_ONE, GL_ZERO);
6072 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
6074 if (ent == r_refdef.worldentity && !r_viewcache.world_surfacevisible[j])
6076 rsurface.texture = surface->texture->currentframe;
6077 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
6079 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
6080 if (r_showtris.value > 0)
6082 if (!rsurface.texture->currentlayers->depthmask)
6083 GL_Color(r_view.colorscale, 0, 0, r_showtris.value);
6084 else if (ent == r_refdef.worldentity)
6085 GL_Color(r_view.colorscale, r_view.colorscale, r_view.colorscale, r_showtris.value);
6087 GL_Color(0, r_view.colorscale, 0, r_showtris.value);
6088 elements = (ent->model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
6091 for (k = 0;k < surface->num_triangles;k++, elements += 3)
6093 #define GLVERTEXELEMENT(n) qglVertex3f(rsurface.vertex3f[elements[n]*3+0], rsurface.vertex3f[elements[n]*3+1], rsurface.vertex3f[elements[n]*3+2])
6094 GLVERTEXELEMENT(0);GLVERTEXELEMENT(1);
6095 GLVERTEXELEMENT(1);GLVERTEXELEMENT(2);
6096 GLVERTEXELEMENT(2);GLVERTEXELEMENT(0);
6101 if (r_shownormals.value > 0)
6103 GL_Color(r_view.colorscale, 0, 0, r_shownormals.value);
6105 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
6107 VectorCopy(rsurface.vertex3f + l * 3, v);
6108 qglVertex3f(v[0], v[1], v[2]);
6109 VectorMA(v, 8, rsurface.svector3f + l * 3, v);
6110 qglVertex3f(v[0], v[1], v[2]);
6114 GL_Color(0, 0, r_view.colorscale, r_shownormals.value);
6116 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
6118 VectorCopy(rsurface.vertex3f + l * 3, v);
6119 qglVertex3f(v[0], v[1], v[2]);
6120 VectorMA(v, 8, rsurface.tvector3f + l * 3, v);
6121 qglVertex3f(v[0], v[1], v[2]);
6125 GL_Color(0, r_view.colorscale, 0, r_shownormals.value);
6127 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
6129 VectorCopy(rsurface.vertex3f + l * 3, v);
6130 qglVertex3f(v[0], v[1], v[2]);
6131 VectorMA(v, 8, rsurface.normal3f + l * 3, v);
6132 qglVertex3f(v[0], v[1], v[2]);
6139 rsurface.texture = NULL;
6143 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
6144 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes, qboolean debug)
6146 int i, j, endj, f, flagsmask;
6147 int counttriangles = 0;
6148 msurface_t *surface, **surfacechain;
6150 model_t *model = r_refdef.worldmodel;
6151 const int maxsurfacelist = 1024;
6152 int numsurfacelist = 0;
6153 msurface_t *surfacelist[1024];
6157 RSurf_ActiveWorldEntity();
6159 // update light styles
6160 if (!skysurfaces && !depthonly && !addwaterplanes && model->brushq1.light_styleupdatechains)
6162 for (i = 0;i < model->brushq1.light_styles;i++)
6164 if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
6166 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
6167 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
6168 for (;(surface = *surfacechain);surfacechain++)
6169 surface->cached_dlight = true;
6174 R_UpdateAllTextureInfo(r_refdef.worldentity);
6175 flagsmask = addwaterplanes ? (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) : (skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL));
6179 R_DrawDebugModel(r_refdef.worldentity);
6185 rsurface.uselightmaptexture = false;
6186 rsurface.texture = NULL;
6188 j = model->firstmodelsurface;
6189 endj = j + model->nummodelsurfaces;
6192 // quickly skip over non-visible surfaces
6193 for (;j < endj && !r_viewcache.world_surfacevisible[j];j++)
6195 // quickly iterate over visible surfaces
6196 for (;j < endj && r_viewcache.world_surfacevisible[j];j++)
6198 // process this surface
6199 surface = model->data_surfaces + j;
6200 // if this surface fits the criteria, add it to the list
6201 if (surface->num_triangles)
6203 // if lightmap parameters changed, rebuild lightmap texture
6204 if (surface->cached_dlight)
6205 R_BuildLightMap(r_refdef.worldentity, surface);
6206 // add face to draw list
6207 surfacelist[numsurfacelist++] = surface;
6208 counttriangles += surface->num_triangles;
6209 if (numsurfacelist >= maxsurfacelist)
6211 R_QueueSurfaceList(r_refdef.worldentity, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
6218 R_QueueSurfaceList(r_refdef.worldentity, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
6219 r_refdef.stats.entities_triangles += counttriangles;
6223 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes, qboolean debug)
6225 int i, f, flagsmask;
6226 int counttriangles = 0;
6227 msurface_t *surface, *endsurface, **surfacechain;
6229 model_t *model = ent->model;
6230 const int maxsurfacelist = 1024;
6231 int numsurfacelist = 0;
6232 msurface_t *surfacelist[1024];
6236 // if the model is static it doesn't matter what value we give for
6237 // wantnormals and wanttangents, so this logic uses only rules applicable
6238 // to a model, knowing that they are meaningless otherwise
6239 if (ent == r_refdef.worldentity)
6240 RSurf_ActiveWorldEntity();
6241 else if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
6242 RSurf_ActiveModelEntity(ent, false, false);
6244 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader && !depthonly);
6246 // update light styles
6247 if (!skysurfaces && !depthonly && !addwaterplanes && model->brushq1.light_styleupdatechains)
6249 for (i = 0;i < model->brushq1.light_styles;i++)
6251 if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
6253 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
6254 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
6255 for (;(surface = *surfacechain);surfacechain++)
6256 surface->cached_dlight = true;
6261 R_UpdateAllTextureInfo(ent);
6262 flagsmask = addwaterplanes ? (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) : (skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL));
6266 R_DrawDebugModel(ent);
6272 rsurface.uselightmaptexture = false;
6273 rsurface.texture = NULL;
6275 surface = model->data_surfaces + model->firstmodelsurface;
6276 endsurface = surface + model->nummodelsurfaces;
6277 for (;surface < endsurface;surface++)
6279 // if this surface fits the criteria, add it to the list
6280 if (surface->num_triangles)
6282 // if lightmap parameters changed, rebuild lightmap texture
6283 if (surface->cached_dlight)
6284 R_BuildLightMap(ent, surface);
6285 // add face to draw list
6286 surfacelist[numsurfacelist++] = surface;
6287 counttriangles += surface->num_triangles;
6288 if (numsurfacelist >= maxsurfacelist)
6290 R_QueueSurfaceList(ent, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
6296 R_QueueSurfaceList(ent, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
6297 r_refdef.stats.entities_triangles += counttriangles;