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.
23 #include "cl_dyntexture.h"
28 mempool_t *r_main_mempool;
29 rtexturepool_t *r_main_texturepool;
36 r_viewcache_t r_viewcache;
38 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"};
39 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
40 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%, 10 = 100%)"};
41 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)"};
42 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
43 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
44 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"};
45 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"};
46 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
47 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"};
48 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"};
49 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"};
50 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
51 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
52 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
53 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
54 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling"};
55 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
56 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
57 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
58 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
59 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
60 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
61 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
62 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this)"};
63 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
64 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
65 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"};
66 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"};
68 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
69 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
70 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
71 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
72 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
73 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
74 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
76 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)"};
78 cvar_t r_glsl = {CVAR_SAVE, "r_glsl", "1", "enables use of OpenGL 2.0 pixel shaders for lighting"};
79 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
80 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
81 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
82 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)"};
83 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)"};
85 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)"};
86 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
87 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"};
88 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
89 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
91 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1", "enables animation smoothing on sprites (requires r_lerpmodels 1)"};
92 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
93 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
95 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
96 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
97 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
98 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
99 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
100 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
101 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
103 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
104 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
105 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
106 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)"};
108 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"};
110 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"};
112 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
114 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
115 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 cvar_t r_track_sprites = {CVAR_SAVE, "r_track_sprites", "1", "track SPR_LABEL* sprites by putting them as indicator at the screen border to rotate to"};
117 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accodringly, 2: Make it a continuous rotation"};
118 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
119 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
121 extern qboolean v_flipped_state;
123 typedef struct r_glsl_bloomshader_s
126 int loc_Texture_Bloom;
128 r_glsl_bloomshader_t;
130 static struct r_bloomstate_s
135 int bloomwidth, bloomheight;
137 int screentexturewidth, screentextureheight;
138 rtexture_t *texture_screen;
140 int bloomtexturewidth, bloomtextureheight;
141 rtexture_t *texture_bloom;
143 r_glsl_bloomshader_t *shader;
145 // arrays for rendering the screen passes
146 float screentexcoord2f[8];
147 float bloomtexcoord2f[8];
148 float offsettexcoord2f[8];
152 typedef struct r_waterstate_waterplane_s
154 rtexture_t *texture_refraction;
155 rtexture_t *texture_reflection;
157 int materialflags; // combined flags of all water surfaces on this plane
158 unsigned char pvsbits[(32768+7)>>3]; // FIXME: buffer overflow on huge maps
161 r_waterstate_waterplane_t;
163 #define MAX_WATERPLANES 16
165 static struct r_waterstate_s
169 qboolean renderingscene; // true while rendering a refraction or reflection texture, disables water surfaces
171 int waterwidth, waterheight;
172 int texturewidth, textureheight;
174 int maxwaterplanes; // same as MAX_WATERPLANES
176 r_waterstate_waterplane_t waterplanes[MAX_WATERPLANES];
178 float screenscale[2];
179 float screencenter[2];
183 // shadow volume bsp struct with automatically growing nodes buffer
186 rtexture_t *r_texture_blanknormalmap;
187 rtexture_t *r_texture_white;
188 rtexture_t *r_texture_grey128;
189 rtexture_t *r_texture_black;
190 rtexture_t *r_texture_notexture;
191 rtexture_t *r_texture_whitecube;
192 rtexture_t *r_texture_normalizationcube;
193 rtexture_t *r_texture_fogattenuation;
194 //rtexture_t *r_texture_fogintensity;
196 char r_qwskincache[MAX_SCOREBOARD][MAX_QPATH];
197 skinframe_t *r_qwskincache_skinframe[MAX_SCOREBOARD];
199 // vertex coordinates for a quad that covers the screen exactly
200 const static float r_screenvertex3f[12] =
208 extern void R_DrawModelShadows(void);
210 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
213 for (i = 0;i < verts;i++)
224 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
227 for (i = 0;i < verts;i++)
237 // FIXME: move this to client?
240 if (gamemode == GAME_NEHAHRA)
242 Cvar_Set("gl_fogenable", "0");
243 Cvar_Set("gl_fogdensity", "0.2");
244 Cvar_Set("gl_fogred", "0.3");
245 Cvar_Set("gl_foggreen", "0.3");
246 Cvar_Set("gl_fogblue", "0.3");
248 r_refdef.fog_density = r_refdef.fog_red = r_refdef.fog_green = r_refdef.fog_blue = 0.0f;
251 float FogPoint_World(const vec3_t p)
253 unsigned int fogmasktableindex = (unsigned int)(VectorDistance((p), r_view.origin) * r_refdef.fogmasktabledistmultiplier);
254 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
257 float FogPoint_Model(const vec3_t p)
259 unsigned int fogmasktableindex = (unsigned int)(VectorDistance((p), rsurface.modelorg) * r_refdef.fogmasktabledistmultiplier);
260 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
263 static void R_BuildBlankTextures(void)
265 unsigned char data[4];
266 data[0] = 128; // normal X
267 data[1] = 128; // normal Y
268 data[2] = 255; // normal Z
269 data[3] = 128; // height
270 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
275 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
280 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
285 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
288 static void R_BuildNoTexture(void)
291 unsigned char pix[16][16][4];
292 // this makes a light grey/dark grey checkerboard texture
293 for (y = 0;y < 16;y++)
295 for (x = 0;x < 16;x++)
297 if ((y < 8) ^ (x < 8))
313 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_RGBA, TEXF_MIPMAP, NULL);
316 static void R_BuildWhiteCube(void)
318 unsigned char data[6*1*1*4];
319 data[ 0] = 255;data[ 1] = 255;data[ 2] = 255;data[ 3] = 255;
320 data[ 4] = 255;data[ 5] = 255;data[ 6] = 255;data[ 7] = 255;
321 data[ 8] = 255;data[ 9] = 255;data[10] = 255;data[11] = 255;
322 data[12] = 255;data[13] = 255;data[14] = 255;data[15] = 255;
323 data[16] = 255;data[17] = 255;data[18] = 255;data[19] = 255;
324 data[20] = 255;data[21] = 255;data[22] = 255;data[23] = 255;
325 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
328 static void R_BuildNormalizationCube(void)
332 vec_t s, t, intensity;
334 unsigned char data[6][NORMSIZE][NORMSIZE][4];
335 for (side = 0;side < 6;side++)
337 for (y = 0;y < NORMSIZE;y++)
339 for (x = 0;x < NORMSIZE;x++)
341 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
342 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
377 intensity = 127.0f / sqrt(DotProduct(v, v));
378 data[side][y][x][0] = (unsigned char)(128.0f + intensity * v[0]);
379 data[side][y][x][1] = (unsigned char)(128.0f + intensity * v[1]);
380 data[side][y][x][2] = (unsigned char)(128.0f + intensity * v[2]);
381 data[side][y][x][3] = 255;
385 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, &data[0][0][0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
388 static void R_BuildFogTexture(void)
392 unsigned char data1[FOGWIDTH][4];
393 //unsigned char data2[FOGWIDTH][4];
394 for (x = 0;x < FOGWIDTH;x++)
396 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
401 //data2[x][0] = 255 - b;
402 //data2[x][1] = 255 - b;
403 //data2[x][2] = 255 - b;
406 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
407 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
410 static const char *builtinshaderstring =
411 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
412 "// written by Forest 'LordHavoc' Hale\n"
414 "// common definitions between vertex shader and fragment shader:\n"
416 "#ifdef __GLSL_CG_DATA_TYPES\n"
417 "# define myhalf half\n"
418 "# define myhvec2 hvec2\n"
419 "# define myhvec3 hvec3\n"
420 "# define myhvec4 hvec4\n"
422 "# define myhalf float\n"
423 "# define myhvec2 vec2\n"
424 "# define myhvec3 vec3\n"
425 "# define myhvec4 vec4\n"
428 "varying vec2 TexCoord;\n"
429 "varying vec2 TexCoordLightmap;\n"
431 "//#ifdef MODE_LIGHTSOURCE\n"
432 "varying vec3 CubeVector;\n"
435 "//#ifdef MODE_LIGHTSOURCE\n"
436 "varying vec3 LightVector;\n"
438 "//# ifdef MODE_LIGHTDIRECTION\n"
439 "//varying vec3 LightVector;\n"
443 "varying vec3 EyeVector;\n"
445 "varying vec3 EyeVectorModelSpace;\n"
448 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
449 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
450 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
452 "//#ifdef MODE_WATER\n"
453 "varying vec4 ModelViewProjectionPosition;\n"
455 "//# ifdef MODE_REFRACTION\n"
456 "//varying vec4 ModelViewProjectionPosition;\n"
458 "//# ifdef USEREFLECTION\n"
459 "//varying vec4 ModelViewProjectionPosition;\n"
468 "// vertex shader specific:\n"
469 "#ifdef VERTEX_SHADER\n"
471 "uniform vec3 LightPosition;\n"
472 "uniform vec3 EyePosition;\n"
473 "uniform vec3 LightDir;\n"
475 "// TODO: get rid of tangentt (texcoord2) and use a crossproduct to regenerate it from tangents (texcoord1) and normal (texcoord3)\n"
479 " gl_FrontColor = gl_Color;\n"
480 " // copy the surface texcoord\n"
481 " TexCoord = vec2(gl_TextureMatrix[0] * gl_MultiTexCoord0);\n"
482 "#ifndef MODE_LIGHTSOURCE\n"
483 "# ifndef MODE_LIGHTDIRECTION\n"
484 " TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
488 "#ifdef MODE_LIGHTSOURCE\n"
489 " // transform vertex position into light attenuation/cubemap space\n"
490 " // (-1 to +1 across the light box)\n"
491 " CubeVector = vec3(gl_TextureMatrix[3] * gl_Vertex);\n"
493 " // transform unnormalized light direction into tangent space\n"
494 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
495 " // normalize it per pixel)\n"
496 " vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
497 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
498 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
499 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
502 "#ifdef MODE_LIGHTDIRECTION\n"
503 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
504 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
505 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
508 " // transform unnormalized eye direction into tangent space\n"
510 " vec3 EyeVectorModelSpace;\n"
512 " EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
513 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
514 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
515 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
517 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
518 " VectorS = gl_MultiTexCoord1.xyz;\n"
519 " VectorT = gl_MultiTexCoord2.xyz;\n"
520 " VectorR = gl_MultiTexCoord3.xyz;\n"
523 "//#if defined(MODE_WATER) || defined(MODE_REFRACTION) || defined(USEREFLECTION)\n"
524 "// ModelViewProjectionPosition = gl_Vertex * gl_ModelViewProjectionMatrix;\n"
525 "// //ModelViewProjectionPosition_svector = (gl_Vertex + vec4(gl_MultiTexCoord1.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
526 "// //ModelViewProjectionPosition_tvector = (gl_Vertex + vec4(gl_MultiTexCoord2.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
529 "// transform vertex to camera space, using ftransform to match non-VS\n"
531 " gl_Position = ftransform();\n"
533 "#ifdef MODE_WATER\n"
534 " ModelViewProjectionPosition = gl_Position;\n"
536 "#ifdef MODE_REFRACTION\n"
537 " ModelViewProjectionPosition = gl_Position;\n"
539 "#ifdef USEREFLECTION\n"
540 " ModelViewProjectionPosition = gl_Position;\n"
544 "#endif // VERTEX_SHADER\n"
549 "// fragment shader specific:\n"
550 "#ifdef FRAGMENT_SHADER\n"
552 "// 13 textures, we can only use up to 16 on DX9-class hardware\n"
553 "uniform sampler2D Texture_Normal;\n"
554 "uniform sampler2D Texture_Color;\n"
555 "uniform sampler2D Texture_Gloss;\n"
556 "uniform samplerCube Texture_Cube;\n"
557 "uniform sampler2D Texture_Attenuation;\n"
558 "uniform sampler2D Texture_FogMask;\n"
559 "uniform sampler2D Texture_Pants;\n"
560 "uniform sampler2D Texture_Shirt;\n"
561 "uniform sampler2D Texture_Lightmap;\n"
562 "uniform sampler2D Texture_Deluxemap;\n"
563 "uniform sampler2D Texture_Glow;\n"
564 "uniform sampler2D Texture_Reflection;\n"
565 "uniform sampler2D Texture_Refraction;\n"
567 "uniform myhvec3 LightColor;\n"
568 "uniform myhvec3 AmbientColor;\n"
569 "uniform myhvec3 DiffuseColor;\n"
570 "uniform myhvec3 SpecularColor;\n"
571 "uniform myhvec3 Color_Pants;\n"
572 "uniform myhvec3 Color_Shirt;\n"
573 "uniform myhvec3 FogColor;\n"
575 "//#ifdef MODE_WATER\n"
576 "uniform vec4 DistortScaleRefractReflect;\n"
577 "uniform vec4 ScreenScaleRefractReflect;\n"
578 "uniform vec4 ScreenCenterRefractReflect;\n"
579 "uniform myhvec4 RefractColor;\n"
580 "uniform myhvec4 ReflectColor;\n"
581 "uniform myhalf ReflectFactor;\n"
582 "uniform myhalf ReflectOffset;\n"
584 "//# ifdef MODE_REFRACTION\n"
585 "//uniform vec4 DistortScaleRefractReflect;\n"
586 "//uniform vec4 ScreenScaleRefractReflect;\n"
587 "//uniform vec4 ScreenCenterRefractReflect;\n"
588 "//uniform myhvec4 RefractColor;\n"
589 "//# ifdef USEREFLECTION\n"
590 "//uniform myhvec4 ReflectColor;\n"
593 "//# ifdef USEREFLECTION\n"
594 "//uniform vec4 DistortScaleRefractReflect;\n"
595 "//uniform vec4 ScreenScaleRefractReflect;\n"
596 "//uniform vec4 ScreenCenterRefractReflect;\n"
597 "//uniform myhvec4 ReflectColor;\n"
602 "uniform myhalf GlowScale;\n"
603 "uniform myhalf SceneBrightness;\n"
604 "#ifdef USECONTRASTBOOST\n"
605 "uniform myhalf ContrastBoostCoeff;\n"
608 "uniform float OffsetMapping_Scale;\n"
609 "uniform float OffsetMapping_Bias;\n"
610 "uniform float FogRangeRecip;\n"
612 "uniform myhalf AmbientScale;\n"
613 "uniform myhalf DiffuseScale;\n"
614 "uniform myhalf SpecularScale;\n"
615 "uniform myhalf SpecularPower;\n"
617 "#ifdef USEOFFSETMAPPING\n"
618 "vec2 OffsetMapping(vec2 TexCoord)\n"
620 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
621 " // 14 sample relief mapping: linear search and then binary search\n"
622 " // this basically steps forward a small amount repeatedly until it finds\n"
623 " // itself inside solid, then jitters forward and back using decreasing\n"
624 " // amounts to find the impact\n"
625 " //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
626 " //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
627 " vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
628 " vec3 RT = vec3(TexCoord, 1);\n"
629 " OffsetVector *= 0.1;\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);\n"
635 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
636 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
637 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
638 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
639 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) - 0.5);\n"
640 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5 - 0.25);\n"
641 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25 - 0.125);\n"
642 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125 - 0.0625);\n"
643 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
646 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
647 " // this basically moves forward the full distance, and then backs up based\n"
648 " // on height of samples\n"
649 " //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
650 " //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
651 " vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
652 " TexCoord += OffsetVector;\n"
653 " OffsetVector *= 0.333;\n"
654 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
655 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
656 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
657 " return TexCoord;\n"
660 "#endif // USEOFFSETMAPPING\n"
662 "#ifdef MODE_WATER\n"
667 "#ifdef USEOFFSETMAPPING\n"
668 " // apply offsetmapping\n"
669 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
670 "#define TexCoord TexCoordOffset\n"
673 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
674 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
675 " vec4 ScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect + vec2(normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5))).xyxy * DistortScaleRefractReflect;\n"
676 " float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 5.0) * ReflectFactor + ReflectOffset;\n"
677 " gl_FragColor = mix(texture2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, texture2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
680 "#else // MODE_WATER\n"
681 "#ifdef MODE_REFRACTION\n"
683 "// refraction pass\n"
686 "#ifdef USEOFFSETMAPPING\n"
687 " // apply offsetmapping\n"
688 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
689 "#define TexCoord TexCoordOffset\n"
692 " vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
693 " //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
694 " vec2 ScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy + vec2(normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
695 " gl_FragColor = texture2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
698 "#else // MODE_REFRACTION\n"
701 "#ifdef USEOFFSETMAPPING\n"
702 " // apply offsetmapping\n"
703 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
704 "#define TexCoord TexCoordOffset\n"
707 " // combine the diffuse textures (base, pants, shirt)\n"
708 " myhvec4 color = myhvec4(texture2D(Texture_Color, TexCoord));\n"
709 "#ifdef USECOLORMAPPING\n"
710 " color.rgb += myhvec3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhvec3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
716 "#ifdef MODE_LIGHTSOURCE\n"
719 " // calculate surface normal, light normal, and specular normal\n"
720 " // compute color intensity for the two textures (colormap and glossmap)\n"
721 " // scale by light color and attenuation as efficiently as possible\n"
722 " // (do as much scalar math as possible rather than vector math)\n"
723 "# ifdef USESPECULAR\n"
724 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
725 " myhvec3 diffusenormal = myhvec3(normalize(LightVector));\n"
726 " myhvec3 specularnormal = normalize(diffusenormal + myhvec3(normalize(EyeVector)));\n"
728 " // calculate directional shading\n"
729 " 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"
731 "# ifdef USEDIFFUSE\n"
732 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
733 " myhvec3 diffusenormal = myhvec3(normalize(LightVector));\n"
735 " // calculate directional shading\n"
736 " 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"
738 " // calculate directionless shading\n"
739 " color.rgb = color.rgb * LightColor * myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
743 "# ifdef USECUBEFILTER\n"
744 " // apply light cubemap filter\n"
745 " //color.rgb *= normalize(CubeVector) * 0.5 + 0.5;//vec3(textureCube(Texture_Cube, CubeVector));\n"
746 " color.rgb *= myhvec3(textureCube(Texture_Cube, CubeVector));\n"
748 " color *= myhvec4(gl_Color);\n"
749 "#endif // MODE_LIGHTSOURCE\n"
754 "#ifdef MODE_LIGHTDIRECTION\n"
755 " // directional model lighting\n"
756 "# ifdef USESPECULAR\n"
757 " // get the surface normal and light normal\n"
758 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
759 " myhvec3 diffusenormal = myhvec3(LightVector);\n"
761 " // calculate directional shading\n"
762 " color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
763 " myhvec3 specularnormal = normalize(diffusenormal + myhvec3(normalize(EyeVector)));\n"
764 " color.rgb += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
766 "# ifdef USEDIFFUSE\n"
767 " // get the surface normal and light normal\n"
768 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
769 " myhvec3 diffusenormal = myhvec3(LightVector);\n"
771 " // calculate directional shading\n"
772 " color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
774 " color.rgb *= AmbientColor;\n"
778 " color *= myhvec4(gl_Color);\n"
779 "#endif // MODE_LIGHTDIRECTION\n"
784 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
785 " // deluxemap lightmapping using light vectors in modelspace (evil q3map2)\n"
787 " // get the surface normal and light normal\n"
788 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
790 " myhvec3 diffusenormal_modelspace = myhvec3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - myhvec3(0.5);\n"
791 " myhvec3 diffusenormal = normalize(myhvec3(dot(diffusenormal_modelspace, myhvec3(VectorS)), dot(diffusenormal_modelspace, myhvec3(VectorT)), dot(diffusenormal_modelspace, myhvec3(VectorR))));\n"
792 " // calculate directional shading\n"
793 " myhvec3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0)));\n"
794 "# ifdef USESPECULAR\n"
795 " myhvec3 specularnormal = myhvec3(normalize(diffusenormal + myhvec3(normalize(EyeVector))));\n"
796 " tempcolor += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
799 " // apply lightmap color\n"
800 " color.rgb = myhvec4(tempcolor,1) * myhvec4(texture2D(Texture_Lightmap, TexCoordLightmap)) * myhvec4(gl_Color) + myhvec4(color.rgb * AmbientScale, 0);\n"
801 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
806 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
807 " // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
809 " // get the surface normal and light normal\n"
810 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
812 " myhvec3 diffusenormal = normalize(myhvec3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - myhvec3(0.5));\n"
813 " // calculate directional shading\n"
814 " myhvec3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0)));\n"
815 "# ifdef USESPECULAR\n"
816 " myhvec3 specularnormal = myhvec3(normalize(diffusenormal + myhvec3(normalize(EyeVector))));\n"
817 " tempcolor += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
820 " // apply lightmap color\n"
821 " color = myhvec4(tempcolor, 1) * myhvec4(texture2D(Texture_Lightmap, TexCoordLightmap)) * myhvec4(gl_Color) + myhvec4(color.rgb * AmbientScale, 0);\n"
822 "#endif // MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
827 "#ifdef MODE_LIGHTMAP\n"
828 " // apply lightmap color\n"
829 " color *= myhvec4(texture2D(Texture_Lightmap, TexCoordLightmap)) * myhvec4(gl_Color) * myhvec4(myhvec3(DiffuseScale), 1) + myhvec4(myhvec3(AmbientScale), 0);\n"
830 "#endif // MODE_LIGHTMAP\n"
840 " color.rgb += myhvec3(texture2D(Texture_Glow, TexCoord)) * GlowScale;\n"
843 "#ifndef MODE_LIGHTSOURCE\n"
844 "# ifdef USEREFLECTION\n"
845 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
846 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
847 " vec4 ScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect + vec3(normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5))).xyxy * DistortScaleRefractReflect;\n"
848 " color.rgb = mix(color.rgb, myhvec3(texture2D(Texture_Reflection, ScreenTexCoord.zw)) * ReflectColor.rgb, ReflectColor.a);\n"
854 " color.rgb = mix(FogColor, color.rgb, myhalf(texture2D(Texture_FogMask, myhvec2(length(EyeVectorModelSpace)*FogRangeRecip, 0.0))));\n"
857 "#ifdef USECONTRASTBOOST\n"
858 " color.rgb = color.rgb / (ContrastBoostCoeff * color.rgb + myhvec3(1, 1, 1));\n"
861 " color.rgb *= SceneBrightness;\n"
863 " gl_FragColor = vec4(color);\n"
865 "#endif // MODE_REFRACTION\n"
866 "#endif // MODE_WATER\n"
868 "#endif // FRAGMENT_SHADER\n"
871 #define SHADERPERMUTATION_COLORMAPPING (1<<0) // indicates this is a colormapped skin
872 #define SHADERPERMUTATION_CONTRASTBOOST (1<<1) // r_glsl_contrastboost boosts the contrast at low color levels (similar to gamma)
873 #define SHADERPERMUTATION_FOG (1<<2) // tint the color by fog color or black if using additive blend mode
874 #define SHADERPERMUTATION_CUBEFILTER (1<<3) // (lightsource) use cubemap light filter
875 #define SHADERPERMUTATION_GLOW (1<<4) // (lightmap) blend in an additive glow texture
876 #define SHADERPERMUTATION_DIFFUSE (1<<5) // (lightsource) whether to use directional shading
877 #define SHADERPERMUTATION_SPECULAR (1<<6) // (lightsource or deluxemapping) render specular effects
878 #define SHADERPERMUTATION_REFLECTION (1<<7) // normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
879 #define SHADERPERMUTATION_OFFSETMAPPING (1<<8) // adjust texcoords to roughly simulate a displacement mapped surface
880 #define SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING (1<<9) // adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
881 #define SHADERPERMUTATION_MODEBASE (1<<10) // multiplier for the SHADERMODE_ values to get a valid index
883 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
884 const char *shaderpermutationinfo[][2] =
886 {"#define USECOLORMAPPING\n", " colormapping"},
887 {"#define USECONTRASTBOOST\n", " contrastboost"},
888 {"#define USEFOG\n", " fog"},
889 {"#define USECUBEFILTER\n", " cubefilter"},
890 {"#define USEGLOW\n", " glow"},
891 {"#define USEDIFFUSE\n", " diffuse"},
892 {"#define USESPECULAR\n", " specular"},
893 {"#define USEREFLECTION\n", " reflection"},
894 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
895 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
899 // this enum is multiplied by SHADERPERMUTATION_MODEBASE
900 typedef enum shadermode_e
902 SHADERMODE_LIGHTMAP, // (lightmap) use directional pixel shading from fixed light direction (q3bsp)
903 SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, // (lightmap) use directional pixel shading from texture containing modelspace light directions (deluxemap)
904 SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, // (lightmap) use directional pixel shading from texture containing tangentspace light directions (deluxemap)
905 SHADERMODE_LIGHTDIRECTION, // (lightmap) use directional pixel shading from fixed light direction (q3bsp)
906 SHADERMODE_LIGHTSOURCE, // (lightsource) use directional pixel shading from light source (rtlight)
907 SHADERMODE_REFRACTION, // refract background (the material is rendered normally after this pass)
908 SHADERMODE_WATER, // refract background and reflection (the material is rendered normally after this pass)
913 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
914 const char *shadermodeinfo[][2] =
916 {"#define MODE_LIGHTMAP\n", " lightmap"},
917 {"#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
918 {"#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
919 {"#define MODE_LIGHTDIRECTION\n", " lightdirection"},
920 {"#define MODE_LIGHTSOURCE\n", " lightsource"},
921 {"#define MODE_REFRACTION\n", " refraction"},
922 {"#define MODE_WATER\n", " water"},
926 #define SHADERPERMUTATION_INDICES (SHADERPERMUTATION_MODEBASE * SHADERMODE_COUNT)
928 typedef struct r_glsl_permutation_s
930 // indicates if we have tried compiling this permutation already
932 // 0 if compilation failed
934 // locations of detected uniforms in program object, or -1 if not found
935 int loc_Texture_Normal;
936 int loc_Texture_Color;
937 int loc_Texture_Gloss;
938 int loc_Texture_Cube;
939 int loc_Texture_Attenuation;
940 int loc_Texture_FogMask;
941 int loc_Texture_Pants;
942 int loc_Texture_Shirt;
943 int loc_Texture_Lightmap;
944 int loc_Texture_Deluxemap;
945 int loc_Texture_Glow;
946 int loc_Texture_Refraction;
947 int loc_Texture_Reflection;
949 int loc_LightPosition;
954 int loc_FogRangeRecip;
955 int loc_AmbientScale;
956 int loc_DiffuseScale;
957 int loc_SpecularScale;
958 int loc_SpecularPower;
960 int loc_SceneBrightness; // or: Scenebrightness * ContrastBoost
961 int loc_OffsetMapping_Scale;
962 int loc_AmbientColor;
963 int loc_DiffuseColor;
964 int loc_SpecularColor;
966 int loc_ContrastBoostCoeff; // 1 - 1/ContrastBoost
967 int loc_DistortScaleRefractReflect;
968 int loc_ScreenScaleRefractReflect;
969 int loc_ScreenCenterRefractReflect;
970 int loc_RefractColor;
971 int loc_ReflectColor;
972 int loc_ReflectFactor;
973 int loc_ReflectOffset;
975 r_glsl_permutation_t;
977 // information about each possible shader permutation
978 r_glsl_permutation_t r_glsl_permutations[SHADERPERMUTATION_INDICES];
979 // currently selected permutation
980 r_glsl_permutation_t *r_glsl_permutation;
982 // these are additional flags used only by R_GLSL_CompilePermutation
983 #define SHADERTYPE_USES_VERTEXSHADER (1<<0)
984 #define SHADERTYPE_USES_GEOMETRYSHADER (1<<1)
985 #define SHADERTYPE_USES_FRAGMENTSHADER (1<<2)
987 static void R_GLSL_CompilePermutation(const char *filename, int permutation, int shadertype)
990 qboolean shaderfound;
991 r_glsl_permutation_t *p = r_glsl_permutations + permutation;
992 int vertstrings_count;
993 int geomstrings_count;
994 int fragstrings_count;
996 const char *vertstrings_list[32+1];
997 const char *geomstrings_list[32+1];
998 const char *fragstrings_list[32+1];
999 char permutationname[256];
1004 vertstrings_list[0] = "#define VERTEX_SHADER\n";
1005 geomstrings_list[0] = "#define GEOMETRY_SHADER\n";
1006 fragstrings_list[0] = "#define FRAGMENT_SHADER\n";
1007 vertstrings_count = 1;
1008 geomstrings_count = 1;
1009 fragstrings_count = 1;
1010 permutationname[0] = 0;
1011 i = permutation / SHADERPERMUTATION_MODEBASE;
1012 vertstrings_list[vertstrings_count++] = shadermodeinfo[i][0];
1013 geomstrings_list[geomstrings_count++] = shadermodeinfo[i][0];
1014 fragstrings_list[fragstrings_count++] = shadermodeinfo[i][0];
1015 strlcat(permutationname, shadermodeinfo[i][1], sizeof(permutationname));
1016 for (i = 0;shaderpermutationinfo[i][0];i++)
1018 if (permutation & (1<<i))
1020 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i][0];
1021 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i][0];
1022 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i][0];
1023 strlcat(permutationname, shaderpermutationinfo[i][1], sizeof(permutationname));
1027 // keep line numbers correct
1028 vertstrings_list[vertstrings_count++] = "\n";
1029 geomstrings_list[geomstrings_count++] = "\n";
1030 fragstrings_list[fragstrings_count++] = "\n";
1033 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1034 shaderfound = false;
1037 Con_DPrint("from disk... ");
1038 vertstrings_list[vertstrings_count++] = shaderstring;
1039 geomstrings_list[geomstrings_count++] = shaderstring;
1040 fragstrings_list[fragstrings_count++] = shaderstring;
1043 else if (!strcmp(filename, "glsl/default.glsl"))
1045 vertstrings_list[vertstrings_count++] = builtinshaderstring;
1046 geomstrings_list[geomstrings_count++] = builtinshaderstring;
1047 fragstrings_list[fragstrings_count++] = builtinshaderstring;
1050 // clear any lists that are not needed by this shader
1051 if (!(shadertype & SHADERTYPE_USES_VERTEXSHADER))
1052 vertstrings_count = 0;
1053 if (!(shadertype & SHADERTYPE_USES_GEOMETRYSHADER))
1054 geomstrings_count = 0;
1055 if (!(shadertype & SHADERTYPE_USES_FRAGMENTSHADER))
1056 fragstrings_count = 0;
1057 // compile the shader program
1058 if (shaderfound && vertstrings_count + geomstrings_count + fragstrings_count)
1059 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1063 qglUseProgramObjectARB(p->program);CHECKGLERROR
1064 // look up all the uniform variable names we care about, so we don't
1065 // have to look them up every time we set them
1066 p->loc_Texture_Normal = qglGetUniformLocationARB(p->program, "Texture_Normal");
1067 p->loc_Texture_Color = qglGetUniformLocationARB(p->program, "Texture_Color");
1068 p->loc_Texture_Gloss = qglGetUniformLocationARB(p->program, "Texture_Gloss");
1069 p->loc_Texture_Cube = qglGetUniformLocationARB(p->program, "Texture_Cube");
1070 p->loc_Texture_Attenuation = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
1071 p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
1072 p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
1073 p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
1074 p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
1075 p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
1076 p->loc_Texture_Glow = qglGetUniformLocationARB(p->program, "Texture_Glow");
1077 p->loc_Texture_Refraction = qglGetUniformLocationARB(p->program, "Texture_Refraction");
1078 p->loc_Texture_Reflection = qglGetUniformLocationARB(p->program, "Texture_Reflection");
1079 p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
1080 p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
1081 p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
1082 p->loc_LightColor = qglGetUniformLocationARB(p->program, "LightColor");
1083 p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants");
1084 p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt");
1085 p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip");
1086 p->loc_AmbientScale = qglGetUniformLocationARB(p->program, "AmbientScale");
1087 p->loc_DiffuseScale = qglGetUniformLocationARB(p->program, "DiffuseScale");
1088 p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
1089 p->loc_SpecularScale = qglGetUniformLocationARB(p->program, "SpecularScale");
1090 p->loc_GlowScale = qglGetUniformLocationARB(p->program, "GlowScale");
1091 p->loc_SceneBrightness = qglGetUniformLocationARB(p->program, "SceneBrightness");
1092 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
1093 p->loc_AmbientColor = qglGetUniformLocationARB(p->program, "AmbientColor");
1094 p->loc_DiffuseColor = qglGetUniformLocationARB(p->program, "DiffuseColor");
1095 p->loc_SpecularColor = qglGetUniformLocationARB(p->program, "SpecularColor");
1096 p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
1097 p->loc_ContrastBoostCoeff = qglGetUniformLocationARB(p->program, "ContrastBoostCoeff");
1098 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
1099 p->loc_ScreenScaleRefractReflect = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
1100 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
1101 p->loc_RefractColor = qglGetUniformLocationARB(p->program, "RefractColor");
1102 p->loc_ReflectColor = qglGetUniformLocationARB(p->program, "ReflectColor");
1103 p->loc_ReflectFactor = qglGetUniformLocationARB(p->program, "ReflectFactor");
1104 p->loc_ReflectOffset = qglGetUniformLocationARB(p->program, "ReflectOffset");
1105 // initialize the samplers to refer to the texture units we use
1106 if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal, 0);
1107 if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color, 1);
1108 if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss, 2);
1109 if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube, 3);
1110 if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask, 4);
1111 if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants, 5);
1112 if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt, 6);
1113 if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap, 7);
1114 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap, 8);
1115 if (p->loc_Texture_Glow >= 0) qglUniform1iARB(p->loc_Texture_Glow, 9);
1116 if (p->loc_Texture_Attenuation >= 0) qglUniform1iARB(p->loc_Texture_Attenuation, 10);
1117 if (p->loc_Texture_Refraction >= 0) qglUniform1iARB(p->loc_Texture_Refraction, 11);
1118 if (p->loc_Texture_Reflection >= 0) qglUniform1iARB(p->loc_Texture_Reflection, 12);
1120 qglUseProgramObjectARB(0);CHECKGLERROR
1121 if (developer.integer)
1122 Con_Printf("GLSL shader %s :%s compiled.\n", filename, permutationname);
1126 if (developer.integer)
1127 Con_Printf("GLSL shader %s :%s failed! source code line offset for above errors is %i.\n", permutationname, filename, -(vertstrings_count - 1));
1129 Con_Printf("GLSL shader %s :%s failed! some features may not work properly.\n", permutationname, filename);
1132 Mem_Free(shaderstring);
1135 void R_GLSL_Restart_f(void)
1138 for (i = 0;i < SHADERPERMUTATION_INDICES;i++)
1139 if (r_glsl_permutations[i].program)
1140 GL_Backend_FreeProgram(r_glsl_permutations[i].program);
1141 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
1144 void R_GLSL_DumpShader_f(void)
1148 qfile_t *file = FS_Open("glsl/default.glsl", "w", false, false);
1151 Con_Printf("failed to write to glsl/default.glsl\n");
1155 FS_Print(file, "// The engine may define the following macros:\n");
1156 FS_Print(file, "// #define VERTEX_SHADER\n// #define GEOMETRY_SHADER\n// #define FRAGMENT_SHADER\n");
1157 for (i = 0;shadermodeinfo[i][0];i++)
1158 FS_Printf(file, "// %s", shadermodeinfo[i][0]);
1159 for (i = 0;shaderpermutationinfo[i][0];i++)
1160 FS_Printf(file, "// %s", shaderpermutationinfo[i][0]);
1161 FS_Print(file, "\n");
1162 FS_Print(file, builtinshaderstring);
1165 Con_Printf("glsl/default.glsl written\n");
1168 extern rtexture_t *r_shadow_attenuationgradienttexture;
1169 extern rtexture_t *r_shadow_attenuation2dtexture;
1170 extern rtexture_t *r_shadow_attenuation3dtexture;
1171 int R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass)
1173 // select a permutation of the lighting shader appropriate to this
1174 // combination of texture, entity, light source, and fogging, only use the
1175 // minimum features necessary to avoid wasting rendering time in the
1176 // fragment shader on features that are not being used
1177 const char *shaderfilename = NULL;
1178 unsigned int permutation = 0;
1179 unsigned int shadertype = 0;
1180 shadermode_t mode = 0;
1181 r_glsl_permutation = NULL;
1182 shaderfilename = "glsl/default.glsl";
1183 shadertype = SHADERTYPE_USES_VERTEXSHADER | SHADERTYPE_USES_FRAGMENTSHADER;
1184 // TODO: implement geometry-shader based shadow volumes someday
1185 if (r_glsl_offsetmapping.integer)
1187 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
1188 if (r_glsl_offsetmapping_reliefmapping.integer)
1189 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
1191 if (rsurfacepass == RSURFPASS_BACKGROUND)
1193 // distorted background
1194 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
1195 mode = SHADERMODE_WATER;
1197 mode = SHADERMODE_REFRACTION;
1199 else if (rsurfacepass == RSURFPASS_RTLIGHT)
1202 mode = SHADERMODE_LIGHTSOURCE;
1203 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
1204 permutation |= SHADERPERMUTATION_CUBEFILTER;
1205 if (diffusescale > 0)
1206 permutation |= SHADERPERMUTATION_DIFFUSE;
1207 if (specularscale > 0)
1208 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
1209 if (r_refdef.fogenabled)
1210 permutation |= SHADERPERMUTATION_FOG;
1211 if (rsurface.texture->colormapping)
1212 permutation |= SHADERPERMUTATION_COLORMAPPING;
1213 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1214 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1215 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1216 permutation |= SHADERPERMUTATION_REFLECTION;
1218 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
1220 // unshaded geometry (fullbright or ambient model lighting)
1221 mode = SHADERMODE_LIGHTMAP;
1222 if (rsurface.texture->currentskinframe->glow)
1223 permutation |= SHADERPERMUTATION_GLOW;
1224 if (r_refdef.fogenabled)
1225 permutation |= SHADERPERMUTATION_FOG;
1226 if (rsurface.texture->colormapping)
1227 permutation |= SHADERPERMUTATION_COLORMAPPING;
1228 if (r_glsl_offsetmapping.integer)
1230 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
1231 if (r_glsl_offsetmapping_reliefmapping.integer)
1232 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
1234 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1235 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1236 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1237 permutation |= SHADERPERMUTATION_REFLECTION;
1239 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
1241 // directional model lighting
1242 mode = SHADERMODE_LIGHTDIRECTION;
1243 if (rsurface.texture->currentskinframe->glow)
1244 permutation |= SHADERPERMUTATION_GLOW;
1245 permutation |= SHADERPERMUTATION_DIFFUSE;
1246 if (specularscale > 0)
1247 permutation |= SHADERPERMUTATION_SPECULAR;
1248 if (r_refdef.fogenabled)
1249 permutation |= SHADERPERMUTATION_FOG;
1250 if (rsurface.texture->colormapping)
1251 permutation |= SHADERPERMUTATION_COLORMAPPING;
1252 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1253 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1254 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1255 permutation |= SHADERPERMUTATION_REFLECTION;
1257 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
1259 // ambient model lighting
1260 mode = SHADERMODE_LIGHTDIRECTION;
1261 if (rsurface.texture->currentskinframe->glow)
1262 permutation |= SHADERPERMUTATION_GLOW;
1263 if (r_refdef.fogenabled)
1264 permutation |= SHADERPERMUTATION_FOG;
1265 if (rsurface.texture->colormapping)
1266 permutation |= SHADERPERMUTATION_COLORMAPPING;
1267 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1268 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1269 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1270 permutation |= SHADERPERMUTATION_REFLECTION;
1275 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.worldmodel && r_refdef.worldmodel->brushq3.deluxemapping)
1277 // deluxemapping (light direction texture)
1278 if (rsurface.uselightmaptexture && r_refdef.worldmodel && r_refdef.worldmodel->brushq3.deluxemapping && r_refdef.worldmodel->brushq3.deluxemapping_modelspace)
1279 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
1281 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
1282 if (specularscale > 0)
1283 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
1285 else if (r_glsl_deluxemapping.integer >= 2)
1287 // fake deluxemapping (uniform light direction in tangentspace)
1288 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
1289 if (specularscale > 0)
1290 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
1294 // ordinary lightmapping
1295 mode = SHADERMODE_LIGHTMAP;
1297 if (rsurface.texture->currentskinframe->glow)
1298 permutation |= SHADERPERMUTATION_GLOW;
1299 if (r_refdef.fogenabled)
1300 permutation |= SHADERPERMUTATION_FOG;
1301 if (rsurface.texture->colormapping)
1302 permutation |= SHADERPERMUTATION_COLORMAPPING;
1303 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1304 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1305 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1306 permutation |= SHADERPERMUTATION_REFLECTION;
1308 permutation |= mode * SHADERPERMUTATION_MODEBASE;
1309 if (!r_glsl_permutations[permutation].program)
1311 if (!r_glsl_permutations[permutation].compiled)
1312 R_GLSL_CompilePermutation(shaderfilename, permutation, shadertype);
1313 if (!r_glsl_permutations[permutation].program)
1315 // remove features until we find a valid permutation
1317 for (i = (SHADERPERMUTATION_MODEBASE >> 1);;i>>=1)
1321 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");
1322 Cvar_SetValueQuick(&r_glsl, 0);
1323 return 0; // no bit left to clear
1325 // reduce i more quickly whenever it would not remove any bits
1326 if (!(permutation & i))
1329 if (!r_glsl_permutations[permutation].compiled)
1330 R_GLSL_CompilePermutation(shaderfilename, permutation, shadertype);
1331 if (r_glsl_permutations[permutation].program)
1336 r_glsl_permutation = r_glsl_permutations + permutation;
1338 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
1339 if (mode == SHADERMODE_LIGHTSOURCE)
1341 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
1342 if (permutation & SHADERPERMUTATION_DIFFUSE)
1344 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
1345 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, ambientscale);
1346 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, diffusescale);
1347 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, specularscale);
1351 // ambient only is simpler
1352 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0] * ambientscale, lightcolorbase[1] * ambientscale, lightcolorbase[2] * ambientscale);
1353 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, 1);
1354 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, 0);
1355 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, 0);
1358 else if (mode == SHADERMODE_LIGHTDIRECTION)
1360 if (r_glsl_permutation->loc_AmbientColor >= 0)
1361 qglUniform3fARB(r_glsl_permutation->loc_AmbientColor, rsurface.modellight_ambient[0] * ambientscale, rsurface.modellight_ambient[1] * ambientscale, rsurface.modellight_ambient[2] * ambientscale);
1362 if (r_glsl_permutation->loc_DiffuseColor >= 0)
1363 qglUniform3fARB(r_glsl_permutation->loc_DiffuseColor, rsurface.modellight_diffuse[0] * diffusescale, rsurface.modellight_diffuse[1] * diffusescale, rsurface.modellight_diffuse[2] * diffusescale);
1364 if (r_glsl_permutation->loc_SpecularColor >= 0)
1365 qglUniform3fARB(r_glsl_permutation->loc_SpecularColor, rsurface.modellight_diffuse[0] * specularscale, rsurface.modellight_diffuse[1] * specularscale, rsurface.modellight_diffuse[2] * specularscale);
1366 if (r_glsl_permutation->loc_LightDir >= 0)
1367 qglUniform3fARB(r_glsl_permutation->loc_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
1371 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_ambient.value * 2.0f / 128.0f);
1372 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_refdef.lightmapintensity * 2.0f);
1373 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, r_refdef.lightmapintensity * specularscale * 2.0f);
1375 if (r_glsl_permutation->loc_GlowScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_GlowScale, r_hdr_glowintensity.value);
1376 if (r_glsl_permutation->loc_ContrastBoostCoeff >= 0)
1378 // The formula used is actually:
1379 // color.rgb *= SceneBrightness;
1380 // color.rgb *= ContrastBoost / ((ContrastBoost - 1) * color.rgb + 1);
1381 // I simplify that to
1382 // color.rgb *= [[SceneBrightness * ContrastBoost]];
1383 // color.rgb /= [[(ContrastBoost - 1) / ContrastBoost]] * color.rgb + 1;
1385 // color.rgb = [[SceneBrightness * ContrastBoost]] * color.rgb / ([[(ContrastBoost - 1) * SceneBrightness]] * color.rgb + 1);
1386 // and do [[calculations]] here in the engine
1387 qglUniform1fARB(r_glsl_permutation->loc_ContrastBoostCoeff, (r_glsl_contrastboost.value - 1) * r_view.colorscale);
1388 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_view.colorscale * r_glsl_contrastboost.value);
1391 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_view.colorscale);
1392 if (r_glsl_permutation->loc_FogColor >= 0)
1394 // additive passes are only darkened by fog, not tinted
1395 if (rsurface.rtlight || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD))
1396 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
1401 // color.rgb *= SceneBrightness;
1402 VectorScale(r_refdef.fogcolor, r_view.colorscale, fogvec);
1403 if(r_glsl_permutation->loc_ContrastBoostCoeff >= 0) // need to support contrast boost
1405 // color.rgb *= ContrastBoost / ((ContrastBoost - 1) * color.rgb + 1);
1406 fogvec[0] *= r_glsl_contrastboost.value / ((r_glsl_contrastboost.value - 1) * fogvec[0] + 1);
1407 fogvec[1] *= r_glsl_contrastboost.value / ((r_glsl_contrastboost.value - 1) * fogvec[1] + 1);
1408 fogvec[2] *= r_glsl_contrastboost.value / ((r_glsl_contrastboost.value - 1) * fogvec[2] + 1);
1410 qglUniform3fARB(r_glsl_permutation->loc_FogColor, fogvec[0], fogvec[1], fogvec[2]);
1413 qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
1415 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.modelorg[0], rsurface.modelorg[1], rsurface.modelorg[2]);
1416 if (r_glsl_permutation->loc_Color_Pants >= 0)
1418 if (rsurface.texture->currentskinframe->pants)
1419 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
1421 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
1423 if (r_glsl_permutation->loc_Color_Shirt >= 0)
1425 if (rsurface.texture->currentskinframe->shirt)
1426 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
1428 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
1430 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, r_refdef.fograngerecip);
1431 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower);
1432 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
1433 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);
1434 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]);
1435 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]);
1436 if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f);
1437 if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f);
1438 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
1439 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
1444 #define SKINFRAME_HASH 1024
1448 int loadsequence; // incremented each level change
1449 memexpandablearray_t array;
1450 skinframe_t *hash[SKINFRAME_HASH];
1454 void R_SkinFrame_PrepareForPurge(void)
1456 r_skinframe.loadsequence++;
1457 // wrap it without hitting zero
1458 if (r_skinframe.loadsequence >= 200)
1459 r_skinframe.loadsequence = 1;
1462 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
1466 // mark the skinframe as used for the purging code
1467 skinframe->loadsequence = r_skinframe.loadsequence;
1470 void R_SkinFrame_Purge(void)
1474 for (i = 0;i < SKINFRAME_HASH;i++)
1476 for (s = r_skinframe.hash[i];s;s = s->next)
1478 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
1480 if (s->base == r_texture_notexture) s->base = NULL;
1481 if (s->nmap == r_texture_blanknormalmap)s->nmap = NULL;
1482 if (s->merged == s->base) s->merged = NULL;
1483 if (s->stain ) R_FreeTexture(s->stain );s->stain = NULL;
1484 if (s->merged) R_FreeTexture(s->merged);s->merged = NULL;
1485 if (s->base ) R_FreeTexture(s->base );s->base = NULL;
1486 if (s->pants ) R_FreeTexture(s->pants );s->pants = NULL;
1487 if (s->shirt ) R_FreeTexture(s->shirt );s->shirt = NULL;
1488 if (s->nmap ) R_FreeTexture(s->nmap );s->nmap = NULL;
1489 if (s->gloss ) R_FreeTexture(s->gloss );s->gloss = NULL;
1490 if (s->glow ) R_FreeTexture(s->glow );s->glow = NULL;
1491 if (s->fog ) R_FreeTexture(s->fog );s->fog = NULL;
1492 s->loadsequence = 0;
1498 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
1500 char basename[MAX_QPATH];
1502 Image_StripImageExtension(name, basename, sizeof(basename));
1504 if( last == NULL ) {
1506 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
1507 item = r_skinframe.hash[hashindex];
1512 // linearly search through the hash bucket
1513 for( ; item ; item = item->next ) {
1514 if( !strcmp( item->basename, basename ) ) {
1521 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
1525 char basename[MAX_QPATH];
1527 Image_StripImageExtension(name, basename, sizeof(basename));
1529 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
1530 for (item = r_skinframe.hash[hashindex];item;item = item->next)
1531 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
1535 rtexture_t *dyntexture;
1536 // check whether its a dynamic texture
1537 dyntexture = CL_GetDynTexture( basename );
1538 if (!add && !dyntexture)
1540 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
1541 memset(item, 0, sizeof(*item));
1542 strlcpy(item->basename, basename, sizeof(item->basename));
1543 item->textureflags = textureflags;
1544 item->base = dyntexture;
1545 item->comparewidth = comparewidth;
1546 item->compareheight = compareheight;
1547 item->comparecrc = comparecrc;
1548 item->next = r_skinframe.hash[hashindex];
1549 r_skinframe.hash[hashindex] = item;
1551 R_SkinFrame_MarkUsed(item);
1555 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
1557 // FIXME: it should be possible to disable loading various layers using
1558 // cvars, to prevent wasted loading time and memory usage if the user does
1560 qboolean loadnormalmap = true;
1561 qboolean loadgloss = true;
1562 qboolean loadpantsandshirt = true;
1563 qboolean loadglow = true;
1565 unsigned char *pixels;
1566 unsigned char *bumppixels;
1567 unsigned char *basepixels = NULL;
1568 int basepixels_width;
1569 int basepixels_height;
1570 skinframe_t *skinframe;
1572 if (cls.state == ca_dedicated)
1575 // return an existing skinframe if already loaded
1576 // if loading of the first image fails, don't make a new skinframe as it
1577 // would cause all future lookups of this to be missing
1578 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
1579 if (skinframe && skinframe->base)
1582 basepixels = loadimagepixels(name, complain, 0, 0, true);
1583 if (basepixels == NULL)
1586 // we've got some pixels to store, so really allocate this new texture now
1588 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
1589 skinframe->stain = NULL;
1590 skinframe->merged = NULL;
1591 skinframe->base = r_texture_notexture;
1592 skinframe->pants = NULL;
1593 skinframe->shirt = NULL;
1594 skinframe->nmap = r_texture_blanknormalmap;
1595 skinframe->gloss = NULL;
1596 skinframe->glow = NULL;
1597 skinframe->fog = NULL;
1599 basepixels_width = image_width;
1600 basepixels_height = image_height;
1601 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);
1603 if (textureflags & TEXF_ALPHA)
1605 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
1606 if (basepixels[j] < 255)
1608 if (j < basepixels_width * basepixels_height * 4)
1610 // has transparent pixels
1611 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
1612 for (j = 0;j < image_width * image_height * 4;j += 4)
1617 pixels[j+3] = basepixels[j+3];
1619 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);
1624 // _norm is the name used by tenebrae and has been adopted as standard
1627 if ((pixels = loadimagepixels(va("%s_norm", skinframe->basename), false, 0, 0, false)) != NULL)
1629 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);
1633 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixels(va("%s_bump", skinframe->basename), false, 0, 0, false)) != NULL)
1635 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
1636 Image_HeightmapToNormalmap(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
1637 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);
1639 Mem_Free(bumppixels);
1641 else if (r_shadow_bumpscale_basetexture.value > 0)
1643 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
1644 Image_HeightmapToNormalmap(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
1645 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);
1649 // _luma is supported for tenebrae compatibility
1650 // (I think it's a very stupid name, but oh well)
1651 // _glow is the preferred name
1652 if (loadglow && ((pixels = loadimagepixels(va("%s_glow", skinframe->basename), false, 0, 0, false)) != NULL || (pixels = loadimagepixels(va("%s_luma", skinframe->basename), false, 0, 0, false)) != 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;}
1653 if (loadgloss && (pixels = loadimagepixels(va("%s_gloss", skinframe->basename), false, 0, 0, false)) != 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;}
1654 if (loadpantsandshirt && (pixels = loadimagepixels(va("%s_pants", skinframe->basename), false, 0, 0, false)) != 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;}
1655 if (loadpantsandshirt && (pixels = loadimagepixels(va("%s_shirt", skinframe->basename), false, 0, 0, false)) != 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;}
1658 Mem_Free(basepixels);
1663 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)
1668 for (i = 0;i < width*height;i++)
1669 if (((unsigned char *)&palette[in[i]])[3] > 0)
1671 if (i == width*height)
1674 return R_LoadTexture2D (r_main_texturepool, name, width, height, in, TEXTYPE_PALETTE, textureflags, palette);
1677 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)
1680 unsigned char *temp1, *temp2;
1681 skinframe_t *skinframe;
1683 if (cls.state == ca_dedicated)
1686 // if already loaded just return it, otherwise make a new skinframe
1687 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*bitsperpixel/8) : 0, true);
1688 if (skinframe && skinframe->base)
1691 skinframe->stain = NULL;
1692 skinframe->merged = NULL;
1693 skinframe->base = r_texture_notexture;
1694 skinframe->pants = NULL;
1695 skinframe->shirt = NULL;
1696 skinframe->nmap = r_texture_blanknormalmap;
1697 skinframe->gloss = NULL;
1698 skinframe->glow = NULL;
1699 skinframe->fog = NULL;
1701 // if no data was provided, then clearly the caller wanted to get a blank skinframe
1705 if (bitsperpixel == 32)
1707 if (r_shadow_bumpscale_basetexture.value > 0)
1709 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
1710 temp2 = temp1 + width * height * 4;
1711 Image_HeightmapToNormalmap(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
1712 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_RGBA, skinframe->textureflags | TEXF_ALPHA, NULL);
1715 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_RGBA, skinframe->textureflags, NULL);
1716 if (textureflags & TEXF_ALPHA)
1718 for (i = 3;i < width * height * 4;i += 4)
1719 if (skindata[i] < 255)
1721 if (i < width * height * 4)
1723 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
1724 memcpy(fogpixels, skindata, width * height * 4);
1725 for (i = 0;i < width * height * 4;i += 4)
1726 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
1727 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_RGBA, skinframe->textureflags, NULL);
1728 Mem_Free(fogpixels);
1732 else if (bitsperpixel == 8)
1734 if (r_shadow_bumpscale_basetexture.value > 0)
1736 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
1737 temp2 = temp1 + width * height * 4;
1738 if (bitsperpixel == 32)
1739 Image_HeightmapToNormalmap(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
1742 // use either a custom palette or the quake palette
1743 Image_Copy8bitRGBA(skindata, temp1, width * height, palette ? palette : palette_complete);
1744 Image_HeightmapToNormalmap(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
1746 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_RGBA, skinframe->textureflags | TEXF_ALPHA, NULL);
1749 // use either a custom palette, or the quake palette
1750 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
1751 if (!palette && loadglowtexture)
1752 skinframe->glow = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_glow", skinframe->basename), palette_onlyfullbrights, skinframe->textureflags, false); // glow
1753 if (!palette && loadpantsandshirt)
1755 skinframe->pants = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_pants", skinframe->basename), palette_pantsaswhite, skinframe->textureflags, false); // pants
1756 skinframe->shirt = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_shirt", skinframe->basename), palette_shirtaswhite, skinframe->textureflags, false); // shirt
1758 if (skinframe->pants || skinframe->shirt)
1759 skinframe->base = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_nospecial", skinframe->basename),loadglowtexture ? palette_nocolormapnofullbrights : palette_nocolormap, skinframe->textureflags, false); // no special colors
1760 if (textureflags & TEXF_ALPHA)
1762 // if not using a custom alphapalette, use the quake one
1764 alphapalette = palette_alpha;
1765 for (i = 0;i < width * height;i++)
1766 if (((unsigned char *)alphapalette)[skindata[i]*4+3] < 255)
1768 if (i < width * height)
1769 skinframe->fog = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_fog", skinframe->basename), alphapalette, skinframe->textureflags, true); // fog mask
1776 skinframe_t *R_SkinFrame_LoadMissing(void)
1778 skinframe_t *skinframe;
1780 if (cls.state == ca_dedicated)
1783 skinframe = R_SkinFrame_Find("missing", TEXF_PRECACHE, 0, 0, 0, true);
1784 skinframe->stain = NULL;
1785 skinframe->merged = NULL;
1786 skinframe->base = r_texture_notexture;
1787 skinframe->pants = NULL;
1788 skinframe->shirt = NULL;
1789 skinframe->nmap = r_texture_blanknormalmap;
1790 skinframe->gloss = NULL;
1791 skinframe->glow = NULL;
1792 skinframe->fog = NULL;
1797 void gl_main_start(void)
1802 r = (-1.0/256.0) * (FOGMASKTABLEWIDTH * FOGMASKTABLEWIDTH);
1803 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
1805 alpha = 1 - exp(r / ((double)x*(double)x));
1806 if (x == FOGMASKTABLEWIDTH - 1)
1808 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
1811 memset(r_qwskincache, 0, sizeof(r_qwskincache));
1812 memset(r_qwskincache_skinframe, 0, sizeof(r_qwskincache_skinframe));
1814 // set up r_skinframe loading system for textures
1815 memset(&r_skinframe, 0, sizeof(r_skinframe));
1816 r_skinframe.loadsequence = 1;
1817 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
1819 r_main_texturepool = R_AllocTexturePool();
1820 R_BuildBlankTextures();
1822 if (gl_texturecubemap)
1825 R_BuildNormalizationCube();
1827 R_BuildFogTexture();
1828 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
1829 memset(&r_waterstate, 0, sizeof(r_waterstate));
1830 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
1831 memset(&r_svbsp, 0, sizeof (r_svbsp));
1834 void gl_main_shutdown(void)
1836 memset(r_qwskincache, 0, sizeof(r_qwskincache));
1837 memset(r_qwskincache_skinframe, 0, sizeof(r_qwskincache_skinframe));
1839 // clear out the r_skinframe state
1840 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
1841 memset(&r_skinframe, 0, sizeof(r_skinframe));
1844 Mem_Free(r_svbsp.nodes);
1845 memset(&r_svbsp, 0, sizeof (r_svbsp));
1846 R_FreeTexturePool(&r_main_texturepool);
1847 r_texture_blanknormalmap = NULL;
1848 r_texture_white = NULL;
1849 r_texture_grey128 = NULL;
1850 r_texture_black = NULL;
1851 r_texture_whitecube = NULL;
1852 r_texture_normalizationcube = NULL;
1853 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
1854 memset(&r_waterstate, 0, sizeof(r_waterstate));
1858 extern void CL_ParseEntityLump(char *entitystring);
1859 void gl_main_newmap(void)
1861 // FIXME: move this code to client
1863 char *entities, entname[MAX_QPATH];
1866 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
1867 l = (int)strlen(entname) - 4;
1868 if (l >= 0 && !strcmp(entname + l, ".bsp"))
1870 memcpy(entname + l, ".ent", 5);
1871 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
1873 CL_ParseEntityLump(entities);
1878 if (cl.worldmodel->brush.entities)
1879 CL_ParseEntityLump(cl.worldmodel->brush.entities);
1883 void GL_Main_Init(void)
1885 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
1887 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
1888 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
1889 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
1890 if (gamemode == GAME_NEHAHRA)
1892 Cvar_RegisterVariable (&gl_fogenable);
1893 Cvar_RegisterVariable (&gl_fogdensity);
1894 Cvar_RegisterVariable (&gl_fogred);
1895 Cvar_RegisterVariable (&gl_foggreen);
1896 Cvar_RegisterVariable (&gl_fogblue);
1897 Cvar_RegisterVariable (&gl_fogstart);
1898 Cvar_RegisterVariable (&gl_fogend);
1900 Cvar_RegisterVariable(&r_depthfirst);
1901 Cvar_RegisterVariable(&r_nearclip);
1902 Cvar_RegisterVariable(&r_showbboxes);
1903 Cvar_RegisterVariable(&r_showsurfaces);
1904 Cvar_RegisterVariable(&r_showtris);
1905 Cvar_RegisterVariable(&r_shownormals);
1906 Cvar_RegisterVariable(&r_showlighting);
1907 Cvar_RegisterVariable(&r_showshadowvolumes);
1908 Cvar_RegisterVariable(&r_showcollisionbrushes);
1909 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
1910 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
1911 Cvar_RegisterVariable(&r_showdisabledepthtest);
1912 Cvar_RegisterVariable(&r_drawportals);
1913 Cvar_RegisterVariable(&r_drawentities);
1914 Cvar_RegisterVariable(&r_cullentities_trace);
1915 Cvar_RegisterVariable(&r_cullentities_trace_samples);
1916 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
1917 Cvar_RegisterVariable(&r_cullentities_trace_delay);
1918 Cvar_RegisterVariable(&r_drawviewmodel);
1919 Cvar_RegisterVariable(&r_speeds);
1920 Cvar_RegisterVariable(&r_fullbrights);
1921 Cvar_RegisterVariable(&r_wateralpha);
1922 Cvar_RegisterVariable(&r_dynamic);
1923 Cvar_RegisterVariable(&r_fullbright);
1924 Cvar_RegisterVariable(&r_shadows);
1925 Cvar_RegisterVariable(&r_shadows_throwdistance);
1926 Cvar_RegisterVariable(&r_q1bsp_skymasking);
1927 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
1928 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
1929 Cvar_RegisterVariable(&r_textureunits);
1930 Cvar_RegisterVariable(&r_glsl);
1931 Cvar_RegisterVariable(&r_glsl_offsetmapping);
1932 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
1933 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
1934 Cvar_RegisterVariable(&r_glsl_deluxemapping);
1935 Cvar_RegisterVariable(&r_water);
1936 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
1937 Cvar_RegisterVariable(&r_water_clippingplanebias);
1938 Cvar_RegisterVariable(&r_water_refractdistort);
1939 Cvar_RegisterVariable(&r_water_reflectdistort);
1940 Cvar_RegisterVariable(&r_lerpsprites);
1941 Cvar_RegisterVariable(&r_lerpmodels);
1942 Cvar_RegisterVariable(&r_waterscroll);
1943 Cvar_RegisterVariable(&r_bloom);
1944 Cvar_RegisterVariable(&r_bloom_colorscale);
1945 Cvar_RegisterVariable(&r_bloom_brighten);
1946 Cvar_RegisterVariable(&r_bloom_blur);
1947 Cvar_RegisterVariable(&r_bloom_resolution);
1948 Cvar_RegisterVariable(&r_bloom_colorexponent);
1949 Cvar_RegisterVariable(&r_bloom_colorsubtract);
1950 Cvar_RegisterVariable(&r_hdr);
1951 Cvar_RegisterVariable(&r_hdr_scenebrightness);
1952 Cvar_RegisterVariable(&r_glsl_contrastboost);
1953 Cvar_RegisterVariable(&r_hdr_glowintensity);
1954 Cvar_RegisterVariable(&r_hdr_range);
1955 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
1956 Cvar_RegisterVariable(&developer_texturelogging);
1957 Cvar_RegisterVariable(&gl_lightmaps);
1958 Cvar_RegisterVariable(&r_test);
1959 Cvar_RegisterVariable(&r_batchmode);
1960 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
1961 Cvar_SetValue("r_fullbrights", 0);
1962 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
1964 Cvar_RegisterVariable(&r_track_sprites);
1965 Cvar_RegisterVariable(&r_track_sprites_flags);
1966 Cvar_RegisterVariable(&r_track_sprites_scalew);
1967 Cvar_RegisterVariable(&r_track_sprites_scaleh);
1970 extern void R_Textures_Init(void);
1971 extern void GL_Draw_Init(void);
1972 extern void GL_Main_Init(void);
1973 extern void R_Shadow_Init(void);
1974 extern void R_Sky_Init(void);
1975 extern void GL_Surf_Init(void);
1976 extern void R_Light_Init(void);
1977 extern void R_Particles_Init(void);
1978 extern void R_Explosion_Init(void);
1979 extern void gl_backend_init(void);
1980 extern void Sbar_Init(void);
1981 extern void R_LightningBeams_Init(void);
1982 extern void Mod_RenderInit(void);
1984 void Render_Init(void)
1997 R_LightningBeams_Init();
2006 extern char *ENGINE_EXTENSIONS;
2009 VID_CheckExtensions();
2011 // LordHavoc: report supported extensions
2012 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
2014 // clear to black (loading plaque will be seen over this)
2016 qglClearColor(0,0,0,1);CHECKGLERROR
2017 qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
2020 int R_CullBox(const vec3_t mins, const vec3_t maxs)
2024 for (i = 0;i < r_view.numfrustumplanes;i++)
2026 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
2029 p = r_view.frustum + i;
2034 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2038 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2042 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2046 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2050 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2054 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2058 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2062 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2070 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
2074 for (i = 0;i < numplanes;i++)
2081 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2085 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2089 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2093 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2097 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2101 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2105 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2109 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2117 //==================================================================================
2119 static void R_UpdateEntityLighting(entity_render_t *ent)
2121 vec3_t tempdiffusenormal;
2123 // fetch the lighting from the worldmodel data
2124 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));
2125 VectorClear(ent->modellight_diffuse);
2126 VectorClear(tempdiffusenormal);
2127 if ((ent->flags & RENDER_LIGHT) && r_refdef.worldmodel && r_refdef.worldmodel->brush.LightPoint)
2130 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
2131 r_refdef.worldmodel->brush.LightPoint(r_refdef.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
2134 VectorSet(ent->modellight_ambient, 1, 1, 1);
2136 // move the light direction into modelspace coordinates for lighting code
2137 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
2138 if(VectorLength2(ent->modellight_lightdir) > 0)
2140 VectorNormalize(ent->modellight_lightdir);
2144 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
2147 // scale ambient and directional light contributions according to rendering variables
2148 ent->modellight_ambient[0] *= ent->colormod[0] * r_refdef.lightmapintensity;
2149 ent->modellight_ambient[1] *= ent->colormod[1] * r_refdef.lightmapintensity;
2150 ent->modellight_ambient[2] *= ent->colormod[2] * r_refdef.lightmapintensity;
2151 ent->modellight_diffuse[0] *= ent->colormod[0] * r_refdef.lightmapintensity;
2152 ent->modellight_diffuse[1] *= ent->colormod[1] * r_refdef.lightmapintensity;
2153 ent->modellight_diffuse[2] *= ent->colormod[2] * r_refdef.lightmapintensity;
2156 static void R_View_UpdateEntityVisible (void)
2159 entity_render_t *ent;
2161 if (!r_drawentities.integer)
2164 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : ((chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL : RENDER_EXTERIORMODEL);
2165 if (r_refdef.worldmodel && r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs)
2167 // worldmodel can check visibility
2168 for (i = 0;i < r_refdef.numentities;i++)
2170 ent = r_refdef.entities[i];
2171 r_viewcache.entityvisible[i] = !(ent->flags & renderimask) && ((ent->model->type == mod_sprite && (ent->model->sprite.sprnum_type == SPR_LABEL || ent->model->sprite.sprnum_type == SPR_LABEL_SCALE)) || !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));
2174 if(r_cullentities_trace.integer)
2176 for (i = 0;i < r_refdef.numentities;i++)
2178 ent = r_refdef.entities[i];
2179 if(r_viewcache.entityvisible[i] && !(ent->effects & EF_NODEPTHTEST) && !(ent->flags & RENDER_VIEWMODEL) && !(ent->model && (ent->model->name[0] == '*')))
2181 if(Mod_CanSeeBox_Trace(r_cullentities_trace_samples.integer, r_cullentities_trace_enlarge.value, r_refdef.worldmodel, r_view.origin, ent->mins, ent->maxs))
2182 ent->last_trace_visibility = realtime;
2183 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
2184 r_viewcache.entityvisible[i] = 0;
2191 // no worldmodel or it can't check visibility
2192 for (i = 0;i < r_refdef.numentities;i++)
2194 ent = r_refdef.entities[i];
2195 r_viewcache.entityvisible[i] = !(ent->flags & renderimask) && ((ent->model->type == mod_sprite && (ent->model->sprite.sprnum_type == SPR_LABEL || ent->model->sprite.sprnum_type == SPR_LABEL_SCALE)) || !R_CullBox(ent->mins, ent->maxs));
2199 // update entity lighting (even on hidden entities for r_shadows)
2200 for (i = 0;i < r_refdef.numentities;i++)
2201 R_UpdateEntityLighting(r_refdef.entities[i]);
2204 // only used if skyrendermasked, and normally returns false
2205 int R_DrawBrushModelsSky (void)
2208 entity_render_t *ent;
2210 if (!r_drawentities.integer)
2214 for (i = 0;i < r_refdef.numentities;i++)
2216 if (!r_viewcache.entityvisible[i])
2218 ent = r_refdef.entities[i];
2219 if (!ent->model || !ent->model->DrawSky)
2221 ent->model->DrawSky(ent);
2227 static void R_DrawNoModel(entity_render_t *ent);
2228 static void R_DrawModels(void)
2231 entity_render_t *ent;
2233 if (!r_drawentities.integer)
2236 for (i = 0;i < r_refdef.numentities;i++)
2238 if (!r_viewcache.entityvisible[i])
2240 ent = r_refdef.entities[i];
2241 r_refdef.stats.entities++;
2242 if (ent->model && ent->model->Draw != NULL)
2243 ent->model->Draw(ent);
2249 static void R_DrawModelsDepth(void)
2252 entity_render_t *ent;
2254 if (!r_drawentities.integer)
2257 for (i = 0;i < r_refdef.numentities;i++)
2259 if (!r_viewcache.entityvisible[i])
2261 ent = r_refdef.entities[i];
2262 if (ent->model && ent->model->DrawDepth != NULL)
2263 ent->model->DrawDepth(ent);
2267 static void R_DrawModelsDebug(void)
2270 entity_render_t *ent;
2272 if (!r_drawentities.integer)
2275 for (i = 0;i < r_refdef.numentities;i++)
2277 if (!r_viewcache.entityvisible[i])
2279 ent = r_refdef.entities[i];
2280 if (ent->model && ent->model->DrawDebug != NULL)
2281 ent->model->DrawDebug(ent);
2285 static void R_DrawModelsAddWaterPlanes(void)
2288 entity_render_t *ent;
2290 if (!r_drawentities.integer)
2293 for (i = 0;i < r_refdef.numentities;i++)
2295 if (!r_viewcache.entityvisible[i])
2297 ent = r_refdef.entities[i];
2298 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
2299 ent->model->DrawAddWaterPlanes(ent);
2303 static void R_View_SetFrustum(void)
2306 double slopex, slopey;
2308 // break apart the view matrix into vectors for various purposes
2309 Matrix4x4_ToVectors(&r_view.matrix, r_view.forward, r_view.left, r_view.up, r_view.origin);
2310 VectorNegate(r_view.left, r_view.right);
2313 r_view.frustum[0].normal[0] = 0 - 1.0 / r_view.frustum_x;
2314 r_view.frustum[0].normal[1] = 0 - 0;
2315 r_view.frustum[0].normal[2] = -1 - 0;
2316 r_view.frustum[1].normal[0] = 0 + 1.0 / r_view.frustum_x;
2317 r_view.frustum[1].normal[1] = 0 + 0;
2318 r_view.frustum[1].normal[2] = -1 + 0;
2319 r_view.frustum[2].normal[0] = 0 - 0;
2320 r_view.frustum[2].normal[1] = 0 - 1.0 / r_view.frustum_y;
2321 r_view.frustum[2].normal[2] = -1 - 0;
2322 r_view.frustum[3].normal[0] = 0 + 0;
2323 r_view.frustum[3].normal[1] = 0 + 1.0 / r_view.frustum_y;
2324 r_view.frustum[3].normal[2] = -1 + 0;
2328 zNear = r_refdef.nearclip;
2329 nudge = 1.0 - 1.0 / (1<<23);
2330 r_view.frustum[4].normal[0] = 0 - 0;
2331 r_view.frustum[4].normal[1] = 0 - 0;
2332 r_view.frustum[4].normal[2] = -1 - -nudge;
2333 r_view.frustum[4].dist = 0 - -2 * zNear * nudge;
2334 r_view.frustum[5].normal[0] = 0 + 0;
2335 r_view.frustum[5].normal[1] = 0 + 0;
2336 r_view.frustum[5].normal[2] = -1 + -nudge;
2337 r_view.frustum[5].dist = 0 + -2 * zNear * nudge;
2343 r_view.frustum[0].normal[0] = m[3] - m[0];
2344 r_view.frustum[0].normal[1] = m[7] - m[4];
2345 r_view.frustum[0].normal[2] = m[11] - m[8];
2346 r_view.frustum[0].dist = m[15] - m[12];
2348 r_view.frustum[1].normal[0] = m[3] + m[0];
2349 r_view.frustum[1].normal[1] = m[7] + m[4];
2350 r_view.frustum[1].normal[2] = m[11] + m[8];
2351 r_view.frustum[1].dist = m[15] + m[12];
2353 r_view.frustum[2].normal[0] = m[3] - m[1];
2354 r_view.frustum[2].normal[1] = m[7] - m[5];
2355 r_view.frustum[2].normal[2] = m[11] - m[9];
2356 r_view.frustum[2].dist = m[15] - m[13];
2358 r_view.frustum[3].normal[0] = m[3] + m[1];
2359 r_view.frustum[3].normal[1] = m[7] + m[5];
2360 r_view.frustum[3].normal[2] = m[11] + m[9];
2361 r_view.frustum[3].dist = m[15] + m[13];
2363 r_view.frustum[4].normal[0] = m[3] - m[2];
2364 r_view.frustum[4].normal[1] = m[7] - m[6];
2365 r_view.frustum[4].normal[2] = m[11] - m[10];
2366 r_view.frustum[4].dist = m[15] - m[14];
2368 r_view.frustum[5].normal[0] = m[3] + m[2];
2369 r_view.frustum[5].normal[1] = m[7] + m[6];
2370 r_view.frustum[5].normal[2] = m[11] + m[10];
2371 r_view.frustum[5].dist = m[15] + m[14];
2374 if (r_view.useperspective)
2376 slopex = 1.0 / r_view.frustum_x;
2377 slopey = 1.0 / r_view.frustum_y;
2378 VectorMA(r_view.forward, -slopex, r_view.left, r_view.frustum[0].normal);
2379 VectorMA(r_view.forward, slopex, r_view.left, r_view.frustum[1].normal);
2380 VectorMA(r_view.forward, -slopey, r_view.up , r_view.frustum[2].normal);
2381 VectorMA(r_view.forward, slopey, r_view.up , r_view.frustum[3].normal);
2382 VectorCopy(r_view.forward, r_view.frustum[4].normal);
2384 // Leaving those out was a mistake, those were in the old code, and they
2385 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
2386 // I couldn't reproduce it after adding those normalizations. --blub
2387 VectorNormalize(r_view.frustum[0].normal);
2388 VectorNormalize(r_view.frustum[1].normal);
2389 VectorNormalize(r_view.frustum[2].normal);
2390 VectorNormalize(r_view.frustum[3].normal);
2392 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
2393 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, -1024 * slopex, r_view.left, -1024 * slopey, r_view.up, r_view.frustumcorner[0]);
2394 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, 1024 * slopex, r_view.left, -1024 * slopey, r_view.up, r_view.frustumcorner[1]);
2395 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, -1024 * slopex, r_view.left, 1024 * slopey, r_view.up, r_view.frustumcorner[2]);
2396 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, 1024 * slopex, r_view.left, 1024 * slopey, r_view.up, r_view.frustumcorner[3]);
2398 r_view.frustum[0].dist = DotProduct (r_view.origin, r_view.frustum[0].normal);
2399 r_view.frustum[1].dist = DotProduct (r_view.origin, r_view.frustum[1].normal);
2400 r_view.frustum[2].dist = DotProduct (r_view.origin, r_view.frustum[2].normal);
2401 r_view.frustum[3].dist = DotProduct (r_view.origin, r_view.frustum[3].normal);
2402 r_view.frustum[4].dist = DotProduct (r_view.origin, r_view.frustum[4].normal) + r_refdef.nearclip;
2406 VectorScale(r_view.left, -r_view.ortho_x, r_view.frustum[0].normal);
2407 VectorScale(r_view.left, r_view.ortho_x, r_view.frustum[1].normal);
2408 VectorScale(r_view.up, -r_view.ortho_y, r_view.frustum[2].normal);
2409 VectorScale(r_view.up, r_view.ortho_y, r_view.frustum[3].normal);
2410 VectorCopy(r_view.forward, r_view.frustum[4].normal);
2411 r_view.frustum[0].dist = DotProduct (r_view.origin, r_view.frustum[0].normal) + r_view.ortho_x;
2412 r_view.frustum[1].dist = DotProduct (r_view.origin, r_view.frustum[1].normal) + r_view.ortho_x;
2413 r_view.frustum[2].dist = DotProduct (r_view.origin, r_view.frustum[2].normal) + r_view.ortho_y;
2414 r_view.frustum[3].dist = DotProduct (r_view.origin, r_view.frustum[3].normal) + r_view.ortho_y;
2415 r_view.frustum[4].dist = DotProduct (r_view.origin, r_view.frustum[4].normal) + r_refdef.nearclip;
2417 r_view.numfrustumplanes = 5;
2419 if (r_view.useclipplane)
2421 r_view.numfrustumplanes = 6;
2422 r_view.frustum[5] = r_view.clipplane;
2425 for (i = 0;i < r_view.numfrustumplanes;i++)
2426 PlaneClassify(r_view.frustum + i);
2428 // LordHavoc: note to all quake engine coders, Quake had a special case
2429 // for 90 degrees which assumed a square view (wrong), so I removed it,
2430 // Quake2 has it disabled as well.
2432 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
2433 //RotatePointAroundVector( r_view.frustum[0].normal, r_view.up, r_view.forward, -(90 - r_refdef.fov_x / 2));
2434 //r_view.frustum[0].dist = DotProduct (r_view.origin, frustum[0].normal);
2435 //PlaneClassify(&frustum[0]);
2437 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
2438 //RotatePointAroundVector( r_view.frustum[1].normal, r_view.up, r_view.forward, (90 - r_refdef.fov_x / 2));
2439 //r_view.frustum[1].dist = DotProduct (r_view.origin, frustum[1].normal);
2440 //PlaneClassify(&frustum[1]);
2442 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
2443 //RotatePointAroundVector( r_view.frustum[2].normal, r_view.left, r_view.forward, -(90 - r_refdef.fov_y / 2));
2444 //r_view.frustum[2].dist = DotProduct (r_view.origin, frustum[2].normal);
2445 //PlaneClassify(&frustum[2]);
2447 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
2448 //RotatePointAroundVector( r_view.frustum[3].normal, r_view.left, r_view.forward, (90 - r_refdef.fov_y / 2));
2449 //r_view.frustum[3].dist = DotProduct (r_view.origin, frustum[3].normal);
2450 //PlaneClassify(&frustum[3]);
2453 //VectorCopy(r_view.forward, r_view.frustum[4].normal);
2454 //r_view.frustum[4].dist = DotProduct (r_view.origin, frustum[4].normal) + r_nearclip.value;
2455 //PlaneClassify(&frustum[4]);
2458 void R_View_Update(void)
2460 R_View_SetFrustum();
2461 R_View_WorldVisibility(r_view.useclipplane);
2462 R_View_UpdateEntityVisible();
2465 void R_SetupView(void)
2467 if (!r_view.useperspective)
2468 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);
2469 else if (r_refdef.rtworldshadows || r_refdef.rtdlightshadows)
2470 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_view.frustum_x, r_view.frustum_y, r_refdef.nearclip);
2472 GL_SetupView_Mode_Perspective(r_view.frustum_x, r_view.frustum_y, r_refdef.nearclip, r_refdef.farclip);
2474 GL_SetupView_Orientation_FromEntity(&r_view.matrix);
2476 if (r_view.useclipplane)
2478 // LordHavoc: couldn't figure out how to make this approach the
2479 vec_t dist = r_view.clipplane.dist - r_water_clippingplanebias.value;
2480 vec_t viewdist = DotProduct(r_view.origin, r_view.clipplane.normal);
2481 if (viewdist < r_view.clipplane.dist + r_water_clippingplanebias.value)
2482 dist = r_view.clipplane.dist;
2483 GL_SetupView_ApplyCustomNearClipPlane(r_view.clipplane.normal[0], r_view.clipplane.normal[1], r_view.clipplane.normal[2], dist);
2487 void R_ResetViewRendering2D(void)
2489 if (gl_support_fragment_shader)
2491 qglUseProgramObjectARB(0);CHECKGLERROR
2496 // GL is weird because it's bottom to top, r_view.y is top to bottom
2497 qglViewport(r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
2498 GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
2499 GL_Scissor(r_view.x, r_view.y, r_view.width, r_view.height);
2500 GL_Color(1, 1, 1, 1);
2501 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
2502 GL_BlendFunc(GL_ONE, GL_ZERO);
2503 GL_AlphaTest(false);
2504 GL_ScissorTest(false);
2505 GL_DepthMask(false);
2506 GL_DepthRange(0, 1);
2507 GL_DepthTest(false);
2508 R_Mesh_Matrix(&identitymatrix);
2509 R_Mesh_ResetTextureState();
2510 GL_PolygonOffset(0, 0);
2511 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
2512 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
2513 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
2514 qglStencilMask(~0);CHECKGLERROR
2515 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
2516 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
2517 GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
2520 void R_ResetViewRendering3D(void)
2522 if (gl_support_fragment_shader)
2524 qglUseProgramObjectARB(0);CHECKGLERROR
2529 // GL is weird because it's bottom to top, r_view.y is top to bottom
2530 qglViewport(r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
2532 GL_Scissor(r_view.x, r_view.y, r_view.width, r_view.height);
2533 GL_Color(1, 1, 1, 1);
2534 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
2535 GL_BlendFunc(GL_ONE, GL_ZERO);
2536 GL_AlphaTest(false);
2537 GL_ScissorTest(true);
2539 GL_DepthRange(0, 1);
2541 R_Mesh_Matrix(&identitymatrix);
2542 R_Mesh_ResetTextureState();
2543 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
2544 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
2545 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
2546 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
2547 qglStencilMask(~0);CHECKGLERROR
2548 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
2549 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
2550 GL_CullFace(r_view.cullface_back);
2554 R_Bloom_SetupShader(
2556 "// written by Forest 'LordHavoc' Hale\n"
2558 "// common definitions between vertex shader and fragment shader:\n"
2560 "#ifdef __GLSL_CG_DATA_TYPES\n"
2561 "#define myhalf half\n"
2562 "#define myhvec2 hvec2\n"
2563 "#define myhvec3 hvec3\n"
2564 "#define myhvec4 hvec4\n"
2566 "#define myhalf float\n"
2567 "#define myhvec2 vec2\n"
2568 "#define myhvec3 vec3\n"
2569 "#define myhvec4 vec4\n"
2572 "varying vec2 ScreenTexCoord;\n"
2573 "varying vec2 BloomTexCoord;\n"
2578 "// vertex shader specific:\n"
2579 "#ifdef VERTEX_SHADER\n"
2583 " ScreenTexCoord = vec2(gl_MultiTexCoord0);\n"
2584 " BloomTexCoord = vec2(gl_MultiTexCoord1);\n"
2585 " // transform vertex to camera space, using ftransform to match non-VS\n"
2587 " gl_Position = ftransform();\n"
2590 "#endif // VERTEX_SHADER\n"
2595 "// fragment shader specific:\n"
2596 "#ifdef FRAGMENT_SHADER\n"
2601 " myhvec3 color = myhvec3(texture2D(Texture_Screen, ScreenTexCoord));\n"
2602 " for (x = -BLUR_X;x <= BLUR_X;x++)
2603 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2604 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2605 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2606 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2608 " gl_FragColor = vec4(color);\n"
2611 "#endif // FRAGMENT_SHADER\n"
2614 void R_RenderScene(qboolean addwaterplanes);
2616 static void R_Water_StartFrame(void)
2619 int waterwidth, waterheight, texturewidth, textureheight;
2620 r_waterstate_waterplane_t *p;
2622 // set waterwidth and waterheight to the water resolution that will be
2623 // used (often less than the screen resolution for faster rendering)
2624 waterwidth = (int)bound(1, r_view.width * r_water_resolutionmultiplier.value, r_view.width);
2625 waterheight = (int)bound(1, r_view.height * r_water_resolutionmultiplier.value, r_view.height);
2627 // calculate desired texture sizes
2628 // can't use water if the card does not support the texture size
2629 if (!r_water.integer || !r_glsl.integer || !gl_support_fragment_shader || waterwidth > gl_max_texture_size || waterheight > gl_max_texture_size)
2630 texturewidth = textureheight = waterwidth = waterheight = 0;
2631 else if (gl_support_arb_texture_non_power_of_two)
2633 texturewidth = waterwidth;
2634 textureheight = waterheight;
2638 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
2639 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
2642 // allocate textures as needed
2643 if (r_waterstate.waterwidth != waterwidth || r_waterstate.waterheight != waterheight || r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight)
2645 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
2646 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
2648 if (p->texture_refraction)
2649 R_FreeTexture(p->texture_refraction);
2650 p->texture_refraction = NULL;
2651 if (p->texture_reflection)
2652 R_FreeTexture(p->texture_reflection);
2653 p->texture_reflection = NULL;
2655 memset(&r_waterstate, 0, sizeof(r_waterstate));
2656 r_waterstate.waterwidth = waterwidth;
2657 r_waterstate.waterheight = waterheight;
2658 r_waterstate.texturewidth = texturewidth;
2659 r_waterstate.textureheight = textureheight;
2662 if (r_waterstate.waterwidth)
2664 r_waterstate.enabled = true;
2666 // set up variables that will be used in shader setup
2667 r_waterstate.screenscale[0] = 0.5f * (float)waterwidth / (float)texturewidth;
2668 r_waterstate.screenscale[1] = 0.5f * (float)waterheight / (float)textureheight;
2669 r_waterstate.screencenter[0] = 0.5f * (float)waterwidth / (float)texturewidth;
2670 r_waterstate.screencenter[1] = 0.5f * (float)waterheight / (float)textureheight;
2673 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
2674 r_waterstate.numwaterplanes = 0;
2677 static void R_Water_AddWaterPlane(msurface_t *surface)
2679 int triangleindex, planeindex;
2685 r_waterstate_waterplane_t *p;
2686 // just use the first triangle with a valid normal for any decisions
2687 VectorClear(normal);
2688 VectorClear(center);
2689 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
2691 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
2692 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
2693 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
2694 TriangleNormal(vert[0], vert[1], vert[2], normal);
2695 if (VectorLength2(normal) >= 0.001)
2698 // now find the center of this surface
2699 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles*3;triangleindex++, e++)
2701 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
2702 VectorAdd(center, vert[0], center);
2704 f = 1.0 / surface->num_triangles*3;
2705 VectorScale(center, f, center);
2707 // find a matching plane if there is one
2708 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
2709 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
2711 if (planeindex >= r_waterstate.maxwaterplanes)
2712 return; // nothing we can do, out of planes
2714 // if this triangle does not fit any known plane rendered this frame, add one
2715 if (planeindex >= r_waterstate.numwaterplanes)
2717 // store the new plane
2718 r_waterstate.numwaterplanes++;
2719 VectorCopy(normal, p->plane.normal);
2720 VectorNormalize(p->plane.normal);
2721 p->plane.dist = DotProduct(vert[0], p->plane.normal);
2722 PlaneClassify(&p->plane);
2723 // flip the plane if it does not face the viewer
2724 if (PlaneDiff(r_view.origin, &p->plane) < 0)
2726 VectorNegate(p->plane.normal, p->plane.normal);
2727 p->plane.dist *= -1;
2728 PlaneClassify(&p->plane);
2730 // clear materialflags and pvs
2731 p->materialflags = 0;
2732 p->pvsvalid = false;
2734 // merge this surface's materialflags into the waterplane
2735 p->materialflags |= surface->texture->currentframe->currentmaterialflags;
2736 // merge this surface's PVS into the waterplane
2737 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.worldmodel && r_refdef.worldmodel->brush.FatPVS)
2739 r_refdef.worldmodel->brush.FatPVS(r_refdef.worldmodel, r_view.origin, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
2744 static void R_Water_ProcessPlanes(void)
2746 r_view_t originalview;
2748 r_waterstate_waterplane_t *p;
2750 originalview = r_view;
2752 // make sure enough textures are allocated
2753 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
2755 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
2757 if (!p->texture_refraction)
2758 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);
2759 if (!p->texture_refraction)
2763 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
2765 if (!p->texture_reflection)
2766 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);
2767 if (!p->texture_reflection)
2773 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
2775 r_view.showdebug = false;
2776 r_view.width = r_waterstate.waterwidth;
2777 r_view.height = r_waterstate.waterheight;
2778 r_view.useclipplane = true;
2779 r_waterstate.renderingscene = true;
2781 // render the normal view scene and copy into texture
2782 // (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)
2783 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
2785 r_view.clipplane = p->plane;
2786 VectorNegate(r_view.clipplane.normal, r_view.clipplane.normal);
2787 r_view.clipplane.dist = -r_view.clipplane.dist;
2788 PlaneClassify(&r_view.clipplane);
2790 R_RenderScene(false);
2792 // copy view into the screen texture
2793 R_Mesh_TexBind(0, R_GetTexture(p->texture_refraction));
2794 GL_ActiveTexture(0);
2796 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
2799 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
2801 // render reflected scene and copy into texture
2802 Matrix4x4_Reflect(&r_view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
2803 r_view.clipplane = p->plane;
2804 // reverse the cullface settings for this render
2805 r_view.cullface_front = GL_FRONT;
2806 r_view.cullface_back = GL_BACK;
2807 if (r_refdef.worldmodel && r_refdef.worldmodel->brush.num_pvsclusterbytes)
2809 r_view.usecustompvs = true;
2811 memcpy(r_viewcache.world_pvsbits, p->pvsbits, r_refdef.worldmodel->brush.num_pvsclusterbytes);
2813 memset(r_viewcache.world_pvsbits, 0xFF, r_refdef.worldmodel->brush.num_pvsclusterbytes);
2816 R_ResetViewRendering3D();
2818 if (r_timereport_active)
2819 R_TimeReport("viewclear");
2821 R_RenderScene(false);
2823 R_Mesh_TexBind(0, R_GetTexture(p->texture_reflection));
2824 GL_ActiveTexture(0);
2826 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
2828 R_ResetViewRendering3D();
2830 if (r_timereport_active)
2831 R_TimeReport("viewclear");
2834 r_view = originalview;
2835 r_view.clear = true;
2836 r_waterstate.renderingscene = false;
2840 r_view = originalview;
2841 r_waterstate.renderingscene = false;
2842 Cvar_SetValueQuick(&r_water, 0);
2843 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
2847 void R_Bloom_StartFrame(void)
2849 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
2851 // set bloomwidth and bloomheight to the bloom resolution that will be
2852 // used (often less than the screen resolution for faster rendering)
2853 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_view.width);
2854 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_view.height / r_view.width;
2855 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_view.height);
2857 // calculate desired texture sizes
2858 if (gl_support_arb_texture_non_power_of_two)
2860 screentexturewidth = r_view.width;
2861 screentextureheight = r_view.height;
2862 bloomtexturewidth = r_bloomstate.bloomwidth;
2863 bloomtextureheight = r_bloomstate.bloomheight;
2867 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
2868 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
2869 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
2870 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
2875 screentexturewidth = screentextureheight = 0;
2877 else if (r_bloom.integer)
2882 screentexturewidth = screentextureheight = 0;
2883 bloomtexturewidth = bloomtextureheight = 0;
2886 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)
2888 // can't use bloom if the parameters are too weird
2889 // can't use bloom if the card does not support the texture size
2890 if (r_bloomstate.texture_screen)
2891 R_FreeTexture(r_bloomstate.texture_screen);
2892 if (r_bloomstate.texture_bloom)
2893 R_FreeTexture(r_bloomstate.texture_bloom);
2894 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
2898 r_bloomstate.enabled = true;
2899 r_bloomstate.hdr = r_hdr.integer != 0;
2901 // allocate textures as needed
2902 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
2904 if (r_bloomstate.texture_screen)
2905 R_FreeTexture(r_bloomstate.texture_screen);
2906 r_bloomstate.texture_screen = NULL;
2907 r_bloomstate.screentexturewidth = screentexturewidth;
2908 r_bloomstate.screentextureheight = screentextureheight;
2909 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
2910 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);
2912 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
2914 if (r_bloomstate.texture_bloom)
2915 R_FreeTexture(r_bloomstate.texture_bloom);
2916 r_bloomstate.texture_bloom = NULL;
2917 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
2918 r_bloomstate.bloomtextureheight = bloomtextureheight;
2919 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
2920 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);
2923 // set up a texcoord array for the full resolution screen image
2924 // (we have to keep this around to copy back during final render)
2925 r_bloomstate.screentexcoord2f[0] = 0;
2926 r_bloomstate.screentexcoord2f[1] = (float)r_view.height / (float)r_bloomstate.screentextureheight;
2927 r_bloomstate.screentexcoord2f[2] = (float)r_view.width / (float)r_bloomstate.screentexturewidth;
2928 r_bloomstate.screentexcoord2f[3] = (float)r_view.height / (float)r_bloomstate.screentextureheight;
2929 r_bloomstate.screentexcoord2f[4] = (float)r_view.width / (float)r_bloomstate.screentexturewidth;
2930 r_bloomstate.screentexcoord2f[5] = 0;
2931 r_bloomstate.screentexcoord2f[6] = 0;
2932 r_bloomstate.screentexcoord2f[7] = 0;
2934 // set up a texcoord array for the reduced resolution bloom image
2935 // (which will be additive blended over the screen image)
2936 r_bloomstate.bloomtexcoord2f[0] = 0;
2937 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
2938 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
2939 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
2940 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
2941 r_bloomstate.bloomtexcoord2f[5] = 0;
2942 r_bloomstate.bloomtexcoord2f[6] = 0;
2943 r_bloomstate.bloomtexcoord2f[7] = 0;
2946 void R_Bloom_CopyScreenTexture(float colorscale)
2948 r_refdef.stats.bloom++;
2950 R_ResetViewRendering2D();
2951 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
2952 R_Mesh_ColorPointer(NULL, 0, 0);
2953 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
2954 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
2956 // copy view into the screen texture
2957 GL_ActiveTexture(0);
2959 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
2960 r_refdef.stats.bloom_copypixels += r_view.width * r_view.height;
2962 // now scale it down to the bloom texture size
2964 qglViewport(r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
2965 GL_BlendFunc(GL_ONE, GL_ZERO);
2966 GL_Color(colorscale, colorscale, colorscale, 1);
2967 // TODO: optimize with multitexture or GLSL
2968 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2969 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2971 // we now have a bloom image in the framebuffer
2972 // copy it into the bloom image texture for later processing
2973 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
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 void R_Bloom_CopyHDRTexture(void)
2982 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2983 GL_ActiveTexture(0);
2985 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
2986 r_refdef.stats.bloom_copypixels += r_view.width * r_view.height;
2989 void R_Bloom_MakeTexture(void)
2992 float xoffset, yoffset, r, brighten;
2994 r_refdef.stats.bloom++;
2996 R_ResetViewRendering2D();
2997 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
2998 R_Mesh_ColorPointer(NULL, 0, 0);
3000 // we have a bloom image in the framebuffer
3002 qglViewport(r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
3004 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
3007 r = bound(0, r_bloom_colorexponent.value / x, 1);
3008 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
3009 GL_Color(r, r, r, 1);
3010 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3011 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3012 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3013 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3015 // copy the vertically blurred bloom view to a texture
3016 GL_ActiveTexture(0);
3018 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
3019 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3022 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
3023 brighten = r_bloom_brighten.value;
3025 brighten *= r_hdr_range.value;
3026 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3027 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
3029 for (dir = 0;dir < 2;dir++)
3031 // blend on at multiple vertical offsets to achieve a vertical blur
3032 // TODO: do offset blends using GLSL
3033 GL_BlendFunc(GL_ONE, GL_ZERO);
3034 for (x = -range;x <= range;x++)
3036 if (!dir){xoffset = 0;yoffset = x;}
3037 else {xoffset = x;yoffset = 0;}
3038 xoffset /= (float)r_bloomstate.bloomtexturewidth;
3039 yoffset /= (float)r_bloomstate.bloomtextureheight;
3040 // compute a texcoord array with the specified x and y offset
3041 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
3042 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3043 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3044 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3045 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3046 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
3047 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
3048 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
3049 // this r value looks like a 'dot' particle, fading sharply to
3050 // black at the edges
3051 // (probably not realistic but looks good enough)
3052 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
3053 //r = (dir ? 1.0f : brighten)/(range*2+1);
3054 r = (dir ? 1.0f : brighten)/(range*2+1)*(1 - x*x/(float)(range*range));
3055 GL_Color(r, r, r, 1);
3056 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3057 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3058 GL_BlendFunc(GL_ONE, GL_ONE);
3061 // copy the vertically blurred bloom view to a texture
3062 GL_ActiveTexture(0);
3064 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
3065 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3068 // apply subtract last
3069 // (just like it would be in a GLSL shader)
3070 if (r_bloom_colorsubtract.value > 0 && gl_support_ext_blend_subtract)
3072 GL_BlendFunc(GL_ONE, GL_ZERO);
3073 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3074 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3075 GL_Color(1, 1, 1, 1);
3076 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3077 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3079 GL_BlendFunc(GL_ONE, GL_ONE);
3080 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
3081 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
3082 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3083 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
3084 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3085 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3086 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
3088 // copy the darkened bloom view to a texture
3089 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3090 GL_ActiveTexture(0);
3092 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
3093 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3097 void R_HDR_RenderBloomTexture(void)
3099 int oldwidth, oldheight;
3101 oldwidth = r_view.width;
3102 oldheight = r_view.height;
3103 r_view.width = r_bloomstate.bloomwidth;
3104 r_view.height = r_bloomstate.bloomheight;
3106 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
3107 // TODO: add exposure compensation features
3108 // TODO: add fp16 framebuffer support
3110 r_view.showdebug = false;
3111 r_view.colorscale = r_bloom_colorscale.value * r_hdr_scenebrightness.value;
3113 r_view.colorscale /= r_hdr_range.value;
3114 r_waterstate.numwaterplanes = 0;
3115 R_RenderScene(r_waterstate.enabled);
3116 r_view.showdebug = true;
3118 R_ResetViewRendering2D();
3120 R_Bloom_CopyHDRTexture();
3121 R_Bloom_MakeTexture();
3123 R_ResetViewRendering3D();
3126 if (r_timereport_active)
3127 R_TimeReport("viewclear");
3129 // restore the view settings
3130 r_view.width = oldwidth;
3131 r_view.height = oldheight;
3134 static void R_BlendView(void)
3136 if (r_bloomstate.enabled && r_bloomstate.hdr)
3138 // render high dynamic range bloom effect
3139 // the bloom texture was made earlier this render, so we just need to
3140 // blend it onto the screen...
3141 R_ResetViewRendering2D();
3142 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3143 R_Mesh_ColorPointer(NULL, 0, 0);
3144 GL_Color(1, 1, 1, 1);
3145 GL_BlendFunc(GL_ONE, GL_ONE);
3146 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3147 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3148 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3149 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
3151 else if (r_bloomstate.enabled)
3153 // render simple bloom effect
3154 // copy the screen and shrink it and darken it for the bloom process
3155 R_Bloom_CopyScreenTexture(r_bloom_colorscale.value);
3156 // make the bloom texture
3157 R_Bloom_MakeTexture();
3158 // put the original screen image back in place and blend the bloom
3160 R_ResetViewRendering2D();
3161 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3162 R_Mesh_ColorPointer(NULL, 0, 0);
3163 GL_Color(1, 1, 1, 1);
3164 GL_BlendFunc(GL_ONE, GL_ZERO);
3165 // do both in one pass if possible
3166 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3167 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3168 if (r_textureunits.integer >= 2 && gl_combine.integer)
3170 R_Mesh_TexCombine(1, GL_ADD, GL_ADD, 1, 1);
3171 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_screen));
3172 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.screentexcoord2f, 0, 0);
3176 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3177 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
3178 // now blend on the bloom texture
3179 GL_BlendFunc(GL_ONE, GL_ONE);
3180 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
3181 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
3183 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3184 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
3186 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
3188 // apply a color tint to the whole view
3189 R_ResetViewRendering2D();
3190 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3191 R_Mesh_ColorPointer(NULL, 0, 0);
3192 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3193 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
3194 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3198 void R_RenderScene(qboolean addwaterplanes);
3200 matrix4x4_t r_waterscrollmatrix;
3202 void R_UpdateVariables(void)
3206 r_refdef.farclip = 4096;
3207 if (r_refdef.worldmodel)
3208 r_refdef.farclip += VectorDistance(r_refdef.worldmodel->normalmins, r_refdef.worldmodel->normalmaxs);
3209 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
3211 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
3212 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
3213 r_refdef.polygonfactor = 0;
3214 r_refdef.polygonoffset = 0;
3215 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
3216 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
3218 r_refdef.rtworld = r_shadow_realtime_world.integer;
3219 r_refdef.rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
3220 r_refdef.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
3221 r_refdef.rtdlightshadows = r_refdef.rtdlight && r_shadow_realtime_dlight_shadows.integer && gl_stencil;
3222 r_refdef.lightmapintensity = r_refdef.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
3223 if (r_showsurfaces.integer)
3225 r_refdef.rtworld = false;
3226 r_refdef.rtworldshadows = false;
3227 r_refdef.rtdlight = false;
3228 r_refdef.rtdlightshadows = false;
3229 r_refdef.lightmapintensity = 0;
3232 if (gamemode == GAME_NEHAHRA)
3234 if (gl_fogenable.integer)
3236 r_refdef.oldgl_fogenable = true;
3237 r_refdef.fog_density = gl_fogdensity.value;
3238 r_refdef.fog_red = gl_fogred.value;
3239 r_refdef.fog_green = gl_foggreen.value;
3240 r_refdef.fog_blue = gl_fogblue.value;
3242 else if (r_refdef.oldgl_fogenable)
3244 r_refdef.oldgl_fogenable = false;
3245 r_refdef.fog_density = 0;
3246 r_refdef.fog_red = 0;
3247 r_refdef.fog_green = 0;
3248 r_refdef.fog_blue = 0;
3251 if (r_refdef.fog_density)
3253 r_refdef.fogcolor[0] = bound(0.0f, r_refdef.fog_red , 1.0f);
3254 r_refdef.fogcolor[1] = bound(0.0f, r_refdef.fog_green, 1.0f);
3255 r_refdef.fogcolor[2] = bound(0.0f, r_refdef.fog_blue , 1.0f);
3257 if (r_refdef.fog_density)
3259 r_refdef.fogenabled = true;
3260 // this is the point where the fog reaches 0.9986 alpha, which we
3261 // consider a good enough cutoff point for the texture
3262 // (0.9986 * 256 == 255.6)
3263 r_refdef.fogrange = 400 / r_refdef.fog_density;
3264 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
3265 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
3266 // fog color was already set
3269 r_refdef.fogenabled = false;
3277 void R_RenderView(void)
3279 if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
3280 return; //Host_Error ("R_RenderView: NULL worldmodel");
3282 R_Shadow_UpdateWorldLightSelection();
3284 R_Bloom_StartFrame();
3285 R_Water_StartFrame();
3288 if (r_timereport_active)
3289 R_TimeReport("viewsetup");
3291 R_ResetViewRendering3D();
3296 if (r_timereport_active)
3297 R_TimeReport("viewclear");
3299 r_view.clear = true;
3301 r_view.showdebug = true;
3303 // this produces a bloom texture to be used in R_BlendView() later
3305 R_HDR_RenderBloomTexture();
3307 r_view.colorscale = r_hdr_scenebrightness.value;
3308 r_waterstate.numwaterplanes = 0;
3309 R_RenderScene(r_waterstate.enabled);
3312 if (r_timereport_active)
3313 R_TimeReport("blendview");
3315 GL_Scissor(0, 0, vid.width, vid.height);
3316 GL_ScissorTest(false);
3320 extern void R_DrawLightningBeams (void);
3321 extern void VM_CL_AddPolygonsToMeshQueue (void);
3322 extern void R_DrawPortals (void);
3323 extern cvar_t cl_locs_show;
3324 static void R_DrawLocs(void);
3325 static void R_DrawEntityBBoxes(void);
3326 void R_RenderScene(qboolean addwaterplanes)
3330 R_ResetViewRendering3D();
3333 if (r_timereport_active)
3334 R_TimeReport("watervis");
3336 if (cl.csqc_vidvars.drawworld && r_refdef.worldmodel && r_refdef.worldmodel->DrawAddWaterPlanes)
3338 r_refdef.worldmodel->DrawAddWaterPlanes(r_refdef.worldentity);
3339 if (r_timereport_active)
3340 R_TimeReport("waterworld");
3343 // don't let sound skip if going slow
3344 if (r_refdef.extraupdate)
3347 R_DrawModelsAddWaterPlanes();
3348 if (r_timereport_active)
3349 R_TimeReport("watermodels");
3351 R_Water_ProcessPlanes();
3352 if (r_timereport_active)
3353 R_TimeReport("waterscenes");
3356 R_ResetViewRendering3D();
3358 // don't let sound skip if going slow
3359 if (r_refdef.extraupdate)
3362 R_MeshQueue_BeginScene();
3367 if (r_timereport_active)
3368 R_TimeReport("visibility");
3370 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);
3372 if (cl.csqc_vidvars.drawworld)
3374 // don't let sound skip if going slow
3375 if (r_refdef.extraupdate)
3378 if (r_refdef.worldmodel && r_refdef.worldmodel->DrawSky)
3380 r_refdef.worldmodel->DrawSky(r_refdef.worldentity);
3381 if (r_timereport_active)
3382 R_TimeReport("worldsky");
3385 if (R_DrawBrushModelsSky() && r_timereport_active)
3386 R_TimeReport("bmodelsky");
3389 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.worldmodel && r_refdef.worldmodel->DrawDepth)
3391 r_refdef.worldmodel->DrawDepth(r_refdef.worldentity);
3392 if (r_timereport_active)
3393 R_TimeReport("worlddepth");
3395 if (r_depthfirst.integer >= 2)
3397 R_DrawModelsDepth();
3398 if (r_timereport_active)
3399 R_TimeReport("modeldepth");
3402 if (cl.csqc_vidvars.drawworld && r_refdef.worldmodel && r_refdef.worldmodel->Draw)
3404 r_refdef.worldmodel->Draw(r_refdef.worldentity);
3405 if (r_timereport_active)
3406 R_TimeReport("world");
3409 // don't let sound skip if going slow
3410 if (r_refdef.extraupdate)
3414 if (r_timereport_active)
3415 R_TimeReport("models");
3417 // don't let sound skip if going slow
3418 if (r_refdef.extraupdate)
3421 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
3423 R_DrawModelShadows();
3425 R_ResetViewRendering3D();
3427 // don't let sound skip if going slow
3428 if (r_refdef.extraupdate)
3432 R_ShadowVolumeLighting(false);
3433 if (r_timereport_active)
3434 R_TimeReport("rtlights");
3436 // don't let sound skip if going slow
3437 if (r_refdef.extraupdate)
3440 if (cl.csqc_vidvars.drawworld)
3442 R_DrawLightningBeams();
3443 if (r_timereport_active)
3444 R_TimeReport("lightning");
3447 if (r_timereport_active)
3448 R_TimeReport("decals");
3451 if (r_timereport_active)
3452 R_TimeReport("particles");
3455 if (r_timereport_active)
3456 R_TimeReport("explosions");
3459 if (gl_support_fragment_shader)
3461 qglUseProgramObjectARB(0);CHECKGLERROR
3463 VM_CL_AddPolygonsToMeshQueue();
3465 if (r_view.showdebug)
3467 if (cl_locs_show.integer)
3470 if (r_timereport_active)
3471 R_TimeReport("showlocs");
3474 if (r_drawportals.integer)
3477 if (r_timereport_active)
3478 R_TimeReport("portals");
3481 if (r_showbboxes.value > 0)
3483 R_DrawEntityBBoxes();
3484 if (r_timereport_active)
3485 R_TimeReport("bboxes");
3489 if (gl_support_fragment_shader)
3491 qglUseProgramObjectARB(0);CHECKGLERROR
3493 R_MeshQueue_RenderTransparent();
3494 if (r_timereport_active)
3495 R_TimeReport("drawtrans");
3497 if (gl_support_fragment_shader)
3499 qglUseProgramObjectARB(0);CHECKGLERROR
3502 if (r_view.showdebug && r_refdef.worldmodel && r_refdef.worldmodel->DrawDebug && (r_showtris.value > 0 || r_shownormals.value > 0 || r_showcollisionbrushes.value > 0))
3504 r_refdef.worldmodel->DrawDebug(r_refdef.worldentity);
3505 if (r_timereport_active)
3506 R_TimeReport("worlddebug");
3507 R_DrawModelsDebug();
3508 if (r_timereport_active)
3509 R_TimeReport("modeldebug");
3512 if (gl_support_fragment_shader)
3514 qglUseProgramObjectARB(0);CHECKGLERROR
3517 if (cl.csqc_vidvars.drawworld)
3520 if (r_timereport_active)
3521 R_TimeReport("coronas");
3524 // don't let sound skip if going slow
3525 if (r_refdef.extraupdate)
3528 R_ResetViewRendering2D();
3531 static const int bboxelements[36] =
3541 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
3544 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
3545 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3546 GL_DepthMask(false);
3547 GL_DepthRange(0, 1);
3548 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3549 R_Mesh_Matrix(&identitymatrix);
3550 R_Mesh_ResetTextureState();
3552 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
3553 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
3554 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
3555 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
3556 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
3557 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
3558 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
3559 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
3560 R_FillColors(color4f, 8, cr, cg, cb, ca);
3561 if (r_refdef.fogenabled)
3563 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
3565 f1 = FogPoint_World(v);
3567 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
3568 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
3569 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
3572 R_Mesh_VertexPointer(vertex3f, 0, 0);
3573 R_Mesh_ColorPointer(color4f, 0, 0);
3574 R_Mesh_ResetTextureState();
3575 R_Mesh_Draw(0, 8, 12, bboxelements, 0, 0);
3578 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
3582 prvm_edict_t *edict;
3583 // this function draws bounding boxes of server entities
3587 for (i = 0;i < numsurfaces;i++)
3589 edict = PRVM_EDICT_NUM(surfacelist[i]);
3590 switch ((int)edict->fields.server->solid)
3592 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
3593 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
3594 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
3595 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
3596 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
3597 default: Vector4Set(color, 0, 0, 0, 0.50);break;
3599 color[3] *= r_showbboxes.value;
3600 color[3] = bound(0, color[3], 1);
3601 GL_DepthTest(!r_showdisabledepthtest.integer);
3602 GL_CullFace(r_view.cullface_front);
3603 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
3608 static void R_DrawEntityBBoxes(void)
3611 prvm_edict_t *edict;
3613 // this function draws bounding boxes of server entities
3617 for (i = 0;i < prog->num_edicts;i++)
3619 edict = PRVM_EDICT_NUM(i);
3620 if (edict->priv.server->free)
3622 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
3623 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
3628 int nomodelelements[24] =
3640 float nomodelvertex3f[6*3] =
3650 float nomodelcolor4f[6*4] =
3652 0.0f, 0.0f, 0.5f, 1.0f,
3653 0.0f, 0.0f, 0.5f, 1.0f,
3654 0.0f, 0.5f, 0.0f, 1.0f,
3655 0.0f, 0.5f, 0.0f, 1.0f,
3656 0.5f, 0.0f, 0.0f, 1.0f,
3657 0.5f, 0.0f, 0.0f, 1.0f
3660 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
3665 // this is only called once per entity so numsurfaces is always 1, and
3666 // surfacelist is always {0}, so this code does not handle batches
3667 R_Mesh_Matrix(&ent->matrix);
3669 if (ent->flags & EF_ADDITIVE)
3671 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
3672 GL_DepthMask(false);
3674 else if (ent->alpha < 1)
3676 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3677 GL_DepthMask(false);
3681 GL_BlendFunc(GL_ONE, GL_ZERO);
3684 GL_DepthRange(0, (ent->flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
3685 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3686 GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
3687 GL_CullFace((ent->effects & EF_DOUBLESIDED) ? GL_NONE : r_view.cullface_back);
3688 R_Mesh_VertexPointer(nomodelvertex3f, 0, 0);
3689 if (r_refdef.fogenabled)
3692 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
3693 R_Mesh_ColorPointer(color4f, 0, 0);
3694 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
3695 f1 = FogPoint_World(org);
3697 for (i = 0, c = color4f;i < 6;i++, c += 4)
3699 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
3700 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
3701 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
3705 else if (ent->alpha != 1)
3707 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
3708 R_Mesh_ColorPointer(color4f, 0, 0);
3709 for (i = 0, c = color4f;i < 6;i++, c += 4)
3713 R_Mesh_ColorPointer(nomodelcolor4f, 0, 0);
3714 R_Mesh_ResetTextureState();
3715 R_Mesh_Draw(0, 6, 8, nomodelelements, 0, 0);
3718 void R_DrawNoModel(entity_render_t *ent)
3721 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
3722 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
3723 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
3725 // R_DrawNoModelCallback(ent, 0);
3728 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
3730 vec3_t right1, right2, diff, normal;
3732 VectorSubtract (org2, org1, normal);
3734 // calculate 'right' vector for start
3735 VectorSubtract (r_view.origin, org1, diff);
3736 CrossProduct (normal, diff, right1);
3737 VectorNormalize (right1);
3739 // calculate 'right' vector for end
3740 VectorSubtract (r_view.origin, org2, diff);
3741 CrossProduct (normal, diff, right2);
3742 VectorNormalize (right2);
3744 vert[ 0] = org1[0] + width * right1[0];
3745 vert[ 1] = org1[1] + width * right1[1];
3746 vert[ 2] = org1[2] + width * right1[2];
3747 vert[ 3] = org1[0] - width * right1[0];
3748 vert[ 4] = org1[1] - width * right1[1];
3749 vert[ 5] = org1[2] - width * right1[2];
3750 vert[ 6] = org2[0] - width * right2[0];
3751 vert[ 7] = org2[1] - width * right2[1];
3752 vert[ 8] = org2[2] - width * right2[2];
3753 vert[ 9] = org2[0] + width * right2[0];
3754 vert[10] = org2[1] + width * right2[1];
3755 vert[11] = org2[2] + width * right2[2];
3758 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
3760 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)
3765 if (r_refdef.fogenabled)
3766 fog = FogPoint_World(origin);
3768 R_Mesh_Matrix(&identitymatrix);
3769 GL_BlendFunc(blendfunc1, blendfunc2);
3775 GL_CullFace(r_view.cullface_front);
3778 GL_CullFace(r_view.cullface_back);
3780 GL_DepthMask(false);
3781 GL_DepthRange(0, depthshort ? 0.0625 : 1);
3782 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3783 GL_DepthTest(!depthdisable);
3785 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
3786 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
3787 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
3788 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
3789 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
3790 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
3791 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
3792 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
3793 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
3794 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
3795 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
3796 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
3798 R_Mesh_VertexPointer(vertex3f, 0, 0);
3799 R_Mesh_ColorPointer(NULL, 0, 0);
3800 R_Mesh_ResetTextureState();
3801 R_Mesh_TexBind(0, R_GetTexture(texture));
3802 R_Mesh_TexCoordPointer(0, 2, spritetexcoord2f, 0, 0);
3803 // FIXME: fixed function path can't properly handle r_view.colorscale > 1
3804 GL_Color(cr * fog * r_view.colorscale, cg * fog * r_view.colorscale, cb * fog * r_view.colorscale, ca);
3805 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3807 if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
3809 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
3810 GL_BlendFunc(blendfunc1, GL_ONE);
3812 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);
3813 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3817 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
3822 VectorSet(v, x, y, z);
3823 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
3824 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
3826 if (i == mesh->numvertices)
3828 if (mesh->numvertices < mesh->maxvertices)
3830 VectorCopy(v, vertex3f);
3831 mesh->numvertices++;
3833 return mesh->numvertices;
3839 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
3843 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
3844 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
3845 e = mesh->element3i + mesh->numtriangles * 3;
3846 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
3848 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
3849 if (mesh->numtriangles < mesh->maxtriangles)
3854 mesh->numtriangles++;
3856 element[1] = element[2];
3860 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
3864 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
3865 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
3866 e = mesh->element3i + mesh->numtriangles * 3;
3867 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
3869 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
3870 if (mesh->numtriangles < mesh->maxtriangles)
3875 mesh->numtriangles++;
3877 element[1] = element[2];
3881 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
3882 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
3884 int planenum, planenum2;
3887 mplane_t *plane, *plane2;
3889 double temppoints[2][256*3];
3890 // figure out how large a bounding box we need to properly compute this brush
3892 for (w = 0;w < numplanes;w++)
3893 maxdist = max(maxdist, planes[w].dist);
3894 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
3895 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
3896 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
3900 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
3901 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
3903 if (planenum2 == planenum)
3905 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);
3908 if (tempnumpoints < 3)
3910 // generate elements forming a triangle fan for this polygon
3911 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
3915 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)
3917 texturelayer_t *layer;
3918 layer = t->currentlayers + t->currentnumlayers++;
3920 layer->depthmask = depthmask;
3921 layer->blendfunc1 = blendfunc1;
3922 layer->blendfunc2 = blendfunc2;
3923 layer->texture = texture;
3924 layer->texmatrix = *matrix;
3925 layer->color[0] = r * r_view.colorscale;
3926 layer->color[1] = g * r_view.colorscale;
3927 layer->color[2] = b * r_view.colorscale;
3928 layer->color[3] = a;
3931 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
3934 index = parms[2] + r_refdef.time * parms[3];
3935 index -= floor(index);
3939 case Q3WAVEFUNC_NONE:
3940 case Q3WAVEFUNC_NOISE:
3941 case Q3WAVEFUNC_COUNT:
3944 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
3945 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
3946 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
3947 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
3948 case Q3WAVEFUNC_TRIANGLE:
3950 f = index - floor(index);
3961 return (float)(parms[0] + parms[1] * f);
3964 void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
3967 model_t *model = ent->model;
3970 q3shaderinfo_layer_tcmod_t *tcmod;
3972 // switch to an alternate material if this is a q1bsp animated material
3974 texture_t *texture = t;
3975 int s = ent->skinnum;
3976 if ((unsigned int)s >= (unsigned int)model->numskins)
3978 if (model->skinscenes)
3980 if (model->skinscenes[s].framecount > 1)
3981 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
3983 s = model->skinscenes[s].firstframe;
3986 t = t + s * model->num_surfaces;
3989 // use an alternate animation if the entity's frame is not 0,
3990 // and only if the texture has an alternate animation
3991 if (ent->frame2 != 0 && t->anim_total[1])
3992 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.time * 5.0f) % t->anim_total[1]) : 0];
3994 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.time * 5.0f) % t->anim_total[0]) : 0];
3996 texture->currentframe = t;
3999 // update currentskinframe to be a qw skin or animation frame
4000 if ((i = ent->entitynumber - 1) >= 0 && i < cl.maxclients)
4002 if (strcmp(r_qwskincache[i], cl.scores[i].qw_skin))
4004 strlcpy(r_qwskincache[i], cl.scores[i].qw_skin, sizeof(r_qwskincache[i]));
4005 Con_DPrintf("loading skins/%s\n", r_qwskincache[i]);
4006 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);
4008 t->currentskinframe = r_qwskincache_skinframe[i];
4009 if (t->currentskinframe == NULL)
4010 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->frame2time)) % t->numskinframes];
4012 else if (t->numskinframes >= 2)
4013 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->frame2time)) % t->numskinframes];
4014 if (t->backgroundnumskinframes >= 2)
4015 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - ent->frame2time)) % t->backgroundnumskinframes];
4017 t->currentmaterialflags = t->basematerialflags;
4018 t->currentalpha = ent->alpha;
4019 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
4021 t->currentalpha *= r_wateralpha.value;
4023 * FIXME what is this supposed to do?
4024 // if rendering refraction/reflection, disable transparency
4025 if (r_waterstate.enabled && (t->currentalpha < 1 || (t->currentmaterialflags & MATERIALFLAG_ALPHA)))
4026 t->currentmaterialflags |= MATERIALFLAG_WATERSHADER;
4029 if(!r_waterstate.enabled)
4030 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION);
4031 if (!(ent->flags & RENDER_LIGHT))
4032 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
4033 else if (rsurface.modeltexcoordlightmap2f == NULL)
4035 // pick a model lighting mode
4036 if (VectorLength2(ent->modellight_diffuse) >= (1.0f / 256.0f))
4037 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
4039 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
4041 if (ent->effects & EF_ADDITIVE)
4042 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
4043 else if (t->currentalpha < 1)
4044 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
4045 if (ent->effects & EF_DOUBLESIDED)
4046 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
4047 if (ent->effects & EF_NODEPTHTEST)
4048 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
4049 if (ent->flags & RENDER_VIEWMODEL)
4050 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
4051 if (t->backgroundnumskinframes && !(t->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED))
4052 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
4054 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && (tcmod->tcmod || i < 1);i++, tcmod++)
4057 switch(tcmod->tcmod)
4061 if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
4062 matrix = r_waterscrollmatrix;
4064 matrix = identitymatrix;
4066 case Q3TCMOD_ENTITYTRANSLATE:
4067 // this is used in Q3 to allow the gamecode to control texcoord
4068 // scrolling on the entity, which is not supported in darkplaces yet.
4069 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
4071 case Q3TCMOD_ROTATE:
4072 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
4073 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.time, 0, 0, 1);
4074 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
4077 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
4079 case Q3TCMOD_SCROLL:
4080 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.time, tcmod->parms[1] * r_refdef.time, 0);
4082 case Q3TCMOD_STRETCH:
4083 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
4084 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
4086 case Q3TCMOD_TRANSFORM:
4087 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
4088 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
4089 VectorSet(tcmat + 6, 0 , 0 , 1);
4090 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
4091 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
4093 case Q3TCMOD_TURBULENT:
4094 // this is handled in the RSurf_PrepareVertices function
4095 matrix = identitymatrix;
4098 // either replace or concatenate the transformation
4100 t->currenttexmatrix = matrix;
4103 matrix4x4_t temp = t->currenttexmatrix;
4104 Matrix4x4_Concat(&t->currenttexmatrix, &matrix, &temp);
4108 t->colormapping = VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f);
4109 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
4110 t->glosstexture = r_texture_black;
4111 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
4112 t->backgroundglosstexture = r_texture_black;
4113 t->specularpower = r_shadow_glossexponent.value;
4114 // TODO: store reference values for these in the texture?
4115 t->specularscale = 0;
4116 if (r_shadow_gloss.integer > 0)
4118 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
4120 if (r_shadow_glossintensity.value > 0)
4122 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
4123 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
4124 t->specularscale = r_shadow_glossintensity.value;
4127 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
4129 t->glosstexture = r_texture_white;
4130 t->backgroundglosstexture = r_texture_white;
4131 t->specularscale = r_shadow_gloss2intensity.value;
4135 // lightmaps mode looks bad with dlights using actual texturing, so turn
4136 // off the colormap and glossmap, but leave the normalmap on as it still
4137 // accurately represents the shading involved
4138 if (gl_lightmaps.integer && !(t->currentmaterialflags & MATERIALFLAG_BLENDED))
4140 t->basetexture = r_texture_white;
4141 t->specularscale = 0;
4144 t->currentpolygonfactor = r_refdef.polygonfactor + t->basepolygonfactor;
4145 t->currentpolygonoffset = r_refdef.polygonoffset + t->basepolygonoffset;
4146 // submodels are biased to avoid z-fighting with world surfaces that they
4147 // may be exactly overlapping (avoids z-fighting artifacts on certain
4148 // doors and things in Quake maps)
4149 if (ent->model->brush.submodel)
4151 t->currentpolygonfactor += r_polygonoffset_submodel_factor.value;
4152 t->currentpolygonoffset += r_polygonoffset_submodel_offset.value;
4155 VectorClear(t->dlightcolor);
4156 t->currentnumlayers = 0;
4157 if (!(t->currentmaterialflags & MATERIALFLAG_NODRAW))
4159 if (!(t->currentmaterialflags & MATERIALFLAG_SKY))
4161 int blendfunc1, blendfunc2, depthmask;
4162 if (t->currentmaterialflags & MATERIALFLAG_ADD)
4164 blendfunc1 = GL_SRC_ALPHA;
4165 blendfunc2 = GL_ONE;
4167 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
4169 blendfunc1 = GL_SRC_ALPHA;
4170 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
4172 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
4174 blendfunc1 = t->customblendfunc[0];
4175 blendfunc2 = t->customblendfunc[1];
4179 blendfunc1 = GL_ONE;
4180 blendfunc2 = GL_ZERO;
4182 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
4183 if (t->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL))
4185 rtexture_t *currentbasetexture;
4187 if (r_refdef.fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED))
4188 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
4189 currentbasetexture = (VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) < (1.0f / 1048576.0f) && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
4190 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
4192 // fullbright is not affected by r_refdef.lightmapintensity
4193 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
4194 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
4195 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);
4196 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
4197 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);
4202 // set the color tint used for lights affecting this surface
4203 VectorSet(t->dlightcolor, ent->colormod[0] * t->currentalpha, ent->colormod[1] * t->currentalpha, ent->colormod[2] * t->currentalpha);
4205 // q3bsp has no lightmap updates, so the lightstylevalue that
4206 // would normally be baked into the lightmap must be
4207 // applied to the color
4208 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
4209 if (ent->model->type == mod_brushq3)
4210 colorscale *= r_refdef.lightstylevalue[0] * (1.0f / 256.0f);
4211 colorscale *= r_refdef.lightmapintensity;
4212 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);
4213 if (r_ambient.value >= (1.0f/64.0f))
4214 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);
4215 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
4217 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);
4218 if (r_ambient.value >= (1.0f/64.0f))
4219 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);
4221 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
4223 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);
4224 if (r_ambient.value >= (1.0f/64.0f))
4225 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);
4228 if (t->currentskinframe->glow != NULL)
4229 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);
4230 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
4232 // if this is opaque use alpha blend which will darken the earlier
4235 // if this is an alpha blended material, all the earlier passes
4236 // were darkened by fog already, so we only need to add the fog
4237 // color ontop through the fog mask texture
4239 // if this is an additive blended material, all the earlier passes
4240 // were darkened by fog already, and we should not add fog color
4241 // (because the background was not darkened, there is no fog color
4242 // that was lost behind it).
4243 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);
4250 void R_UpdateAllTextureInfo(entity_render_t *ent)
4254 for (i = 0;i < ent->model->num_texturesperskin;i++)
4255 R_UpdateTextureInfo(ent, ent->model->data_textures + i);
4258 rsurfacestate_t rsurface;
4260 void R_Mesh_ResizeArrays(int newvertices)
4263 if (rsurface.array_size >= newvertices)
4265 if (rsurface.array_modelvertex3f)
4266 Mem_Free(rsurface.array_modelvertex3f);
4267 rsurface.array_size = (newvertices + 1023) & ~1023;
4268 base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
4269 rsurface.array_modelvertex3f = base + rsurface.array_size * 0;
4270 rsurface.array_modelsvector3f = base + rsurface.array_size * 3;
4271 rsurface.array_modeltvector3f = base + rsurface.array_size * 6;
4272 rsurface.array_modelnormal3f = base + rsurface.array_size * 9;
4273 rsurface.array_deformedvertex3f = base + rsurface.array_size * 12;
4274 rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
4275 rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
4276 rsurface.array_deformednormal3f = base + rsurface.array_size * 21;
4277 rsurface.array_texcoord3f = base + rsurface.array_size * 24;
4278 rsurface.array_color4f = base + rsurface.array_size * 27;
4279 rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
4282 void RSurf_CleanUp(void)
4285 if (rsurface.mode == RSURFMODE_GLSL)
4287 qglUseProgramObjectARB(0);CHECKGLERROR
4289 GL_AlphaTest(false);
4290 rsurface.mode = RSURFMODE_NONE;
4291 rsurface.uselightmaptexture = false;
4292 rsurface.texture = NULL;
4295 void RSurf_ActiveWorldEntity(void)
4297 model_t *model = r_refdef.worldmodel;
4299 if (rsurface.array_size < model->surfmesh.num_vertices)
4300 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
4301 rsurface.matrix = identitymatrix;
4302 rsurface.inversematrix = identitymatrix;
4303 R_Mesh_Matrix(&identitymatrix);
4304 VectorCopy(r_view.origin, rsurface.modelorg);
4305 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
4306 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
4307 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
4308 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
4309 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
4310 rsurface.frameblend[0].frame = 0;
4311 rsurface.frameblend[0].lerp = 1;
4312 rsurface.frameblend[1].frame = 0;
4313 rsurface.frameblend[1].lerp = 0;
4314 rsurface.frameblend[2].frame = 0;
4315 rsurface.frameblend[2].lerp = 0;
4316 rsurface.frameblend[3].frame = 0;
4317 rsurface.frameblend[3].lerp = 0;
4318 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
4319 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
4320 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
4321 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
4322 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
4323 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
4324 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
4325 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
4326 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
4327 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
4328 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
4329 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
4330 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
4331 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
4332 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
4333 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
4334 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
4335 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
4336 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
4337 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
4338 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
4339 rsurface.modelelement3i = model->surfmesh.data_element3i;
4340 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo;
4341 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
4342 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
4343 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
4344 rsurface.modelsurfaces = model->data_surfaces;
4345 rsurface.generatedvertex = false;
4346 rsurface.vertex3f = rsurface.modelvertex3f;
4347 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
4348 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
4349 rsurface.svector3f = rsurface.modelsvector3f;
4350 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
4351 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
4352 rsurface.tvector3f = rsurface.modeltvector3f;
4353 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
4354 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
4355 rsurface.normal3f = rsurface.modelnormal3f;
4356 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
4357 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
4358 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
4361 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4363 model_t *model = ent->model;
4365 if (rsurface.array_size < model->surfmesh.num_vertices)
4366 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
4367 rsurface.matrix = ent->matrix;
4368 rsurface.inversematrix = ent->inversematrix;
4369 R_Mesh_Matrix(&rsurface.matrix);
4370 Matrix4x4_Transform(&rsurface.inversematrix, r_view.origin, rsurface.modelorg);
4371 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
4372 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
4373 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
4374 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
4375 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
4376 rsurface.frameblend[0] = ent->frameblend[0];
4377 rsurface.frameblend[1] = ent->frameblend[1];
4378 rsurface.frameblend[2] = ent->frameblend[2];
4379 rsurface.frameblend[3] = ent->frameblend[3];
4380 if (model->surfmesh.isanimated && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].frame != 0))
4384 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
4385 rsurface.modelsvector3f = rsurface.array_modelsvector3f;
4386 rsurface.modeltvector3f = rsurface.array_modeltvector3f;
4387 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
4388 Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
4390 else if (wantnormals)
4392 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
4393 rsurface.modelsvector3f = NULL;
4394 rsurface.modeltvector3f = NULL;
4395 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
4396 Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
4400 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
4401 rsurface.modelsvector3f = NULL;
4402 rsurface.modeltvector3f = NULL;
4403 rsurface.modelnormal3f = NULL;
4404 Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, NULL, NULL, NULL);
4406 rsurface.modelvertex3f_bufferobject = 0;
4407 rsurface.modelvertex3f_bufferoffset = 0;
4408 rsurface.modelsvector3f_bufferobject = 0;
4409 rsurface.modelsvector3f_bufferoffset = 0;
4410 rsurface.modeltvector3f_bufferobject = 0;
4411 rsurface.modeltvector3f_bufferoffset = 0;
4412 rsurface.modelnormal3f_bufferobject = 0;
4413 rsurface.modelnormal3f_bufferoffset = 0;
4414 rsurface.generatedvertex = true;
4418 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
4419 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
4420 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
4421 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
4422 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
4423 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
4424 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
4425 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
4426 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
4427 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
4428 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
4429 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
4430 rsurface.generatedvertex = false;
4432 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
4433 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
4434 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
4435 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
4436 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
4437 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
4438 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
4439 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
4440 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
4441 rsurface.modelelement3i = model->surfmesh.data_element3i;
4442 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo;
4443 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
4444 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
4445 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
4446 rsurface.modelsurfaces = model->data_surfaces;
4447 rsurface.vertex3f = rsurface.modelvertex3f;
4448 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
4449 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
4450 rsurface.svector3f = rsurface.modelsvector3f;
4451 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
4452 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
4453 rsurface.tvector3f = rsurface.modeltvector3f;
4454 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
4455 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
4456 rsurface.normal3f = rsurface.modelnormal3f;
4457 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
4458 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
4459 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
4462 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
4463 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, msurface_t **texturesurfacelist)
4466 int texturesurfaceindex;
4471 const float *v1, *in_tc;
4473 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
4475 q3shaderinfo_deform_t *deform;
4476 // 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
4477 if (rsurface.generatedvertex)
4479 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
4480 generatenormals = true;
4481 for (i = 0;i < Q3MAXDEFORMS;i++)
4483 if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
4485 generatetangents = true;
4486 generatenormals = true;
4488 if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
4489 generatenormals = true;
4491 if (generatenormals && !rsurface.modelnormal3f)
4493 rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
4494 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
4495 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
4496 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer);
4498 if (generatetangents && !rsurface.modelsvector3f)
4500 rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
4501 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
4502 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
4503 rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
4504 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
4505 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
4506 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);
4509 rsurface.vertex3f = rsurface.modelvertex3f;
4510 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
4511 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
4512 rsurface.svector3f = rsurface.modelsvector3f;
4513 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
4514 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
4515 rsurface.tvector3f = rsurface.modeltvector3f;
4516 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
4517 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
4518 rsurface.normal3f = rsurface.modelnormal3f;
4519 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
4520 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
4521 // if vertices are deformed (sprite flares and things in maps, possibly
4522 // water waves, bulges and other deformations), generate them into
4523 // rsurface.deform* arrays from whatever the rsurface.* arrays point to
4524 // (may be static model data or generated data for an animated model, or
4525 // the previous deform pass)
4526 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
4528 switch (deform->deform)
4531 case Q3DEFORM_PROJECTIONSHADOW:
4532 case Q3DEFORM_TEXT0:
4533 case Q3DEFORM_TEXT1:
4534 case Q3DEFORM_TEXT2:
4535 case Q3DEFORM_TEXT3:
4536 case Q3DEFORM_TEXT4:
4537 case Q3DEFORM_TEXT5:
4538 case Q3DEFORM_TEXT6:
4539 case Q3DEFORM_TEXT7:
4542 case Q3DEFORM_AUTOSPRITE:
4543 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.forward, newforward);
4544 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.right, newright);
4545 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.up, newup);
4546 VectorNormalize(newforward);
4547 VectorNormalize(newright);
4548 VectorNormalize(newup);
4549 // make deformed versions of only the model vertices used by the specified surfaces
4550 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4552 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4553 // a single autosprite surface can contain multiple sprites...
4554 for (j = 0;j < surface->num_vertices - 3;j += 4)
4556 VectorClear(center);
4557 for (i = 0;i < 4;i++)
4558 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
4559 VectorScale(center, 0.25f, center);
4560 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, forward);
4561 VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
4562 VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
4563 for (i = 0;i < 4;i++)
4565 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
4566 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
4569 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);
4570 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);
4572 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4573 rsurface.vertex3f_bufferobject = 0;
4574 rsurface.vertex3f_bufferoffset = 0;
4575 rsurface.svector3f = rsurface.array_deformedsvector3f;
4576 rsurface.svector3f_bufferobject = 0;
4577 rsurface.svector3f_bufferoffset = 0;
4578 rsurface.tvector3f = rsurface.array_deformedtvector3f;
4579 rsurface.tvector3f_bufferobject = 0;
4580 rsurface.tvector3f_bufferoffset = 0;
4581 rsurface.normal3f = rsurface.array_deformednormal3f;
4582 rsurface.normal3f_bufferobject = 0;
4583 rsurface.normal3f_bufferoffset = 0;
4585 case Q3DEFORM_AUTOSPRITE2:
4586 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.forward, newforward);
4587 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.right, newright);
4588 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.up, newup);
4589 VectorNormalize(newforward);
4590 VectorNormalize(newright);
4591 VectorNormalize(newup);
4592 // make deformed versions of only the model vertices used by the specified surfaces
4593 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4595 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4596 const float *v1, *v2;
4606 memset(shortest, 0, sizeof(shortest));
4607 // a single autosprite surface can contain multiple sprites...
4608 for (j = 0;j < surface->num_vertices - 3;j += 4)
4610 VectorClear(center);
4611 for (i = 0;i < 4;i++)
4612 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
4613 VectorScale(center, 0.25f, center);
4614 // find the two shortest edges, then use them to define the
4615 // axis vectors for rotating around the central axis
4616 for (i = 0;i < 6;i++)
4618 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
4619 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
4621 Debug_PolygonBegin(NULL, 0, false, 0);
4622 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
4623 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);
4624 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
4627 l = VectorDistance2(v1, v2);
4628 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
4630 l += (1.0f / 1024.0f);
4631 if (shortest[0].length2 > l || i == 0)
4633 shortest[1] = shortest[0];
4634 shortest[0].length2 = l;
4635 shortest[0].v1 = v1;
4636 shortest[0].v2 = v2;
4638 else if (shortest[1].length2 > l || i == 1)
4640 shortest[1].length2 = l;
4641 shortest[1].v1 = v1;
4642 shortest[1].v2 = v2;
4645 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
4646 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
4648 Debug_PolygonBegin(NULL, 0, false, 0);
4649 Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
4650 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);
4651 Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
4654 // this calculates the right vector from the shortest edge
4655 // and the up vector from the edge midpoints
4656 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
4657 VectorNormalize(right);
4658 VectorSubtract(end, start, up);
4659 VectorNormalize(up);
4660 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
4661 //VectorSubtract(rsurface.modelorg, center, forward);
4662 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.forward, forward);
4663 VectorNegate(forward, forward);
4664 VectorReflect(forward, 0, up, forward);
4665 VectorNormalize(forward);
4666 CrossProduct(up, forward, newright);
4667 VectorNormalize(newright);
4669 Debug_PolygonBegin(NULL, 0, false, 0);
4670 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);
4671 Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
4672 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
4676 Debug_PolygonBegin(NULL, 0, false, 0);
4677 Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
4678 Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
4679 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
4682 // rotate the quad around the up axis vector, this is made
4683 // especially easy by the fact we know the quad is flat,
4684 // so we only have to subtract the center position and
4685 // measure distance along the right vector, and then
4686 // multiply that by the newright vector and add back the
4688 // we also need to subtract the old position to undo the
4689 // displacement from the center, which we do with a
4690 // DotProduct, the subtraction/addition of center is also
4691 // optimized into DotProducts here
4692 l = DotProduct(right, center);
4693 for (i = 0;i < 4;i++)
4695 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
4696 f = DotProduct(right, v1) - l;
4697 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
4700 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);
4701 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);
4703 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4704 rsurface.vertex3f_bufferobject = 0;
4705 rsurface.vertex3f_bufferoffset = 0;
4706 rsurface.svector3f = rsurface.array_deformedsvector3f;
4707 rsurface.svector3f_bufferobject = 0;
4708 rsurface.svector3f_bufferoffset = 0;
4709 rsurface.tvector3f = rsurface.array_deformedtvector3f;
4710 rsurface.tvector3f_bufferobject = 0;
4711 rsurface.tvector3f_bufferoffset = 0;
4712 rsurface.normal3f = rsurface.array_deformednormal3f;
4713 rsurface.normal3f_bufferobject = 0;
4714 rsurface.normal3f_bufferoffset = 0;
4716 case Q3DEFORM_NORMAL:
4717 // deform the normals to make reflections wavey
4718 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4720 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4721 for (j = 0;j < surface->num_vertices;j++)
4724 float *normal = (rsurface.array_deformednormal3f + 3 * surface->num_firstvertex) + j*3;
4725 VectorScale((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
4726 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, normal);
4727 normal[0] += deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.time * deform->parms[1]);
4728 normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.time * deform->parms[1]);
4729 normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.time * deform->parms[1]);
4730 VectorNormalize(normal);
4732 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);
4734 rsurface.svector3f = rsurface.array_deformedsvector3f;
4735 rsurface.svector3f_bufferobject = 0;
4736 rsurface.svector3f_bufferoffset = 0;
4737 rsurface.tvector3f = rsurface.array_deformedtvector3f;
4738 rsurface.tvector3f_bufferobject = 0;
4739 rsurface.tvector3f_bufferoffset = 0;
4740 rsurface.normal3f = rsurface.array_deformednormal3f;
4741 rsurface.normal3f_bufferobject = 0;
4742 rsurface.normal3f_bufferoffset = 0;
4745 // deform vertex array to make wavey water and flags and such
4746 waveparms[0] = deform->waveparms[0];
4747 waveparms[1] = deform->waveparms[1];
4748 waveparms[2] = deform->waveparms[2];
4749 waveparms[3] = deform->waveparms[3];
4750 // this is how a divisor of vertex influence on deformation
4751 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
4752 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
4753 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4755 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4756 for (j = 0;j < surface->num_vertices;j++)
4758 float *vertex = (rsurface.array_deformedvertex3f + 3 * surface->num_firstvertex) + j*3;
4759 VectorCopy((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, vertex);
4760 // if the wavefunc depends on time, evaluate it per-vertex
4763 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
4764 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
4766 VectorMA(vertex, scale, (rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, vertex);
4769 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4770 rsurface.vertex3f_bufferobject = 0;
4771 rsurface.vertex3f_bufferoffset = 0;
4773 case Q3DEFORM_BULGE:
4774 // deform vertex array to make the surface have moving bulges
4775 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4777 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4778 for (j = 0;j < surface->num_vertices;j++)
4780 scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.time * deform->parms[2])) * deform->parms[1];
4781 VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
4784 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4785 rsurface.vertex3f_bufferobject = 0;
4786 rsurface.vertex3f_bufferoffset = 0;
4789 // deform vertex array
4790 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
4791 VectorScale(deform->parms, scale, waveparms);
4792 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4794 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4795 for (j = 0;j < surface->num_vertices;j++)
4796 VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
4798 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4799 rsurface.vertex3f_bufferobject = 0;
4800 rsurface.vertex3f_bufferoffset = 0;
4804 // generate texcoords based on the chosen texcoord source
4805 switch(rsurface.texture->tcgen.tcgen)
4808 case Q3TCGEN_TEXTURE:
4809 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
4810 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordtexture2f_bufferobject;
4811 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
4813 case Q3TCGEN_LIGHTMAP:
4814 rsurface.texcoordtexture2f = rsurface.modeltexcoordlightmap2f;
4815 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
4816 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
4818 case Q3TCGEN_VECTOR:
4819 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4821 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4822 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)
4824 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
4825 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
4828 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
4829 rsurface.texcoordtexture2f_bufferobject = 0;
4830 rsurface.texcoordtexture2f_bufferoffset = 0;
4832 case Q3TCGEN_ENVIRONMENT:
4833 // make environment reflections using a spheremap
4834 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4836 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4837 const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
4838 const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
4839 float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
4840 for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
4842 float l, d, eyedir[3];
4843 VectorSubtract(rsurface.modelorg, vertex, eyedir);
4844 l = 0.5f / VectorLength(eyedir);
4845 d = DotProduct(normal, eyedir)*2;
4846 out_tc[0] = 0.5f + (normal[1]*d - eyedir[1])*l;
4847 out_tc[1] = 0.5f - (normal[2]*d - eyedir[2])*l;
4850 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
4851 rsurface.texcoordtexture2f_bufferobject = 0;
4852 rsurface.texcoordtexture2f_bufferoffset = 0;
4855 // the only tcmod that needs software vertex processing is turbulent, so
4856 // check for it here and apply the changes if needed
4857 // and we only support that as the first one
4858 // (handling a mixture of turbulent and other tcmods would be problematic
4859 // without punting it entirely to a software path)
4860 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
4862 amplitude = rsurface.texture->tcmods[0].parms[1];
4863 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.time * rsurface.texture->tcmods[0].parms[3];
4864 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4866 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4867 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)
4869 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
4870 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
4873 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
4874 rsurface.texcoordtexture2f_bufferobject = 0;
4875 rsurface.texcoordtexture2f_bufferoffset = 0;
4877 rsurface.texcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
4878 rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
4879 rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
4880 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
4883 void RSurf_DrawBatch_Simple(int texturenumsurfaces, msurface_t **texturesurfacelist)
4886 const msurface_t *surface = texturesurfacelist[0];
4887 const msurface_t *surface2;
4892 // TODO: lock all array ranges before render, rather than on each surface
4893 if (texturenumsurfaces == 1)
4895 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
4896 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));
4898 else if (r_batchmode.integer == 2)
4900 #define MAXBATCHTRIANGLES 4096
4901 int batchtriangles = 0;
4902 int batchelements[MAXBATCHTRIANGLES*3];
4903 for (i = 0;i < texturenumsurfaces;i = j)
4905 surface = texturesurfacelist[i];
4907 if (surface->num_triangles > MAXBATCHTRIANGLES)
4909 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));
4912 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
4913 batchtriangles = surface->num_triangles;
4914 firstvertex = surface->num_firstvertex;
4915 endvertex = surface->num_firstvertex + surface->num_vertices;
4916 for (;j < texturenumsurfaces;j++)
4918 surface2 = texturesurfacelist[j];
4919 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
4921 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
4922 batchtriangles += surface2->num_triangles;
4923 firstvertex = min(firstvertex, surface2->num_firstvertex);
4924 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
4926 surface2 = texturesurfacelist[j-1];
4927 numvertices = endvertex - firstvertex;
4928 R_Mesh_Draw(firstvertex, numvertices, batchtriangles, batchelements, 0, 0);
4931 else if (r_batchmode.integer == 1)
4933 for (i = 0;i < texturenumsurfaces;i = j)
4935 surface = texturesurfacelist[i];
4936 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
4937 if (texturesurfacelist[j] != surface2)
4939 surface2 = texturesurfacelist[j-1];
4940 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
4941 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
4942 GL_LockArrays(surface->num_firstvertex, numvertices);
4943 R_Mesh_Draw(surface->num_firstvertex, numvertices, numtriangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
4948 for (i = 0;i < texturenumsurfaces;i++)
4950 surface = texturesurfacelist[i];
4951 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
4952 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));
4957 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit, int refractiontexunit, int reflectiontexunit)
4959 int i, planeindex, vertexindex;
4963 r_waterstate_waterplane_t *p, *bestp;
4964 msurface_t *surface;
4965 if (r_waterstate.renderingscene)
4967 for (i = 0;i < texturenumsurfaces;i++)
4969 surface = texturesurfacelist[i];
4970 if (lightmaptexunit >= 0)
4971 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
4972 if (deluxemaptexunit >= 0)
4973 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
4974 // pick the closest matching water plane
4977 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
4980 for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
4982 Matrix4x4_Transform(&rsurface.matrix, v, vert);
4983 d += fabs(PlaneDiff(vert, &p->plane));
4985 if (bestd > d || !bestp)
4993 if (refractiontexunit >= 0)
4994 R_Mesh_TexBind(refractiontexunit, R_GetTexture(bestp->texture_refraction));
4995 if (reflectiontexunit >= 0)
4996 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(bestp->texture_reflection));
5000 if (refractiontexunit >= 0)
5001 R_Mesh_TexBind(refractiontexunit, R_GetTexture(r_texture_black));
5002 if (reflectiontexunit >= 0)
5003 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(r_texture_black));
5005 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5006 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));
5010 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit)
5014 const msurface_t *surface = texturesurfacelist[0];
5015 const msurface_t *surface2;
5020 // TODO: lock all array ranges before render, rather than on each surface
5021 if (texturenumsurfaces == 1)
5023 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5024 if (deluxemaptexunit >= 0)
5025 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5026 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5027 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));
5029 else if (r_batchmode.integer == 2)
5031 #define MAXBATCHTRIANGLES 4096
5032 int batchtriangles = 0;
5033 int batchelements[MAXBATCHTRIANGLES*3];
5034 for (i = 0;i < texturenumsurfaces;i = j)
5036 surface = texturesurfacelist[i];
5037 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5038 if (deluxemaptexunit >= 0)
5039 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5041 if (surface->num_triangles > MAXBATCHTRIANGLES)
5043 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));
5046 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
5047 batchtriangles = surface->num_triangles;
5048 firstvertex = surface->num_firstvertex;
5049 endvertex = surface->num_firstvertex + surface->num_vertices;
5050 for (;j < texturenumsurfaces;j++)
5052 surface2 = texturesurfacelist[j];
5053 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
5055 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
5056 batchtriangles += surface2->num_triangles;
5057 firstvertex = min(firstvertex, surface2->num_firstvertex);
5058 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
5060 surface2 = texturesurfacelist[j-1];
5061 numvertices = endvertex - firstvertex;
5062 R_Mesh_Draw(firstvertex, numvertices, batchtriangles, batchelements, 0, 0);
5065 else if (r_batchmode.integer == 1)
5068 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
5069 for (i = 0;i < texturenumsurfaces;i = j)
5071 surface = texturesurfacelist[i];
5072 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
5073 if (texturesurfacelist[j] != surface2)
5075 Con_Printf(" %i", j - i);
5078 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
5080 for (i = 0;i < texturenumsurfaces;i = j)
5082 surface = texturesurfacelist[i];
5083 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5084 if (deluxemaptexunit >= 0)
5085 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5086 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
5087 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
5090 Con_Printf(" %i", j - i);
5092 surface2 = texturesurfacelist[j-1];
5093 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
5094 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
5095 GL_LockArrays(surface->num_firstvertex, numvertices);
5096 R_Mesh_Draw(surface->num_firstvertex, numvertices, numtriangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
5104 for (i = 0;i < texturenumsurfaces;i++)
5106 surface = texturesurfacelist[i];
5107 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5108 if (deluxemaptexunit >= 0)
5109 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5110 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5111 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));
5116 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
5119 int texturesurfaceindex;
5120 if (r_showsurfaces.integer == 2)
5122 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5124 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5125 for (j = 0;j < surface->num_triangles;j++)
5127 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_view.colorscale;
5128 GL_Color(f, f, f, 1);
5129 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)));
5135 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5137 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5138 int k = (int)(((size_t)surface) / sizeof(msurface_t));
5139 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);
5140 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5141 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));
5146 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, msurface_t **texturesurfacelist)
5148 int texturesurfaceindex;
5152 if (rsurface.lightmapcolor4f)
5154 // generate color arrays for the surfaces in this list
5155 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5157 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5158 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)
5160 f = FogPoint_Model(v);
5170 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5172 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5173 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)
5175 f = FogPoint_Model(v);
5183 rsurface.lightmapcolor4f = rsurface.array_color4f;
5184 rsurface.lightmapcolor4f_bufferobject = 0;
5185 rsurface.lightmapcolor4f_bufferoffset = 0;
5188 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a)
5190 int texturesurfaceindex;
5193 if (!rsurface.lightmapcolor4f)
5195 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5197 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5198 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)
5206 rsurface.lightmapcolor4f = rsurface.array_color4f;
5207 rsurface.lightmapcolor4f_bufferobject = 0;
5208 rsurface.lightmapcolor4f_bufferoffset = 0;
5211 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5214 rsurface.lightmapcolor4f = NULL;
5215 rsurface.lightmapcolor4f_bufferobject = 0;
5216 rsurface.lightmapcolor4f_bufferoffset = 0;
5217 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5218 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5219 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5220 GL_Color(r, g, b, a);
5221 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 0, -1);
5224 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5226 // TODO: optimize applyfog && applycolor case
5227 // just apply fog if necessary, and tint the fog color array if necessary
5228 rsurface.lightmapcolor4f = NULL;
5229 rsurface.lightmapcolor4f_bufferobject = 0;
5230 rsurface.lightmapcolor4f_bufferoffset = 0;
5231 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5232 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5233 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5234 GL_Color(r, g, b, a);
5235 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5238 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5240 int texturesurfaceindex;
5244 if (texturesurfacelist[0]->lightmapinfo && texturesurfacelist[0]->lightmapinfo->stainsamples)
5246 // generate color arrays for the surfaces in this list
5247 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5249 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5250 for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
5252 if (surface->lightmapinfo->samples)
5254 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
5255 float scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
5256 VectorScale(lm, scale, c);
5257 if (surface->lightmapinfo->styles[1] != 255)
5259 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
5261 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
5262 VectorMA(c, scale, lm, c);
5263 if (surface->lightmapinfo->styles[2] != 255)
5266 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
5267 VectorMA(c, scale, lm, c);
5268 if (surface->lightmapinfo->styles[3] != 255)
5271 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
5272 VectorMA(c, scale, lm, c);
5282 rsurface.lightmapcolor4f = rsurface.array_color4f;
5283 rsurface.lightmapcolor4f_bufferobject = 0;
5284 rsurface.lightmapcolor4f_bufferoffset = 0;
5288 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
5289 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
5290 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
5292 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5293 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5294 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5295 GL_Color(r, g, b, a);
5296 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5299 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5301 int texturesurfaceindex;
5305 vec3_t ambientcolor;
5306 vec3_t diffusecolor;
5310 VectorCopy(rsurface.modellight_lightdir, lightdir);
5311 ambientcolor[0] = rsurface.modellight_ambient[0] * r * 0.5f;
5312 ambientcolor[1] = rsurface.modellight_ambient[1] * g * 0.5f;
5313 ambientcolor[2] = rsurface.modellight_ambient[2] * b * 0.5f;
5314 diffusecolor[0] = rsurface.modellight_diffuse[0] * r * 0.5f;
5315 diffusecolor[1] = rsurface.modellight_diffuse[1] * g * 0.5f;
5316 diffusecolor[2] = rsurface.modellight_diffuse[2] * b * 0.5f;
5317 if (VectorLength2(diffusecolor) > 0)
5319 // generate color arrays for the surfaces in this list
5320 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5322 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5323 int numverts = surface->num_vertices;
5324 v = rsurface.vertex3f + 3 * surface->num_firstvertex;
5325 c2 = rsurface.normal3f + 3 * surface->num_firstvertex;
5326 c = rsurface.array_color4f + 4 * surface->num_firstvertex;
5327 // q3-style directional shading
5328 for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
5330 if ((f = DotProduct(c2, lightdir)) > 0)
5331 VectorMA(ambientcolor, f, diffusecolor, c);
5333 VectorCopy(ambientcolor, c);
5342 rsurface.lightmapcolor4f = rsurface.array_color4f;
5343 rsurface.lightmapcolor4f_bufferobject = 0;
5344 rsurface.lightmapcolor4f_bufferoffset = 0;
5348 r = ambientcolor[0];
5349 g = ambientcolor[1];
5350 b = ambientcolor[2];
5351 rsurface.lightmapcolor4f = NULL;
5352 rsurface.lightmapcolor4f_bufferobject = 0;
5353 rsurface.lightmapcolor4f_bufferoffset = 0;
5355 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5356 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5357 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5358 GL_Color(r, g, b, a);
5359 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5362 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
5364 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5365 GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset);
5366 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
5367 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_view.cullface_back);
5368 if (rsurface.mode != RSURFMODE_SHOWSURFACES)
5370 rsurface.mode = RSURFMODE_SHOWSURFACES;
5372 GL_BlendFunc(GL_ONE, GL_ZERO);
5373 R_Mesh_ColorPointer(NULL, 0, 0);
5374 R_Mesh_ResetTextureState();
5376 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
5377 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
5380 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, msurface_t **texturesurfacelist)
5382 // transparent sky would be ridiculous
5383 if ((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED))
5385 if (rsurface.mode != RSURFMODE_SKY)
5387 if (rsurface.mode == RSURFMODE_GLSL)
5389 qglUseProgramObjectARB(0);CHECKGLERROR
5391 rsurface.mode = RSURFMODE_SKY;
5395 skyrendernow = false;
5397 // restore entity matrix
5398 R_Mesh_Matrix(&rsurface.matrix);
5400 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5401 GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset);
5402 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
5403 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_view.cullface_back);
5405 // LordHavoc: HalfLife maps have freaky skypolys so don't use
5406 // skymasking on them, and Quake3 never did sky masking (unlike
5407 // software Quake and software Quake2), so disable the sky masking
5408 // in Quake3 maps as it causes problems with q3map2 sky tricks,
5409 // and skymasking also looks very bad when noclipping outside the
5410 // level, so don't use it then either.
5411 if (r_refdef.worldmodel && r_refdef.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_viewcache.world_novis)
5413 GL_Color(r_refdef.fogcolor[0] * r_view.colorscale, r_refdef.fogcolor[1] * r_view.colorscale, r_refdef.fogcolor[2] * r_view.colorscale, 1);
5414 R_Mesh_ColorPointer(NULL, 0, 0);
5415 R_Mesh_ResetTextureState();
5416 if (skyrendermasked)
5418 // depth-only (masking)
5419 GL_ColorMask(0,0,0,0);
5420 // just to make sure that braindead drivers don't draw
5421 // anything despite that colormask...
5422 GL_BlendFunc(GL_ZERO, GL_ONE);
5427 GL_BlendFunc(GL_ONE, GL_ZERO);
5429 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
5430 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5431 if (skyrendermasked)
5432 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
5436 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, msurface_t **texturesurfacelist)
5438 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION)))
5441 if (rsurface.mode != RSURFMODE_GLSL)
5443 rsurface.mode = RSURFMODE_GLSL;
5444 R_Mesh_ResetTextureState();
5447 R_Mesh_TexMatrix(0, &rsurface.texture->currenttexmatrix);
5448 R_Mesh_TexBind(0, R_GetTexture(rsurface.texture->currentskinframe->nmap));
5449 R_Mesh_TexBind(1, R_GetTexture(rsurface.texture->basetexture));
5450 R_Mesh_TexBind(2, R_GetTexture(rsurface.texture->glosstexture));
5451 R_Mesh_TexBind(4, R_GetTexture(r_texture_fogattenuation));
5452 R_Mesh_TexBind(5, R_GetTexture(rsurface.texture->currentskinframe->pants));
5453 R_Mesh_TexBind(6, R_GetTexture(rsurface.texture->currentskinframe->shirt));
5454 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
5456 R_Mesh_TexBind(7, R_GetTexture(r_texture_grey128));
5457 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
5458 R_Mesh_ColorPointer(NULL, 0, 0);
5460 else if (rsurface.uselightmaptexture)
5462 R_Mesh_TexBind(7, R_GetTexture(texturesurfacelist[0]->lightmaptexture));
5463 R_Mesh_TexBind(8, R_GetTexture(texturesurfacelist[0]->deluxemaptexture));
5464 R_Mesh_ColorPointer(NULL, 0, 0);
5468 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
5469 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
5470 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
5472 R_Mesh_TexBind(9, R_GetTexture(rsurface.texture->currentskinframe->glow));
5473 R_Mesh_TexBind(11, R_GetTexture(r_texture_white)); // changed per surface
5474 R_Mesh_TexBind(12, R_GetTexture(r_texture_white)); // changed per surface
5476 if (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5478 // render background
5479 GL_BlendFunc(GL_ONE, GL_ZERO);
5481 GL_AlphaTest(false);
5483 GL_Color(1, 1, 1, 1);
5484 R_Mesh_ColorPointer(NULL, 0, 0);
5486 R_SetupSurfaceShader(vec3_origin, rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
5487 if (r_glsl_permutation)
5489 RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
5490 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
5491 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
5492 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
5493 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
5494 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
5495 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist, -1, -1, r_glsl_permutation->loc_Texture_Refraction ? 11 : -1, r_glsl_permutation->loc_Texture_Reflection ? 12 : -1);
5498 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5499 GL_DepthMask(false);
5500 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5501 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
5503 R_Mesh_TexBind(7, R_GetTexture(r_texture_grey128));
5504 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
5505 R_Mesh_ColorPointer(NULL, 0, 0);
5507 else if (rsurface.uselightmaptexture)
5509 R_Mesh_TexBind(7, R_GetTexture(texturesurfacelist[0]->lightmaptexture));
5510 R_Mesh_TexBind(8, R_GetTexture(texturesurfacelist[0]->deluxemaptexture));
5511 R_Mesh_ColorPointer(NULL, 0, 0);
5515 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
5516 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
5517 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
5519 R_Mesh_TexBind(11, R_GetTexture(r_texture_white)); // changed per surface
5520 R_Mesh_TexBind(12, R_GetTexture(r_texture_white)); // changed per surface
5523 R_SetupSurfaceShader(vec3_origin, rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE);
5524 if (!r_glsl_permutation)
5527 RSurf_PrepareVerticesForBatch(r_glsl_permutation->loc_Texture_Normal >= 0 || r_glsl_permutation->loc_LightDir >= 0, r_glsl_permutation->loc_Texture_Normal >= 0, texturenumsurfaces, texturesurfacelist);
5528 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
5529 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
5530 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
5531 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
5532 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
5533 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]);
5535 if (r_glsl_permutation->loc_Texture_Refraction >= 0)
5537 GL_BlendFunc(GL_ONE, GL_ZERO);
5539 GL_AlphaTest(false);
5542 if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
5544 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
5545 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);
5547 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 7, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? 8 : -1);
5551 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
5552 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);
5554 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5556 if (rsurface.texture->backgroundnumskinframes && !(rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED))
5561 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, msurface_t **texturesurfacelist)
5563 // OpenGL 1.3 path - anything not completely ancient
5564 int texturesurfaceindex;
5565 qboolean applycolor;
5569 const texturelayer_t *layer;
5570 if (rsurface.mode != RSURFMODE_MULTIPASS)
5571 rsurface.mode = RSURFMODE_MULTIPASS;
5572 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
5574 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
5577 int layertexrgbscale;
5578 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5580 if (layerindex == 0)
5584 GL_AlphaTest(false);
5585 qglDepthFunc(GL_EQUAL);CHECKGLERROR
5588 GL_DepthMask(layer->depthmask);
5589 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
5590 if ((layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2) && (gl_combine.integer || layer->depthmask))
5592 layertexrgbscale = 4;
5593 VectorScale(layer->color, 0.25f, layercolor);
5595 else if ((layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1) && (gl_combine.integer || layer->depthmask))
5597 layertexrgbscale = 2;
5598 VectorScale(layer->color, 0.5f, layercolor);
5602 layertexrgbscale = 1;
5603 VectorScale(layer->color, 1.0f, layercolor);
5605 layercolor[3] = layer->color[3];
5606 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
5607 R_Mesh_ColorPointer(NULL, 0, 0);
5608 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
5609 switch (layer->type)
5611 case TEXTURELAYERTYPE_LITTEXTURE:
5612 memset(&m, 0, sizeof(m));
5613 m.tex[0] = R_GetTexture(r_texture_white);
5614 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
5615 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
5616 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
5617 m.tex[1] = R_GetTexture(layer->texture);
5618 m.texmatrix[1] = layer->texmatrix;
5619 m.texrgbscale[1] = layertexrgbscale;
5620 m.pointer_texcoord[1] = rsurface.texcoordtexture2f;
5621 m.pointer_texcoord_bufferobject[1] = rsurface.texcoordtexture2f_bufferobject;
5622 m.pointer_texcoord_bufferoffset[1] = rsurface.texcoordtexture2f_bufferoffset;
5623 R_Mesh_TextureState(&m);
5624 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
5625 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
5626 else if (rsurface.uselightmaptexture)
5627 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
5629 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
5631 case TEXTURELAYERTYPE_TEXTURE:
5632 memset(&m, 0, sizeof(m));
5633 m.tex[0] = R_GetTexture(layer->texture);
5634 m.texmatrix[0] = layer->texmatrix;
5635 m.texrgbscale[0] = layertexrgbscale;
5636 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5637 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5638 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5639 R_Mesh_TextureState(&m);
5640 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
5642 case TEXTURELAYERTYPE_FOG:
5643 memset(&m, 0, sizeof(m));
5644 m.texrgbscale[0] = layertexrgbscale;
5647 m.tex[0] = R_GetTexture(layer->texture);
5648 m.texmatrix[0] = layer->texmatrix;
5649 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5650 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5651 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5653 R_Mesh_TextureState(&m);
5654 // generate a color array for the fog pass
5655 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
5656 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5660 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5661 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)
5663 f = 1 - FogPoint_Model(v);
5664 c[0] = layercolor[0];
5665 c[1] = layercolor[1];
5666 c[2] = layercolor[2];
5667 c[3] = f * layercolor[3];
5670 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5673 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
5675 GL_LockArrays(0, 0);
5678 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5680 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
5681 GL_AlphaTest(false);
5685 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, msurface_t **texturesurfacelist)
5687 // OpenGL 1.1 - crusty old voodoo path
5688 int texturesurfaceindex;
5692 const texturelayer_t *layer;
5693 if (rsurface.mode != RSURFMODE_MULTIPASS)
5694 rsurface.mode = RSURFMODE_MULTIPASS;
5695 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
5697 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
5699 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5701 if (layerindex == 0)
5705 GL_AlphaTest(false);
5706 qglDepthFunc(GL_EQUAL);CHECKGLERROR
5709 GL_DepthMask(layer->depthmask);
5710 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
5711 R_Mesh_ColorPointer(NULL, 0, 0);
5712 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
5713 switch (layer->type)
5715 case TEXTURELAYERTYPE_LITTEXTURE:
5716 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
5718 // two-pass lit texture with 2x rgbscale
5719 // first the lightmap pass
5720 memset(&m, 0, sizeof(m));
5721 m.tex[0] = R_GetTexture(r_texture_white);
5722 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
5723 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
5724 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
5725 R_Mesh_TextureState(&m);
5726 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
5727 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5728 else if (rsurface.uselightmaptexture)
5729 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5731 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5732 GL_LockArrays(0, 0);
5733 // then apply the texture to it
5734 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
5735 memset(&m, 0, sizeof(m));
5736 m.tex[0] = R_GetTexture(layer->texture);
5737 m.texmatrix[0] = layer->texmatrix;
5738 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5739 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5740 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5741 R_Mesh_TextureState(&m);
5742 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);
5746 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
5747 memset(&m, 0, sizeof(m));
5748 m.tex[0] = R_GetTexture(layer->texture);
5749 m.texmatrix[0] = layer->texmatrix;
5750 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5751 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5752 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5753 R_Mesh_TextureState(&m);
5754 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
5755 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);
5757 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);
5760 case TEXTURELAYERTYPE_TEXTURE:
5761 // singletexture unlit texture with transparency support
5762 memset(&m, 0, sizeof(m));
5763 m.tex[0] = R_GetTexture(layer->texture);
5764 m.texmatrix[0] = layer->texmatrix;
5765 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5766 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5767 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5768 R_Mesh_TextureState(&m);
5769 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);
5771 case TEXTURELAYERTYPE_FOG:
5772 // singletexture fogging
5773 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
5776 memset(&m, 0, sizeof(m));
5777 m.tex[0] = R_GetTexture(layer->texture);
5778 m.texmatrix[0] = layer->texmatrix;
5779 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5780 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5781 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5782 R_Mesh_TextureState(&m);
5785 R_Mesh_ResetTextureState();
5786 // generate a color array for the fog pass
5787 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5791 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5792 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)
5794 f = 1 - FogPoint_Model(v);
5795 c[0] = layer->color[0];
5796 c[1] = layer->color[1];
5797 c[2] = layer->color[2];
5798 c[3] = f * layer->color[3];
5801 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5804 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
5806 GL_LockArrays(0, 0);
5809 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5811 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
5812 GL_AlphaTest(false);
5816 static void R_DrawTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly)
5818 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW)
5820 rsurface.rtlight = NULL;
5824 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
5826 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
5828 if (rsurface.mode != RSURFMODE_MULTIPASS)
5829 rsurface.mode = RSURFMODE_MULTIPASS;
5830 if (r_depthfirst.integer == 3)
5832 int i = (int)(texturesurfacelist[0] - rsurface.modelsurfaces);
5833 if (!r_view.showdebug)
5834 GL_Color(0, 0, 0, 1);
5836 GL_Color(((i >> 6) & 7) / 7.0f, ((i >> 3) & 7) / 7.0f, (i & 7) / 7.0f,1);
5840 GL_ColorMask(0,0,0,0);
5843 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5844 GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset);
5845 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_view.cullface_back);
5847 GL_BlendFunc(GL_ONE, GL_ZERO);
5849 GL_AlphaTest(false);
5850 R_Mesh_ColorPointer(NULL, 0, 0);
5851 R_Mesh_ResetTextureState();
5852 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
5853 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5854 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
5856 else if (r_depthfirst.integer == 3)
5858 else if (!r_view.showdebug && (r_showsurfaces.integer || gl_lightmaps.integer))
5860 GL_Color(0, 0, 0, 1);
5861 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5863 else if (r_showsurfaces.integer)
5865 if (rsurface.mode != RSURFMODE_MULTIPASS)
5866 rsurface.mode = RSURFMODE_MULTIPASS;
5867 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5868 GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset);
5870 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_view.cullface_back);
5871 GL_BlendFunc(GL_ONE, GL_ZERO);
5872 GL_DepthMask(writedepth);
5874 GL_AlphaTest(false);
5875 R_Mesh_ColorPointer(NULL, 0, 0);
5876 R_Mesh_ResetTextureState();
5877 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
5878 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
5880 else if (gl_lightmaps.integer)
5883 if (rsurface.mode != RSURFMODE_MULTIPASS)
5884 rsurface.mode = RSURFMODE_MULTIPASS;
5885 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5887 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_view.cullface_back);
5888 GL_BlendFunc(GL_ONE, GL_ZERO);
5889 GL_DepthMask(writedepth);
5891 GL_AlphaTest(false);
5892 R_Mesh_ColorPointer(NULL, 0, 0);
5893 memset(&m, 0, sizeof(m));
5894 m.tex[0] = R_GetTexture(r_texture_white);
5895 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
5896 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
5897 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
5898 R_Mesh_TextureState(&m);
5899 RSurf_PrepareVerticesForBatch(rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT, false, texturenumsurfaces, texturesurfacelist);
5900 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
5901 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5902 else if (rsurface.uselightmaptexture)
5903 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5905 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5907 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
5908 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
5909 else if (rsurface.texture->currentnumlayers)
5911 // write depth for anything we skipped on the depth-only pass earlier
5912 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5914 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5915 GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset);
5916 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
5917 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_view.cullface_back);
5918 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5919 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
5920 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5921 if (r_glsl.integer && gl_support_fragment_shader)
5922 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist);
5923 else if (gl_combine.integer && r_textureunits.integer >= 2)
5924 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist);
5926 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist);
5929 GL_LockArrays(0, 0);
5932 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
5935 int texturenumsurfaces, endsurface;
5937 msurface_t *surface;
5938 msurface_t *texturesurfacelist[1024];
5940 // if the model is static it doesn't matter what value we give for
5941 // wantnormals and wanttangents, so this logic uses only rules applicable
5942 // to a model, knowing that they are meaningless otherwise
5943 if (ent == r_refdef.worldentity)
5944 RSurf_ActiveWorldEntity();
5945 else if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
5946 RSurf_ActiveModelEntity(ent, false, false);
5948 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
5950 for (i = 0;i < numsurfaces;i = j)
5953 surface = rsurface.modelsurfaces + surfacelist[i];
5954 texture = surface->texture;
5955 R_UpdateTextureInfo(ent, texture);
5956 rsurface.texture = texture->currentframe;
5957 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
5958 // scan ahead until we find a different texture
5959 endsurface = min(i + 1024, numsurfaces);
5960 texturenumsurfaces = 0;
5961 texturesurfacelist[texturenumsurfaces++] = surface;
5962 for (;j < endsurface;j++)
5964 surface = rsurface.modelsurfaces + surfacelist[j];
5965 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
5967 texturesurfacelist[texturenumsurfaces++] = surface;
5969 // render the range of surfaces
5970 R_DrawTextureSurfaceList(texturenumsurfaces, texturesurfacelist, true, false);
5976 void R_QueueSurfaceList(entity_render_t *ent, int numsurfaces, msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes)
5979 vec3_t tempcenter, center;
5981 // if we're rendering water textures (extra scene renders), use a separate loop to avoid burdening the main one
5984 for (i = 0;i < numsurfaces;i++)
5985 if (surfacelist[i]->texture->currentframe->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION))
5986 R_Water_AddWaterPlane(surfacelist[i]);
5989 // break the surface list down into batches by texture and use of lightmapping
5990 for (i = 0;i < numsurfaces;i = j)
5993 // texture is the base texture pointer, rsurface.texture is the
5994 // current frame/skin the texture is directing us to use (for example
5995 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
5996 // use skin 1 instead)
5997 texture = surfacelist[i]->texture;
5998 rsurface.texture = texture->currentframe;
5999 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
6000 if (!(rsurface.texture->currentmaterialflags & flagsmask))
6002 // if this texture is not the kind we want, skip ahead to the next one
6003 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
6007 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
6009 // transparent surfaces get pushed off into the transparent queue
6010 const msurface_t *surface = surfacelist[i];
6013 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
6014 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
6015 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
6016 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
6017 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_view.origin : center, R_DrawSurface_TransparentCallback, ent, surface - rsurface.modelsurfaces, rsurface.rtlight);
6021 // simply scan ahead until we find a different texture or lightmap state
6022 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
6024 // render the range of surfaces
6025 R_DrawTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly);
6030 float locboxvertex3f[6*4*3] =
6032 1,0,1, 1,0,0, 1,1,0, 1,1,1,
6033 0,1,1, 0,1,0, 0,0,0, 0,0,1,
6034 1,1,1, 1,1,0, 0,1,0, 0,1,1,
6035 0,0,1, 0,0,0, 1,0,0, 1,0,1,
6036 0,0,1, 1,0,1, 1,1,1, 0,1,1,
6037 1,0,0, 0,0,0, 0,1,0, 1,1,0
6040 int locboxelement3i[6*2*3] =
6050 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6053 cl_locnode_t *loc = (cl_locnode_t *)ent;
6055 float vertex3f[6*4*3];
6057 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6058 GL_DepthMask(false);
6059 GL_DepthRange(0, 1);
6060 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6062 GL_CullFace(GL_NONE);
6063 R_Mesh_Matrix(&identitymatrix);
6065 R_Mesh_VertexPointer(vertex3f, 0, 0);
6066 R_Mesh_ColorPointer(NULL, 0, 0);
6067 R_Mesh_ResetTextureState();
6070 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_view.colorscale,
6071 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_view.colorscale,
6072 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_view.colorscale,
6073 surfacelist[0] < 0 ? 0.5f : 0.125f);
6075 if (VectorCompare(loc->mins, loc->maxs))
6077 VectorSet(size, 2, 2, 2);
6078 VectorMA(loc->mins, -0.5f, size, mins);
6082 VectorCopy(loc->mins, mins);
6083 VectorSubtract(loc->maxs, loc->mins, size);
6086 for (i = 0;i < 6*4*3;)
6087 for (j = 0;j < 3;j++, i++)
6088 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
6090 R_Mesh_Draw(0, 6*4, 6*2, locboxelement3i, 0, 0);
6093 void R_DrawLocs(void)
6096 cl_locnode_t *loc, *nearestloc;
6098 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
6099 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
6101 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
6102 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
6106 void R_DrawDebugModel(entity_render_t *ent)
6108 int i, j, k, l, flagsmask;
6109 const int *elements;
6111 msurface_t *surface;
6112 model_t *model = ent->model;
6115 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WATER | MATERIALFLAG_WALL;
6117 R_Mesh_ColorPointer(NULL, 0, 0);
6118 R_Mesh_ResetTextureState();
6119 GL_DepthRange(0, 1);
6120 GL_DepthTest(!r_showdisabledepthtest.integer);
6121 GL_DepthMask(false);
6122 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6124 if (r_showcollisionbrushes.value > 0 && model->brush.num_brushes)
6126 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
6127 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
6129 if (brush->colbrushf && brush->colbrushf->numtriangles)
6131 R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
6132 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);
6133 R_Mesh_Draw(0, brush->colbrushf->numpoints, brush->colbrushf->numtriangles, brush->colbrushf->elements, 0, 0);
6136 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
6138 if (surface->num_collisiontriangles)
6140 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
6141 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);
6142 R_Mesh_Draw(0, surface->num_collisionvertices, surface->num_collisiontriangles, surface->data_collisionelement3i, 0, 0);
6147 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6149 if (r_showtris.integer || r_shownormals.integer)
6151 if (r_showdisabledepthtest.integer)
6153 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6154 GL_DepthMask(false);
6158 GL_BlendFunc(GL_ONE, GL_ZERO);
6161 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
6163 if (ent == r_refdef.worldentity && !r_viewcache.world_surfacevisible[j])
6165 rsurface.texture = surface->texture->currentframe;
6166 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
6168 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
6169 if (r_showtris.value > 0)
6171 if (!rsurface.texture->currentlayers->depthmask)
6172 GL_Color(r_view.colorscale, 0, 0, r_showtris.value);
6173 else if (ent == r_refdef.worldentity)
6174 GL_Color(r_view.colorscale, r_view.colorscale, r_view.colorscale, r_showtris.value);
6176 GL_Color(0, r_view.colorscale, 0, r_showtris.value);
6177 elements = (ent->model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
6180 for (k = 0;k < surface->num_triangles;k++, elements += 3)
6182 #define GLVERTEXELEMENT(n) qglVertex3f(rsurface.vertex3f[elements[n]*3+0], rsurface.vertex3f[elements[n]*3+1], rsurface.vertex3f[elements[n]*3+2])
6183 GLVERTEXELEMENT(0);GLVERTEXELEMENT(1);
6184 GLVERTEXELEMENT(1);GLVERTEXELEMENT(2);
6185 GLVERTEXELEMENT(2);GLVERTEXELEMENT(0);
6190 if (r_shownormals.value > 0)
6192 GL_Color(r_view.colorscale, 0, 0, r_shownormals.value);
6194 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
6196 VectorCopy(rsurface.vertex3f + l * 3, v);
6197 qglVertex3f(v[0], v[1], v[2]);
6198 VectorMA(v, 8, rsurface.svector3f + l * 3, v);
6199 qglVertex3f(v[0], v[1], v[2]);
6203 GL_Color(0, 0, r_view.colorscale, r_shownormals.value);
6205 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
6207 VectorCopy(rsurface.vertex3f + l * 3, v);
6208 qglVertex3f(v[0], v[1], v[2]);
6209 VectorMA(v, 8, rsurface.tvector3f + l * 3, v);
6210 qglVertex3f(v[0], v[1], v[2]);
6214 GL_Color(0, r_view.colorscale, 0, r_shownormals.value);
6216 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
6218 VectorCopy(rsurface.vertex3f + l * 3, v);
6219 qglVertex3f(v[0], v[1], v[2]);
6220 VectorMA(v, 8, rsurface.normal3f + l * 3, v);
6221 qglVertex3f(v[0], v[1], v[2]);
6228 rsurface.texture = NULL;
6232 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
6233 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes, qboolean debug)
6235 int i, j, endj, f, flagsmask;
6236 msurface_t *surface, **surfacechain;
6238 model_t *model = r_refdef.worldmodel;
6239 const int maxsurfacelist = 1024;
6240 int numsurfacelist = 0;
6241 msurface_t *surfacelist[1024];
6245 RSurf_ActiveWorldEntity();
6247 // update light styles
6248 if (!skysurfaces && !depthonly && !addwaterplanes && model->brushq1.light_styleupdatechains)
6250 for (i = 0;i < model->brushq1.light_styles;i++)
6252 if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
6254 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
6255 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
6256 for (;(surface = *surfacechain);surfacechain++)
6257 surface->cached_dlight = true;
6262 R_UpdateAllTextureInfo(r_refdef.worldentity);
6263 flagsmask = addwaterplanes ? (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) : (skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL));
6267 R_DrawDebugModel(r_refdef.worldentity);
6273 rsurface.uselightmaptexture = false;
6274 rsurface.texture = NULL;
6276 j = model->firstmodelsurface;
6277 endj = j + model->nummodelsurfaces;
6280 // quickly skip over non-visible surfaces
6281 for (;j < endj && !r_viewcache.world_surfacevisible[j];j++)
6283 // quickly iterate over visible surfaces
6284 for (;j < endj && r_viewcache.world_surfacevisible[j];j++)
6286 // process this surface
6287 surface = model->data_surfaces + j;
6288 // if this surface fits the criteria, add it to the list
6289 if (surface->num_triangles)
6291 // if lightmap parameters changed, rebuild lightmap texture
6292 if (surface->cached_dlight)
6293 R_BuildLightMap(r_refdef.worldentity, surface);
6294 // add face to draw list
6295 surfacelist[numsurfacelist++] = surface;
6296 r_refdef.stats.world_triangles += surface->num_triangles;
6297 if (numsurfacelist >= maxsurfacelist)
6299 r_refdef.stats.world_surfaces += numsurfacelist;
6300 R_QueueSurfaceList(r_refdef.worldentity, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
6306 r_refdef.stats.world_surfaces += numsurfacelist;
6308 R_QueueSurfaceList(r_refdef.worldentity, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
6312 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes, qboolean debug)
6314 int i, f, flagsmask;
6315 msurface_t *surface, *endsurface, **surfacechain;
6317 model_t *model = ent->model;
6318 const int maxsurfacelist = 1024;
6319 int numsurfacelist = 0;
6320 msurface_t *surfacelist[1024];
6324 // if the model is static it doesn't matter what value we give for
6325 // wantnormals and wanttangents, so this logic uses only rules applicable
6326 // to a model, knowing that they are meaningless otherwise
6327 if (ent == r_refdef.worldentity)
6328 RSurf_ActiveWorldEntity();
6329 else if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
6330 RSurf_ActiveModelEntity(ent, false, false);
6332 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader && !depthonly);
6334 // update light styles
6335 if (!skysurfaces && !depthonly && !addwaterplanes && model->brushq1.light_styleupdatechains)
6337 for (i = 0;i < model->brushq1.light_styles;i++)
6339 if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
6341 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
6342 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
6343 for (;(surface = *surfacechain);surfacechain++)
6344 surface->cached_dlight = true;
6349 R_UpdateAllTextureInfo(ent);
6350 flagsmask = addwaterplanes ? (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) : (skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL));
6354 R_DrawDebugModel(ent);
6360 rsurface.uselightmaptexture = false;
6361 rsurface.texture = NULL;
6363 surface = model->data_surfaces + model->firstmodelsurface;
6364 endsurface = surface + model->nummodelsurfaces;
6365 for (;surface < endsurface;surface++)
6367 // if this surface fits the criteria, add it to the list
6368 if (surface->num_triangles)
6370 // if lightmap parameters changed, rebuild lightmap texture
6371 if (surface->cached_dlight)
6372 R_BuildLightMap(ent, surface);
6373 // add face to draw list
6374 surfacelist[numsurfacelist++] = surface;
6375 r_refdef.stats.entities_triangles += surface->num_triangles;
6376 if (numsurfacelist >= maxsurfacelist)
6378 r_refdef.stats.entities_surfaces += numsurfacelist;
6379 R_QueueSurfaceList(ent, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
6384 r_refdef.stats.entities_surfaces += numsurfacelist;
6386 R_QueueSurfaceList(ent, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);