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[2] = 128; // normal X
267 data[1] = 128; // normal Y
268 data[0] = 255; // normal Z
269 data[3] = 128; // height
270 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE, NULL);
275 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE, NULL);
280 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE, NULL);
285 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, 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_BGRA, TEXF_MIPMAP, NULL);
316 static void R_BuildWhiteCube(void)
318 unsigned char data[6*1*1*4];
319 memset(data, 255, sizeof(data));
320 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
323 static void R_BuildNormalizationCube(void)
327 vec_t s, t, intensity;
329 unsigned char data[6][NORMSIZE][NORMSIZE][4];
330 for (side = 0;side < 6;side++)
332 for (y = 0;y < NORMSIZE;y++)
334 for (x = 0;x < NORMSIZE;x++)
336 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
337 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
372 intensity = 127.0f / sqrt(DotProduct(v, v));
373 data[side][y][x][2] = (unsigned char)(128.0f + intensity * v[0]);
374 data[side][y][x][1] = (unsigned char)(128.0f + intensity * v[1]);
375 data[side][y][x][0] = (unsigned char)(128.0f + intensity * v[2]);
376 data[side][y][x][3] = 255;
380 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, &data[0][0][0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
383 static void R_BuildFogTexture(void)
387 unsigned char data1[FOGWIDTH][4];
388 //unsigned char data2[FOGWIDTH][4];
389 for (x = 0;x < FOGWIDTH;x++)
391 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
396 //data2[x][0] = 255 - b;
397 //data2[x][1] = 255 - b;
398 //data2[x][2] = 255 - b;
401 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
402 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
405 static const char *builtinshaderstring =
406 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
407 "// written by Forest 'LordHavoc' Hale\n"
409 "// common definitions between vertex shader and fragment shader:\n"
411 "#ifdef __GLSL_CG_DATA_TYPES\n"
412 "# define myhalf half\n"
413 "# define myhvec2 hvec2\n"
414 "# define myhvec3 hvec3\n"
415 "# define myhvec4 hvec4\n"
417 "# define myhalf float\n"
418 "# define myhvec2 vec2\n"
419 "# define myhvec3 vec3\n"
420 "# define myhvec4 vec4\n"
423 "varying vec2 TexCoord;\n"
424 "varying vec2 TexCoordLightmap;\n"
426 "//#ifdef MODE_LIGHTSOURCE\n"
427 "varying vec3 CubeVector;\n"
430 "//#ifdef MODE_LIGHTSOURCE\n"
431 "varying vec3 LightVector;\n"
433 "//# ifdef MODE_LIGHTDIRECTION\n"
434 "//varying vec3 LightVector;\n"
438 "varying vec3 EyeVector;\n"
440 "varying vec3 EyeVectorModelSpace;\n"
443 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
444 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
445 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
447 "//#ifdef MODE_WATER\n"
448 "varying vec4 ModelViewProjectionPosition;\n"
450 "//# ifdef MODE_REFRACTION\n"
451 "//varying vec4 ModelViewProjectionPosition;\n"
453 "//# ifdef USEREFLECTION\n"
454 "//varying vec4 ModelViewProjectionPosition;\n"
463 "// vertex shader specific:\n"
464 "#ifdef VERTEX_SHADER\n"
466 "uniform vec3 LightPosition;\n"
467 "uniform vec3 EyePosition;\n"
468 "uniform vec3 LightDir;\n"
470 "// TODO: get rid of tangentt (texcoord2) and use a crossproduct to regenerate it from tangents (texcoord1) and normal (texcoord3)\n"
474 " gl_FrontColor = gl_Color;\n"
475 " // copy the surface texcoord\n"
476 " TexCoord = vec2(gl_TextureMatrix[0] * gl_MultiTexCoord0);\n"
477 "#ifndef MODE_LIGHTSOURCE\n"
478 "# ifndef MODE_LIGHTDIRECTION\n"
479 " TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
483 "#ifdef MODE_LIGHTSOURCE\n"
484 " // transform vertex position into light attenuation/cubemap space\n"
485 " // (-1 to +1 across the light box)\n"
486 " CubeVector = vec3(gl_TextureMatrix[3] * gl_Vertex);\n"
488 " // transform unnormalized light direction into tangent space\n"
489 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
490 " // normalize it per pixel)\n"
491 " vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
492 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
493 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
494 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
497 "#ifdef MODE_LIGHTDIRECTION\n"
498 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
499 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
500 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
503 " // transform unnormalized eye direction into tangent space\n"
505 " vec3 EyeVectorModelSpace;\n"
507 " EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
508 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
509 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
510 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
512 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
513 " VectorS = gl_MultiTexCoord1.xyz;\n"
514 " VectorT = gl_MultiTexCoord2.xyz;\n"
515 " VectorR = gl_MultiTexCoord3.xyz;\n"
518 "//#if defined(MODE_WATER) || defined(MODE_REFRACTION) || defined(USEREFLECTION)\n"
519 "// ModelViewProjectionPosition = gl_Vertex * gl_ModelViewProjectionMatrix;\n"
520 "// //ModelViewProjectionPosition_svector = (gl_Vertex + vec4(gl_MultiTexCoord1.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
521 "// //ModelViewProjectionPosition_tvector = (gl_Vertex + vec4(gl_MultiTexCoord2.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
524 "// transform vertex to camera space, using ftransform to match non-VS\n"
526 " gl_Position = ftransform();\n"
528 "#ifdef MODE_WATER\n"
529 " ModelViewProjectionPosition = gl_Position;\n"
531 "#ifdef MODE_REFRACTION\n"
532 " ModelViewProjectionPosition = gl_Position;\n"
534 "#ifdef USEREFLECTION\n"
535 " ModelViewProjectionPosition = gl_Position;\n"
539 "#endif // VERTEX_SHADER\n"
544 "// fragment shader specific:\n"
545 "#ifdef FRAGMENT_SHADER\n"
547 "// 13 textures, we can only use up to 16 on DX9-class hardware\n"
548 "uniform sampler2D Texture_Normal;\n"
549 "uniform sampler2D Texture_Color;\n"
550 "uniform sampler2D Texture_Gloss;\n"
551 "uniform samplerCube Texture_Cube;\n"
552 "uniform sampler2D Texture_Attenuation;\n"
553 "uniform sampler2D Texture_FogMask;\n"
554 "uniform sampler2D Texture_Pants;\n"
555 "uniform sampler2D Texture_Shirt;\n"
556 "uniform sampler2D Texture_Lightmap;\n"
557 "uniform sampler2D Texture_Deluxemap;\n"
558 "uniform sampler2D Texture_Glow;\n"
559 "uniform sampler2D Texture_Reflection;\n"
560 "uniform sampler2D Texture_Refraction;\n"
562 "uniform myhvec3 LightColor;\n"
563 "uniform myhvec3 AmbientColor;\n"
564 "uniform myhvec3 DiffuseColor;\n"
565 "uniform myhvec3 SpecularColor;\n"
566 "uniform myhvec3 Color_Pants;\n"
567 "uniform myhvec3 Color_Shirt;\n"
568 "uniform myhvec3 FogColor;\n"
570 "//#ifdef MODE_WATER\n"
571 "uniform vec4 DistortScaleRefractReflect;\n"
572 "uniform vec4 ScreenScaleRefractReflect;\n"
573 "uniform vec4 ScreenCenterRefractReflect;\n"
574 "uniform myhvec4 RefractColor;\n"
575 "uniform myhvec4 ReflectColor;\n"
576 "uniform myhalf ReflectFactor;\n"
577 "uniform myhalf ReflectOffset;\n"
579 "//# ifdef MODE_REFRACTION\n"
580 "//uniform vec4 DistortScaleRefractReflect;\n"
581 "//uniform vec4 ScreenScaleRefractReflect;\n"
582 "//uniform vec4 ScreenCenterRefractReflect;\n"
583 "//uniform myhvec4 RefractColor;\n"
584 "//# ifdef USEREFLECTION\n"
585 "//uniform myhvec4 ReflectColor;\n"
588 "//# ifdef USEREFLECTION\n"
589 "//uniform vec4 DistortScaleRefractReflect;\n"
590 "//uniform vec4 ScreenScaleRefractReflect;\n"
591 "//uniform vec4 ScreenCenterRefractReflect;\n"
592 "//uniform myhvec4 ReflectColor;\n"
597 "uniform myhalf GlowScale;\n"
598 "uniform myhalf SceneBrightness;\n"
599 "#ifdef USECONTRASTBOOST\n"
600 "uniform myhalf ContrastBoostCoeff;\n"
603 "uniform float OffsetMapping_Scale;\n"
604 "uniform float OffsetMapping_Bias;\n"
605 "uniform float FogRangeRecip;\n"
607 "uniform myhalf AmbientScale;\n"
608 "uniform myhalf DiffuseScale;\n"
609 "uniform myhalf SpecularScale;\n"
610 "uniform myhalf SpecularPower;\n"
612 "#ifdef USEOFFSETMAPPING\n"
613 "vec2 OffsetMapping(vec2 TexCoord)\n"
615 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
616 " // 14 sample relief mapping: linear search and then binary search\n"
617 " // this basically steps forward a small amount repeatedly until it finds\n"
618 " // itself inside solid, then jitters forward and back using decreasing\n"
619 " // amounts to find the impact\n"
620 " //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
621 " //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
622 " vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
623 " vec3 RT = vec3(TexCoord, 1);\n"
624 " OffsetVector *= 0.1;\n"
625 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
626 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
627 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
628 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
629 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
630 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
631 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
632 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
633 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
634 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) - 0.5);\n"
635 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5 - 0.25);\n"
636 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25 - 0.125);\n"
637 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125 - 0.0625);\n"
638 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
641 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
642 " // this basically moves forward the full distance, and then backs up based\n"
643 " // on height of samples\n"
644 " //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
645 " //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
646 " vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
647 " TexCoord += OffsetVector;\n"
648 " OffsetVector *= 0.333;\n"
649 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
650 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
651 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
652 " return TexCoord;\n"
655 "#endif // USEOFFSETMAPPING\n"
657 "#ifdef MODE_WATER\n"
662 "#ifdef USEOFFSETMAPPING\n"
663 " // apply offsetmapping\n"
664 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
665 "#define TexCoord TexCoordOffset\n"
668 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
669 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
670 " vec4 ScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect + vec2(normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5))).xyxy * DistortScaleRefractReflect;\n"
671 " float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 5.0) * ReflectFactor + ReflectOffset;\n"
672 " gl_FragColor = mix(texture2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, texture2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
675 "#else // MODE_WATER\n"
676 "#ifdef MODE_REFRACTION\n"
678 "// refraction pass\n"
681 "#ifdef USEOFFSETMAPPING\n"
682 " // apply offsetmapping\n"
683 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
684 "#define TexCoord TexCoordOffset\n"
687 " vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
688 " //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
689 " vec2 ScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy + vec2(normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
690 " gl_FragColor = texture2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
693 "#else // MODE_REFRACTION\n"
696 "#ifdef USEOFFSETMAPPING\n"
697 " // apply offsetmapping\n"
698 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
699 "#define TexCoord TexCoordOffset\n"
702 " // combine the diffuse textures (base, pants, shirt)\n"
703 " myhvec4 color = myhvec4(texture2D(Texture_Color, TexCoord));\n"
704 "#ifdef USECOLORMAPPING\n"
705 " color.rgb += myhvec3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhvec3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
711 "#ifdef MODE_LIGHTSOURCE\n"
714 " // calculate surface normal, light normal, and specular normal\n"
715 " // compute color intensity for the two textures (colormap and glossmap)\n"
716 " // scale by light color and attenuation as efficiently as possible\n"
717 " // (do as much scalar math as possible rather than vector math)\n"
718 "# ifdef USESPECULAR\n"
719 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
720 " myhvec3 diffusenormal = myhvec3(normalize(LightVector));\n"
721 " myhvec3 specularnormal = normalize(diffusenormal + myhvec3(normalize(EyeVector)));\n"
723 " // calculate directional shading\n"
724 " color.rgb = LightColor * myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0))) * (color.rgb * (AmbientScale + DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0))) + (SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower)) * myhvec3(texture2D(Texture_Gloss, TexCoord)));\n"
726 "# ifdef USEDIFFUSE\n"
727 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
728 " myhvec3 diffusenormal = myhvec3(normalize(LightVector));\n"
730 " // calculate directional shading\n"
731 " color.rgb = color.rgb * LightColor * (myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0))) * (AmbientScale + DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0))));\n"
733 " // calculate directionless shading\n"
734 " color.rgb = color.rgb * LightColor * myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
738 "# ifdef USECUBEFILTER\n"
739 " // apply light cubemap filter\n"
740 " //color.rgb *= normalize(CubeVector) * 0.5 + 0.5;//vec3(textureCube(Texture_Cube, CubeVector));\n"
741 " color.rgb *= myhvec3(textureCube(Texture_Cube, CubeVector));\n"
743 " color *= myhvec4(gl_Color);\n"
744 "#endif // MODE_LIGHTSOURCE\n"
749 "#ifdef MODE_LIGHTDIRECTION\n"
750 " // directional model lighting\n"
751 "# ifdef USESPECULAR\n"
752 " // get the surface normal and light normal\n"
753 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
754 " myhvec3 diffusenormal = myhvec3(LightVector);\n"
756 " // calculate directional shading\n"
757 " color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
758 " myhvec3 specularnormal = normalize(diffusenormal + myhvec3(normalize(EyeVector)));\n"
759 " color.rgb += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
761 "# ifdef USEDIFFUSE\n"
762 " // get the surface normal and light normal\n"
763 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
764 " myhvec3 diffusenormal = myhvec3(LightVector);\n"
766 " // calculate directional shading\n"
767 " color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
769 " color.rgb *= AmbientColor;\n"
773 " color *= myhvec4(gl_Color);\n"
774 "#endif // MODE_LIGHTDIRECTION\n"
779 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
780 " // deluxemap lightmapping using light vectors in modelspace (evil q3map2)\n"
782 " // get the surface normal and light normal\n"
783 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
785 " myhvec3 diffusenormal_modelspace = myhvec3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - myhvec3(0.5);\n"
786 " myhvec3 diffusenormal = normalize(myhvec3(dot(diffusenormal_modelspace, myhvec3(VectorS)), dot(diffusenormal_modelspace, myhvec3(VectorT)), dot(diffusenormal_modelspace, myhvec3(VectorR))));\n"
787 " // calculate directional shading\n"
788 " myhvec3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0)));\n"
789 "# ifdef USESPECULAR\n"
790 " myhvec3 specularnormal = myhvec3(normalize(diffusenormal + myhvec3(normalize(EyeVector))));\n"
791 " tempcolor += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
794 " // apply lightmap color\n"
795 " color.rgb = myhvec4(tempcolor,1) * myhvec4(texture2D(Texture_Lightmap, TexCoordLightmap)) * myhvec4(gl_Color) + myhvec4(color.rgb * AmbientScale, 0);\n"
796 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
801 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
802 " // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
804 " // get the surface normal and light normal\n"
805 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
807 " myhvec3 diffusenormal = normalize(myhvec3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - myhvec3(0.5));\n"
808 " // calculate directional shading\n"
809 " myhvec3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0)));\n"
810 "# ifdef USESPECULAR\n"
811 " myhvec3 specularnormal = myhvec3(normalize(diffusenormal + myhvec3(normalize(EyeVector))));\n"
812 " tempcolor += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
815 " // apply lightmap color\n"
816 " color = myhvec4(tempcolor, 1) * myhvec4(texture2D(Texture_Lightmap, TexCoordLightmap)) * myhvec4(gl_Color) + myhvec4(color.rgb * AmbientScale, 0);\n"
817 "#endif // MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
822 "#ifdef MODE_LIGHTMAP\n"
823 " // apply lightmap color\n"
824 " color *= myhvec4(texture2D(Texture_Lightmap, TexCoordLightmap)) * myhvec4(gl_Color) * myhvec4(myhvec3(DiffuseScale), 1) + myhvec4(myhvec3(AmbientScale), 0);\n"
825 "#endif // MODE_LIGHTMAP\n"
835 " color.rgb += myhvec3(texture2D(Texture_Glow, TexCoord)) * GlowScale;\n"
838 "#ifndef MODE_LIGHTSOURCE\n"
839 "# ifdef USEREFLECTION\n"
840 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
841 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
842 " vec4 ScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect + vec3(normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5))).xyxy * DistortScaleRefractReflect;\n"
843 " color.rgb = mix(color.rgb, myhvec3(texture2D(Texture_Reflection, ScreenTexCoord.zw)) * ReflectColor.rgb, ReflectColor.a);\n"
849 " color.rgb = mix(FogColor, color.rgb, myhalf(texture2D(Texture_FogMask, myhvec2(length(EyeVectorModelSpace)*FogRangeRecip, 0.0))));\n"
852 "#ifdef USECONTRASTBOOST\n"
853 " color.rgb = color.rgb / (ContrastBoostCoeff * color.rgb + myhvec3(1, 1, 1));\n"
856 " color.rgb *= SceneBrightness;\n"
858 " gl_FragColor = vec4(color);\n"
860 "#endif // MODE_REFRACTION\n"
861 "#endif // MODE_WATER\n"
863 "#endif // FRAGMENT_SHADER\n"
866 #define SHADERPERMUTATION_COLORMAPPING (1<<0) // indicates this is a colormapped skin
867 #define SHADERPERMUTATION_CONTRASTBOOST (1<<1) // r_glsl_contrastboost boosts the contrast at low color levels (similar to gamma)
868 #define SHADERPERMUTATION_FOG (1<<2) // tint the color by fog color or black if using additive blend mode
869 #define SHADERPERMUTATION_CUBEFILTER (1<<3) // (lightsource) use cubemap light filter
870 #define SHADERPERMUTATION_GLOW (1<<4) // (lightmap) blend in an additive glow texture
871 #define SHADERPERMUTATION_DIFFUSE (1<<5) // (lightsource) whether to use directional shading
872 #define SHADERPERMUTATION_SPECULAR (1<<6) // (lightsource or deluxemapping) render specular effects
873 #define SHADERPERMUTATION_REFLECTION (1<<7) // normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
874 #define SHADERPERMUTATION_OFFSETMAPPING (1<<8) // adjust texcoords to roughly simulate a displacement mapped surface
875 #define SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING (1<<9) // adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
876 #define SHADERPERMUTATION_MODEBASE (1<<10) // multiplier for the SHADERMODE_ values to get a valid index
878 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
879 const char *shaderpermutationinfo[][2] =
881 {"#define USECOLORMAPPING\n", " colormapping"},
882 {"#define USECONTRASTBOOST\n", " contrastboost"},
883 {"#define USEFOG\n", " fog"},
884 {"#define USECUBEFILTER\n", " cubefilter"},
885 {"#define USEGLOW\n", " glow"},
886 {"#define USEDIFFUSE\n", " diffuse"},
887 {"#define USESPECULAR\n", " specular"},
888 {"#define USEREFLECTION\n", " reflection"},
889 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
890 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
894 // this enum is multiplied by SHADERPERMUTATION_MODEBASE
895 typedef enum shadermode_e
897 SHADERMODE_LIGHTMAP, // (lightmap) use directional pixel shading from fixed light direction (q3bsp)
898 SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, // (lightmap) use directional pixel shading from texture containing modelspace light directions (deluxemap)
899 SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, // (lightmap) use directional pixel shading from texture containing tangentspace light directions (deluxemap)
900 SHADERMODE_LIGHTDIRECTION, // (lightmap) use directional pixel shading from fixed light direction (q3bsp)
901 SHADERMODE_LIGHTSOURCE, // (lightsource) use directional pixel shading from light source (rtlight)
902 SHADERMODE_REFRACTION, // refract background (the material is rendered normally after this pass)
903 SHADERMODE_WATER, // refract background and reflection (the material is rendered normally after this pass)
908 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
909 const char *shadermodeinfo[][2] =
911 {"#define MODE_LIGHTMAP\n", " lightmap"},
912 {"#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
913 {"#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
914 {"#define MODE_LIGHTDIRECTION\n", " lightdirection"},
915 {"#define MODE_LIGHTSOURCE\n", " lightsource"},
916 {"#define MODE_REFRACTION\n", " refraction"},
917 {"#define MODE_WATER\n", " water"},
921 #define SHADERPERMUTATION_INDICES (SHADERPERMUTATION_MODEBASE * SHADERMODE_COUNT)
923 typedef struct r_glsl_permutation_s
925 // indicates if we have tried compiling this permutation already
927 // 0 if compilation failed
929 // locations of detected uniforms in program object, or -1 if not found
930 int loc_Texture_Normal;
931 int loc_Texture_Color;
932 int loc_Texture_Gloss;
933 int loc_Texture_Cube;
934 int loc_Texture_Attenuation;
935 int loc_Texture_FogMask;
936 int loc_Texture_Pants;
937 int loc_Texture_Shirt;
938 int loc_Texture_Lightmap;
939 int loc_Texture_Deluxemap;
940 int loc_Texture_Glow;
941 int loc_Texture_Refraction;
942 int loc_Texture_Reflection;
944 int loc_LightPosition;
949 int loc_FogRangeRecip;
950 int loc_AmbientScale;
951 int loc_DiffuseScale;
952 int loc_SpecularScale;
953 int loc_SpecularPower;
955 int loc_SceneBrightness; // or: Scenebrightness * ContrastBoost
956 int loc_OffsetMapping_Scale;
957 int loc_AmbientColor;
958 int loc_DiffuseColor;
959 int loc_SpecularColor;
961 int loc_ContrastBoostCoeff; // 1 - 1/ContrastBoost
962 int loc_DistortScaleRefractReflect;
963 int loc_ScreenScaleRefractReflect;
964 int loc_ScreenCenterRefractReflect;
965 int loc_RefractColor;
966 int loc_ReflectColor;
967 int loc_ReflectFactor;
968 int loc_ReflectOffset;
970 r_glsl_permutation_t;
972 // information about each possible shader permutation
973 r_glsl_permutation_t r_glsl_permutations[SHADERPERMUTATION_INDICES];
974 // currently selected permutation
975 r_glsl_permutation_t *r_glsl_permutation;
977 // these are additional flags used only by R_GLSL_CompilePermutation
978 #define SHADERTYPE_USES_VERTEXSHADER (1<<0)
979 #define SHADERTYPE_USES_GEOMETRYSHADER (1<<1)
980 #define SHADERTYPE_USES_FRAGMENTSHADER (1<<2)
982 static void R_GLSL_CompilePermutation(const char *filename, int permutation, int shadertype)
985 qboolean shaderfound;
986 r_glsl_permutation_t *p = r_glsl_permutations + permutation;
987 int vertstrings_count;
988 int geomstrings_count;
989 int fragstrings_count;
991 const char *vertstrings_list[32+1];
992 const char *geomstrings_list[32+1];
993 const char *fragstrings_list[32+1];
994 char permutationname[256];
999 vertstrings_list[0] = "#define VERTEX_SHADER\n";
1000 geomstrings_list[0] = "#define GEOMETRY_SHADER\n";
1001 fragstrings_list[0] = "#define FRAGMENT_SHADER\n";
1002 vertstrings_count = 1;
1003 geomstrings_count = 1;
1004 fragstrings_count = 1;
1005 permutationname[0] = 0;
1006 i = permutation / SHADERPERMUTATION_MODEBASE;
1007 vertstrings_list[vertstrings_count++] = shadermodeinfo[i][0];
1008 geomstrings_list[geomstrings_count++] = shadermodeinfo[i][0];
1009 fragstrings_list[fragstrings_count++] = shadermodeinfo[i][0];
1010 strlcat(permutationname, shadermodeinfo[i][1], sizeof(permutationname));
1011 for (i = 0;shaderpermutationinfo[i][0];i++)
1013 if (permutation & (1<<i))
1015 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i][0];
1016 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i][0];
1017 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i][0];
1018 strlcat(permutationname, shaderpermutationinfo[i][1], sizeof(permutationname));
1022 // keep line numbers correct
1023 vertstrings_list[vertstrings_count++] = "\n";
1024 geomstrings_list[geomstrings_count++] = "\n";
1025 fragstrings_list[fragstrings_count++] = "\n";
1028 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1029 shaderfound = false;
1032 Con_DPrint("from disk... ");
1033 vertstrings_list[vertstrings_count++] = shaderstring;
1034 geomstrings_list[geomstrings_count++] = shaderstring;
1035 fragstrings_list[fragstrings_count++] = shaderstring;
1038 else if (!strcmp(filename, "glsl/default.glsl"))
1040 vertstrings_list[vertstrings_count++] = builtinshaderstring;
1041 geomstrings_list[geomstrings_count++] = builtinshaderstring;
1042 fragstrings_list[fragstrings_count++] = builtinshaderstring;
1045 // clear any lists that are not needed by this shader
1046 if (!(shadertype & SHADERTYPE_USES_VERTEXSHADER))
1047 vertstrings_count = 0;
1048 if (!(shadertype & SHADERTYPE_USES_GEOMETRYSHADER))
1049 geomstrings_count = 0;
1050 if (!(shadertype & SHADERTYPE_USES_FRAGMENTSHADER))
1051 fragstrings_count = 0;
1052 // compile the shader program
1053 if (shaderfound && vertstrings_count + geomstrings_count + fragstrings_count)
1054 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1058 qglUseProgramObjectARB(p->program);CHECKGLERROR
1059 // look up all the uniform variable names we care about, so we don't
1060 // have to look them up every time we set them
1061 p->loc_Texture_Normal = qglGetUniformLocationARB(p->program, "Texture_Normal");
1062 p->loc_Texture_Color = qglGetUniformLocationARB(p->program, "Texture_Color");
1063 p->loc_Texture_Gloss = qglGetUniformLocationARB(p->program, "Texture_Gloss");
1064 p->loc_Texture_Cube = qglGetUniformLocationARB(p->program, "Texture_Cube");
1065 p->loc_Texture_Attenuation = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
1066 p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
1067 p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
1068 p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
1069 p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
1070 p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
1071 p->loc_Texture_Glow = qglGetUniformLocationARB(p->program, "Texture_Glow");
1072 p->loc_Texture_Refraction = qglGetUniformLocationARB(p->program, "Texture_Refraction");
1073 p->loc_Texture_Reflection = qglGetUniformLocationARB(p->program, "Texture_Reflection");
1074 p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
1075 p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
1076 p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
1077 p->loc_LightColor = qglGetUniformLocationARB(p->program, "LightColor");
1078 p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants");
1079 p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt");
1080 p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip");
1081 p->loc_AmbientScale = qglGetUniformLocationARB(p->program, "AmbientScale");
1082 p->loc_DiffuseScale = qglGetUniformLocationARB(p->program, "DiffuseScale");
1083 p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
1084 p->loc_SpecularScale = qglGetUniformLocationARB(p->program, "SpecularScale");
1085 p->loc_GlowScale = qglGetUniformLocationARB(p->program, "GlowScale");
1086 p->loc_SceneBrightness = qglGetUniformLocationARB(p->program, "SceneBrightness");
1087 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
1088 p->loc_AmbientColor = qglGetUniformLocationARB(p->program, "AmbientColor");
1089 p->loc_DiffuseColor = qglGetUniformLocationARB(p->program, "DiffuseColor");
1090 p->loc_SpecularColor = qglGetUniformLocationARB(p->program, "SpecularColor");
1091 p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
1092 p->loc_ContrastBoostCoeff = qglGetUniformLocationARB(p->program, "ContrastBoostCoeff");
1093 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
1094 p->loc_ScreenScaleRefractReflect = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
1095 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
1096 p->loc_RefractColor = qglGetUniformLocationARB(p->program, "RefractColor");
1097 p->loc_ReflectColor = qglGetUniformLocationARB(p->program, "ReflectColor");
1098 p->loc_ReflectFactor = qglGetUniformLocationARB(p->program, "ReflectFactor");
1099 p->loc_ReflectOffset = qglGetUniformLocationARB(p->program, "ReflectOffset");
1100 // initialize the samplers to refer to the texture units we use
1101 if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal, 0);
1102 if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color, 1);
1103 if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss, 2);
1104 if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube, 3);
1105 if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask, 4);
1106 if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants, 5);
1107 if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt, 6);
1108 if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap, 7);
1109 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap, 8);
1110 if (p->loc_Texture_Glow >= 0) qglUniform1iARB(p->loc_Texture_Glow, 9);
1111 if (p->loc_Texture_Attenuation >= 0) qglUniform1iARB(p->loc_Texture_Attenuation, 10);
1112 if (p->loc_Texture_Refraction >= 0) qglUniform1iARB(p->loc_Texture_Refraction, 11);
1113 if (p->loc_Texture_Reflection >= 0) qglUniform1iARB(p->loc_Texture_Reflection, 12);
1115 qglUseProgramObjectARB(0);CHECKGLERROR
1116 if (developer.integer)
1117 Con_Printf("GLSL shader %s :%s compiled.\n", filename, permutationname);
1121 if (developer.integer)
1122 Con_Printf("GLSL shader %s :%s failed! source code line offset for above errors is %i.\n", permutationname, filename, -(vertstrings_count - 1));
1124 Con_Printf("GLSL shader %s :%s failed! some features may not work properly.\n", permutationname, filename);
1127 Mem_Free(shaderstring);
1130 void R_GLSL_Restart_f(void)
1133 for (i = 0;i < SHADERPERMUTATION_INDICES;i++)
1134 if (r_glsl_permutations[i].program)
1135 GL_Backend_FreeProgram(r_glsl_permutations[i].program);
1136 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
1139 void R_GLSL_DumpShader_f(void)
1143 qfile_t *file = FS_Open("glsl/default.glsl", "w", false, false);
1146 Con_Printf("failed to write to glsl/default.glsl\n");
1150 FS_Print(file, "// The engine may define the following macros:\n");
1151 FS_Print(file, "// #define VERTEX_SHADER\n// #define GEOMETRY_SHADER\n// #define FRAGMENT_SHADER\n");
1152 for (i = 0;shadermodeinfo[i][0];i++)
1153 FS_Printf(file, "// %s", shadermodeinfo[i][0]);
1154 for (i = 0;shaderpermutationinfo[i][0];i++)
1155 FS_Printf(file, "// %s", shaderpermutationinfo[i][0]);
1156 FS_Print(file, "\n");
1157 FS_Print(file, builtinshaderstring);
1160 Con_Printf("glsl/default.glsl written\n");
1163 extern rtexture_t *r_shadow_attenuationgradienttexture;
1164 extern rtexture_t *r_shadow_attenuation2dtexture;
1165 extern rtexture_t *r_shadow_attenuation3dtexture;
1166 int R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass)
1168 // select a permutation of the lighting shader appropriate to this
1169 // combination of texture, entity, light source, and fogging, only use the
1170 // minimum features necessary to avoid wasting rendering time in the
1171 // fragment shader on features that are not being used
1172 const char *shaderfilename = NULL;
1173 unsigned int permutation = 0;
1174 unsigned int shadertype = 0;
1175 shadermode_t mode = 0;
1176 r_glsl_permutation = NULL;
1177 shaderfilename = "glsl/default.glsl";
1178 shadertype = SHADERTYPE_USES_VERTEXSHADER | SHADERTYPE_USES_FRAGMENTSHADER;
1179 // TODO: implement geometry-shader based shadow volumes someday
1180 if (r_glsl_offsetmapping.integer)
1182 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
1183 if (r_glsl_offsetmapping_reliefmapping.integer)
1184 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
1186 if (rsurfacepass == RSURFPASS_BACKGROUND)
1188 // distorted background
1189 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
1190 mode = SHADERMODE_WATER;
1192 mode = SHADERMODE_REFRACTION;
1194 else if (rsurfacepass == RSURFPASS_RTLIGHT)
1197 mode = SHADERMODE_LIGHTSOURCE;
1198 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
1199 permutation |= SHADERPERMUTATION_CUBEFILTER;
1200 if (diffusescale > 0)
1201 permutation |= SHADERPERMUTATION_DIFFUSE;
1202 if (specularscale > 0)
1203 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
1204 if (r_refdef.fogenabled)
1205 permutation |= SHADERPERMUTATION_FOG;
1206 if (rsurface.texture->colormapping)
1207 permutation |= SHADERPERMUTATION_COLORMAPPING;
1208 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1209 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1210 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1211 permutation |= SHADERPERMUTATION_REFLECTION;
1213 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
1215 // unshaded geometry (fullbright or ambient model lighting)
1216 mode = SHADERMODE_LIGHTMAP;
1217 if (rsurface.texture->currentskinframe->glow)
1218 permutation |= SHADERPERMUTATION_GLOW;
1219 if (r_refdef.fogenabled)
1220 permutation |= SHADERPERMUTATION_FOG;
1221 if (rsurface.texture->colormapping)
1222 permutation |= SHADERPERMUTATION_COLORMAPPING;
1223 if (r_glsl_offsetmapping.integer)
1225 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
1226 if (r_glsl_offsetmapping_reliefmapping.integer)
1227 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
1229 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1230 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1231 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1232 permutation |= SHADERPERMUTATION_REFLECTION;
1234 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
1236 // directional model lighting
1237 mode = SHADERMODE_LIGHTDIRECTION;
1238 if (rsurface.texture->currentskinframe->glow)
1239 permutation |= SHADERPERMUTATION_GLOW;
1240 permutation |= SHADERPERMUTATION_DIFFUSE;
1241 if (specularscale > 0)
1242 permutation |= SHADERPERMUTATION_SPECULAR;
1243 if (r_refdef.fogenabled)
1244 permutation |= SHADERPERMUTATION_FOG;
1245 if (rsurface.texture->colormapping)
1246 permutation |= SHADERPERMUTATION_COLORMAPPING;
1247 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1248 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1249 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1250 permutation |= SHADERPERMUTATION_REFLECTION;
1252 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
1254 // ambient model lighting
1255 mode = SHADERMODE_LIGHTDIRECTION;
1256 if (rsurface.texture->currentskinframe->glow)
1257 permutation |= SHADERPERMUTATION_GLOW;
1258 if (r_refdef.fogenabled)
1259 permutation |= SHADERPERMUTATION_FOG;
1260 if (rsurface.texture->colormapping)
1261 permutation |= SHADERPERMUTATION_COLORMAPPING;
1262 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1263 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1264 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1265 permutation |= SHADERPERMUTATION_REFLECTION;
1270 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.worldmodel && r_refdef.worldmodel->brushq3.deluxemapping)
1272 // deluxemapping (light direction texture)
1273 if (rsurface.uselightmaptexture && r_refdef.worldmodel && r_refdef.worldmodel->brushq3.deluxemapping && r_refdef.worldmodel->brushq3.deluxemapping_modelspace)
1274 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
1276 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
1277 if (specularscale > 0)
1278 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
1280 else if (r_glsl_deluxemapping.integer >= 2)
1282 // fake deluxemapping (uniform light direction in tangentspace)
1283 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
1284 if (specularscale > 0)
1285 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
1289 // ordinary lightmapping
1290 mode = SHADERMODE_LIGHTMAP;
1292 if (rsurface.texture->currentskinframe->glow)
1293 permutation |= SHADERPERMUTATION_GLOW;
1294 if (r_refdef.fogenabled)
1295 permutation |= SHADERPERMUTATION_FOG;
1296 if (rsurface.texture->colormapping)
1297 permutation |= SHADERPERMUTATION_COLORMAPPING;
1298 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1299 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1300 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1301 permutation |= SHADERPERMUTATION_REFLECTION;
1303 permutation |= mode * SHADERPERMUTATION_MODEBASE;
1304 if (!r_glsl_permutations[permutation].program)
1306 if (!r_glsl_permutations[permutation].compiled)
1307 R_GLSL_CompilePermutation(shaderfilename, permutation, shadertype);
1308 if (!r_glsl_permutations[permutation].program)
1310 // remove features until we find a valid permutation
1312 for (i = (SHADERPERMUTATION_MODEBASE >> 1);;i>>=1)
1316 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");
1317 Cvar_SetValueQuick(&r_glsl, 0);
1318 return 0; // no bit left to clear
1320 // reduce i more quickly whenever it would not remove any bits
1321 if (!(permutation & i))
1324 if (!r_glsl_permutations[permutation].compiled)
1325 R_GLSL_CompilePermutation(shaderfilename, permutation, shadertype);
1326 if (r_glsl_permutations[permutation].program)
1331 r_glsl_permutation = r_glsl_permutations + permutation;
1333 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
1334 if (mode == SHADERMODE_LIGHTSOURCE)
1336 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
1337 if (permutation & SHADERPERMUTATION_DIFFUSE)
1339 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
1340 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, ambientscale);
1341 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, diffusescale);
1342 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, specularscale);
1346 // ambient only is simpler
1347 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0] * ambientscale, lightcolorbase[1] * ambientscale, lightcolorbase[2] * ambientscale);
1348 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, 1);
1349 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, 0);
1350 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, 0);
1353 else if (mode == SHADERMODE_LIGHTDIRECTION)
1355 if (r_glsl_permutation->loc_AmbientColor >= 0)
1356 qglUniform3fARB(r_glsl_permutation->loc_AmbientColor, rsurface.modellight_ambient[0] * ambientscale, rsurface.modellight_ambient[1] * ambientscale, rsurface.modellight_ambient[2] * ambientscale);
1357 if (r_glsl_permutation->loc_DiffuseColor >= 0)
1358 qglUniform3fARB(r_glsl_permutation->loc_DiffuseColor, rsurface.modellight_diffuse[0] * diffusescale, rsurface.modellight_diffuse[1] * diffusescale, rsurface.modellight_diffuse[2] * diffusescale);
1359 if (r_glsl_permutation->loc_SpecularColor >= 0)
1360 qglUniform3fARB(r_glsl_permutation->loc_SpecularColor, rsurface.modellight_diffuse[0] * specularscale, rsurface.modellight_diffuse[1] * specularscale, rsurface.modellight_diffuse[2] * specularscale);
1361 if (r_glsl_permutation->loc_LightDir >= 0)
1362 qglUniform3fARB(r_glsl_permutation->loc_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
1366 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_ambient.value * 2.0f / 128.0f);
1367 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_refdef.lightmapintensity * 2.0f);
1368 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, r_refdef.lightmapintensity * specularscale * 2.0f);
1370 if (r_glsl_permutation->loc_GlowScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_GlowScale, r_hdr_glowintensity.value);
1371 if (r_glsl_permutation->loc_ContrastBoostCoeff >= 0)
1373 // The formula used is actually:
1374 // color.rgb *= SceneBrightness;
1375 // color.rgb *= ContrastBoost / ((ContrastBoost - 1) * color.rgb + 1);
1376 // I simplify that to
1377 // color.rgb *= [[SceneBrightness * ContrastBoost]];
1378 // color.rgb /= [[(ContrastBoost - 1) / ContrastBoost]] * color.rgb + 1;
1380 // color.rgb = [[SceneBrightness * ContrastBoost]] * color.rgb / ([[(ContrastBoost - 1) * SceneBrightness]] * color.rgb + 1);
1381 // and do [[calculations]] here in the engine
1382 qglUniform1fARB(r_glsl_permutation->loc_ContrastBoostCoeff, (r_glsl_contrastboost.value - 1) * r_view.colorscale);
1383 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_view.colorscale * r_glsl_contrastboost.value);
1386 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_view.colorscale);
1387 if (r_glsl_permutation->loc_FogColor >= 0)
1389 // additive passes are only darkened by fog, not tinted
1390 if (rsurface.rtlight || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD))
1391 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
1396 // color.rgb *= SceneBrightness;
1397 VectorScale(r_refdef.fogcolor, r_view.colorscale, fogvec);
1398 if(r_glsl_permutation->loc_ContrastBoostCoeff >= 0) // need to support contrast boost
1400 // color.rgb *= ContrastBoost / ((ContrastBoost - 1) * color.rgb + 1);
1401 fogvec[0] *= r_glsl_contrastboost.value / ((r_glsl_contrastboost.value - 1) * fogvec[0] + 1);
1402 fogvec[1] *= r_glsl_contrastboost.value / ((r_glsl_contrastboost.value - 1) * fogvec[1] + 1);
1403 fogvec[2] *= r_glsl_contrastboost.value / ((r_glsl_contrastboost.value - 1) * fogvec[2] + 1);
1405 qglUniform3fARB(r_glsl_permutation->loc_FogColor, fogvec[0], fogvec[1], fogvec[2]);
1408 qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
1410 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.modelorg[0], rsurface.modelorg[1], rsurface.modelorg[2]);
1411 if (r_glsl_permutation->loc_Color_Pants >= 0)
1413 if (rsurface.texture->currentskinframe->pants)
1414 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
1416 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
1418 if (r_glsl_permutation->loc_Color_Shirt >= 0)
1420 if (rsurface.texture->currentskinframe->shirt)
1421 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
1423 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
1425 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, r_refdef.fograngerecip);
1426 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower);
1427 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
1428 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);
1429 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]);
1430 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]);
1431 if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f);
1432 if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f);
1433 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
1434 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
1439 #define SKINFRAME_HASH 1024
1443 int loadsequence; // incremented each level change
1444 memexpandablearray_t array;
1445 skinframe_t *hash[SKINFRAME_HASH];
1449 void R_SkinFrame_PrepareForPurge(void)
1451 r_skinframe.loadsequence++;
1452 // wrap it without hitting zero
1453 if (r_skinframe.loadsequence >= 200)
1454 r_skinframe.loadsequence = 1;
1457 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
1461 // mark the skinframe as used for the purging code
1462 skinframe->loadsequence = r_skinframe.loadsequence;
1465 void R_SkinFrame_Purge(void)
1469 for (i = 0;i < SKINFRAME_HASH;i++)
1471 for (s = r_skinframe.hash[i];s;s = s->next)
1473 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
1475 if (s->base == r_texture_notexture) s->base = NULL;
1476 if (s->nmap == r_texture_blanknormalmap)s->nmap = NULL;
1477 if (s->merged == s->base) s->merged = NULL;
1478 if (s->stain ) R_FreeTexture(s->stain );s->stain = NULL;
1479 if (s->merged) R_FreeTexture(s->merged);s->merged = NULL;
1480 if (s->base ) R_FreeTexture(s->base );s->base = NULL;
1481 if (s->pants ) R_FreeTexture(s->pants );s->pants = NULL;
1482 if (s->shirt ) R_FreeTexture(s->shirt );s->shirt = NULL;
1483 if (s->nmap ) R_FreeTexture(s->nmap );s->nmap = NULL;
1484 if (s->gloss ) R_FreeTexture(s->gloss );s->gloss = NULL;
1485 if (s->glow ) R_FreeTexture(s->glow );s->glow = NULL;
1486 if (s->fog ) R_FreeTexture(s->fog );s->fog = NULL;
1487 s->loadsequence = 0;
1493 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
1495 char basename[MAX_QPATH];
1497 Image_StripImageExtension(name, basename, sizeof(basename));
1499 if( last == NULL ) {
1501 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
1502 item = r_skinframe.hash[hashindex];
1507 // linearly search through the hash bucket
1508 for( ; item ; item = item->next ) {
1509 if( !strcmp( item->basename, basename ) ) {
1516 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
1520 char basename[MAX_QPATH];
1522 Image_StripImageExtension(name, basename, sizeof(basename));
1524 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
1525 for (item = r_skinframe.hash[hashindex];item;item = item->next)
1526 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
1530 rtexture_t *dyntexture;
1531 // check whether its a dynamic texture
1532 dyntexture = CL_GetDynTexture( basename );
1533 if (!add && !dyntexture)
1535 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
1536 memset(item, 0, sizeof(*item));
1537 strlcpy(item->basename, basename, sizeof(item->basename));
1538 item->textureflags = textureflags;
1539 item->base = dyntexture;
1540 item->comparewidth = comparewidth;
1541 item->compareheight = compareheight;
1542 item->comparecrc = comparecrc;
1543 item->next = r_skinframe.hash[hashindex];
1544 r_skinframe.hash[hashindex] = item;
1546 R_SkinFrame_MarkUsed(item);
1550 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
1552 // FIXME: it should be possible to disable loading various layers using
1553 // cvars, to prevent wasted loading time and memory usage if the user does
1555 qboolean loadnormalmap = true;
1556 qboolean loadgloss = true;
1557 qboolean loadpantsandshirt = true;
1558 qboolean loadglow = true;
1560 unsigned char *pixels;
1561 unsigned char *bumppixels;
1562 unsigned char *basepixels = NULL;
1563 int basepixels_width;
1564 int basepixels_height;
1565 skinframe_t *skinframe;
1567 if (cls.state == ca_dedicated)
1570 // return an existing skinframe if already loaded
1571 // if loading of the first image fails, don't make a new skinframe as it
1572 // would cause all future lookups of this to be missing
1573 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
1574 if (skinframe && skinframe->base)
1577 basepixels = loadimagepixelsbgra(name, complain, true);
1578 if (basepixels == NULL)
1581 // we've got some pixels to store, so really allocate this new texture now
1583 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
1584 skinframe->stain = NULL;
1585 skinframe->merged = NULL;
1586 skinframe->base = r_texture_notexture;
1587 skinframe->pants = NULL;
1588 skinframe->shirt = NULL;
1589 skinframe->nmap = r_texture_blanknormalmap;
1590 skinframe->gloss = NULL;
1591 skinframe->glow = NULL;
1592 skinframe->fog = NULL;
1594 basepixels_width = image_width;
1595 basepixels_height = image_height;
1596 skinframe->base = R_LoadTexture2D (r_main_texturepool, skinframe->basename, basepixels_width, basepixels_height, basepixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), NULL);
1598 if (textureflags & TEXF_ALPHA)
1600 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
1601 if (basepixels[j] < 255)
1603 if (j < basepixels_width * basepixels_height * 4)
1605 // has transparent pixels
1606 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
1607 for (j = 0;j < image_width * image_height * 4;j += 4)
1612 pixels[j+3] = basepixels[j+3];
1614 skinframe->fog = R_LoadTexture2D (r_main_texturepool, va("%s_mask", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), NULL);
1619 // _norm is the name used by tenebrae and has been adopted as standard
1622 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false)) != NULL)
1624 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), NULL);
1628 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false)) != NULL)
1630 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
1631 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
1632 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), NULL);
1634 Mem_Free(bumppixels);
1636 else if (r_shadow_bumpscale_basetexture.value > 0)
1638 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
1639 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
1640 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), basepixels_width, basepixels_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), NULL);
1644 // _luma is supported for tenebrae compatibility
1645 // (I think it's a very stupid name, but oh well)
1646 // _glow is the preferred name
1647 if (loadglow && ((pixels = loadimagepixelsbgra(va("%s_glow", skinframe->basename), false, false)) != NULL || (pixels = loadimagepixelsbgra(va("%s_luma", skinframe->basename), false, false)) != NULL)) {skinframe->glow = R_LoadTexture2D (r_main_texturepool, va("%s_glow", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_glow.integer ? ~0 : ~TEXF_COMPRESS), NULL);Mem_Free(pixels);pixels = NULL;}
1648 if (loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false)) != NULL) {skinframe->gloss = R_LoadTexture2D (r_main_texturepool, va("%s_gloss", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_gloss.integer ? ~0 : ~TEXF_COMPRESS), NULL);Mem_Free(pixels);pixels = NULL;}
1649 if (loadpantsandshirt && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false)) != NULL) {skinframe->pants = R_LoadTexture2D (r_main_texturepool, va("%s_pants", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), NULL);Mem_Free(pixels);pixels = NULL;}
1650 if (loadpantsandshirt && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false)) != NULL) {skinframe->shirt = R_LoadTexture2D (r_main_texturepool, va("%s_shirt", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), NULL);Mem_Free(pixels);pixels = NULL;}
1653 Mem_Free(basepixels);
1658 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)
1663 for (i = 0;i < width*height;i++)
1664 if (((unsigned char *)&palette[in[i]])[3] > 0)
1666 if (i == width*height)
1669 return R_LoadTexture2D (r_main_texturepool, name, width, height, in, TEXTYPE_PALETTE, textureflags, palette);
1672 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
1673 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
1676 unsigned char *temp1, *temp2;
1677 skinframe_t *skinframe;
1679 if (cls.state == ca_dedicated)
1682 // if already loaded just return it, otherwise make a new skinframe
1683 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
1684 if (skinframe && skinframe->base)
1687 skinframe->stain = NULL;
1688 skinframe->merged = NULL;
1689 skinframe->base = r_texture_notexture;
1690 skinframe->pants = NULL;
1691 skinframe->shirt = NULL;
1692 skinframe->nmap = r_texture_blanknormalmap;
1693 skinframe->gloss = NULL;
1694 skinframe->glow = NULL;
1695 skinframe->fog = NULL;
1697 // if no data was provided, then clearly the caller wanted to get a blank skinframe
1701 if (r_shadow_bumpscale_basetexture.value > 0)
1703 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
1704 temp2 = temp1 + width * height * 4;
1705 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
1706 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
1709 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, skinframe->textureflags, NULL);
1710 if (textureflags & TEXF_ALPHA)
1712 for (i = 3;i < width * height * 4;i += 4)
1713 if (skindata[i] < 255)
1715 if (i < width * height * 4)
1717 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
1718 memcpy(fogpixels, skindata, width * height * 4);
1719 for (i = 0;i < width * height * 4;i += 4)
1720 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
1721 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, skinframe->textureflags, NULL);
1722 Mem_Free(fogpixels);
1729 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
1732 unsigned char *temp1, *temp2;
1733 skinframe_t *skinframe;
1735 if (cls.state == ca_dedicated)
1738 // if already loaded just return it, otherwise make a new skinframe
1739 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
1740 if (skinframe && skinframe->base)
1743 skinframe->stain = NULL;
1744 skinframe->merged = NULL;
1745 skinframe->base = r_texture_notexture;
1746 skinframe->pants = NULL;
1747 skinframe->shirt = NULL;
1748 skinframe->nmap = r_texture_blanknormalmap;
1749 skinframe->gloss = NULL;
1750 skinframe->glow = NULL;
1751 skinframe->fog = NULL;
1753 // if no data was provided, then clearly the caller wanted to get a blank skinframe
1757 if (r_shadow_bumpscale_basetexture.value > 0)
1759 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
1760 temp2 = temp1 + width * height * 4;
1761 // use either a custom palette or the quake palette
1762 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
1763 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
1764 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
1767 // use either a custom palette, or the quake palette
1768 skinframe->base = skinframe->merged = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_merged", skinframe->basename), (loadglowtexture ? palette_bgra_nofullbrights : ((skinframe->textureflags & TEXF_ALPHA) ? palette_bgra_transparent : palette_bgra_complete)), skinframe->textureflags, true); // all
1769 if (loadglowtexture)
1770 skinframe->glow = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_glow", skinframe->basename), palette_bgra_onlyfullbrights, skinframe->textureflags, false); // glow
1771 if (loadpantsandshirt)
1773 skinframe->pants = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_pants", skinframe->basename), palette_bgra_pantsaswhite, skinframe->textureflags, false); // pants
1774 skinframe->shirt = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_shirt", skinframe->basename), palette_bgra_shirtaswhite, skinframe->textureflags, false); // shirt
1776 if (skinframe->pants || skinframe->shirt)
1777 skinframe->base = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_nospecial", skinframe->basename), loadglowtexture ? palette_bgra_nocolormapnofullbrights : palette_bgra_nocolormap, skinframe->textureflags, false); // no special colors
1778 if (textureflags & TEXF_ALPHA)
1780 for (i = 0;i < width * height;i++)
1781 if (((unsigned char *)palette_bgra_alpha)[skindata[i]*4+3] < 255)
1783 if (i < width * height)
1784 skinframe->fog = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_fog", skinframe->basename), palette_bgra_alpha, skinframe->textureflags, true); // fog mask
1790 skinframe_t *R_SkinFrame_LoadMissing(void)
1792 skinframe_t *skinframe;
1794 if (cls.state == ca_dedicated)
1797 skinframe = R_SkinFrame_Find("missing", TEXF_PRECACHE, 0, 0, 0, true);
1798 skinframe->stain = NULL;
1799 skinframe->merged = NULL;
1800 skinframe->base = r_texture_notexture;
1801 skinframe->pants = NULL;
1802 skinframe->shirt = NULL;
1803 skinframe->nmap = r_texture_blanknormalmap;
1804 skinframe->gloss = NULL;
1805 skinframe->glow = NULL;
1806 skinframe->fog = NULL;
1811 void gl_main_start(void)
1816 r = (-1.0/256.0) * (FOGMASKTABLEWIDTH * FOGMASKTABLEWIDTH);
1817 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
1819 alpha = 1 - exp(r / ((double)x*(double)x));
1820 if (x == FOGMASKTABLEWIDTH - 1)
1822 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
1825 memset(r_qwskincache, 0, sizeof(r_qwskincache));
1826 memset(r_qwskincache_skinframe, 0, sizeof(r_qwskincache_skinframe));
1828 // set up r_skinframe loading system for textures
1829 memset(&r_skinframe, 0, sizeof(r_skinframe));
1830 r_skinframe.loadsequence = 1;
1831 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
1833 r_main_texturepool = R_AllocTexturePool();
1834 R_BuildBlankTextures();
1836 if (gl_texturecubemap)
1839 R_BuildNormalizationCube();
1841 R_BuildFogTexture();
1842 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
1843 memset(&r_waterstate, 0, sizeof(r_waterstate));
1844 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
1845 memset(&r_svbsp, 0, sizeof (r_svbsp));
1848 void gl_main_shutdown(void)
1850 memset(r_qwskincache, 0, sizeof(r_qwskincache));
1851 memset(r_qwskincache_skinframe, 0, sizeof(r_qwskincache_skinframe));
1853 // clear out the r_skinframe state
1854 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
1855 memset(&r_skinframe, 0, sizeof(r_skinframe));
1858 Mem_Free(r_svbsp.nodes);
1859 memset(&r_svbsp, 0, sizeof (r_svbsp));
1860 R_FreeTexturePool(&r_main_texturepool);
1861 r_texture_blanknormalmap = NULL;
1862 r_texture_white = NULL;
1863 r_texture_grey128 = NULL;
1864 r_texture_black = NULL;
1865 r_texture_whitecube = NULL;
1866 r_texture_normalizationcube = NULL;
1867 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
1868 memset(&r_waterstate, 0, sizeof(r_waterstate));
1872 extern void CL_ParseEntityLump(char *entitystring);
1873 void gl_main_newmap(void)
1875 // FIXME: move this code to client
1877 char *entities, entname[MAX_QPATH];
1880 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
1881 l = (int)strlen(entname) - 4;
1882 if (l >= 0 && !strcmp(entname + l, ".bsp"))
1884 memcpy(entname + l, ".ent", 5);
1885 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
1887 CL_ParseEntityLump(entities);
1892 if (cl.worldmodel->brush.entities)
1893 CL_ParseEntityLump(cl.worldmodel->brush.entities);
1897 void GL_Main_Init(void)
1899 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
1901 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
1902 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
1903 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
1904 if (gamemode == GAME_NEHAHRA)
1906 Cvar_RegisterVariable (&gl_fogenable);
1907 Cvar_RegisterVariable (&gl_fogdensity);
1908 Cvar_RegisterVariable (&gl_fogred);
1909 Cvar_RegisterVariable (&gl_foggreen);
1910 Cvar_RegisterVariable (&gl_fogblue);
1911 Cvar_RegisterVariable (&gl_fogstart);
1912 Cvar_RegisterVariable (&gl_fogend);
1914 Cvar_RegisterVariable(&r_depthfirst);
1915 Cvar_RegisterVariable(&r_nearclip);
1916 Cvar_RegisterVariable(&r_showbboxes);
1917 Cvar_RegisterVariable(&r_showsurfaces);
1918 Cvar_RegisterVariable(&r_showtris);
1919 Cvar_RegisterVariable(&r_shownormals);
1920 Cvar_RegisterVariable(&r_showlighting);
1921 Cvar_RegisterVariable(&r_showshadowvolumes);
1922 Cvar_RegisterVariable(&r_showcollisionbrushes);
1923 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
1924 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
1925 Cvar_RegisterVariable(&r_showdisabledepthtest);
1926 Cvar_RegisterVariable(&r_drawportals);
1927 Cvar_RegisterVariable(&r_drawentities);
1928 Cvar_RegisterVariable(&r_cullentities_trace);
1929 Cvar_RegisterVariable(&r_cullentities_trace_samples);
1930 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
1931 Cvar_RegisterVariable(&r_cullentities_trace_delay);
1932 Cvar_RegisterVariable(&r_drawviewmodel);
1933 Cvar_RegisterVariable(&r_speeds);
1934 Cvar_RegisterVariable(&r_fullbrights);
1935 Cvar_RegisterVariable(&r_wateralpha);
1936 Cvar_RegisterVariable(&r_dynamic);
1937 Cvar_RegisterVariable(&r_fullbright);
1938 Cvar_RegisterVariable(&r_shadows);
1939 Cvar_RegisterVariable(&r_shadows_throwdistance);
1940 Cvar_RegisterVariable(&r_q1bsp_skymasking);
1941 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
1942 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
1943 Cvar_RegisterVariable(&r_textureunits);
1944 Cvar_RegisterVariable(&r_glsl);
1945 Cvar_RegisterVariable(&r_glsl_offsetmapping);
1946 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
1947 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
1948 Cvar_RegisterVariable(&r_glsl_deluxemapping);
1949 Cvar_RegisterVariable(&r_water);
1950 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
1951 Cvar_RegisterVariable(&r_water_clippingplanebias);
1952 Cvar_RegisterVariable(&r_water_refractdistort);
1953 Cvar_RegisterVariable(&r_water_reflectdistort);
1954 Cvar_RegisterVariable(&r_lerpsprites);
1955 Cvar_RegisterVariable(&r_lerpmodels);
1956 Cvar_RegisterVariable(&r_waterscroll);
1957 Cvar_RegisterVariable(&r_bloom);
1958 Cvar_RegisterVariable(&r_bloom_colorscale);
1959 Cvar_RegisterVariable(&r_bloom_brighten);
1960 Cvar_RegisterVariable(&r_bloom_blur);
1961 Cvar_RegisterVariable(&r_bloom_resolution);
1962 Cvar_RegisterVariable(&r_bloom_colorexponent);
1963 Cvar_RegisterVariable(&r_bloom_colorsubtract);
1964 Cvar_RegisterVariable(&r_hdr);
1965 Cvar_RegisterVariable(&r_hdr_scenebrightness);
1966 Cvar_RegisterVariable(&r_glsl_contrastboost);
1967 Cvar_RegisterVariable(&r_hdr_glowintensity);
1968 Cvar_RegisterVariable(&r_hdr_range);
1969 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
1970 Cvar_RegisterVariable(&developer_texturelogging);
1971 Cvar_RegisterVariable(&gl_lightmaps);
1972 Cvar_RegisterVariable(&r_test);
1973 Cvar_RegisterVariable(&r_batchmode);
1974 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
1975 Cvar_SetValue("r_fullbrights", 0);
1976 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
1978 Cvar_RegisterVariable(&r_track_sprites);
1979 Cvar_RegisterVariable(&r_track_sprites_flags);
1980 Cvar_RegisterVariable(&r_track_sprites_scalew);
1981 Cvar_RegisterVariable(&r_track_sprites_scaleh);
1984 extern void R_Textures_Init(void);
1985 extern void GL_Draw_Init(void);
1986 extern void GL_Main_Init(void);
1987 extern void R_Shadow_Init(void);
1988 extern void R_Sky_Init(void);
1989 extern void GL_Surf_Init(void);
1990 extern void R_Light_Init(void);
1991 extern void R_Particles_Init(void);
1992 extern void R_Explosion_Init(void);
1993 extern void gl_backend_init(void);
1994 extern void Sbar_Init(void);
1995 extern void R_LightningBeams_Init(void);
1996 extern void Mod_RenderInit(void);
1998 void Render_Init(void)
2011 R_LightningBeams_Init();
2020 extern char *ENGINE_EXTENSIONS;
2023 VID_CheckExtensions();
2025 // LordHavoc: report supported extensions
2026 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
2028 // clear to black (loading plaque will be seen over this)
2030 qglClearColor(0,0,0,1);CHECKGLERROR
2031 qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
2034 int R_CullBox(const vec3_t mins, const vec3_t maxs)
2038 for (i = 0;i < r_view.numfrustumplanes;i++)
2040 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
2043 p = r_view.frustum + i;
2048 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2052 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2056 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2060 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2064 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2068 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2072 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2076 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2084 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
2088 for (i = 0;i < numplanes;i++)
2095 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2099 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2103 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2107 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2111 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2115 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2119 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2123 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2131 //==================================================================================
2133 static void R_UpdateEntityLighting(entity_render_t *ent)
2135 vec3_t tempdiffusenormal;
2137 // fetch the lighting from the worldmodel data
2138 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));
2139 VectorClear(ent->modellight_diffuse);
2140 VectorClear(tempdiffusenormal);
2141 if ((ent->flags & RENDER_LIGHT) && r_refdef.worldmodel && r_refdef.worldmodel->brush.LightPoint)
2144 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
2145 r_refdef.worldmodel->brush.LightPoint(r_refdef.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
2148 VectorSet(ent->modellight_ambient, 1, 1, 1);
2150 // move the light direction into modelspace coordinates for lighting code
2151 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
2152 if(VectorLength2(ent->modellight_lightdir) > 0)
2154 VectorNormalize(ent->modellight_lightdir);
2158 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
2161 // scale ambient and directional light contributions according to rendering variables
2162 ent->modellight_ambient[0] *= ent->colormod[0] * r_refdef.lightmapintensity;
2163 ent->modellight_ambient[1] *= ent->colormod[1] * r_refdef.lightmapintensity;
2164 ent->modellight_ambient[2] *= ent->colormod[2] * r_refdef.lightmapintensity;
2165 ent->modellight_diffuse[0] *= ent->colormod[0] * r_refdef.lightmapintensity;
2166 ent->modellight_diffuse[1] *= ent->colormod[1] * r_refdef.lightmapintensity;
2167 ent->modellight_diffuse[2] *= ent->colormod[2] * r_refdef.lightmapintensity;
2170 static void R_View_UpdateEntityVisible (void)
2173 entity_render_t *ent;
2175 if (!r_drawentities.integer)
2178 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : ((chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL : RENDER_EXTERIORMODEL);
2179 if (r_refdef.worldmodel && r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs)
2181 // worldmodel can check visibility
2182 for (i = 0;i < r_refdef.numentities;i++)
2184 ent = r_refdef.entities[i];
2185 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));
2188 if(r_cullentities_trace.integer)
2190 for (i = 0;i < r_refdef.numentities;i++)
2192 ent = r_refdef.entities[i];
2193 if(r_viewcache.entityvisible[i] && !(ent->effects & EF_NODEPTHTEST) && !(ent->flags & RENDER_VIEWMODEL) && !(ent->model && (ent->model->name[0] == '*')))
2195 if(Mod_CanSeeBox_Trace(r_cullentities_trace_samples.integer, r_cullentities_trace_enlarge.value, r_refdef.worldmodel, r_view.origin, ent->mins, ent->maxs))
2196 ent->last_trace_visibility = realtime;
2197 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
2198 r_viewcache.entityvisible[i] = 0;
2205 // no worldmodel or it can't check visibility
2206 for (i = 0;i < r_refdef.numentities;i++)
2208 ent = r_refdef.entities[i];
2209 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));
2213 // update entity lighting (even on hidden entities for r_shadows)
2214 for (i = 0;i < r_refdef.numentities;i++)
2215 R_UpdateEntityLighting(r_refdef.entities[i]);
2218 // only used if skyrendermasked, and normally returns false
2219 int R_DrawBrushModelsSky (void)
2222 entity_render_t *ent;
2224 if (!r_drawentities.integer)
2228 for (i = 0;i < r_refdef.numentities;i++)
2230 if (!r_viewcache.entityvisible[i])
2232 ent = r_refdef.entities[i];
2233 if (!ent->model || !ent->model->DrawSky)
2235 ent->model->DrawSky(ent);
2241 static void R_DrawNoModel(entity_render_t *ent);
2242 static void R_DrawModels(void)
2245 entity_render_t *ent;
2247 if (!r_drawentities.integer)
2250 for (i = 0;i < r_refdef.numentities;i++)
2252 if (!r_viewcache.entityvisible[i])
2254 ent = r_refdef.entities[i];
2255 r_refdef.stats.entities++;
2256 if (ent->model && ent->model->Draw != NULL)
2257 ent->model->Draw(ent);
2263 static void R_DrawModelsDepth(void)
2266 entity_render_t *ent;
2268 if (!r_drawentities.integer)
2271 for (i = 0;i < r_refdef.numentities;i++)
2273 if (!r_viewcache.entityvisible[i])
2275 ent = r_refdef.entities[i];
2276 if (ent->model && ent->model->DrawDepth != NULL)
2277 ent->model->DrawDepth(ent);
2281 static void R_DrawModelsDebug(void)
2284 entity_render_t *ent;
2286 if (!r_drawentities.integer)
2289 for (i = 0;i < r_refdef.numentities;i++)
2291 if (!r_viewcache.entityvisible[i])
2293 ent = r_refdef.entities[i];
2294 if (ent->model && ent->model->DrawDebug != NULL)
2295 ent->model->DrawDebug(ent);
2299 static void R_DrawModelsAddWaterPlanes(void)
2302 entity_render_t *ent;
2304 if (!r_drawentities.integer)
2307 for (i = 0;i < r_refdef.numentities;i++)
2309 if (!r_viewcache.entityvisible[i])
2311 ent = r_refdef.entities[i];
2312 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
2313 ent->model->DrawAddWaterPlanes(ent);
2317 static void R_View_SetFrustum(void)
2320 double slopex, slopey;
2322 // break apart the view matrix into vectors for various purposes
2323 Matrix4x4_ToVectors(&r_view.matrix, r_view.forward, r_view.left, r_view.up, r_view.origin);
2324 VectorNegate(r_view.left, r_view.right);
2327 r_view.frustum[0].normal[0] = 0 - 1.0 / r_view.frustum_x;
2328 r_view.frustum[0].normal[1] = 0 - 0;
2329 r_view.frustum[0].normal[2] = -1 - 0;
2330 r_view.frustum[1].normal[0] = 0 + 1.0 / r_view.frustum_x;
2331 r_view.frustum[1].normal[1] = 0 + 0;
2332 r_view.frustum[1].normal[2] = -1 + 0;
2333 r_view.frustum[2].normal[0] = 0 - 0;
2334 r_view.frustum[2].normal[1] = 0 - 1.0 / r_view.frustum_y;
2335 r_view.frustum[2].normal[2] = -1 - 0;
2336 r_view.frustum[3].normal[0] = 0 + 0;
2337 r_view.frustum[3].normal[1] = 0 + 1.0 / r_view.frustum_y;
2338 r_view.frustum[3].normal[2] = -1 + 0;
2342 zNear = r_refdef.nearclip;
2343 nudge = 1.0 - 1.0 / (1<<23);
2344 r_view.frustum[4].normal[0] = 0 - 0;
2345 r_view.frustum[4].normal[1] = 0 - 0;
2346 r_view.frustum[4].normal[2] = -1 - -nudge;
2347 r_view.frustum[4].dist = 0 - -2 * zNear * nudge;
2348 r_view.frustum[5].normal[0] = 0 + 0;
2349 r_view.frustum[5].normal[1] = 0 + 0;
2350 r_view.frustum[5].normal[2] = -1 + -nudge;
2351 r_view.frustum[5].dist = 0 + -2 * zNear * nudge;
2357 r_view.frustum[0].normal[0] = m[3] - m[0];
2358 r_view.frustum[0].normal[1] = m[7] - m[4];
2359 r_view.frustum[0].normal[2] = m[11] - m[8];
2360 r_view.frustum[0].dist = m[15] - m[12];
2362 r_view.frustum[1].normal[0] = m[3] + m[0];
2363 r_view.frustum[1].normal[1] = m[7] + m[4];
2364 r_view.frustum[1].normal[2] = m[11] + m[8];
2365 r_view.frustum[1].dist = m[15] + m[12];
2367 r_view.frustum[2].normal[0] = m[3] - m[1];
2368 r_view.frustum[2].normal[1] = m[7] - m[5];
2369 r_view.frustum[2].normal[2] = m[11] - m[9];
2370 r_view.frustum[2].dist = m[15] - m[13];
2372 r_view.frustum[3].normal[0] = m[3] + m[1];
2373 r_view.frustum[3].normal[1] = m[7] + m[5];
2374 r_view.frustum[3].normal[2] = m[11] + m[9];
2375 r_view.frustum[3].dist = m[15] + m[13];
2377 r_view.frustum[4].normal[0] = m[3] - m[2];
2378 r_view.frustum[4].normal[1] = m[7] - m[6];
2379 r_view.frustum[4].normal[2] = m[11] - m[10];
2380 r_view.frustum[4].dist = m[15] - m[14];
2382 r_view.frustum[5].normal[0] = m[3] + m[2];
2383 r_view.frustum[5].normal[1] = m[7] + m[6];
2384 r_view.frustum[5].normal[2] = m[11] + m[10];
2385 r_view.frustum[5].dist = m[15] + m[14];
2388 if (r_view.useperspective)
2390 slopex = 1.0 / r_view.frustum_x;
2391 slopey = 1.0 / r_view.frustum_y;
2392 VectorMA(r_view.forward, -slopex, r_view.left, r_view.frustum[0].normal);
2393 VectorMA(r_view.forward, slopex, r_view.left, r_view.frustum[1].normal);
2394 VectorMA(r_view.forward, -slopey, r_view.up , r_view.frustum[2].normal);
2395 VectorMA(r_view.forward, slopey, r_view.up , r_view.frustum[3].normal);
2396 VectorCopy(r_view.forward, r_view.frustum[4].normal);
2398 // Leaving those out was a mistake, those were in the old code, and they
2399 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
2400 // I couldn't reproduce it after adding those normalizations. --blub
2401 VectorNormalize(r_view.frustum[0].normal);
2402 VectorNormalize(r_view.frustum[1].normal);
2403 VectorNormalize(r_view.frustum[2].normal);
2404 VectorNormalize(r_view.frustum[3].normal);
2406 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
2407 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, -1024 * slopex, r_view.left, -1024 * slopey, r_view.up, r_view.frustumcorner[0]);
2408 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, 1024 * slopex, r_view.left, -1024 * slopey, r_view.up, r_view.frustumcorner[1]);
2409 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, -1024 * slopex, r_view.left, 1024 * slopey, r_view.up, r_view.frustumcorner[2]);
2410 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, 1024 * slopex, r_view.left, 1024 * slopey, r_view.up, r_view.frustumcorner[3]);
2412 r_view.frustum[0].dist = DotProduct (r_view.origin, r_view.frustum[0].normal);
2413 r_view.frustum[1].dist = DotProduct (r_view.origin, r_view.frustum[1].normal);
2414 r_view.frustum[2].dist = DotProduct (r_view.origin, r_view.frustum[2].normal);
2415 r_view.frustum[3].dist = DotProduct (r_view.origin, r_view.frustum[3].normal);
2416 r_view.frustum[4].dist = DotProduct (r_view.origin, r_view.frustum[4].normal) + r_refdef.nearclip;
2420 VectorScale(r_view.left, -r_view.ortho_x, r_view.frustum[0].normal);
2421 VectorScale(r_view.left, r_view.ortho_x, r_view.frustum[1].normal);
2422 VectorScale(r_view.up, -r_view.ortho_y, r_view.frustum[2].normal);
2423 VectorScale(r_view.up, r_view.ortho_y, r_view.frustum[3].normal);
2424 VectorCopy(r_view.forward, r_view.frustum[4].normal);
2425 r_view.frustum[0].dist = DotProduct (r_view.origin, r_view.frustum[0].normal) + r_view.ortho_x;
2426 r_view.frustum[1].dist = DotProduct (r_view.origin, r_view.frustum[1].normal) + r_view.ortho_x;
2427 r_view.frustum[2].dist = DotProduct (r_view.origin, r_view.frustum[2].normal) + r_view.ortho_y;
2428 r_view.frustum[3].dist = DotProduct (r_view.origin, r_view.frustum[3].normal) + r_view.ortho_y;
2429 r_view.frustum[4].dist = DotProduct (r_view.origin, r_view.frustum[4].normal) + r_refdef.nearclip;
2431 r_view.numfrustumplanes = 5;
2433 if (r_view.useclipplane)
2435 r_view.numfrustumplanes = 6;
2436 r_view.frustum[5] = r_view.clipplane;
2439 for (i = 0;i < r_view.numfrustumplanes;i++)
2440 PlaneClassify(r_view.frustum + i);
2442 // LordHavoc: note to all quake engine coders, Quake had a special case
2443 // for 90 degrees which assumed a square view (wrong), so I removed it,
2444 // Quake2 has it disabled as well.
2446 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
2447 //RotatePointAroundVector( r_view.frustum[0].normal, r_view.up, r_view.forward, -(90 - r_refdef.fov_x / 2));
2448 //r_view.frustum[0].dist = DotProduct (r_view.origin, frustum[0].normal);
2449 //PlaneClassify(&frustum[0]);
2451 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
2452 //RotatePointAroundVector( r_view.frustum[1].normal, r_view.up, r_view.forward, (90 - r_refdef.fov_x / 2));
2453 //r_view.frustum[1].dist = DotProduct (r_view.origin, frustum[1].normal);
2454 //PlaneClassify(&frustum[1]);
2456 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
2457 //RotatePointAroundVector( r_view.frustum[2].normal, r_view.left, r_view.forward, -(90 - r_refdef.fov_y / 2));
2458 //r_view.frustum[2].dist = DotProduct (r_view.origin, frustum[2].normal);
2459 //PlaneClassify(&frustum[2]);
2461 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
2462 //RotatePointAroundVector( r_view.frustum[3].normal, r_view.left, r_view.forward, (90 - r_refdef.fov_y / 2));
2463 //r_view.frustum[3].dist = DotProduct (r_view.origin, frustum[3].normal);
2464 //PlaneClassify(&frustum[3]);
2467 //VectorCopy(r_view.forward, r_view.frustum[4].normal);
2468 //r_view.frustum[4].dist = DotProduct (r_view.origin, frustum[4].normal) + r_nearclip.value;
2469 //PlaneClassify(&frustum[4]);
2472 void R_View_Update(void)
2474 R_View_SetFrustum();
2475 R_View_WorldVisibility(r_view.useclipplane);
2476 R_View_UpdateEntityVisible();
2479 void R_SetupView(void)
2481 if (!r_view.useperspective)
2482 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);
2483 else if (r_refdef.rtworldshadows || r_refdef.rtdlightshadows)
2484 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_view.frustum_x, r_view.frustum_y, r_refdef.nearclip);
2486 GL_SetupView_Mode_Perspective(r_view.frustum_x, r_view.frustum_y, r_refdef.nearclip, r_refdef.farclip);
2488 GL_SetupView_Orientation_FromEntity(&r_view.matrix);
2490 if (r_view.useclipplane)
2492 // LordHavoc: couldn't figure out how to make this approach the
2493 vec_t dist = r_view.clipplane.dist - r_water_clippingplanebias.value;
2494 vec_t viewdist = DotProduct(r_view.origin, r_view.clipplane.normal);
2495 if (viewdist < r_view.clipplane.dist + r_water_clippingplanebias.value)
2496 dist = r_view.clipplane.dist;
2497 GL_SetupView_ApplyCustomNearClipPlane(r_view.clipplane.normal[0], r_view.clipplane.normal[1], r_view.clipplane.normal[2], dist);
2501 void R_ResetViewRendering2D(void)
2503 if (gl_support_fragment_shader)
2505 qglUseProgramObjectARB(0);CHECKGLERROR
2510 // GL is weird because it's bottom to top, r_view.y is top to bottom
2511 qglViewport(r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
2512 GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
2513 GL_Scissor(r_view.x, r_view.y, r_view.width, r_view.height);
2514 GL_Color(1, 1, 1, 1);
2515 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
2516 GL_BlendFunc(GL_ONE, GL_ZERO);
2517 GL_AlphaTest(false);
2518 GL_ScissorTest(false);
2519 GL_DepthMask(false);
2520 GL_DepthRange(0, 1);
2521 GL_DepthTest(false);
2522 R_Mesh_Matrix(&identitymatrix);
2523 R_Mesh_ResetTextureState();
2524 GL_PolygonOffset(0, 0);
2525 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
2526 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
2527 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
2528 qglStencilMask(~0);CHECKGLERROR
2529 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
2530 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
2531 GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
2534 void R_ResetViewRendering3D(void)
2536 if (gl_support_fragment_shader)
2538 qglUseProgramObjectARB(0);CHECKGLERROR
2543 // GL is weird because it's bottom to top, r_view.y is top to bottom
2544 qglViewport(r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
2546 GL_Scissor(r_view.x, r_view.y, r_view.width, r_view.height);
2547 GL_Color(1, 1, 1, 1);
2548 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
2549 GL_BlendFunc(GL_ONE, GL_ZERO);
2550 GL_AlphaTest(false);
2551 GL_ScissorTest(true);
2553 GL_DepthRange(0, 1);
2555 R_Mesh_Matrix(&identitymatrix);
2556 R_Mesh_ResetTextureState();
2557 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
2558 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
2559 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
2560 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
2561 qglStencilMask(~0);CHECKGLERROR
2562 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
2563 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
2564 GL_CullFace(r_view.cullface_back);
2568 R_Bloom_SetupShader(
2570 "// written by Forest 'LordHavoc' Hale\n"
2572 "// common definitions between vertex shader and fragment shader:\n"
2574 "#ifdef __GLSL_CG_DATA_TYPES\n"
2575 "#define myhalf half\n"
2576 "#define myhvec2 hvec2\n"
2577 "#define myhvec3 hvec3\n"
2578 "#define myhvec4 hvec4\n"
2580 "#define myhalf float\n"
2581 "#define myhvec2 vec2\n"
2582 "#define myhvec3 vec3\n"
2583 "#define myhvec4 vec4\n"
2586 "varying vec2 ScreenTexCoord;\n"
2587 "varying vec2 BloomTexCoord;\n"
2592 "// vertex shader specific:\n"
2593 "#ifdef VERTEX_SHADER\n"
2597 " ScreenTexCoord = vec2(gl_MultiTexCoord0);\n"
2598 " BloomTexCoord = vec2(gl_MultiTexCoord1);\n"
2599 " // transform vertex to camera space, using ftransform to match non-VS\n"
2601 " gl_Position = ftransform();\n"
2604 "#endif // VERTEX_SHADER\n"
2609 "// fragment shader specific:\n"
2610 "#ifdef FRAGMENT_SHADER\n"
2615 " myhvec3 color = myhvec3(texture2D(Texture_Screen, ScreenTexCoord));\n"
2616 " for (x = -BLUR_X;x <= BLUR_X;x++)
2617 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2618 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2619 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2620 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2622 " gl_FragColor = vec4(color);\n"
2625 "#endif // FRAGMENT_SHADER\n"
2628 void R_RenderScene(qboolean addwaterplanes);
2630 static void R_Water_StartFrame(void)
2633 int waterwidth, waterheight, texturewidth, textureheight;
2634 r_waterstate_waterplane_t *p;
2636 // set waterwidth and waterheight to the water resolution that will be
2637 // used (often less than the screen resolution for faster rendering)
2638 waterwidth = (int)bound(1, r_view.width * r_water_resolutionmultiplier.value, r_view.width);
2639 waterheight = (int)bound(1, r_view.height * r_water_resolutionmultiplier.value, r_view.height);
2641 // calculate desired texture sizes
2642 // can't use water if the card does not support the texture size
2643 if (!r_water.integer || !r_glsl.integer || !gl_support_fragment_shader || waterwidth > gl_max_texture_size || waterheight > gl_max_texture_size)
2644 texturewidth = textureheight = waterwidth = waterheight = 0;
2645 else if (gl_support_arb_texture_non_power_of_two)
2647 texturewidth = waterwidth;
2648 textureheight = waterheight;
2652 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
2653 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
2656 // allocate textures as needed
2657 if (r_waterstate.waterwidth != waterwidth || r_waterstate.waterheight != waterheight || r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight)
2659 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
2660 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
2662 if (p->texture_refraction)
2663 R_FreeTexture(p->texture_refraction);
2664 p->texture_refraction = NULL;
2665 if (p->texture_reflection)
2666 R_FreeTexture(p->texture_reflection);
2667 p->texture_reflection = NULL;
2669 memset(&r_waterstate, 0, sizeof(r_waterstate));
2670 r_waterstate.waterwidth = waterwidth;
2671 r_waterstate.waterheight = waterheight;
2672 r_waterstate.texturewidth = texturewidth;
2673 r_waterstate.textureheight = textureheight;
2676 if (r_waterstate.waterwidth)
2678 r_waterstate.enabled = true;
2680 // set up variables that will be used in shader setup
2681 r_waterstate.screenscale[0] = 0.5f * (float)waterwidth / (float)texturewidth;
2682 r_waterstate.screenscale[1] = 0.5f * (float)waterheight / (float)textureheight;
2683 r_waterstate.screencenter[0] = 0.5f * (float)waterwidth / (float)texturewidth;
2684 r_waterstate.screencenter[1] = 0.5f * (float)waterheight / (float)textureheight;
2687 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
2688 r_waterstate.numwaterplanes = 0;
2691 static void R_Water_AddWaterPlane(msurface_t *surface)
2693 int triangleindex, planeindex;
2699 r_waterstate_waterplane_t *p;
2700 // just use the first triangle with a valid normal for any decisions
2701 VectorClear(normal);
2702 VectorClear(center);
2703 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
2705 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
2706 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
2707 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
2708 TriangleNormal(vert[0], vert[1], vert[2], normal);
2709 if (VectorLength2(normal) >= 0.001)
2712 // now find the center of this surface
2713 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles*3;triangleindex++, e++)
2715 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
2716 VectorAdd(center, vert[0], center);
2718 f = 1.0 / surface->num_triangles*3;
2719 VectorScale(center, f, center);
2721 // find a matching plane if there is one
2722 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
2723 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
2725 if (planeindex >= r_waterstate.maxwaterplanes)
2726 return; // nothing we can do, out of planes
2728 // if this triangle does not fit any known plane rendered this frame, add one
2729 if (planeindex >= r_waterstate.numwaterplanes)
2731 // store the new plane
2732 r_waterstate.numwaterplanes++;
2733 VectorCopy(normal, p->plane.normal);
2734 VectorNormalize(p->plane.normal);
2735 p->plane.dist = DotProduct(vert[0], p->plane.normal);
2736 PlaneClassify(&p->plane);
2737 // flip the plane if it does not face the viewer
2738 if (PlaneDiff(r_view.origin, &p->plane) < 0)
2740 VectorNegate(p->plane.normal, p->plane.normal);
2741 p->plane.dist *= -1;
2742 PlaneClassify(&p->plane);
2744 // clear materialflags and pvs
2745 p->materialflags = 0;
2746 p->pvsvalid = false;
2748 // merge this surface's materialflags into the waterplane
2749 p->materialflags |= surface->texture->currentframe->currentmaterialflags;
2750 // merge this surface's PVS into the waterplane
2751 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.worldmodel && r_refdef.worldmodel->brush.FatPVS)
2753 r_refdef.worldmodel->brush.FatPVS(r_refdef.worldmodel, r_view.origin, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
2758 static void R_Water_ProcessPlanes(void)
2760 r_view_t originalview;
2762 r_waterstate_waterplane_t *p;
2764 originalview = r_view;
2766 // make sure enough textures are allocated
2767 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
2769 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
2771 if (!p->texture_refraction)
2772 p->texture_refraction = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_refraction", planeindex), r_waterstate.texturewidth, r_waterstate.textureheight, NULL, TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
2773 if (!p->texture_refraction)
2777 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
2779 if (!p->texture_reflection)
2780 p->texture_reflection = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_reflection", planeindex), r_waterstate.texturewidth, r_waterstate.textureheight, NULL, TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
2781 if (!p->texture_reflection)
2787 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
2789 r_view.showdebug = false;
2790 r_view.width = r_waterstate.waterwidth;
2791 r_view.height = r_waterstate.waterheight;
2792 r_view.useclipplane = true;
2793 r_waterstate.renderingscene = true;
2795 // render the normal view scene and copy into texture
2796 // (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)
2797 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
2799 r_view.clipplane = p->plane;
2800 VectorNegate(r_view.clipplane.normal, r_view.clipplane.normal);
2801 r_view.clipplane.dist = -r_view.clipplane.dist;
2802 PlaneClassify(&r_view.clipplane);
2804 R_RenderScene(false);
2806 // copy view into the screen texture
2807 R_Mesh_TexBind(0, R_GetTexture(p->texture_refraction));
2808 GL_ActiveTexture(0);
2810 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
2813 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
2815 // render reflected scene and copy into texture
2816 Matrix4x4_Reflect(&r_view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
2817 r_view.clipplane = p->plane;
2818 // reverse the cullface settings for this render
2819 r_view.cullface_front = GL_FRONT;
2820 r_view.cullface_back = GL_BACK;
2821 if (r_refdef.worldmodel && r_refdef.worldmodel->brush.num_pvsclusterbytes)
2823 r_view.usecustompvs = true;
2825 memcpy(r_viewcache.world_pvsbits, p->pvsbits, r_refdef.worldmodel->brush.num_pvsclusterbytes);
2827 memset(r_viewcache.world_pvsbits, 0xFF, r_refdef.worldmodel->brush.num_pvsclusterbytes);
2830 R_ResetViewRendering3D();
2832 if (r_timereport_active)
2833 R_TimeReport("viewclear");
2835 R_RenderScene(false);
2837 R_Mesh_TexBind(0, R_GetTexture(p->texture_reflection));
2838 GL_ActiveTexture(0);
2840 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
2842 R_ResetViewRendering3D();
2844 if (r_timereport_active)
2845 R_TimeReport("viewclear");
2848 r_view = originalview;
2849 r_view.clear = true;
2850 r_waterstate.renderingscene = false;
2854 r_view = originalview;
2855 r_waterstate.renderingscene = false;
2856 Cvar_SetValueQuick(&r_water, 0);
2857 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
2861 void R_Bloom_StartFrame(void)
2863 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
2865 // set bloomwidth and bloomheight to the bloom resolution that will be
2866 // used (often less than the screen resolution for faster rendering)
2867 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_view.width);
2868 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_view.height / r_view.width;
2869 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_view.height);
2871 // calculate desired texture sizes
2872 if (gl_support_arb_texture_non_power_of_two)
2874 screentexturewidth = r_view.width;
2875 screentextureheight = r_view.height;
2876 bloomtexturewidth = r_bloomstate.bloomwidth;
2877 bloomtextureheight = r_bloomstate.bloomheight;
2881 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
2882 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
2883 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
2884 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
2889 screentexturewidth = screentextureheight = 0;
2891 else if (r_bloom.integer)
2896 screentexturewidth = screentextureheight = 0;
2897 bloomtexturewidth = bloomtextureheight = 0;
2900 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)
2902 // can't use bloom if the parameters are too weird
2903 // can't use bloom if the card does not support the texture size
2904 if (r_bloomstate.texture_screen)
2905 R_FreeTexture(r_bloomstate.texture_screen);
2906 if (r_bloomstate.texture_bloom)
2907 R_FreeTexture(r_bloomstate.texture_bloom);
2908 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
2912 r_bloomstate.enabled = true;
2913 r_bloomstate.hdr = r_hdr.integer != 0;
2915 // allocate textures as needed
2916 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
2918 if (r_bloomstate.texture_screen)
2919 R_FreeTexture(r_bloomstate.texture_screen);
2920 r_bloomstate.texture_screen = NULL;
2921 r_bloomstate.screentexturewidth = screentexturewidth;
2922 r_bloomstate.screentextureheight = screentextureheight;
2923 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
2924 r_bloomstate.texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, TEXTYPE_BGRA, TEXF_FORCENEAREST | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
2926 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
2928 if (r_bloomstate.texture_bloom)
2929 R_FreeTexture(r_bloomstate.texture_bloom);
2930 r_bloomstate.texture_bloom = NULL;
2931 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
2932 r_bloomstate.bloomtextureheight = bloomtextureheight;
2933 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
2934 r_bloomstate.texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", r_bloomstate.bloomtexturewidth, r_bloomstate.bloomtextureheight, NULL, TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
2937 // set up a texcoord array for the full resolution screen image
2938 // (we have to keep this around to copy back during final render)
2939 r_bloomstate.screentexcoord2f[0] = 0;
2940 r_bloomstate.screentexcoord2f[1] = (float)r_view.height / (float)r_bloomstate.screentextureheight;
2941 r_bloomstate.screentexcoord2f[2] = (float)r_view.width / (float)r_bloomstate.screentexturewidth;
2942 r_bloomstate.screentexcoord2f[3] = (float)r_view.height / (float)r_bloomstate.screentextureheight;
2943 r_bloomstate.screentexcoord2f[4] = (float)r_view.width / (float)r_bloomstate.screentexturewidth;
2944 r_bloomstate.screentexcoord2f[5] = 0;
2945 r_bloomstate.screentexcoord2f[6] = 0;
2946 r_bloomstate.screentexcoord2f[7] = 0;
2948 // set up a texcoord array for the reduced resolution bloom image
2949 // (which will be additive blended over the screen image)
2950 r_bloomstate.bloomtexcoord2f[0] = 0;
2951 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
2952 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
2953 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
2954 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
2955 r_bloomstate.bloomtexcoord2f[5] = 0;
2956 r_bloomstate.bloomtexcoord2f[6] = 0;
2957 r_bloomstate.bloomtexcoord2f[7] = 0;
2960 void R_Bloom_CopyScreenTexture(float colorscale)
2962 r_refdef.stats.bloom++;
2964 R_ResetViewRendering2D();
2965 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
2966 R_Mesh_ColorPointer(NULL, 0, 0);
2967 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
2968 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
2970 // copy view into the screen texture
2971 GL_ActiveTexture(0);
2973 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
2974 r_refdef.stats.bloom_copypixels += r_view.width * r_view.height;
2976 // now scale it down to the bloom texture size
2978 qglViewport(r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
2979 GL_BlendFunc(GL_ONE, GL_ZERO);
2980 GL_Color(colorscale, colorscale, colorscale, 1);
2981 // TODO: optimize with multitexture or GLSL
2982 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2983 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2985 // we now have a bloom image in the framebuffer
2986 // copy it into the bloom image texture for later processing
2987 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2988 GL_ActiveTexture(0);
2990 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
2991 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2994 void R_Bloom_CopyHDRTexture(void)
2996 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2997 GL_ActiveTexture(0);
2999 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
3000 r_refdef.stats.bloom_copypixels += r_view.width * r_view.height;
3003 void R_Bloom_MakeTexture(void)
3006 float xoffset, yoffset, r, brighten;
3008 r_refdef.stats.bloom++;
3010 R_ResetViewRendering2D();
3011 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3012 R_Mesh_ColorPointer(NULL, 0, 0);
3014 // we have a bloom image in the framebuffer
3016 qglViewport(r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
3018 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
3021 r = bound(0, r_bloom_colorexponent.value / x, 1);
3022 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
3023 GL_Color(r, r, r, 1);
3024 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3025 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3026 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3027 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3029 // copy the vertically blurred bloom view to a texture
3030 GL_ActiveTexture(0);
3032 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
3033 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3036 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
3037 brighten = r_bloom_brighten.value;
3039 brighten *= r_hdr_range.value;
3040 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3041 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
3043 for (dir = 0;dir < 2;dir++)
3045 // blend on at multiple vertical offsets to achieve a vertical blur
3046 // TODO: do offset blends using GLSL
3047 GL_BlendFunc(GL_ONE, GL_ZERO);
3048 for (x = -range;x <= range;x++)
3050 if (!dir){xoffset = 0;yoffset = x;}
3051 else {xoffset = x;yoffset = 0;}
3052 xoffset /= (float)r_bloomstate.bloomtexturewidth;
3053 yoffset /= (float)r_bloomstate.bloomtextureheight;
3054 // compute a texcoord array with the specified x and y offset
3055 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
3056 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3057 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3058 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3059 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3060 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
3061 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
3062 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
3063 // this r value looks like a 'dot' particle, fading sharply to
3064 // black at the edges
3065 // (probably not realistic but looks good enough)
3066 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
3067 //r = (dir ? 1.0f : brighten)/(range*2+1);
3068 r = (dir ? 1.0f : brighten)/(range*2+1)*(1 - x*x/(float)(range*range));
3069 GL_Color(r, r, r, 1);
3070 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3071 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3072 GL_BlendFunc(GL_ONE, GL_ONE);
3075 // copy the vertically blurred bloom view to a texture
3076 GL_ActiveTexture(0);
3078 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
3079 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3082 // apply subtract last
3083 // (just like it would be in a GLSL shader)
3084 if (r_bloom_colorsubtract.value > 0 && gl_support_ext_blend_subtract)
3086 GL_BlendFunc(GL_ONE, GL_ZERO);
3087 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3088 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3089 GL_Color(1, 1, 1, 1);
3090 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3091 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3093 GL_BlendFunc(GL_ONE, GL_ONE);
3094 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
3095 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
3096 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3097 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
3098 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3099 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3100 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
3102 // copy the darkened bloom view to a texture
3103 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3104 GL_ActiveTexture(0);
3106 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
3107 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3111 void R_HDR_RenderBloomTexture(void)
3113 int oldwidth, oldheight;
3115 oldwidth = r_view.width;
3116 oldheight = r_view.height;
3117 r_view.width = r_bloomstate.bloomwidth;
3118 r_view.height = r_bloomstate.bloomheight;
3120 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
3121 // TODO: add exposure compensation features
3122 // TODO: add fp16 framebuffer support
3124 r_view.showdebug = false;
3125 r_view.colorscale = r_bloom_colorscale.value * r_hdr_scenebrightness.value;
3127 r_view.colorscale /= r_hdr_range.value;
3128 r_waterstate.numwaterplanes = 0;
3129 R_RenderScene(r_waterstate.enabled);
3130 r_view.showdebug = true;
3132 R_ResetViewRendering2D();
3134 R_Bloom_CopyHDRTexture();
3135 R_Bloom_MakeTexture();
3137 R_ResetViewRendering3D();
3140 if (r_timereport_active)
3141 R_TimeReport("viewclear");
3143 // restore the view settings
3144 r_view.width = oldwidth;
3145 r_view.height = oldheight;
3148 static void R_BlendView(void)
3150 if (r_bloomstate.enabled && r_bloomstate.hdr)
3152 // render high dynamic range bloom effect
3153 // the bloom texture was made earlier this render, so we just need to
3154 // blend it onto the screen...
3155 R_ResetViewRendering2D();
3156 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3157 R_Mesh_ColorPointer(NULL, 0, 0);
3158 GL_Color(1, 1, 1, 1);
3159 GL_BlendFunc(GL_ONE, GL_ONE);
3160 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3161 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3162 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3163 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
3165 else if (r_bloomstate.enabled)
3167 // render simple bloom effect
3168 // copy the screen and shrink it and darken it for the bloom process
3169 R_Bloom_CopyScreenTexture(r_bloom_colorscale.value);
3170 // make the bloom texture
3171 R_Bloom_MakeTexture();
3172 // put the original screen image back in place and blend the bloom
3174 R_ResetViewRendering2D();
3175 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3176 R_Mesh_ColorPointer(NULL, 0, 0);
3177 GL_Color(1, 1, 1, 1);
3178 GL_BlendFunc(GL_ONE, GL_ZERO);
3179 // do both in one pass if possible
3180 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3181 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3182 if (r_textureunits.integer >= 2 && gl_combine.integer)
3184 R_Mesh_TexCombine(1, GL_ADD, GL_ADD, 1, 1);
3185 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_screen));
3186 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.screentexcoord2f, 0, 0);
3190 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3191 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
3192 // now blend on the bloom texture
3193 GL_BlendFunc(GL_ONE, GL_ONE);
3194 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
3195 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
3197 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3198 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
3200 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
3202 // apply a color tint to the whole view
3203 R_ResetViewRendering2D();
3204 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3205 R_Mesh_ColorPointer(NULL, 0, 0);
3206 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3207 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
3208 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3212 void R_RenderScene(qboolean addwaterplanes);
3214 matrix4x4_t r_waterscrollmatrix;
3216 void R_UpdateVariables(void)
3220 r_refdef.farclip = 4096;
3221 if (r_refdef.worldmodel)
3222 r_refdef.farclip += VectorDistance(r_refdef.worldmodel->normalmins, r_refdef.worldmodel->normalmaxs);
3223 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
3225 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
3226 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
3227 r_refdef.polygonfactor = 0;
3228 r_refdef.polygonoffset = 0;
3229 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
3230 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
3232 r_refdef.rtworld = r_shadow_realtime_world.integer;
3233 r_refdef.rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
3234 r_refdef.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
3235 r_refdef.rtdlightshadows = r_refdef.rtdlight && r_shadow_realtime_dlight_shadows.integer && gl_stencil;
3236 r_refdef.lightmapintensity = r_refdef.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
3237 if (r_showsurfaces.integer)
3239 r_refdef.rtworld = false;
3240 r_refdef.rtworldshadows = false;
3241 r_refdef.rtdlight = false;
3242 r_refdef.rtdlightshadows = false;
3243 r_refdef.lightmapintensity = 0;
3246 if (gamemode == GAME_NEHAHRA)
3248 if (gl_fogenable.integer)
3250 r_refdef.oldgl_fogenable = true;
3251 r_refdef.fog_density = gl_fogdensity.value;
3252 r_refdef.fog_red = gl_fogred.value;
3253 r_refdef.fog_green = gl_foggreen.value;
3254 r_refdef.fog_blue = gl_fogblue.value;
3256 else if (r_refdef.oldgl_fogenable)
3258 r_refdef.oldgl_fogenable = false;
3259 r_refdef.fog_density = 0;
3260 r_refdef.fog_red = 0;
3261 r_refdef.fog_green = 0;
3262 r_refdef.fog_blue = 0;
3265 if (r_refdef.fog_density)
3267 r_refdef.fogcolor[0] = bound(0.0f, r_refdef.fog_red , 1.0f);
3268 r_refdef.fogcolor[1] = bound(0.0f, r_refdef.fog_green, 1.0f);
3269 r_refdef.fogcolor[2] = bound(0.0f, r_refdef.fog_blue , 1.0f);
3271 if (r_refdef.fog_density)
3273 r_refdef.fogenabled = true;
3274 // this is the point where the fog reaches 0.9986 alpha, which we
3275 // consider a good enough cutoff point for the texture
3276 // (0.9986 * 256 == 255.6)
3277 r_refdef.fogrange = 400 / r_refdef.fog_density;
3278 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
3279 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
3280 // fog color was already set
3283 r_refdef.fogenabled = false;
3291 void R_RenderView(void)
3293 if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
3294 return; //Host_Error ("R_RenderView: NULL worldmodel");
3296 R_Shadow_UpdateWorldLightSelection();
3298 R_Bloom_StartFrame();
3299 R_Water_StartFrame();
3302 if (r_timereport_active)
3303 R_TimeReport("viewsetup");
3305 R_ResetViewRendering3D();
3310 if (r_timereport_active)
3311 R_TimeReport("viewclear");
3313 r_view.clear = true;
3315 r_view.showdebug = true;
3317 // this produces a bloom texture to be used in R_BlendView() later
3319 R_HDR_RenderBloomTexture();
3321 r_view.colorscale = r_hdr_scenebrightness.value;
3322 r_waterstate.numwaterplanes = 0;
3323 R_RenderScene(r_waterstate.enabled);
3326 if (r_timereport_active)
3327 R_TimeReport("blendview");
3329 GL_Scissor(0, 0, vid.width, vid.height);
3330 GL_ScissorTest(false);
3334 extern void R_DrawLightningBeams (void);
3335 extern void VM_CL_AddPolygonsToMeshQueue (void);
3336 extern void R_DrawPortals (void);
3337 extern cvar_t cl_locs_show;
3338 static void R_DrawLocs(void);
3339 static void R_DrawEntityBBoxes(void);
3340 void R_RenderScene(qboolean addwaterplanes)
3344 R_ResetViewRendering3D();
3347 if (r_timereport_active)
3348 R_TimeReport("watervis");
3350 if (cl.csqc_vidvars.drawworld && r_refdef.worldmodel && r_refdef.worldmodel->DrawAddWaterPlanes)
3352 r_refdef.worldmodel->DrawAddWaterPlanes(r_refdef.worldentity);
3353 if (r_timereport_active)
3354 R_TimeReport("waterworld");
3357 // don't let sound skip if going slow
3358 if (r_refdef.extraupdate)
3361 R_DrawModelsAddWaterPlanes();
3362 if (r_timereport_active)
3363 R_TimeReport("watermodels");
3365 R_Water_ProcessPlanes();
3366 if (r_timereport_active)
3367 R_TimeReport("waterscenes");
3370 R_ResetViewRendering3D();
3372 // don't let sound skip if going slow
3373 if (r_refdef.extraupdate)
3376 R_MeshQueue_BeginScene();
3381 if (r_timereport_active)
3382 R_TimeReport("visibility");
3384 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);
3386 if (cl.csqc_vidvars.drawworld)
3388 // don't let sound skip if going slow
3389 if (r_refdef.extraupdate)
3392 if (r_refdef.worldmodel && r_refdef.worldmodel->DrawSky)
3394 r_refdef.worldmodel->DrawSky(r_refdef.worldentity);
3395 if (r_timereport_active)
3396 R_TimeReport("worldsky");
3399 if (R_DrawBrushModelsSky() && r_timereport_active)
3400 R_TimeReport("bmodelsky");
3403 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.worldmodel && r_refdef.worldmodel->DrawDepth)
3405 r_refdef.worldmodel->DrawDepth(r_refdef.worldentity);
3406 if (r_timereport_active)
3407 R_TimeReport("worlddepth");
3409 if (r_depthfirst.integer >= 2)
3411 R_DrawModelsDepth();
3412 if (r_timereport_active)
3413 R_TimeReport("modeldepth");
3416 if (cl.csqc_vidvars.drawworld && r_refdef.worldmodel && r_refdef.worldmodel->Draw)
3418 r_refdef.worldmodel->Draw(r_refdef.worldentity);
3419 if (r_timereport_active)
3420 R_TimeReport("world");
3423 // don't let sound skip if going slow
3424 if (r_refdef.extraupdate)
3428 if (r_timereport_active)
3429 R_TimeReport("models");
3431 // don't let sound skip if going slow
3432 if (r_refdef.extraupdate)
3435 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
3437 R_DrawModelShadows();
3439 R_ResetViewRendering3D();
3441 // don't let sound skip if going slow
3442 if (r_refdef.extraupdate)
3446 R_ShadowVolumeLighting(false);
3447 if (r_timereport_active)
3448 R_TimeReport("rtlights");
3450 // don't let sound skip if going slow
3451 if (r_refdef.extraupdate)
3454 if (cl.csqc_vidvars.drawworld)
3456 R_DrawLightningBeams();
3457 if (r_timereport_active)
3458 R_TimeReport("lightning");
3461 if (r_timereport_active)
3462 R_TimeReport("decals");
3465 if (r_timereport_active)
3466 R_TimeReport("particles");
3469 if (r_timereport_active)
3470 R_TimeReport("explosions");
3473 if (gl_support_fragment_shader)
3475 qglUseProgramObjectARB(0);CHECKGLERROR
3477 VM_CL_AddPolygonsToMeshQueue();
3479 if (r_view.showdebug)
3481 if (cl_locs_show.integer)
3484 if (r_timereport_active)
3485 R_TimeReport("showlocs");
3488 if (r_drawportals.integer)
3491 if (r_timereport_active)
3492 R_TimeReport("portals");
3495 if (r_showbboxes.value > 0)
3497 R_DrawEntityBBoxes();
3498 if (r_timereport_active)
3499 R_TimeReport("bboxes");
3503 if (gl_support_fragment_shader)
3505 qglUseProgramObjectARB(0);CHECKGLERROR
3507 R_MeshQueue_RenderTransparent();
3508 if (r_timereport_active)
3509 R_TimeReport("drawtrans");
3511 if (gl_support_fragment_shader)
3513 qglUseProgramObjectARB(0);CHECKGLERROR
3516 if (r_view.showdebug && r_refdef.worldmodel && r_refdef.worldmodel->DrawDebug && (r_showtris.value > 0 || r_shownormals.value > 0 || r_showcollisionbrushes.value > 0))
3518 r_refdef.worldmodel->DrawDebug(r_refdef.worldentity);
3519 if (r_timereport_active)
3520 R_TimeReport("worlddebug");
3521 R_DrawModelsDebug();
3522 if (r_timereport_active)
3523 R_TimeReport("modeldebug");
3526 if (gl_support_fragment_shader)
3528 qglUseProgramObjectARB(0);CHECKGLERROR
3531 if (cl.csqc_vidvars.drawworld)
3534 if (r_timereport_active)
3535 R_TimeReport("coronas");
3538 // don't let sound skip if going slow
3539 if (r_refdef.extraupdate)
3542 R_ResetViewRendering2D();
3545 static const int bboxelements[36] =
3555 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
3558 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
3559 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3560 GL_DepthMask(false);
3561 GL_DepthRange(0, 1);
3562 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3563 R_Mesh_Matrix(&identitymatrix);
3564 R_Mesh_ResetTextureState();
3566 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
3567 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
3568 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
3569 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
3570 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
3571 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
3572 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
3573 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
3574 R_FillColors(color4f, 8, cr, cg, cb, ca);
3575 if (r_refdef.fogenabled)
3577 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
3579 f1 = FogPoint_World(v);
3581 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
3582 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
3583 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
3586 R_Mesh_VertexPointer(vertex3f, 0, 0);
3587 R_Mesh_ColorPointer(color4f, 0, 0);
3588 R_Mesh_ResetTextureState();
3589 R_Mesh_Draw(0, 8, 12, bboxelements, 0, 0);
3592 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
3596 prvm_edict_t *edict;
3597 // this function draws bounding boxes of server entities
3601 for (i = 0;i < numsurfaces;i++)
3603 edict = PRVM_EDICT_NUM(surfacelist[i]);
3604 switch ((int)edict->fields.server->solid)
3606 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
3607 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
3608 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
3609 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
3610 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
3611 default: Vector4Set(color, 0, 0, 0, 0.50);break;
3613 color[3] *= r_showbboxes.value;
3614 color[3] = bound(0, color[3], 1);
3615 GL_DepthTest(!r_showdisabledepthtest.integer);
3616 GL_CullFace(r_view.cullface_front);
3617 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
3622 static void R_DrawEntityBBoxes(void)
3625 prvm_edict_t *edict;
3627 // this function draws bounding boxes of server entities
3631 for (i = 0;i < prog->num_edicts;i++)
3633 edict = PRVM_EDICT_NUM(i);
3634 if (edict->priv.server->free)
3636 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
3637 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
3642 int nomodelelements[24] =
3654 float nomodelvertex3f[6*3] =
3664 float nomodelcolor4f[6*4] =
3666 0.0f, 0.0f, 0.5f, 1.0f,
3667 0.0f, 0.0f, 0.5f, 1.0f,
3668 0.0f, 0.5f, 0.0f, 1.0f,
3669 0.0f, 0.5f, 0.0f, 1.0f,
3670 0.5f, 0.0f, 0.0f, 1.0f,
3671 0.5f, 0.0f, 0.0f, 1.0f
3674 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
3679 // this is only called once per entity so numsurfaces is always 1, and
3680 // surfacelist is always {0}, so this code does not handle batches
3681 R_Mesh_Matrix(&ent->matrix);
3683 if (ent->flags & EF_ADDITIVE)
3685 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
3686 GL_DepthMask(false);
3688 else if (ent->alpha < 1)
3690 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3691 GL_DepthMask(false);
3695 GL_BlendFunc(GL_ONE, GL_ZERO);
3698 GL_DepthRange(0, (ent->flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
3699 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3700 GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
3701 GL_CullFace((ent->effects & EF_DOUBLESIDED) ? GL_NONE : r_view.cullface_back);
3702 R_Mesh_VertexPointer(nomodelvertex3f, 0, 0);
3703 if (r_refdef.fogenabled)
3706 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
3707 R_Mesh_ColorPointer(color4f, 0, 0);
3708 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
3709 f1 = FogPoint_World(org);
3711 for (i = 0, c = color4f;i < 6;i++, c += 4)
3713 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
3714 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
3715 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
3719 else if (ent->alpha != 1)
3721 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
3722 R_Mesh_ColorPointer(color4f, 0, 0);
3723 for (i = 0, c = color4f;i < 6;i++, c += 4)
3727 R_Mesh_ColorPointer(nomodelcolor4f, 0, 0);
3728 R_Mesh_ResetTextureState();
3729 R_Mesh_Draw(0, 6, 8, nomodelelements, 0, 0);
3732 void R_DrawNoModel(entity_render_t *ent)
3735 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
3736 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
3737 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
3739 // R_DrawNoModelCallback(ent, 0);
3742 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
3744 vec3_t right1, right2, diff, normal;
3746 VectorSubtract (org2, org1, normal);
3748 // calculate 'right' vector for start
3749 VectorSubtract (r_view.origin, org1, diff);
3750 CrossProduct (normal, diff, right1);
3751 VectorNormalize (right1);
3753 // calculate 'right' vector for end
3754 VectorSubtract (r_view.origin, org2, diff);
3755 CrossProduct (normal, diff, right2);
3756 VectorNormalize (right2);
3758 vert[ 0] = org1[0] + width * right1[0];
3759 vert[ 1] = org1[1] + width * right1[1];
3760 vert[ 2] = org1[2] + width * right1[2];
3761 vert[ 3] = org1[0] - width * right1[0];
3762 vert[ 4] = org1[1] - width * right1[1];
3763 vert[ 5] = org1[2] - width * right1[2];
3764 vert[ 6] = org2[0] - width * right2[0];
3765 vert[ 7] = org2[1] - width * right2[1];
3766 vert[ 8] = org2[2] - width * right2[2];
3767 vert[ 9] = org2[0] + width * right2[0];
3768 vert[10] = org2[1] + width * right2[1];
3769 vert[11] = org2[2] + width * right2[2];
3772 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
3774 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)
3779 if (r_refdef.fogenabled)
3780 fog = FogPoint_World(origin);
3782 R_Mesh_Matrix(&identitymatrix);
3783 GL_BlendFunc(blendfunc1, blendfunc2);
3789 GL_CullFace(r_view.cullface_front);
3792 GL_CullFace(r_view.cullface_back);
3794 GL_DepthMask(false);
3795 GL_DepthRange(0, depthshort ? 0.0625 : 1);
3796 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3797 GL_DepthTest(!depthdisable);
3799 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
3800 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
3801 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
3802 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
3803 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
3804 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
3805 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
3806 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
3807 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
3808 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
3809 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
3810 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
3812 R_Mesh_VertexPointer(vertex3f, 0, 0);
3813 R_Mesh_ColorPointer(NULL, 0, 0);
3814 R_Mesh_ResetTextureState();
3815 R_Mesh_TexBind(0, R_GetTexture(texture));
3816 R_Mesh_TexCoordPointer(0, 2, spritetexcoord2f, 0, 0);
3817 // FIXME: fixed function path can't properly handle r_view.colorscale > 1
3818 GL_Color(cr * fog * r_view.colorscale, cg * fog * r_view.colorscale, cb * fog * r_view.colorscale, ca);
3819 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3821 if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
3823 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
3824 GL_BlendFunc(blendfunc1, GL_ONE);
3826 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);
3827 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3831 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
3836 VectorSet(v, x, y, z);
3837 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
3838 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
3840 if (i == mesh->numvertices)
3842 if (mesh->numvertices < mesh->maxvertices)
3844 VectorCopy(v, vertex3f);
3845 mesh->numvertices++;
3847 return mesh->numvertices;
3853 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
3857 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
3858 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
3859 e = mesh->element3i + mesh->numtriangles * 3;
3860 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
3862 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
3863 if (mesh->numtriangles < mesh->maxtriangles)
3868 mesh->numtriangles++;
3870 element[1] = element[2];
3874 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
3878 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
3879 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
3880 e = mesh->element3i + mesh->numtriangles * 3;
3881 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
3883 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
3884 if (mesh->numtriangles < mesh->maxtriangles)
3889 mesh->numtriangles++;
3891 element[1] = element[2];
3895 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
3896 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
3898 int planenum, planenum2;
3901 mplane_t *plane, *plane2;
3903 double temppoints[2][256*3];
3904 // figure out how large a bounding box we need to properly compute this brush
3906 for (w = 0;w < numplanes;w++)
3907 maxdist = max(maxdist, planes[w].dist);
3908 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
3909 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
3910 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
3914 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
3915 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
3917 if (planenum2 == planenum)
3919 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);
3922 if (tempnumpoints < 3)
3924 // generate elements forming a triangle fan for this polygon
3925 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
3929 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)
3931 texturelayer_t *layer;
3932 layer = t->currentlayers + t->currentnumlayers++;
3934 layer->depthmask = depthmask;
3935 layer->blendfunc1 = blendfunc1;
3936 layer->blendfunc2 = blendfunc2;
3937 layer->texture = texture;
3938 layer->texmatrix = *matrix;
3939 layer->color[0] = r * r_view.colorscale;
3940 layer->color[1] = g * r_view.colorscale;
3941 layer->color[2] = b * r_view.colorscale;
3942 layer->color[3] = a;
3945 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
3948 index = parms[2] + r_refdef.time * parms[3];
3949 index -= floor(index);
3953 case Q3WAVEFUNC_NONE:
3954 case Q3WAVEFUNC_NOISE:
3955 case Q3WAVEFUNC_COUNT:
3958 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
3959 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
3960 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
3961 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
3962 case Q3WAVEFUNC_TRIANGLE:
3964 f = index - floor(index);
3975 return (float)(parms[0] + parms[1] * f);
3978 void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
3981 model_t *model = ent->model;
3984 q3shaderinfo_layer_tcmod_t *tcmod;
3986 // switch to an alternate material if this is a q1bsp animated material
3988 texture_t *texture = t;
3989 int s = ent->skinnum;
3990 if ((unsigned int)s >= (unsigned int)model->numskins)
3992 if (model->skinscenes)
3994 if (model->skinscenes[s].framecount > 1)
3995 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
3997 s = model->skinscenes[s].firstframe;
4000 t = t + s * model->num_surfaces;
4003 // use an alternate animation if the entity's frame is not 0,
4004 // and only if the texture has an alternate animation
4005 if (ent->frame2 != 0 && t->anim_total[1])
4006 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.time * 5.0f) % t->anim_total[1]) : 0];
4008 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.time * 5.0f) % t->anim_total[0]) : 0];
4010 texture->currentframe = t;
4013 // update currentskinframe to be a qw skin or animation frame
4014 if ((i = ent->entitynumber - 1) >= 0 && i < cl.maxclients)
4016 if (strcmp(r_qwskincache[i], cl.scores[i].qw_skin))
4018 strlcpy(r_qwskincache[i], cl.scores[i].qw_skin, sizeof(r_qwskincache[i]));
4019 Con_DPrintf("loading skins/%s\n", r_qwskincache[i]);
4020 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);
4022 t->currentskinframe = r_qwskincache_skinframe[i];
4023 if (t->currentskinframe == NULL)
4024 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->frame2time)) % t->numskinframes];
4026 else if (t->numskinframes >= 2)
4027 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->frame2time)) % t->numskinframes];
4028 if (t->backgroundnumskinframes >= 2)
4029 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - ent->frame2time)) % t->backgroundnumskinframes];
4031 t->currentmaterialflags = t->basematerialflags;
4032 t->currentalpha = ent->alpha;
4033 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
4035 t->currentalpha *= r_wateralpha.value;
4037 * FIXME what is this supposed to do?
4038 // if rendering refraction/reflection, disable transparency
4039 if (r_waterstate.enabled && (t->currentalpha < 1 || (t->currentmaterialflags & MATERIALFLAG_ALPHA)))
4040 t->currentmaterialflags |= MATERIALFLAG_WATERSHADER;
4043 if(!r_waterstate.enabled)
4044 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION);
4045 if (!(ent->flags & RENDER_LIGHT))
4046 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
4047 else if (rsurface.modeltexcoordlightmap2f == NULL)
4049 // pick a model lighting mode
4050 if (VectorLength2(ent->modellight_diffuse) >= (1.0f / 256.0f))
4051 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
4053 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
4055 if (ent->effects & EF_ADDITIVE)
4056 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
4057 else if (t->currentalpha < 1)
4058 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
4059 if (ent->effects & EF_DOUBLESIDED)
4060 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
4061 if (ent->effects & EF_NODEPTHTEST)
4062 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
4063 if (ent->flags & RENDER_VIEWMODEL)
4064 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
4065 if (t->backgroundnumskinframes && !(t->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED))
4066 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
4068 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && (tcmod->tcmod || i < 1);i++, tcmod++)
4071 switch(tcmod->tcmod)
4075 if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
4076 matrix = r_waterscrollmatrix;
4078 matrix = identitymatrix;
4080 case Q3TCMOD_ENTITYTRANSLATE:
4081 // this is used in Q3 to allow the gamecode to control texcoord
4082 // scrolling on the entity, which is not supported in darkplaces yet.
4083 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
4085 case Q3TCMOD_ROTATE:
4086 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
4087 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.time, 0, 0, 1);
4088 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
4091 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
4093 case Q3TCMOD_SCROLL:
4094 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.time, tcmod->parms[1] * r_refdef.time, 0);
4096 case Q3TCMOD_STRETCH:
4097 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
4098 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
4100 case Q3TCMOD_TRANSFORM:
4101 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
4102 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
4103 VectorSet(tcmat + 6, 0 , 0 , 1);
4104 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
4105 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
4107 case Q3TCMOD_TURBULENT:
4108 // this is handled in the RSurf_PrepareVertices function
4109 matrix = identitymatrix;
4112 // either replace or concatenate the transformation
4114 t->currenttexmatrix = matrix;
4117 matrix4x4_t temp = t->currenttexmatrix;
4118 Matrix4x4_Concat(&t->currenttexmatrix, &matrix, &temp);
4122 t->colormapping = VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f);
4123 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
4124 t->glosstexture = r_texture_black;
4125 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
4126 t->backgroundglosstexture = r_texture_black;
4127 t->specularpower = r_shadow_glossexponent.value;
4128 // TODO: store reference values for these in the texture?
4129 t->specularscale = 0;
4130 if (r_shadow_gloss.integer > 0)
4132 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
4134 if (r_shadow_glossintensity.value > 0)
4136 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
4137 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
4138 t->specularscale = r_shadow_glossintensity.value;
4141 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
4143 t->glosstexture = r_texture_white;
4144 t->backgroundglosstexture = r_texture_white;
4145 t->specularscale = r_shadow_gloss2intensity.value;
4149 // lightmaps mode looks bad with dlights using actual texturing, so turn
4150 // off the colormap and glossmap, but leave the normalmap on as it still
4151 // accurately represents the shading involved
4152 if (gl_lightmaps.integer && !(t->currentmaterialflags & MATERIALFLAG_BLENDED))
4154 t->basetexture = r_texture_white;
4155 t->specularscale = 0;
4158 t->currentpolygonfactor = r_refdef.polygonfactor + t->basepolygonfactor;
4159 t->currentpolygonoffset = r_refdef.polygonoffset + t->basepolygonoffset;
4160 // submodels are biased to avoid z-fighting with world surfaces that they
4161 // may be exactly overlapping (avoids z-fighting artifacts on certain
4162 // doors and things in Quake maps)
4163 if (ent->model->brush.submodel)
4165 t->currentpolygonfactor += r_polygonoffset_submodel_factor.value;
4166 t->currentpolygonoffset += r_polygonoffset_submodel_offset.value;
4169 VectorClear(t->dlightcolor);
4170 t->currentnumlayers = 0;
4171 if (!(t->currentmaterialflags & MATERIALFLAG_NODRAW))
4173 if (!(t->currentmaterialflags & MATERIALFLAG_SKY))
4175 int blendfunc1, blendfunc2, depthmask;
4176 if (t->currentmaterialflags & MATERIALFLAG_ADD)
4178 blendfunc1 = GL_SRC_ALPHA;
4179 blendfunc2 = GL_ONE;
4181 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
4183 blendfunc1 = GL_SRC_ALPHA;
4184 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
4186 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
4188 blendfunc1 = t->customblendfunc[0];
4189 blendfunc2 = t->customblendfunc[1];
4193 blendfunc1 = GL_ONE;
4194 blendfunc2 = GL_ZERO;
4196 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
4197 if (t->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL))
4199 rtexture_t *currentbasetexture;
4201 if (r_refdef.fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED))
4202 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
4203 currentbasetexture = (VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) < (1.0f / 1048576.0f) && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
4204 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
4206 // fullbright is not affected by r_refdef.lightmapintensity
4207 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
4208 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
4209 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);
4210 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
4211 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);
4216 // set the color tint used for lights affecting this surface
4217 VectorSet(t->dlightcolor, ent->colormod[0] * t->currentalpha, ent->colormod[1] * t->currentalpha, ent->colormod[2] * t->currentalpha);
4219 // q3bsp has no lightmap updates, so the lightstylevalue that
4220 // would normally be baked into the lightmap must be
4221 // applied to the color
4222 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
4223 if (ent->model->type == mod_brushq3)
4224 colorscale *= r_refdef.lightstylevalue[0] * (1.0f / 256.0f);
4225 colorscale *= r_refdef.lightmapintensity;
4226 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);
4227 if (r_ambient.value >= (1.0f/64.0f))
4228 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);
4229 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
4231 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);
4232 if (r_ambient.value >= (1.0f/64.0f))
4233 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);
4235 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
4237 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);
4238 if (r_ambient.value >= (1.0f/64.0f))
4239 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);
4242 if (t->currentskinframe->glow != NULL)
4243 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);
4244 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
4246 // if this is opaque use alpha blend which will darken the earlier
4249 // if this is an alpha blended material, all the earlier passes
4250 // were darkened by fog already, so we only need to add the fog
4251 // color ontop through the fog mask texture
4253 // if this is an additive blended material, all the earlier passes
4254 // were darkened by fog already, and we should not add fog color
4255 // (because the background was not darkened, there is no fog color
4256 // that was lost behind it).
4257 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);
4264 void R_UpdateAllTextureInfo(entity_render_t *ent)
4268 for (i = 0;i < ent->model->num_texturesperskin;i++)
4269 R_UpdateTextureInfo(ent, ent->model->data_textures + i);
4272 rsurfacestate_t rsurface;
4274 void R_Mesh_ResizeArrays(int newvertices)
4277 if (rsurface.array_size >= newvertices)
4279 if (rsurface.array_modelvertex3f)
4280 Mem_Free(rsurface.array_modelvertex3f);
4281 rsurface.array_size = (newvertices + 1023) & ~1023;
4282 base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
4283 rsurface.array_modelvertex3f = base + rsurface.array_size * 0;
4284 rsurface.array_modelsvector3f = base + rsurface.array_size * 3;
4285 rsurface.array_modeltvector3f = base + rsurface.array_size * 6;
4286 rsurface.array_modelnormal3f = base + rsurface.array_size * 9;
4287 rsurface.array_deformedvertex3f = base + rsurface.array_size * 12;
4288 rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
4289 rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
4290 rsurface.array_deformednormal3f = base + rsurface.array_size * 21;
4291 rsurface.array_texcoord3f = base + rsurface.array_size * 24;
4292 rsurface.array_color4f = base + rsurface.array_size * 27;
4293 rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
4296 void RSurf_CleanUp(void)
4299 if (rsurface.mode == RSURFMODE_GLSL)
4301 qglUseProgramObjectARB(0);CHECKGLERROR
4303 GL_AlphaTest(false);
4304 rsurface.mode = RSURFMODE_NONE;
4305 rsurface.uselightmaptexture = false;
4306 rsurface.texture = NULL;
4309 void RSurf_ActiveWorldEntity(void)
4311 model_t *model = r_refdef.worldmodel;
4313 if (rsurface.array_size < model->surfmesh.num_vertices)
4314 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
4315 rsurface.matrix = identitymatrix;
4316 rsurface.inversematrix = identitymatrix;
4317 R_Mesh_Matrix(&identitymatrix);
4318 VectorCopy(r_view.origin, rsurface.modelorg);
4319 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
4320 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
4321 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
4322 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
4323 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
4324 rsurface.frameblend[0].frame = 0;
4325 rsurface.frameblend[0].lerp = 1;
4326 rsurface.frameblend[1].frame = 0;
4327 rsurface.frameblend[1].lerp = 0;
4328 rsurface.frameblend[2].frame = 0;
4329 rsurface.frameblend[2].lerp = 0;
4330 rsurface.frameblend[3].frame = 0;
4331 rsurface.frameblend[3].lerp = 0;
4332 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
4333 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
4334 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
4335 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
4336 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
4337 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
4338 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
4339 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
4340 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
4341 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
4342 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
4343 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
4344 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
4345 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
4346 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
4347 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
4348 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
4349 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
4350 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
4351 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
4352 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
4353 rsurface.modelelement3i = model->surfmesh.data_element3i;
4354 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo;
4355 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
4356 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
4357 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
4358 rsurface.modelsurfaces = model->data_surfaces;
4359 rsurface.generatedvertex = false;
4360 rsurface.vertex3f = rsurface.modelvertex3f;
4361 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
4362 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
4363 rsurface.svector3f = rsurface.modelsvector3f;
4364 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
4365 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
4366 rsurface.tvector3f = rsurface.modeltvector3f;
4367 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
4368 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
4369 rsurface.normal3f = rsurface.modelnormal3f;
4370 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
4371 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
4372 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
4375 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4377 model_t *model = ent->model;
4379 if (rsurface.array_size < model->surfmesh.num_vertices)
4380 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
4381 rsurface.matrix = ent->matrix;
4382 rsurface.inversematrix = ent->inversematrix;
4383 R_Mesh_Matrix(&rsurface.matrix);
4384 Matrix4x4_Transform(&rsurface.inversematrix, r_view.origin, rsurface.modelorg);
4385 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
4386 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
4387 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
4388 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
4389 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
4390 rsurface.frameblend[0] = ent->frameblend[0];
4391 rsurface.frameblend[1] = ent->frameblend[1];
4392 rsurface.frameblend[2] = ent->frameblend[2];
4393 rsurface.frameblend[3] = ent->frameblend[3];
4394 if (model->surfmesh.isanimated && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].frame != 0))
4398 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
4399 rsurface.modelsvector3f = rsurface.array_modelsvector3f;
4400 rsurface.modeltvector3f = rsurface.array_modeltvector3f;
4401 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
4402 Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
4404 else if (wantnormals)
4406 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
4407 rsurface.modelsvector3f = NULL;
4408 rsurface.modeltvector3f = NULL;
4409 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
4410 Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
4414 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
4415 rsurface.modelsvector3f = NULL;
4416 rsurface.modeltvector3f = NULL;
4417 rsurface.modelnormal3f = NULL;
4418 Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, NULL, NULL, NULL);
4420 rsurface.modelvertex3f_bufferobject = 0;
4421 rsurface.modelvertex3f_bufferoffset = 0;
4422 rsurface.modelsvector3f_bufferobject = 0;
4423 rsurface.modelsvector3f_bufferoffset = 0;
4424 rsurface.modeltvector3f_bufferobject = 0;
4425 rsurface.modeltvector3f_bufferoffset = 0;
4426 rsurface.modelnormal3f_bufferobject = 0;
4427 rsurface.modelnormal3f_bufferoffset = 0;
4428 rsurface.generatedvertex = true;
4432 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
4433 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
4434 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
4435 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
4436 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
4437 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
4438 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
4439 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
4440 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
4441 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
4442 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
4443 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
4444 rsurface.generatedvertex = false;
4446 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
4447 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
4448 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
4449 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
4450 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
4451 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
4452 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
4453 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
4454 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
4455 rsurface.modelelement3i = model->surfmesh.data_element3i;
4456 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo;
4457 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
4458 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
4459 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
4460 rsurface.modelsurfaces = model->data_surfaces;
4461 rsurface.vertex3f = rsurface.modelvertex3f;
4462 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
4463 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
4464 rsurface.svector3f = rsurface.modelsvector3f;
4465 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
4466 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
4467 rsurface.tvector3f = rsurface.modeltvector3f;
4468 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
4469 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
4470 rsurface.normal3f = rsurface.modelnormal3f;
4471 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
4472 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
4473 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
4476 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
4477 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, msurface_t **texturesurfacelist)
4480 int texturesurfaceindex;
4485 const float *v1, *in_tc;
4487 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
4489 q3shaderinfo_deform_t *deform;
4490 // 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
4491 if (rsurface.generatedvertex)
4493 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
4494 generatenormals = true;
4495 for (i = 0;i < Q3MAXDEFORMS;i++)
4497 if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
4499 generatetangents = true;
4500 generatenormals = true;
4502 if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
4503 generatenormals = true;
4505 if (generatenormals && !rsurface.modelnormal3f)
4507 rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
4508 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
4509 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
4510 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer);
4512 if (generatetangents && !rsurface.modelsvector3f)
4514 rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
4515 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
4516 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
4517 rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
4518 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
4519 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
4520 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);
4523 rsurface.vertex3f = rsurface.modelvertex3f;
4524 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
4525 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
4526 rsurface.svector3f = rsurface.modelsvector3f;
4527 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
4528 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
4529 rsurface.tvector3f = rsurface.modeltvector3f;
4530 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
4531 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
4532 rsurface.normal3f = rsurface.modelnormal3f;
4533 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
4534 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
4535 // if vertices are deformed (sprite flares and things in maps, possibly
4536 // water waves, bulges and other deformations), generate them into
4537 // rsurface.deform* arrays from whatever the rsurface.* arrays point to
4538 // (may be static model data or generated data for an animated model, or
4539 // the previous deform pass)
4540 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
4542 switch (deform->deform)
4545 case Q3DEFORM_PROJECTIONSHADOW:
4546 case Q3DEFORM_TEXT0:
4547 case Q3DEFORM_TEXT1:
4548 case Q3DEFORM_TEXT2:
4549 case Q3DEFORM_TEXT3:
4550 case Q3DEFORM_TEXT4:
4551 case Q3DEFORM_TEXT5:
4552 case Q3DEFORM_TEXT6:
4553 case Q3DEFORM_TEXT7:
4556 case Q3DEFORM_AUTOSPRITE:
4557 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.forward, newforward);
4558 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.right, newright);
4559 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.up, newup);
4560 VectorNormalize(newforward);
4561 VectorNormalize(newright);
4562 VectorNormalize(newup);
4563 // make deformed versions of only the model vertices used by the specified surfaces
4564 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4566 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4567 // a single autosprite surface can contain multiple sprites...
4568 for (j = 0;j < surface->num_vertices - 3;j += 4)
4570 VectorClear(center);
4571 for (i = 0;i < 4;i++)
4572 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
4573 VectorScale(center, 0.25f, center);
4574 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, forward);
4575 VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
4576 VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
4577 for (i = 0;i < 4;i++)
4579 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
4580 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
4583 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);
4584 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);
4586 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4587 rsurface.vertex3f_bufferobject = 0;
4588 rsurface.vertex3f_bufferoffset = 0;
4589 rsurface.svector3f = rsurface.array_deformedsvector3f;
4590 rsurface.svector3f_bufferobject = 0;
4591 rsurface.svector3f_bufferoffset = 0;
4592 rsurface.tvector3f = rsurface.array_deformedtvector3f;
4593 rsurface.tvector3f_bufferobject = 0;
4594 rsurface.tvector3f_bufferoffset = 0;
4595 rsurface.normal3f = rsurface.array_deformednormal3f;
4596 rsurface.normal3f_bufferobject = 0;
4597 rsurface.normal3f_bufferoffset = 0;
4599 case Q3DEFORM_AUTOSPRITE2:
4600 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.forward, newforward);
4601 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.right, newright);
4602 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.up, newup);
4603 VectorNormalize(newforward);
4604 VectorNormalize(newright);
4605 VectorNormalize(newup);
4606 // make deformed versions of only the model vertices used by the specified surfaces
4607 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4609 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4610 const float *v1, *v2;
4620 memset(shortest, 0, sizeof(shortest));
4621 // a single autosprite surface can contain multiple sprites...
4622 for (j = 0;j < surface->num_vertices - 3;j += 4)
4624 VectorClear(center);
4625 for (i = 0;i < 4;i++)
4626 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
4627 VectorScale(center, 0.25f, center);
4628 // find the two shortest edges, then use them to define the
4629 // axis vectors for rotating around the central axis
4630 for (i = 0;i < 6;i++)
4632 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
4633 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
4635 Debug_PolygonBegin(NULL, 0, false, 0);
4636 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
4637 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);
4638 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
4641 l = VectorDistance2(v1, v2);
4642 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
4644 l += (1.0f / 1024.0f);
4645 if (shortest[0].length2 > l || i == 0)
4647 shortest[1] = shortest[0];
4648 shortest[0].length2 = l;
4649 shortest[0].v1 = v1;
4650 shortest[0].v2 = v2;
4652 else if (shortest[1].length2 > l || i == 1)
4654 shortest[1].length2 = l;
4655 shortest[1].v1 = v1;
4656 shortest[1].v2 = v2;
4659 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
4660 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
4662 Debug_PolygonBegin(NULL, 0, false, 0);
4663 Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
4664 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);
4665 Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
4668 // this calculates the right vector from the shortest edge
4669 // and the up vector from the edge midpoints
4670 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
4671 VectorNormalize(right);
4672 VectorSubtract(end, start, up);
4673 VectorNormalize(up);
4674 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
4675 //VectorSubtract(rsurface.modelorg, center, forward);
4676 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.forward, forward);
4677 VectorNegate(forward, forward);
4678 VectorReflect(forward, 0, up, forward);
4679 VectorNormalize(forward);
4680 CrossProduct(up, forward, newright);
4681 VectorNormalize(newright);
4683 Debug_PolygonBegin(NULL, 0, false, 0);
4684 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);
4685 Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
4686 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
4690 Debug_PolygonBegin(NULL, 0, false, 0);
4691 Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
4692 Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
4693 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
4696 // rotate the quad around the up axis vector, this is made
4697 // especially easy by the fact we know the quad is flat,
4698 // so we only have to subtract the center position and
4699 // measure distance along the right vector, and then
4700 // multiply that by the newright vector and add back the
4702 // we also need to subtract the old position to undo the
4703 // displacement from the center, which we do with a
4704 // DotProduct, the subtraction/addition of center is also
4705 // optimized into DotProducts here
4706 l = DotProduct(right, center);
4707 for (i = 0;i < 4;i++)
4709 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
4710 f = DotProduct(right, v1) - l;
4711 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
4714 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);
4715 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);
4717 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4718 rsurface.vertex3f_bufferobject = 0;
4719 rsurface.vertex3f_bufferoffset = 0;
4720 rsurface.svector3f = rsurface.array_deformedsvector3f;
4721 rsurface.svector3f_bufferobject = 0;
4722 rsurface.svector3f_bufferoffset = 0;
4723 rsurface.tvector3f = rsurface.array_deformedtvector3f;
4724 rsurface.tvector3f_bufferobject = 0;
4725 rsurface.tvector3f_bufferoffset = 0;
4726 rsurface.normal3f = rsurface.array_deformednormal3f;
4727 rsurface.normal3f_bufferobject = 0;
4728 rsurface.normal3f_bufferoffset = 0;
4730 case Q3DEFORM_NORMAL:
4731 // deform the normals to make reflections wavey
4732 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4734 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4735 for (j = 0;j < surface->num_vertices;j++)
4738 float *normal = (rsurface.array_deformednormal3f + 3 * surface->num_firstvertex) + j*3;
4739 VectorScale((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
4740 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, normal);
4741 normal[0] += deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.time * deform->parms[1]);
4742 normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.time * deform->parms[1]);
4743 normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.time * deform->parms[1]);
4744 VectorNormalize(normal);
4746 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);
4748 rsurface.svector3f = rsurface.array_deformedsvector3f;
4749 rsurface.svector3f_bufferobject = 0;
4750 rsurface.svector3f_bufferoffset = 0;
4751 rsurface.tvector3f = rsurface.array_deformedtvector3f;
4752 rsurface.tvector3f_bufferobject = 0;
4753 rsurface.tvector3f_bufferoffset = 0;
4754 rsurface.normal3f = rsurface.array_deformednormal3f;
4755 rsurface.normal3f_bufferobject = 0;
4756 rsurface.normal3f_bufferoffset = 0;
4759 // deform vertex array to make wavey water and flags and such
4760 waveparms[0] = deform->waveparms[0];
4761 waveparms[1] = deform->waveparms[1];
4762 waveparms[2] = deform->waveparms[2];
4763 waveparms[3] = deform->waveparms[3];
4764 // this is how a divisor of vertex influence on deformation
4765 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
4766 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
4767 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4769 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4770 for (j = 0;j < surface->num_vertices;j++)
4772 float *vertex = (rsurface.array_deformedvertex3f + 3 * surface->num_firstvertex) + j*3;
4773 VectorCopy((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, vertex);
4774 // if the wavefunc depends on time, evaluate it per-vertex
4777 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
4778 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
4780 VectorMA(vertex, scale, (rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, vertex);
4783 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4784 rsurface.vertex3f_bufferobject = 0;
4785 rsurface.vertex3f_bufferoffset = 0;
4787 case Q3DEFORM_BULGE:
4788 // deform vertex array to make the surface have moving bulges
4789 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4791 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4792 for (j = 0;j < surface->num_vertices;j++)
4794 scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.time * deform->parms[2])) * deform->parms[1];
4795 VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
4798 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4799 rsurface.vertex3f_bufferobject = 0;
4800 rsurface.vertex3f_bufferoffset = 0;
4803 // deform vertex array
4804 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
4805 VectorScale(deform->parms, scale, waveparms);
4806 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4808 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4809 for (j = 0;j < surface->num_vertices;j++)
4810 VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
4812 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4813 rsurface.vertex3f_bufferobject = 0;
4814 rsurface.vertex3f_bufferoffset = 0;
4818 // generate texcoords based on the chosen texcoord source
4819 switch(rsurface.texture->tcgen.tcgen)
4822 case Q3TCGEN_TEXTURE:
4823 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
4824 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordtexture2f_bufferobject;
4825 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
4827 case Q3TCGEN_LIGHTMAP:
4828 rsurface.texcoordtexture2f = rsurface.modeltexcoordlightmap2f;
4829 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
4830 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
4832 case Q3TCGEN_VECTOR:
4833 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4835 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4836 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)
4838 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
4839 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
4842 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
4843 rsurface.texcoordtexture2f_bufferobject = 0;
4844 rsurface.texcoordtexture2f_bufferoffset = 0;
4846 case Q3TCGEN_ENVIRONMENT:
4847 // make environment reflections using a spheremap
4848 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4850 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4851 const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
4852 const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
4853 float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
4854 for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
4856 float l, d, eyedir[3];
4857 VectorSubtract(rsurface.modelorg, vertex, eyedir);
4858 l = 0.5f / VectorLength(eyedir);
4859 d = DotProduct(normal, eyedir)*2;
4860 out_tc[0] = 0.5f + (normal[1]*d - eyedir[1])*l;
4861 out_tc[1] = 0.5f - (normal[2]*d - eyedir[2])*l;
4864 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
4865 rsurface.texcoordtexture2f_bufferobject = 0;
4866 rsurface.texcoordtexture2f_bufferoffset = 0;
4869 // the only tcmod that needs software vertex processing is turbulent, so
4870 // check for it here and apply the changes if needed
4871 // and we only support that as the first one
4872 // (handling a mixture of turbulent and other tcmods would be problematic
4873 // without punting it entirely to a software path)
4874 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
4876 amplitude = rsurface.texture->tcmods[0].parms[1];
4877 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.time * rsurface.texture->tcmods[0].parms[3];
4878 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4880 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4881 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)
4883 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
4884 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
4887 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
4888 rsurface.texcoordtexture2f_bufferobject = 0;
4889 rsurface.texcoordtexture2f_bufferoffset = 0;
4891 rsurface.texcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
4892 rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
4893 rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
4894 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
4897 void RSurf_DrawBatch_Simple(int texturenumsurfaces, msurface_t **texturesurfacelist)
4900 const msurface_t *surface = texturesurfacelist[0];
4901 const msurface_t *surface2;
4906 // TODO: lock all array ranges before render, rather than on each surface
4907 if (texturenumsurfaces == 1)
4909 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
4910 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 else if (r_batchmode.integer == 2)
4914 #define MAXBATCHTRIANGLES 4096
4915 int batchtriangles = 0;
4916 int batchelements[MAXBATCHTRIANGLES*3];
4917 for (i = 0;i < texturenumsurfaces;i = j)
4919 surface = texturesurfacelist[i];
4921 if (surface->num_triangles > MAXBATCHTRIANGLES)
4923 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
4926 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
4927 batchtriangles = surface->num_triangles;
4928 firstvertex = surface->num_firstvertex;
4929 endvertex = surface->num_firstvertex + surface->num_vertices;
4930 for (;j < texturenumsurfaces;j++)
4932 surface2 = texturesurfacelist[j];
4933 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
4935 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
4936 batchtriangles += surface2->num_triangles;
4937 firstvertex = min(firstvertex, surface2->num_firstvertex);
4938 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
4940 surface2 = texturesurfacelist[j-1];
4941 numvertices = endvertex - firstvertex;
4942 R_Mesh_Draw(firstvertex, numvertices, batchtriangles, batchelements, 0, 0);
4945 else if (r_batchmode.integer == 1)
4947 for (i = 0;i < texturenumsurfaces;i = j)
4949 surface = texturesurfacelist[i];
4950 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
4951 if (texturesurfacelist[j] != surface2)
4953 surface2 = texturesurfacelist[j-1];
4954 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
4955 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
4956 GL_LockArrays(surface->num_firstvertex, numvertices);
4957 R_Mesh_Draw(surface->num_firstvertex, numvertices, numtriangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
4962 for (i = 0;i < texturenumsurfaces;i++)
4964 surface = texturesurfacelist[i];
4965 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
4966 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));
4971 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit, int refractiontexunit, int reflectiontexunit)
4973 int i, planeindex, vertexindex;
4977 r_waterstate_waterplane_t *p, *bestp;
4978 msurface_t *surface;
4979 if (r_waterstate.renderingscene)
4981 for (i = 0;i < texturenumsurfaces;i++)
4983 surface = texturesurfacelist[i];
4984 if (lightmaptexunit >= 0)
4985 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
4986 if (deluxemaptexunit >= 0)
4987 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
4988 // pick the closest matching water plane
4991 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
4994 for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
4996 Matrix4x4_Transform(&rsurface.matrix, v, vert);
4997 d += fabs(PlaneDiff(vert, &p->plane));
4999 if (bestd > d || !bestp)
5007 if (refractiontexunit >= 0)
5008 R_Mesh_TexBind(refractiontexunit, R_GetTexture(bestp->texture_refraction));
5009 if (reflectiontexunit >= 0)
5010 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(bestp->texture_reflection));
5014 if (refractiontexunit >= 0)
5015 R_Mesh_TexBind(refractiontexunit, R_GetTexture(r_texture_black));
5016 if (reflectiontexunit >= 0)
5017 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(r_texture_black));
5019 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5020 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));
5024 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit)
5028 const msurface_t *surface = texturesurfacelist[0];
5029 const msurface_t *surface2;
5034 // TODO: lock all array ranges before render, rather than on each surface
5035 if (texturenumsurfaces == 1)
5037 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5038 if (deluxemaptexunit >= 0)
5039 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5040 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5041 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
5043 else if (r_batchmode.integer == 2)
5045 #define MAXBATCHTRIANGLES 4096
5046 int batchtriangles = 0;
5047 int batchelements[MAXBATCHTRIANGLES*3];
5048 for (i = 0;i < texturenumsurfaces;i = j)
5050 surface = texturesurfacelist[i];
5051 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5052 if (deluxemaptexunit >= 0)
5053 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5055 if (surface->num_triangles > MAXBATCHTRIANGLES)
5057 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));
5060 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
5061 batchtriangles = surface->num_triangles;
5062 firstvertex = surface->num_firstvertex;
5063 endvertex = surface->num_firstvertex + surface->num_vertices;
5064 for (;j < texturenumsurfaces;j++)
5066 surface2 = texturesurfacelist[j];
5067 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
5069 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
5070 batchtriangles += surface2->num_triangles;
5071 firstvertex = min(firstvertex, surface2->num_firstvertex);
5072 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
5074 surface2 = texturesurfacelist[j-1];
5075 numvertices = endvertex - firstvertex;
5076 R_Mesh_Draw(firstvertex, numvertices, batchtriangles, batchelements, 0, 0);
5079 else if (r_batchmode.integer == 1)
5082 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
5083 for (i = 0;i < texturenumsurfaces;i = j)
5085 surface = texturesurfacelist[i];
5086 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
5087 if (texturesurfacelist[j] != surface2)
5089 Con_Printf(" %i", j - i);
5092 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
5094 for (i = 0;i < texturenumsurfaces;i = j)
5096 surface = texturesurfacelist[i];
5097 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5098 if (deluxemaptexunit >= 0)
5099 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5100 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
5101 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
5104 Con_Printf(" %i", j - i);
5106 surface2 = texturesurfacelist[j-1];
5107 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
5108 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
5109 GL_LockArrays(surface->num_firstvertex, numvertices);
5110 R_Mesh_Draw(surface->num_firstvertex, numvertices, numtriangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
5118 for (i = 0;i < texturenumsurfaces;i++)
5120 surface = texturesurfacelist[i];
5121 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5122 if (deluxemaptexunit >= 0)
5123 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5124 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5125 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));
5130 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
5133 int texturesurfaceindex;
5134 if (r_showsurfaces.integer == 2)
5136 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5138 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5139 for (j = 0;j < surface->num_triangles;j++)
5141 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_view.colorscale;
5142 GL_Color(f, f, f, 1);
5143 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)));
5149 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5151 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5152 int k = (int)(((size_t)surface) / sizeof(msurface_t));
5153 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);
5154 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5155 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));
5160 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, msurface_t **texturesurfacelist)
5162 int texturesurfaceindex;
5166 if (rsurface.lightmapcolor4f)
5168 // generate color arrays for the surfaces in this list
5169 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5171 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5172 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)
5174 f = FogPoint_Model(v);
5184 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5186 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5187 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)
5189 f = FogPoint_Model(v);
5197 rsurface.lightmapcolor4f = rsurface.array_color4f;
5198 rsurface.lightmapcolor4f_bufferobject = 0;
5199 rsurface.lightmapcolor4f_bufferoffset = 0;
5202 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a)
5204 int texturesurfaceindex;
5207 if (!rsurface.lightmapcolor4f)
5209 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5211 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5212 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)
5220 rsurface.lightmapcolor4f = rsurface.array_color4f;
5221 rsurface.lightmapcolor4f_bufferobject = 0;
5222 rsurface.lightmapcolor4f_bufferoffset = 0;
5225 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
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_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 0, -1);
5238 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5240 // TODO: optimize applyfog && applycolor case
5241 // just apply fog if necessary, and tint the fog color array if necessary
5242 rsurface.lightmapcolor4f = NULL;
5243 rsurface.lightmapcolor4f_bufferobject = 0;
5244 rsurface.lightmapcolor4f_bufferoffset = 0;
5245 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5246 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5247 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5248 GL_Color(r, g, b, a);
5249 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5252 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5254 int texturesurfaceindex;
5258 if (texturesurfacelist[0]->lightmapinfo && texturesurfacelist[0]->lightmapinfo->stainsamples)
5260 // generate color arrays for the surfaces in this list
5261 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5263 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5264 for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
5266 if (surface->lightmapinfo->samples)
5268 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
5269 float scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
5270 VectorScale(lm, scale, c);
5271 if (surface->lightmapinfo->styles[1] != 255)
5273 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
5275 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
5276 VectorMA(c, scale, lm, c);
5277 if (surface->lightmapinfo->styles[2] != 255)
5280 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
5281 VectorMA(c, scale, lm, c);
5282 if (surface->lightmapinfo->styles[3] != 255)
5285 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
5286 VectorMA(c, scale, lm, c);
5296 rsurface.lightmapcolor4f = rsurface.array_color4f;
5297 rsurface.lightmapcolor4f_bufferobject = 0;
5298 rsurface.lightmapcolor4f_bufferoffset = 0;
5302 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
5303 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
5304 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
5306 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5307 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5308 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5309 GL_Color(r, g, b, a);
5310 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5313 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5315 int texturesurfaceindex;
5319 vec3_t ambientcolor;
5320 vec3_t diffusecolor;
5324 VectorCopy(rsurface.modellight_lightdir, lightdir);
5325 ambientcolor[0] = rsurface.modellight_ambient[0] * r * 0.5f;
5326 ambientcolor[1] = rsurface.modellight_ambient[1] * g * 0.5f;
5327 ambientcolor[2] = rsurface.modellight_ambient[2] * b * 0.5f;
5328 diffusecolor[0] = rsurface.modellight_diffuse[0] * r * 0.5f;
5329 diffusecolor[1] = rsurface.modellight_diffuse[1] * g * 0.5f;
5330 diffusecolor[2] = rsurface.modellight_diffuse[2] * b * 0.5f;
5331 if (VectorLength2(diffusecolor) > 0)
5333 // generate color arrays for the surfaces in this list
5334 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5336 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5337 int numverts = surface->num_vertices;
5338 v = rsurface.vertex3f + 3 * surface->num_firstvertex;
5339 c2 = rsurface.normal3f + 3 * surface->num_firstvertex;
5340 c = rsurface.array_color4f + 4 * surface->num_firstvertex;
5341 // q3-style directional shading
5342 for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
5344 if ((f = DotProduct(c2, lightdir)) > 0)
5345 VectorMA(ambientcolor, f, diffusecolor, c);
5347 VectorCopy(ambientcolor, c);
5356 rsurface.lightmapcolor4f = rsurface.array_color4f;
5357 rsurface.lightmapcolor4f_bufferobject = 0;
5358 rsurface.lightmapcolor4f_bufferoffset = 0;
5362 r = ambientcolor[0];
5363 g = ambientcolor[1];
5364 b = ambientcolor[2];
5365 rsurface.lightmapcolor4f = NULL;
5366 rsurface.lightmapcolor4f_bufferobject = 0;
5367 rsurface.lightmapcolor4f_bufferoffset = 0;
5369 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5370 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5371 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5372 GL_Color(r, g, b, a);
5373 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5376 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
5378 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5379 GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset);
5380 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
5381 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_view.cullface_back);
5382 if (rsurface.mode != RSURFMODE_SHOWSURFACES)
5384 rsurface.mode = RSURFMODE_SHOWSURFACES;
5386 GL_BlendFunc(GL_ONE, GL_ZERO);
5387 R_Mesh_ColorPointer(NULL, 0, 0);
5388 R_Mesh_ResetTextureState();
5390 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
5391 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
5394 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, msurface_t **texturesurfacelist)
5396 // transparent sky would be ridiculous
5397 if ((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED))
5399 if (rsurface.mode != RSURFMODE_SKY)
5401 if (rsurface.mode == RSURFMODE_GLSL)
5403 qglUseProgramObjectARB(0);CHECKGLERROR
5405 rsurface.mode = RSURFMODE_SKY;
5409 skyrendernow = false;
5411 // restore entity matrix
5412 R_Mesh_Matrix(&rsurface.matrix);
5414 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5415 GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset);
5416 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
5417 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_view.cullface_back);
5419 // LordHavoc: HalfLife maps have freaky skypolys so don't use
5420 // skymasking on them, and Quake3 never did sky masking (unlike
5421 // software Quake and software Quake2), so disable the sky masking
5422 // in Quake3 maps as it causes problems with q3map2 sky tricks,
5423 // and skymasking also looks very bad when noclipping outside the
5424 // level, so don't use it then either.
5425 if (r_refdef.worldmodel && r_refdef.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_viewcache.world_novis)
5427 GL_Color(r_refdef.fogcolor[0] * r_view.colorscale, r_refdef.fogcolor[1] * r_view.colorscale, r_refdef.fogcolor[2] * r_view.colorscale, 1);
5428 R_Mesh_ColorPointer(NULL, 0, 0);
5429 R_Mesh_ResetTextureState();
5430 if (skyrendermasked)
5432 // depth-only (masking)
5433 GL_ColorMask(0,0,0,0);
5434 // just to make sure that braindead drivers don't draw
5435 // anything despite that colormask...
5436 GL_BlendFunc(GL_ZERO, GL_ONE);
5441 GL_BlendFunc(GL_ONE, GL_ZERO);
5443 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
5444 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5445 if (skyrendermasked)
5446 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
5450 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, msurface_t **texturesurfacelist)
5452 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION)))
5455 if (rsurface.mode != RSURFMODE_GLSL)
5457 rsurface.mode = RSURFMODE_GLSL;
5458 R_Mesh_ResetTextureState();
5461 R_Mesh_TexMatrix(0, &rsurface.texture->currenttexmatrix);
5462 R_Mesh_TexBind(0, R_GetTexture(rsurface.texture->currentskinframe->nmap));
5463 R_Mesh_TexBind(1, R_GetTexture(rsurface.texture->basetexture));
5464 R_Mesh_TexBind(2, R_GetTexture(rsurface.texture->glosstexture));
5465 R_Mesh_TexBind(4, R_GetTexture(r_texture_fogattenuation));
5466 R_Mesh_TexBind(5, R_GetTexture(rsurface.texture->currentskinframe->pants));
5467 R_Mesh_TexBind(6, R_GetTexture(rsurface.texture->currentskinframe->shirt));
5468 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
5470 R_Mesh_TexBind(7, R_GetTexture(r_texture_grey128));
5471 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
5472 R_Mesh_ColorPointer(NULL, 0, 0);
5474 else if (rsurface.uselightmaptexture)
5476 R_Mesh_TexBind(7, R_GetTexture(texturesurfacelist[0]->lightmaptexture));
5477 R_Mesh_TexBind(8, R_GetTexture(texturesurfacelist[0]->deluxemaptexture));
5478 R_Mesh_ColorPointer(NULL, 0, 0);
5482 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
5483 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
5484 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
5486 R_Mesh_TexBind(9, R_GetTexture(rsurface.texture->currentskinframe->glow));
5487 R_Mesh_TexBind(11, R_GetTexture(r_texture_white)); // changed per surface
5488 R_Mesh_TexBind(12, R_GetTexture(r_texture_white)); // changed per surface
5490 if (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5492 // render background
5493 GL_BlendFunc(GL_ONE, GL_ZERO);
5495 GL_AlphaTest(false);
5497 GL_Color(1, 1, 1, 1);
5498 R_Mesh_ColorPointer(NULL, 0, 0);
5500 R_SetupSurfaceShader(vec3_origin, rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
5501 if (r_glsl_permutation)
5503 RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
5504 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
5505 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
5506 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
5507 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
5508 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
5509 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist, -1, -1, r_glsl_permutation->loc_Texture_Refraction ? 11 : -1, r_glsl_permutation->loc_Texture_Reflection ? 12 : -1);
5512 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5513 GL_DepthMask(false);
5514 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5515 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
5517 R_Mesh_TexBind(7, R_GetTexture(r_texture_grey128));
5518 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
5519 R_Mesh_ColorPointer(NULL, 0, 0);
5521 else if (rsurface.uselightmaptexture)
5523 R_Mesh_TexBind(7, R_GetTexture(texturesurfacelist[0]->lightmaptexture));
5524 R_Mesh_TexBind(8, R_GetTexture(texturesurfacelist[0]->deluxemaptexture));
5525 R_Mesh_ColorPointer(NULL, 0, 0);
5529 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
5530 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
5531 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
5533 R_Mesh_TexBind(11, R_GetTexture(r_texture_white)); // changed per surface
5534 R_Mesh_TexBind(12, R_GetTexture(r_texture_white)); // changed per surface
5537 R_SetupSurfaceShader(vec3_origin, rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE);
5538 if (!r_glsl_permutation)
5541 RSurf_PrepareVerticesForBatch(r_glsl_permutation->loc_Texture_Normal >= 0 || r_glsl_permutation->loc_LightDir >= 0, r_glsl_permutation->loc_Texture_Normal >= 0, texturenumsurfaces, texturesurfacelist);
5542 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
5543 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
5544 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
5545 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
5546 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
5547 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]);
5549 if (r_glsl_permutation->loc_Texture_Refraction >= 0)
5551 GL_BlendFunc(GL_ONE, GL_ZERO);
5553 GL_AlphaTest(false);
5556 if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
5558 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
5559 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);
5561 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 7, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? 8 : -1);
5565 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
5566 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);
5568 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5570 if (rsurface.texture->backgroundnumskinframes && !(rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED))
5575 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, msurface_t **texturesurfacelist)
5577 // OpenGL 1.3 path - anything not completely ancient
5578 int texturesurfaceindex;
5579 qboolean applycolor;
5583 const texturelayer_t *layer;
5584 if (rsurface.mode != RSURFMODE_MULTIPASS)
5585 rsurface.mode = RSURFMODE_MULTIPASS;
5586 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
5588 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
5591 int layertexrgbscale;
5592 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5594 if (layerindex == 0)
5598 GL_AlphaTest(false);
5599 qglDepthFunc(GL_EQUAL);CHECKGLERROR
5602 GL_DepthMask(layer->depthmask);
5603 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
5604 if ((layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2) && (gl_combine.integer || layer->depthmask))
5606 layertexrgbscale = 4;
5607 VectorScale(layer->color, 0.25f, layercolor);
5609 else if ((layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1) && (gl_combine.integer || layer->depthmask))
5611 layertexrgbscale = 2;
5612 VectorScale(layer->color, 0.5f, layercolor);
5616 layertexrgbscale = 1;
5617 VectorScale(layer->color, 1.0f, layercolor);
5619 layercolor[3] = layer->color[3];
5620 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
5621 R_Mesh_ColorPointer(NULL, 0, 0);
5622 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
5623 switch (layer->type)
5625 case TEXTURELAYERTYPE_LITTEXTURE:
5626 memset(&m, 0, sizeof(m));
5627 m.tex[0] = R_GetTexture(r_texture_white);
5628 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
5629 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
5630 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
5631 m.tex[1] = R_GetTexture(layer->texture);
5632 m.texmatrix[1] = layer->texmatrix;
5633 m.texrgbscale[1] = layertexrgbscale;
5634 m.pointer_texcoord[1] = rsurface.texcoordtexture2f;
5635 m.pointer_texcoord_bufferobject[1] = rsurface.texcoordtexture2f_bufferobject;
5636 m.pointer_texcoord_bufferoffset[1] = rsurface.texcoordtexture2f_bufferoffset;
5637 R_Mesh_TextureState(&m);
5638 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
5639 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
5640 else if (rsurface.uselightmaptexture)
5641 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
5643 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
5645 case TEXTURELAYERTYPE_TEXTURE:
5646 memset(&m, 0, sizeof(m));
5647 m.tex[0] = R_GetTexture(layer->texture);
5648 m.texmatrix[0] = layer->texmatrix;
5649 m.texrgbscale[0] = layertexrgbscale;
5650 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5651 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5652 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5653 R_Mesh_TextureState(&m);
5654 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
5656 case TEXTURELAYERTYPE_FOG:
5657 memset(&m, 0, sizeof(m));
5658 m.texrgbscale[0] = layertexrgbscale;
5661 m.tex[0] = R_GetTexture(layer->texture);
5662 m.texmatrix[0] = layer->texmatrix;
5663 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5664 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5665 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5667 R_Mesh_TextureState(&m);
5668 // generate a color array for the fog pass
5669 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
5670 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5674 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5675 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)
5677 f = 1 - FogPoint_Model(v);
5678 c[0] = layercolor[0];
5679 c[1] = layercolor[1];
5680 c[2] = layercolor[2];
5681 c[3] = f * layercolor[3];
5684 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5687 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
5689 GL_LockArrays(0, 0);
5692 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5694 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
5695 GL_AlphaTest(false);
5699 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, msurface_t **texturesurfacelist)
5701 // OpenGL 1.1 - crusty old voodoo path
5702 int texturesurfaceindex;
5706 const texturelayer_t *layer;
5707 if (rsurface.mode != RSURFMODE_MULTIPASS)
5708 rsurface.mode = RSURFMODE_MULTIPASS;
5709 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
5711 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
5713 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5715 if (layerindex == 0)
5719 GL_AlphaTest(false);
5720 qglDepthFunc(GL_EQUAL);CHECKGLERROR
5723 GL_DepthMask(layer->depthmask);
5724 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
5725 R_Mesh_ColorPointer(NULL, 0, 0);
5726 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
5727 switch (layer->type)
5729 case TEXTURELAYERTYPE_LITTEXTURE:
5730 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
5732 // two-pass lit texture with 2x rgbscale
5733 // first the lightmap pass
5734 memset(&m, 0, sizeof(m));
5735 m.tex[0] = R_GetTexture(r_texture_white);
5736 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
5737 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
5738 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
5739 R_Mesh_TextureState(&m);
5740 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
5741 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5742 else if (rsurface.uselightmaptexture)
5743 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5745 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5746 GL_LockArrays(0, 0);
5747 // then apply the texture to it
5748 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
5749 memset(&m, 0, sizeof(m));
5750 m.tex[0] = R_GetTexture(layer->texture);
5751 m.texmatrix[0] = layer->texmatrix;
5752 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5753 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5754 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5755 R_Mesh_TextureState(&m);
5756 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);
5760 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
5761 memset(&m, 0, sizeof(m));
5762 m.tex[0] = R_GetTexture(layer->texture);
5763 m.texmatrix[0] = layer->texmatrix;
5764 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5765 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5766 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5767 R_Mesh_TextureState(&m);
5768 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
5769 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);
5771 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);
5774 case TEXTURELAYERTYPE_TEXTURE:
5775 // singletexture unlit texture with transparency support
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);
5783 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);
5785 case TEXTURELAYERTYPE_FOG:
5786 // singletexture fogging
5787 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
5790 memset(&m, 0, sizeof(m));
5791 m.tex[0] = R_GetTexture(layer->texture);
5792 m.texmatrix[0] = layer->texmatrix;
5793 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5794 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5795 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5796 R_Mesh_TextureState(&m);
5799 R_Mesh_ResetTextureState();
5800 // generate a color array for the fog pass
5801 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5805 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5806 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)
5808 f = 1 - FogPoint_Model(v);
5809 c[0] = layer->color[0];
5810 c[1] = layer->color[1];
5811 c[2] = layer->color[2];
5812 c[3] = f * layer->color[3];
5815 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5818 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
5820 GL_LockArrays(0, 0);
5823 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5825 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
5826 GL_AlphaTest(false);
5830 static void R_DrawTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly)
5832 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW)
5834 rsurface.rtlight = NULL;
5838 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
5840 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
5842 if (rsurface.mode != RSURFMODE_MULTIPASS)
5843 rsurface.mode = RSURFMODE_MULTIPASS;
5844 if (r_depthfirst.integer == 3)
5846 int i = (int)(texturesurfacelist[0] - rsurface.modelsurfaces);
5847 if (!r_view.showdebug)
5848 GL_Color(0, 0, 0, 1);
5850 GL_Color(((i >> 6) & 7) / 7.0f, ((i >> 3) & 7) / 7.0f, (i & 7) / 7.0f,1);
5854 GL_ColorMask(0,0,0,0);
5857 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5858 GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset);
5859 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_view.cullface_back);
5861 GL_BlendFunc(GL_ONE, GL_ZERO);
5863 GL_AlphaTest(false);
5864 R_Mesh_ColorPointer(NULL, 0, 0);
5865 R_Mesh_ResetTextureState();
5866 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
5867 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5868 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
5870 else if (r_depthfirst.integer == 3)
5872 else if (!r_view.showdebug && (r_showsurfaces.integer || gl_lightmaps.integer))
5874 GL_Color(0, 0, 0, 1);
5875 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5877 else if (r_showsurfaces.integer)
5879 if (rsurface.mode != RSURFMODE_MULTIPASS)
5880 rsurface.mode = RSURFMODE_MULTIPASS;
5881 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5882 GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset);
5884 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_view.cullface_back);
5885 GL_BlendFunc(GL_ONE, GL_ZERO);
5886 GL_DepthMask(writedepth);
5888 GL_AlphaTest(false);
5889 R_Mesh_ColorPointer(NULL, 0, 0);
5890 R_Mesh_ResetTextureState();
5891 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
5892 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
5894 else if (gl_lightmaps.integer)
5897 if (rsurface.mode != RSURFMODE_MULTIPASS)
5898 rsurface.mode = RSURFMODE_MULTIPASS;
5899 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5901 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_view.cullface_back);
5902 GL_BlendFunc(GL_ONE, GL_ZERO);
5903 GL_DepthMask(writedepth);
5905 GL_AlphaTest(false);
5906 R_Mesh_ColorPointer(NULL, 0, 0);
5907 memset(&m, 0, sizeof(m));
5908 m.tex[0] = R_GetTexture(r_texture_white);
5909 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
5910 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
5911 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
5912 R_Mesh_TextureState(&m);
5913 RSurf_PrepareVerticesForBatch(rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT, false, texturenumsurfaces, texturesurfacelist);
5914 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
5915 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5916 else if (rsurface.uselightmaptexture)
5917 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5919 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5921 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
5922 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
5923 else if (rsurface.texture->currentnumlayers)
5925 // write depth for anything we skipped on the depth-only pass earlier
5926 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5928 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5929 GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset);
5930 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
5931 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_view.cullface_back);
5932 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5933 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
5934 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5935 if (r_glsl.integer && gl_support_fragment_shader)
5936 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist);
5937 else if (gl_combine.integer && r_textureunits.integer >= 2)
5938 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist);
5940 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist);
5943 GL_LockArrays(0, 0);
5946 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
5949 int texturenumsurfaces, endsurface;
5951 msurface_t *surface;
5952 msurface_t *texturesurfacelist[1024];
5954 // if the model is static it doesn't matter what value we give for
5955 // wantnormals and wanttangents, so this logic uses only rules applicable
5956 // to a model, knowing that they are meaningless otherwise
5957 if (ent == r_refdef.worldentity)
5958 RSurf_ActiveWorldEntity();
5959 else if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
5960 RSurf_ActiveModelEntity(ent, false, false);
5962 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
5964 for (i = 0;i < numsurfaces;i = j)
5967 surface = rsurface.modelsurfaces + surfacelist[i];
5968 texture = surface->texture;
5969 R_UpdateTextureInfo(ent, texture);
5970 rsurface.texture = texture->currentframe;
5971 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
5972 // scan ahead until we find a different texture
5973 endsurface = min(i + 1024, numsurfaces);
5974 texturenumsurfaces = 0;
5975 texturesurfacelist[texturenumsurfaces++] = surface;
5976 for (;j < endsurface;j++)
5978 surface = rsurface.modelsurfaces + surfacelist[j];
5979 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
5981 texturesurfacelist[texturenumsurfaces++] = surface;
5983 // render the range of surfaces
5984 R_DrawTextureSurfaceList(texturenumsurfaces, texturesurfacelist, true, false);
5990 void R_QueueSurfaceList(entity_render_t *ent, int numsurfaces, msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes)
5993 vec3_t tempcenter, center;
5995 // if we're rendering water textures (extra scene renders), use a separate loop to avoid burdening the main one
5998 for (i = 0;i < numsurfaces;i++)
5999 if (surfacelist[i]->texture->currentframe->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION))
6000 R_Water_AddWaterPlane(surfacelist[i]);
6003 // break the surface list down into batches by texture and use of lightmapping
6004 for (i = 0;i < numsurfaces;i = j)
6007 // texture is the base texture pointer, rsurface.texture is the
6008 // current frame/skin the texture is directing us to use (for example
6009 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
6010 // use skin 1 instead)
6011 texture = surfacelist[i]->texture;
6012 rsurface.texture = texture->currentframe;
6013 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
6014 if (!(rsurface.texture->currentmaterialflags & flagsmask))
6016 // if this texture is not the kind we want, skip ahead to the next one
6017 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
6021 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
6023 // transparent surfaces get pushed off into the transparent queue
6024 const msurface_t *surface = surfacelist[i];
6027 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
6028 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
6029 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
6030 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
6031 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_view.origin : center, R_DrawSurface_TransparentCallback, ent, surface - rsurface.modelsurfaces, rsurface.rtlight);
6035 // simply scan ahead until we find a different texture or lightmap state
6036 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
6038 // render the range of surfaces
6039 R_DrawTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly);
6044 float locboxvertex3f[6*4*3] =
6046 1,0,1, 1,0,0, 1,1,0, 1,1,1,
6047 0,1,1, 0,1,0, 0,0,0, 0,0,1,
6048 1,1,1, 1,1,0, 0,1,0, 0,1,1,
6049 0,0,1, 0,0,0, 1,0,0, 1,0,1,
6050 0,0,1, 1,0,1, 1,1,1, 0,1,1,
6051 1,0,0, 0,0,0, 0,1,0, 1,1,0
6054 int locboxelement3i[6*2*3] =
6064 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6067 cl_locnode_t *loc = (cl_locnode_t *)ent;
6069 float vertex3f[6*4*3];
6071 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6072 GL_DepthMask(false);
6073 GL_DepthRange(0, 1);
6074 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6076 GL_CullFace(GL_NONE);
6077 R_Mesh_Matrix(&identitymatrix);
6079 R_Mesh_VertexPointer(vertex3f, 0, 0);
6080 R_Mesh_ColorPointer(NULL, 0, 0);
6081 R_Mesh_ResetTextureState();
6084 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_view.colorscale,
6085 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_view.colorscale,
6086 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_view.colorscale,
6087 surfacelist[0] < 0 ? 0.5f : 0.125f);
6089 if (VectorCompare(loc->mins, loc->maxs))
6091 VectorSet(size, 2, 2, 2);
6092 VectorMA(loc->mins, -0.5f, size, mins);
6096 VectorCopy(loc->mins, mins);
6097 VectorSubtract(loc->maxs, loc->mins, size);
6100 for (i = 0;i < 6*4*3;)
6101 for (j = 0;j < 3;j++, i++)
6102 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
6104 R_Mesh_Draw(0, 6*4, 6*2, locboxelement3i, 0, 0);
6107 void R_DrawLocs(void)
6110 cl_locnode_t *loc, *nearestloc;
6112 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
6113 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
6115 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
6116 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
6120 void R_DrawDebugModel(entity_render_t *ent)
6122 int i, j, k, l, flagsmask;
6123 const int *elements;
6125 msurface_t *surface;
6126 model_t *model = ent->model;
6129 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WATER | MATERIALFLAG_WALL;
6131 R_Mesh_ColorPointer(NULL, 0, 0);
6132 R_Mesh_ResetTextureState();
6133 GL_DepthRange(0, 1);
6134 GL_DepthTest(!r_showdisabledepthtest.integer);
6135 GL_DepthMask(false);
6136 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6138 if (r_showcollisionbrushes.value > 0 && model->brush.num_brushes)
6140 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
6141 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
6143 if (brush->colbrushf && brush->colbrushf->numtriangles)
6145 R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
6146 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);
6147 R_Mesh_Draw(0, brush->colbrushf->numpoints, brush->colbrushf->numtriangles, brush->colbrushf->elements, 0, 0);
6150 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
6152 if (surface->num_collisiontriangles)
6154 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
6155 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);
6156 R_Mesh_Draw(0, surface->num_collisionvertices, surface->num_collisiontriangles, surface->data_collisionelement3i, 0, 0);
6161 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6163 if (r_showtris.integer || r_shownormals.integer)
6165 if (r_showdisabledepthtest.integer)
6167 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6168 GL_DepthMask(false);
6172 GL_BlendFunc(GL_ONE, GL_ZERO);
6175 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
6177 if (ent == r_refdef.worldentity && !r_viewcache.world_surfacevisible[j])
6179 rsurface.texture = surface->texture->currentframe;
6180 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
6182 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
6183 if (r_showtris.value > 0)
6185 if (!rsurface.texture->currentlayers->depthmask)
6186 GL_Color(r_view.colorscale, 0, 0, r_showtris.value);
6187 else if (ent == r_refdef.worldentity)
6188 GL_Color(r_view.colorscale, r_view.colorscale, r_view.colorscale, r_showtris.value);
6190 GL_Color(0, r_view.colorscale, 0, r_showtris.value);
6191 elements = (ent->model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
6194 for (k = 0;k < surface->num_triangles;k++, elements += 3)
6196 #define GLVERTEXELEMENT(n) qglVertex3f(rsurface.vertex3f[elements[n]*3+0], rsurface.vertex3f[elements[n]*3+1], rsurface.vertex3f[elements[n]*3+2])
6197 GLVERTEXELEMENT(0);GLVERTEXELEMENT(1);
6198 GLVERTEXELEMENT(1);GLVERTEXELEMENT(2);
6199 GLVERTEXELEMENT(2);GLVERTEXELEMENT(0);
6204 if (r_shownormals.value > 0)
6206 GL_Color(r_view.colorscale, 0, 0, r_shownormals.value);
6208 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
6210 VectorCopy(rsurface.vertex3f + l * 3, v);
6211 qglVertex3f(v[0], v[1], v[2]);
6212 VectorMA(v, 8, rsurface.svector3f + l * 3, v);
6213 qglVertex3f(v[0], v[1], v[2]);
6217 GL_Color(0, 0, r_view.colorscale, r_shownormals.value);
6219 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
6221 VectorCopy(rsurface.vertex3f + l * 3, v);
6222 qglVertex3f(v[0], v[1], v[2]);
6223 VectorMA(v, 8, rsurface.tvector3f + l * 3, v);
6224 qglVertex3f(v[0], v[1], v[2]);
6228 GL_Color(0, r_view.colorscale, 0, r_shownormals.value);
6230 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
6232 VectorCopy(rsurface.vertex3f + l * 3, v);
6233 qglVertex3f(v[0], v[1], v[2]);
6234 VectorMA(v, 8, rsurface.normal3f + l * 3, v);
6235 qglVertex3f(v[0], v[1], v[2]);
6242 rsurface.texture = NULL;
6246 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
6247 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes, qboolean debug)
6249 int i, j, endj, f, flagsmask;
6250 msurface_t *surface, **surfacechain;
6252 model_t *model = r_refdef.worldmodel;
6253 const int maxsurfacelist = 1024;
6254 int numsurfacelist = 0;
6255 msurface_t *surfacelist[1024];
6259 RSurf_ActiveWorldEntity();
6261 // update light styles
6262 if (!skysurfaces && !depthonly && !addwaterplanes && model->brushq1.light_styleupdatechains)
6264 for (i = 0;i < model->brushq1.light_styles;i++)
6266 if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
6268 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
6269 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
6270 for (;(surface = *surfacechain);surfacechain++)
6271 surface->cached_dlight = true;
6276 R_UpdateAllTextureInfo(r_refdef.worldentity);
6277 flagsmask = addwaterplanes ? (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) : (skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL));
6281 R_DrawDebugModel(r_refdef.worldentity);
6287 rsurface.uselightmaptexture = false;
6288 rsurface.texture = NULL;
6290 j = model->firstmodelsurface;
6291 endj = j + model->nummodelsurfaces;
6294 // quickly skip over non-visible surfaces
6295 for (;j < endj && !r_viewcache.world_surfacevisible[j];j++)
6297 // quickly iterate over visible surfaces
6298 for (;j < endj && r_viewcache.world_surfacevisible[j];j++)
6300 // process this surface
6301 surface = model->data_surfaces + j;
6302 // if this surface fits the criteria, add it to the list
6303 if (surface->num_triangles)
6305 // if lightmap parameters changed, rebuild lightmap texture
6306 if (surface->cached_dlight)
6307 R_BuildLightMap(r_refdef.worldentity, surface);
6308 // add face to draw list
6309 surfacelist[numsurfacelist++] = surface;
6310 r_refdef.stats.world_triangles += surface->num_triangles;
6311 if (numsurfacelist >= maxsurfacelist)
6313 r_refdef.stats.world_surfaces += numsurfacelist;
6314 R_QueueSurfaceList(r_refdef.worldentity, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
6320 r_refdef.stats.world_surfaces += numsurfacelist;
6322 R_QueueSurfaceList(r_refdef.worldentity, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
6326 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes, qboolean debug)
6328 int i, f, flagsmask;
6329 msurface_t *surface, *endsurface, **surfacechain;
6331 model_t *model = ent->model;
6332 const int maxsurfacelist = 1024;
6333 int numsurfacelist = 0;
6334 msurface_t *surfacelist[1024];
6338 // if the model is static it doesn't matter what value we give for
6339 // wantnormals and wanttangents, so this logic uses only rules applicable
6340 // to a model, knowing that they are meaningless otherwise
6341 if (ent == r_refdef.worldentity)
6342 RSurf_ActiveWorldEntity();
6343 else if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
6344 RSurf_ActiveModelEntity(ent, false, false);
6346 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader && !depthonly);
6348 // update light styles
6349 if (!skysurfaces && !depthonly && !addwaterplanes && model->brushq1.light_styleupdatechains)
6351 for (i = 0;i < model->brushq1.light_styles;i++)
6353 if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
6355 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
6356 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
6357 for (;(surface = *surfacechain);surfacechain++)
6358 surface->cached_dlight = true;
6363 R_UpdateAllTextureInfo(ent);
6364 flagsmask = addwaterplanes ? (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) : (skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL));
6368 R_DrawDebugModel(ent);
6374 rsurface.uselightmaptexture = false;
6375 rsurface.texture = NULL;
6377 surface = model->data_surfaces + model->firstmodelsurface;
6378 endsurface = surface + model->nummodelsurfaces;
6379 for (;surface < endsurface;surface++)
6381 // if this surface fits the criteria, add it to the list
6382 if (surface->num_triangles)
6384 // if lightmap parameters changed, rebuild lightmap texture
6385 if (surface->cached_dlight)
6386 R_BuildLightMap(ent, surface);
6387 // add face to draw list
6388 surfacelist[numsurfacelist++] = surface;
6389 r_refdef.stats.entities_triangles += surface->num_triangles;
6390 if (numsurfacelist >= maxsurfacelist)
6392 r_refdef.stats.entities_surfaces += numsurfacelist;
6393 R_QueueSurfaceList(ent, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
6398 r_refdef.stats.entities_surfaces += numsurfacelist;
6400 R_QueueSurfaceList(ent, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);