2 Copyright (C) 1996-1997 Id Software, Inc.
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
27 mempool_t *r_main_mempool;
28 rtexturepool_t *r_main_texturepool;
35 r_viewcache_t r_viewcache;
37 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "1", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
38 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
39 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%, 10 = 100%)"};
40 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
41 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
42 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
43 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
44 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
45 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
46 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
47 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
48 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
49 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
50 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
51 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
52 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
53 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling"};
54 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
55 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
56 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
57 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
58 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
59 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
60 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
61 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this)"};
62 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
63 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
64 cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
65 cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "2", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
67 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
68 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
69 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
70 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
71 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
72 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
73 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
75 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of hardware texture units reported by driver (note: setting this to 1 turns off gl_combine)"};
77 cvar_t r_glsl = {CVAR_SAVE, "r_glsl", "1", "enables use of OpenGL 2.0 pixel shaders for lighting"};
78 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
79 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
80 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
81 cvar_t r_glsl_water = {CVAR_SAVE, "r_glsl_water", "0", "whether to use reflections and refraction on water surfaces (note: r_wateralpha must be set below 1)"};
82 cvar_t r_glsl_water_clippingplanebias = {CVAR_SAVE, "r_glsl_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
83 cvar_t r_glsl_water_resolutionmultiplier = {CVAR_SAVE, "r_glsl_water_resolutionmultiplier", "0.5", "multiplier for screen resolution when rendering refracted/reflected scenes, 1 is full quality, lower values are faster"};
84 cvar_t r_glsl_water_refractcolor_r = {CVAR_SAVE, "r_glsl_water_refractcolor_r", "1", "water color tint for refraction"};
85 cvar_t r_glsl_water_refractcolor_g = {CVAR_SAVE, "r_glsl_water_refractcolor_g", "1", "water color tint for refraction"};
86 cvar_t r_glsl_water_refractcolor_b = {CVAR_SAVE, "r_glsl_water_refractcolor_b", "1", "water color tint for refraction"};
87 cvar_t r_glsl_water_reflectcolor_r = {CVAR_SAVE, "r_glsl_water_reflectcolor_r", "1", "water color tint for reflection"};
88 cvar_t r_glsl_water_reflectcolor_g = {CVAR_SAVE, "r_glsl_water_reflectcolor_g", "1", "water color tint for reflection"};
89 cvar_t r_glsl_water_reflectcolor_b = {CVAR_SAVE, "r_glsl_water_reflectcolor_b", "1", "water color tint for reflection"};
90 cvar_t r_glsl_water_refractdistort = {CVAR_SAVE, "r_glsl_water_refractdistort", "0.01", "how much water refractions shimmer"};
91 cvar_t r_glsl_water_reflectdistort = {CVAR_SAVE, "r_glsl_water_reflectdistort", "0.01", "how much water reflections shimmer"};
92 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)"};
93 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)"};
95 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1", "enables animation smoothing on sprites (requires r_lerpmodels 1)"};
96 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
97 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
99 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
100 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
101 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
102 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
103 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
104 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
105 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
107 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
108 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
109 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
110 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)"};
112 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"};
114 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"};
116 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
118 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
119 cvar_t r_batchmode = {0, "r_batchmode", "1", "selects method of rendering multiple surfaces with one driver call (values are 0, 1, 2, etc...)"};
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 // information about each possible shader permutation
197 r_glsl_permutation_t r_glsl_permutations[SHADERPERMUTATION_MAX];
198 // currently selected permutation
199 r_glsl_permutation_t *r_glsl_permutation;
201 char r_qwskincache[MAX_SCOREBOARD][MAX_QPATH];
202 skinframe_t *r_qwskincache_skinframe[MAX_SCOREBOARD];
204 // vertex coordinates for a quad that covers the screen exactly
205 const static float r_screenvertex3f[12] =
213 extern void R_DrawModelShadows(void);
215 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
218 for (i = 0;i < verts;i++)
229 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
232 for (i = 0;i < verts;i++)
242 // FIXME: move this to client?
245 if (gamemode == GAME_NEHAHRA)
247 Cvar_Set("gl_fogenable", "0");
248 Cvar_Set("gl_fogdensity", "0.2");
249 Cvar_Set("gl_fogred", "0.3");
250 Cvar_Set("gl_foggreen", "0.3");
251 Cvar_Set("gl_fogblue", "0.3");
253 r_refdef.fog_density = r_refdef.fog_red = r_refdef.fog_green = r_refdef.fog_blue = 0.0f;
256 float FogPoint_World(const vec3_t p)
258 int fogmasktableindex = (int)(VectorDistance((p), r_view.origin) * r_refdef.fogmasktabledistmultiplier);
259 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
262 float FogPoint_Model(const vec3_t p)
264 int fogmasktableindex = (int)(VectorDistance((p), rsurface.modelorg) * r_refdef.fogmasktabledistmultiplier);
265 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
268 static void R_BuildBlankTextures(void)
270 unsigned char data[4];
271 data[0] = 128; // normal X
272 data[1] = 128; // normal Y
273 data[2] = 255; // normal Z
274 data[3] = 128; // height
275 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
280 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
285 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
290 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
293 static void R_BuildNoTexture(void)
296 unsigned char pix[16][16][4];
297 // this makes a light grey/dark grey checkerboard texture
298 for (y = 0;y < 16;y++)
300 for (x = 0;x < 16;x++)
302 if ((y < 8) ^ (x < 8))
318 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_RGBA, TEXF_MIPMAP, NULL);
321 static void R_BuildWhiteCube(void)
323 unsigned char data[6*1*1*4];
324 data[ 0] = 255;data[ 1] = 255;data[ 2] = 255;data[ 3] = 255;
325 data[ 4] = 255;data[ 5] = 255;data[ 6] = 255;data[ 7] = 255;
326 data[ 8] = 255;data[ 9] = 255;data[10] = 255;data[11] = 255;
327 data[12] = 255;data[13] = 255;data[14] = 255;data[15] = 255;
328 data[16] = 255;data[17] = 255;data[18] = 255;data[19] = 255;
329 data[20] = 255;data[21] = 255;data[22] = 255;data[23] = 255;
330 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
333 static void R_BuildNormalizationCube(void)
337 vec_t s, t, intensity;
339 unsigned char data[6][NORMSIZE][NORMSIZE][4];
340 for (side = 0;side < 6;side++)
342 for (y = 0;y < NORMSIZE;y++)
344 for (x = 0;x < NORMSIZE;x++)
346 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
347 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
382 intensity = 127.0f / sqrt(DotProduct(v, v));
383 data[side][y][x][0] = (unsigned char)(128.0f + intensity * v[0]);
384 data[side][y][x][1] = (unsigned char)(128.0f + intensity * v[1]);
385 data[side][y][x][2] = (unsigned char)(128.0f + intensity * v[2]);
386 data[side][y][x][3] = 255;
390 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, &data[0][0][0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
393 static void R_BuildFogTexture(void)
397 unsigned char data1[FOGWIDTH][4];
398 //unsigned char data2[FOGWIDTH][4];
399 for (x = 0;x < FOGWIDTH;x++)
401 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
406 //data2[x][0] = 255 - b;
407 //data2[x][1] = 255 - b;
408 //data2[x][2] = 255 - b;
411 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
412 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
415 static const char *builtinshaderstring =
416 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
417 "// written by Forest 'LordHavoc' Hale\n"
419 "// common definitions between vertex shader and fragment shader:\n"
421 "#ifdef __GLSL_CG_DATA_TYPES\n"
422 "# define myhalf half\n"
423 "# define myhvec2 hvec2\n"
424 "# define myhvec3 hvec3\n"
425 "# define myhvec4 hvec4\n"
427 "# define myhalf float\n"
428 "# define myhvec2 vec2\n"
429 "# define myhvec3 vec3\n"
430 "# define myhvec4 vec4\n"
433 "varying vec2 TexCoord;\n"
434 "varying vec2 TexCoordLightmap;\n"
436 "//#ifdef MODE_LIGHTSOURCE\n"
437 "varying vec3 CubeVector;\n"
440 "//#ifdef MODE_LIGHTSOURCE\n"
441 "varying vec3 LightVector;\n"
443 "//# ifdef MODE_LIGHTDIRECTION\n"
444 "//varying vec3 LightVector;\n"
448 "varying vec3 EyeVector;\n"
450 "varying vec3 EyeVectorModelSpace;\n"
453 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
454 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
455 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
457 "//#ifdef USEWATER\n"
458 "varying vec4 ModelViewProjectionPosition;\n"
460 "//# ifdef USEREFLECTION\n"
461 "//varying vec4 ModelViewProjectionPosition;\n"
469 "// vertex shader specific:\n"
470 "#ifdef VERTEX_SHADER\n"
472 "uniform vec3 LightPosition;\n"
473 "uniform vec3 EyePosition;\n"
474 "uniform vec3 LightDir;\n"
476 "// TODO: get rid of tangentt (texcoord2) and use a crossproduct to regenerate it from tangents (texcoord1) and normal (texcoord3)\n"
480 " gl_FrontColor = gl_Color;\n"
481 " // copy the surface texcoord\n"
482 " TexCoord = vec2(gl_TextureMatrix[0] * gl_MultiTexCoord0);\n"
483 "#ifndef MODE_LIGHTSOURCE\n"
484 "# ifndef MODE_LIGHTDIRECTION\n"
485 " TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
489 "#ifdef MODE_LIGHTSOURCE\n"
490 " // transform vertex position into light attenuation/cubemap space\n"
491 " // (-1 to +1 across the light box)\n"
492 " CubeVector = vec3(gl_TextureMatrix[3] * gl_Vertex);\n"
494 " // transform unnormalized light direction into tangent space\n"
495 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
496 " // normalize it per pixel)\n"
497 " vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
498 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
499 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
500 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
503 "#ifdef MODE_LIGHTDIRECTION\n"
504 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
505 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
506 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
509 " // transform unnormalized eye direction into tangent space\n"
511 " vec3 EyeVectorModelSpace;\n"
513 " EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
514 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
515 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
516 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
518 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
519 " VectorS = gl_MultiTexCoord1.xyz;\n"
520 " VectorT = gl_MultiTexCoord2.xyz;\n"
521 " VectorR = gl_MultiTexCoord3.xyz;\n"
524 "//#if defined(USEWATER) || defined(USEREFLECTION)\n"
525 "// ModelViewProjectionPosition = gl_Vertex * gl_ModelViewProjectionMatrix;\n"
526 "// //ModelViewProjectionPosition_svector = (gl_Vertex + vec4(gl_MultiTexCoord1.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
527 "// //ModelViewProjectionPosition_tvector = (gl_Vertex + vec4(gl_MultiTexCoord2.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
530 "// transform vertex to camera space, using ftransform to match non-VS\n"
532 " gl_Position = ftransform();\n"
535 " ModelViewProjectionPosition = gl_Position;\n"
537 "# ifdef USEREFLECTION\n"
538 " ModelViewProjectionPosition = gl_Position;\n"
543 "#endif // VERTEX_SHADER\n"
548 "// fragment shader specific:\n"
549 "#ifdef FRAGMENT_SHADER\n"
551 "// 13 textures, we can only use up to 16 on DX9-class hardware\n"
552 "uniform sampler2D Texture_Normal;\n"
553 "uniform sampler2D Texture_Color;\n"
554 "uniform sampler2D Texture_Gloss;\n"
555 "uniform samplerCube Texture_Cube;\n"
556 "uniform sampler2D Texture_Attenuation;\n"
557 "uniform sampler2D Texture_FogMask;\n"
558 "uniform sampler2D Texture_Pants;\n"
559 "uniform sampler2D Texture_Shirt;\n"
560 "uniform sampler2D Texture_Lightmap;\n"
561 "uniform sampler2D Texture_Deluxemap;\n"
562 "uniform sampler2D Texture_Glow;\n"
563 "uniform sampler2D Texture_Reflection;\n"
564 "uniform sampler2D Texture_Refraction;\n"
566 "uniform myhvec3 LightColor;\n"
567 "uniform myhvec3 AmbientColor;\n"
568 "uniform myhvec3 DiffuseColor;\n"
569 "uniform myhvec3 SpecularColor;\n"
570 "uniform myhvec3 Color_Pants;\n"
571 "uniform myhvec3 Color_Shirt;\n"
572 "uniform myhvec3 FogColor;\n"
574 "//#ifdef USEWATER\n"
575 "uniform vec4 DistortScaleRefractReflect;\n"
576 "uniform vec4 ScreenScaleRefractReflect;\n"
577 "uniform vec4 ScreenCenterRefractReflect;\n"
578 "uniform myhvec3 RefractColor;\n"
579 "uniform myhvec3 ReflectColor;\n"
581 "//# ifdef USEREFLECTION\n"
582 "//uniform vec4 DistortScaleRefractReflect;\n"
583 "//uniform vec4 ScreenScaleRefractReflect;\n"
584 "//uniform vec4 ScreenCenterRefractReflect;\n"
585 "//uniform myhvec3 ReflectColor;\n"
589 "uniform myhalf GlowScale;\n"
590 "uniform myhalf SceneBrightness;\n"
591 "#ifdef USECONTRASTBOOST\n"
592 "uniform myhalf ContrastBoostCoeff;\n"
595 "uniform float OffsetMapping_Scale;\n"
596 "uniform float OffsetMapping_Bias;\n"
597 "uniform float FogRangeRecip;\n"
599 "uniform myhalf AmbientScale;\n"
600 "uniform myhalf DiffuseScale;\n"
601 "uniform myhalf SpecularScale;\n"
602 "uniform myhalf SpecularPower;\n"
604 "#ifdef USEOFFSETMAPPING\n"
605 "vec2 OffsetMapping(vec2 TexCoord)\n"
607 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
608 " // 14 sample relief mapping: linear search and then binary search\n"
609 " // this basically steps forward a small amount repeatedly until it finds\n"
610 " // itself inside solid, then jitters forward and back using decreasing\n"
611 " // amounts to find the impact\n"
612 " //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
613 " //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
614 " vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
615 " vec3 RT = vec3(TexCoord, 1);\n"
616 " OffsetVector *= 0.1;\n"
617 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
618 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
619 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
620 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
621 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
622 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
623 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
624 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\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) - 0.5);\n"
627 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5 - 0.25);\n"
628 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25 - 0.125);\n"
629 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125 - 0.0625);\n"
630 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
633 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
634 " // this basically moves forward the full distance, and then backs up based\n"
635 " // on height of samples\n"
636 " //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
637 " //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
638 " vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
639 " TexCoord += OffsetVector;\n"
640 " OffsetVector *= 0.333;\n"
641 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
642 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
643 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
644 " return TexCoord;\n"
651 "#ifdef USEOFFSETMAPPING\n"
652 " // apply offsetmapping\n"
653 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
654 "#define TexCoord TexCoordOffset\n"
657 " // combine the diffuse textures (base, pants, shirt)\n"
658 " myhvec4 color = myhvec4(texture2D(Texture_Color, TexCoord));\n"
659 "#ifdef USECOLORMAPPING\n"
660 " color.rgb += myhvec3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhvec3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
666 "#ifdef MODE_LIGHTSOURCE\n"
669 " // calculate surface normal, light normal, and specular normal\n"
670 " // compute color intensity for the two textures (colormap and glossmap)\n"
671 " // scale by light color and attenuation as efficiently as possible\n"
672 " // (do as much scalar math as possible rather than vector math)\n"
673 "# ifdef USESPECULAR\n"
674 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
675 " myhvec3 diffusenormal = myhvec3(normalize(LightVector));\n"
676 " myhvec3 specularnormal = normalize(diffusenormal + myhvec3(normalize(EyeVector)));\n"
678 " // calculate directional shading\n"
679 " 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"
681 "# ifdef USEDIFFUSE\n"
682 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
683 " myhvec3 diffusenormal = myhvec3(normalize(LightVector));\n"
685 " // calculate directional shading\n"
686 " 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"
688 " // calculate directionless shading\n"
689 " color.rgb = color.rgb * LightColor * myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
693 "# ifdef USECUBEFILTER\n"
694 " // apply light cubemap filter\n"
695 " //color.rgb *= normalize(CubeVector) * 0.5 + 0.5;//vec3(textureCube(Texture_Cube, CubeVector));\n"
696 " color.rgb *= myhvec3(textureCube(Texture_Cube, CubeVector));\n"
698 " color *= myhvec4(gl_Color);\n"
699 "#endif // MODE_LIGHTSOURCE\n"
704 "#ifdef MODE_LIGHTDIRECTION\n"
705 " // directional model lighting\n"
707 " // get the surface normal and light normal\n"
708 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
709 " myhvec3 diffusenormal = myhvec3(LightVector);\n"
711 " // calculate directional shading\n"
712 " color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
713 "# ifdef USESPECULAR\n"
714 " myhvec3 specularnormal = normalize(diffusenormal + myhvec3(normalize(EyeVector)));\n"
715 " color.rgb += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
717 " color *= myhvec4(gl_Color);\n"
718 "#endif // MODE_LIGHTDIRECTION\n"
723 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
724 " // deluxemap lightmapping using light vectors in modelspace (evil q3map2)\n"
726 " // get the surface normal and light normal\n"
727 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
729 " myhvec3 diffusenormal_modelspace = myhvec3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - myhvec3(0.5);\n"
730 " myhvec3 diffusenormal = normalize(myhvec3(dot(diffusenormal_modelspace, myhvec3(VectorS)), dot(diffusenormal_modelspace, myhvec3(VectorT)), dot(diffusenormal_modelspace, myhvec3(VectorR))));\n"
731 " // calculate directional shading\n"
732 " myhvec3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0)));\n"
733 "# ifdef USESPECULAR\n"
734 " myhvec3 specularnormal = myhvec3(normalize(diffusenormal + myhvec3(normalize(EyeVector))));\n"
735 " tempcolor += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
738 " // apply lightmap color\n"
739 " color.rgb = myhvec4(tempcolor,1) * myhvec4(texture2D(Texture_Lightmap, TexCoordLightmap)) * myhvec4(gl_Color) + myhvec4(color.rgb * AmbientScale, 0);\n"
740 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
745 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
746 " // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
748 " // get the surface normal and light normal\n"
749 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
751 " myhvec3 diffusenormal = normalize(myhvec3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - myhvec3(0.5));\n"
752 " // calculate directional shading\n"
753 " myhvec3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0)));\n"
754 "# ifdef USESPECULAR\n"
755 " myhvec3 specularnormal = myhvec3(normalize(diffusenormal + myhvec3(normalize(EyeVector))));\n"
756 " tempcolor += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
759 " // apply lightmap color\n"
760 " color = myhvec4(tempcolor, 1) * myhvec4(texture2D(Texture_Lightmap, TexCoordLightmap)) * myhvec4(gl_Color) + myhvec4(color.rgb * AmbientScale, 0);\n"
761 "#endif // MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
766 "#ifdef MODE_LIGHTMAP\n"
767 " // apply lightmap color\n"
768 " color *= myhvec4(texture2D(Texture_Lightmap, TexCoordLightmap)) * myhvec4(gl_Color) * myhvec4(myhvec3(DiffuseScale), 1) + myhvec4(myhvec3(AmbientScale), 0);\n"
769 "#endif // MODE_LIGHTMAP\n"
778 "#ifdef MODE_LIGHTSOURCE\n"
780 " color.rgb *= color.a;\n"
784 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
785 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
786 " vec4 ScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect + vec3(normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5))).xyxy * DistortScaleRefractReflect;\n"
787 " myhalf Fresnel = myhalf(pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0));\n"
788 " color.rgb = mix(mix(myhvec3(texture2D(Texture_Refraction, ScreenTexCoord.xy)) * RefractColor, myhvec3(texture2D(Texture_Reflection, ScreenTexCoord.zw)) * ReflectColor, Fresnel), color.rgb, color.a);\n"
790 "# ifdef USEREFLECTION\n"
791 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
792 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
793 " vec4 ScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect + vec3(normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5))).xyxy * DistortScaleRefractReflect;\n"
794 " color.rgb += myhvec3(texture2D(Texture_Gloss, TexCoord)) * myhvec3(texture2D(Texture_Reflection, ScreenTexCoord.zw));\n"
800 " color.rgb += myhvec3(texture2D(Texture_Glow, TexCoord)) * GlowScale;\n"
805 " color.rgb = mix(FogColor, color.rgb, myhalf(texture2D(Texture_FogMask, myhvec2(length(EyeVectorModelSpace)*FogRangeRecip, 0.0))));\n"
808 "#ifdef USECONTRASTBOOST\n"
809 " color.rgb = color.rgb * SceneBrightness / (ContrastBoostCoeff * color.rgb + myhvec3(1, 1, 1));\n"
811 " color.rgb *= SceneBrightness;\n"
814 " gl_FragColor = vec4(color);\n"
817 "#endif // FRAGMENT_SHADER\n"
820 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
821 const char *permutationinfo[][2] =
823 {"#define MODE_LIGHTMAP\n", " lightmap"},
824 {"#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
825 {"#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
826 {"#define MODE_LIGHTDIRECTION\n", " lightdirection"},
827 {"#define MODE_LIGHTSOURCE\n", " lightsource"},
828 {"#define USEWATER\n", " water"},
829 {"#define USEREFLECTION\n", " reflection"},
830 {"#define USEGLOW\n", " glow"},
831 {"#define USEFOG\n", " fog"},
832 {"#define USECOLORMAPPING\n", " colormapping"},
833 {"#define USEDIFFUSE\n", " diffuse"},
834 {"#define USECONTRASTBOOST\n", " contrastboost"},
835 {"#define USESPECULAR\n", " specular"},
836 {"#define USECUBEFILTER\n", " cubefilter"},
837 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
838 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
842 void R_GLSL_CompilePermutation(const char *filename, int permutation)
845 qboolean shaderfound;
846 r_glsl_permutation_t *p = r_glsl_permutations + (permutation & SHADERPERMUTATION_MASK);
847 int vertstrings_count;
848 int geomstrings_count;
849 int fragstrings_count;
851 const char *vertstrings_list[32+1];
852 const char *geomstrings_list[32+1];
853 const char *fragstrings_list[32+1];
854 char permutationname[256];
859 vertstrings_list[0] = "#define VERTEX_SHADER\n";
860 geomstrings_list[0] = "#define GEOMETRY_SHADER\n";
861 fragstrings_list[0] = "#define FRAGMENT_SHADER\n";
862 vertstrings_count = 1;
863 geomstrings_count = 1;
864 fragstrings_count = 1;
865 permutationname[0] = 0;
866 for (i = 0;permutationinfo[i][0];i++)
868 if (permutation & (1<<i))
870 vertstrings_list[vertstrings_count++] = permutationinfo[i][0];
871 geomstrings_list[geomstrings_count++] = permutationinfo[i][0];
872 fragstrings_list[fragstrings_count++] = permutationinfo[i][0];
873 strlcat(permutationname, permutationinfo[i][1], sizeof(permutationname));
877 // keep line numbers correct
878 vertstrings_list[vertstrings_count++] = "\n";
879 geomstrings_list[geomstrings_count++] = "\n";
880 fragstrings_list[fragstrings_count++] = "\n";
883 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
887 Con_DPrintf("GLSL shader text for \"%s\" loaded from disk\n", filename);
888 vertstrings_list[vertstrings_count++] = shaderstring;
889 geomstrings_list[geomstrings_count++] = shaderstring;
890 fragstrings_list[fragstrings_count++] = shaderstring;
893 else if (!strcmp(filename, "glsl/default.glsl"))
895 Con_DPrintf("GLSL shader text for \"%s\" loaded from engine\n", filename);
896 vertstrings_list[vertstrings_count++] = builtinshaderstring;
897 geomstrings_list[geomstrings_count++] = builtinshaderstring;
898 fragstrings_list[fragstrings_count++] = builtinshaderstring;
901 // clear any lists that are not needed by this shader
902 if (!(permutation & SHADERPERMUTATION_USES_VERTEXSHADER))
903 vertstrings_count = 0;
904 if (!(permutation & SHADERPERMUTATION_USES_GEOMETRYSHADER))
905 geomstrings_count = 0;
906 if (!(permutation & SHADERPERMUTATION_USES_FRAGMENTSHADER))
907 fragstrings_count = 0;
908 // compile the shader program
909 if (shaderfound && vertstrings_count + geomstrings_count + fragstrings_count)
910 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
914 qglUseProgramObjectARB(p->program);CHECKGLERROR
915 // look up all the uniform variable names we care about, so we don't
916 // have to look them up every time we set them
917 p->loc_Texture_Normal = qglGetUniformLocationARB(p->program, "Texture_Normal");
918 p->loc_Texture_Color = qglGetUniformLocationARB(p->program, "Texture_Color");
919 p->loc_Texture_Gloss = qglGetUniformLocationARB(p->program, "Texture_Gloss");
920 p->loc_Texture_Cube = qglGetUniformLocationARB(p->program, "Texture_Cube");
921 p->loc_Texture_Attenuation = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
922 p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
923 p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
924 p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
925 p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
926 p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
927 p->loc_Texture_Glow = qglGetUniformLocationARB(p->program, "Texture_Glow");
928 p->loc_Texture_Refraction = qglGetUniformLocationARB(p->program, "Texture_Refraction");
929 p->loc_Texture_Reflection = qglGetUniformLocationARB(p->program, "Texture_Reflection");
930 p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
931 p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
932 p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
933 p->loc_LightColor = qglGetUniformLocationARB(p->program, "LightColor");
934 p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants");
935 p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt");
936 p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip");
937 p->loc_AmbientScale = qglGetUniformLocationARB(p->program, "AmbientScale");
938 p->loc_DiffuseScale = qglGetUniformLocationARB(p->program, "DiffuseScale");
939 p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
940 p->loc_SpecularScale = qglGetUniformLocationARB(p->program, "SpecularScale");
941 p->loc_GlowScale = qglGetUniformLocationARB(p->program, "GlowScale");
942 p->loc_SceneBrightness = qglGetUniformLocationARB(p->program, "SceneBrightness");
943 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
944 p->loc_AmbientColor = qglGetUniformLocationARB(p->program, "AmbientColor");
945 p->loc_DiffuseColor = qglGetUniformLocationARB(p->program, "DiffuseColor");
946 p->loc_SpecularColor = qglGetUniformLocationARB(p->program, "SpecularColor");
947 p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
948 p->loc_ContrastBoostCoeff = qglGetUniformLocationARB(p->program, "ContrastBoostCoeff");
949 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
950 p->loc_ScreenScaleRefractReflect = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
951 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
952 p->loc_RefractColor = qglGetUniformLocationARB(p->program, "RefractColor");
953 p->loc_ReflectColor = qglGetUniformLocationARB(p->program, "ReflectColor");
954 // initialize the samplers to refer to the texture units we use
955 if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal, 0);
956 if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color, 1);
957 if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss, 2);
958 if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube, 3);
959 if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask, 4);
960 if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants, 5);
961 if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt, 6);
962 if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap, 7);
963 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap, 8);
964 if (p->loc_Texture_Glow >= 0) qglUniform1iARB(p->loc_Texture_Glow, 9);
965 if (p->loc_Texture_Attenuation >= 0) qglUniform1iARB(p->loc_Texture_Attenuation, 10);
966 if (p->loc_Texture_Refraction >= 0) qglUniform1iARB(p->loc_Texture_Refraction, 11);
967 if (p->loc_Texture_Reflection >= 0) qglUniform1iARB(p->loc_Texture_Reflection, 12);
969 qglUseProgramObjectARB(0);CHECKGLERROR
972 Con_Printf("permutation%s failed for shader %s, some features may not work properly!\n", permutationname, filename);
974 Mem_Free(shaderstring);
977 void R_GLSL_Restart_f(void)
980 for (i = 0;i < SHADERPERMUTATION_MAX;i++)
981 if (r_glsl_permutations[i].program)
982 GL_Backend_FreeProgram(r_glsl_permutations[i].program);
983 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
986 void R_GLSL_DumpShader_f(void)
990 qfile_t *file = FS_Open("glsl/default.glsl", "w", false, false);
993 Con_Printf("failed to write to glsl/default.glsl\n");
997 FS_Print(file, "// The engine may define the following macros:\n");
998 FS_Print(file, "// #define VERTEX_SHADER\n// #define GEOMETRY_SHADER\n// #define FRAGMENT_SHADER\n");
999 for (i = 0;permutationinfo[i][0];i++)
1000 FS_Printf(file, "// %s", permutationinfo[i][0]);
1001 FS_Print(file, "\n");
1002 FS_Print(file, builtinshaderstring);
1005 Con_Printf("glsl/default.glsl written\n");
1008 extern rtexture_t *r_shadow_attenuationgradienttexture;
1009 extern rtexture_t *r_shadow_attenuation2dtexture;
1010 extern rtexture_t *r_shadow_attenuation3dtexture;
1011 int R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale)
1013 // select a permutation of the lighting shader appropriate to this
1014 // combination of texture, entity, light source, and fogging, only use the
1015 // minimum features necessary to avoid wasting rendering time in the
1016 // fragment shader on features that are not being used
1017 const char *shaderfilename = NULL;
1018 unsigned int permutation = 0;
1020 r_glsl_permutation = NULL;
1021 // TODO: implement geometry-shader based shadow volumes someday
1022 if (rsurface.rtlight)
1025 shaderfilename = "glsl/default.glsl";
1026 permutation = SHADERPERMUTATION_MODE_LIGHTSOURCE | SHADERPERMUTATION_USES_VERTEXSHADER | SHADERPERMUTATION_USES_FRAGMENTSHADER;
1027 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
1028 permutation |= SHADERPERMUTATION_CUBEFILTER;
1029 if (diffusescale > 0)
1030 permutation |= SHADERPERMUTATION_DIFFUSE;
1031 if (specularscale > 0)
1032 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
1033 if (r_refdef.fogenabled)
1034 permutation |= SHADERPERMUTATION_FOG;
1035 if (rsurface.texture->colormapping)
1036 permutation |= SHADERPERMUTATION_COLORMAPPING;
1037 if (r_glsl_offsetmapping.integer)
1039 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
1040 if (r_glsl_offsetmapping_reliefmapping.integer)
1041 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
1043 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1044 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1045 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
1046 permutation |= SHADERPERMUTATION_WATER;
1047 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1048 permutation |= SHADERPERMUTATION_REFLECTION;
1050 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
1052 // bright unshaded geometry
1053 shaderfilename = "glsl/default.glsl";
1054 permutation = SHADERPERMUTATION_USES_VERTEXSHADER | SHADERPERMUTATION_USES_FRAGMENTSHADER;
1055 permutation |= SHADERPERMUTATION_MODE_LIGHTMAP;
1056 if (rsurface.texture->currentskinframe->glow)
1057 permutation |= SHADERPERMUTATION_GLOW;
1058 if (r_refdef.fogenabled)
1059 permutation |= SHADERPERMUTATION_FOG;
1060 if (rsurface.texture->colormapping)
1061 permutation |= SHADERPERMUTATION_COLORMAPPING;
1062 if (r_glsl_offsetmapping.integer)
1064 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
1065 if (r_glsl_offsetmapping_reliefmapping.integer)
1066 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
1068 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1069 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1070 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
1071 permutation |= SHADERPERMUTATION_WATER;
1072 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1073 permutation |= SHADERPERMUTATION_REFLECTION;
1075 else if (modellighting)
1077 // directional model lighting
1078 shaderfilename = "glsl/default.glsl";
1079 permutation = SHADERPERMUTATION_USES_VERTEXSHADER | SHADERPERMUTATION_USES_FRAGMENTSHADER;
1080 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTION;
1081 if (rsurface.texture->currentskinframe->glow)
1082 permutation |= SHADERPERMUTATION_GLOW;
1083 if (specularscale > 0)
1084 permutation |= SHADERPERMUTATION_SPECULAR;
1085 if (r_refdef.fogenabled)
1086 permutation |= SHADERPERMUTATION_FOG;
1087 if (rsurface.texture->colormapping)
1088 permutation |= SHADERPERMUTATION_COLORMAPPING;
1089 if (r_glsl_offsetmapping.integer)
1091 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
1092 if (r_glsl_offsetmapping_reliefmapping.integer)
1093 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
1095 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1096 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1097 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
1098 permutation |= SHADERPERMUTATION_WATER;
1099 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1100 permutation |= SHADERPERMUTATION_REFLECTION;
1105 shaderfilename = "glsl/default.glsl";
1106 permutation = SHADERPERMUTATION_USES_VERTEXSHADER | SHADERPERMUTATION_USES_FRAGMENTSHADER;
1107 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.worldmodel && r_refdef.worldmodel->brushq3.deluxemapping)
1109 // deluxemapping (light direction texture)
1110 if (rsurface.uselightmaptexture && r_refdef.worldmodel && r_refdef.worldmodel->brushq3.deluxemapping && r_refdef.worldmodel->brushq3.deluxemapping_modelspace)
1111 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_MODELSPACE;
1113 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
1114 if (specularscale > 0)
1115 permutation |= SHADERPERMUTATION_SPECULAR;
1117 else if (r_glsl_deluxemapping.integer >= 2)
1119 // fake deluxemapping (uniform light direction in tangentspace)
1120 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
1121 if (specularscale > 0)
1122 permutation |= SHADERPERMUTATION_SPECULAR;
1126 // ordinary lightmapping
1127 permutation |= SHADERPERMUTATION_MODE_LIGHTMAP;
1129 if (rsurface.texture->currentskinframe->glow)
1130 permutation |= SHADERPERMUTATION_GLOW;
1131 if (r_refdef.fogenabled)
1132 permutation |= SHADERPERMUTATION_FOG;
1133 if (rsurface.texture->colormapping)
1134 permutation |= SHADERPERMUTATION_COLORMAPPING;
1135 if (r_glsl_offsetmapping.integer)
1137 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
1138 if (r_glsl_offsetmapping_reliefmapping.integer)
1139 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
1141 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1142 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1143 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
1144 permutation |= SHADERPERMUTATION_WATER;
1145 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1146 permutation |= SHADERPERMUTATION_REFLECTION;
1148 if (!r_glsl_permutations[permutation & SHADERPERMUTATION_MASK].program)
1150 if (!r_glsl_permutations[permutation & SHADERPERMUTATION_MASK].compiled)
1151 R_GLSL_CompilePermutation(shaderfilename, permutation);
1152 if (!r_glsl_permutations[permutation & SHADERPERMUTATION_MASK].program)
1154 // remove features until we find a valid permutation
1156 for (i = (SHADERPERMUTATION_MAX >> 1);;i>>=1)
1160 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");
1161 Cvar_SetValueQuick(&r_glsl, 0);
1162 return 0; // no bit left to clear
1164 // reduce i more quickly whenever it would not remove any bits
1165 if (!(permutation & i))
1168 if (!r_glsl_permutations[permutation & SHADERPERMUTATION_MASK].compiled)
1169 R_GLSL_CompilePermutation(shaderfilename, permutation);
1170 if (r_glsl_permutations[permutation & SHADERPERMUTATION_MASK].program)
1175 r_glsl_permutation = r_glsl_permutations + (permutation & SHADERPERMUTATION_MASK);
1177 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
1178 R_Mesh_TexMatrix(0, &rsurface.texture->currenttexmatrix);
1179 if (permutation & SHADERPERMUTATION_MODE_LIGHTSOURCE)
1181 if (r_glsl_permutation->loc_Texture_Cube >= 0 && rsurface.rtlight) R_Mesh_TexBindCubeMap(3, R_GetTexture(rsurface.rtlight->currentcubemap));
1182 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
1183 if (permutation & SHADERPERMUTATION_DIFFUSE)
1185 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
1186 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, ambientscale);
1187 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, diffusescale);
1188 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, specularscale);
1192 // ambient only is simpler
1193 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0] * ambientscale, lightcolorbase[1] * ambientscale, lightcolorbase[2] * ambientscale);
1194 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, 1);
1195 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, 0);
1196 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, 0);
1199 else if (permutation & SHADERPERMUTATION_MODE_LIGHTDIRECTION)
1201 if (r_glsl_permutation->loc_AmbientColor >= 0)
1202 qglUniform3fARB(r_glsl_permutation->loc_AmbientColor, rsurface.modellight_ambient[0] * ambientscale, rsurface.modellight_ambient[1] * ambientscale, rsurface.modellight_ambient[2] * ambientscale);
1203 if (r_glsl_permutation->loc_DiffuseColor >= 0)
1204 qglUniform3fARB(r_glsl_permutation->loc_DiffuseColor, rsurface.modellight_diffuse[0] * diffusescale, rsurface.modellight_diffuse[1] * diffusescale, rsurface.modellight_diffuse[2] * diffusescale);
1205 if (r_glsl_permutation->loc_SpecularColor >= 0)
1206 qglUniform3fARB(r_glsl_permutation->loc_SpecularColor, rsurface.modellight_diffuse[0] * specularscale, rsurface.modellight_diffuse[1] * specularscale, rsurface.modellight_diffuse[2] * specularscale);
1207 if (r_glsl_permutation->loc_LightDir >= 0)
1208 qglUniform3fARB(r_glsl_permutation->loc_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
1212 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_ambient.value * 2.0f / 128.0f);
1213 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_refdef.lightmapintensity * 2.0f);
1214 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, r_refdef.lightmapintensity * specularscale * 2.0f);
1216 nmap = rsurface.texture->currentskinframe->nmap;
1217 if (gl_lightmaps.integer)
1218 nmap = r_texture_blanknormalmap;
1219 if (r_glsl_permutation->loc_Texture_Normal >= 0) R_Mesh_TexBind(0, R_GetTexture(nmap));
1220 if (r_glsl_permutation->loc_Texture_Color >= 0) R_Mesh_TexBind(1, R_GetTexture(rsurface.texture->basetexture));
1221 if (r_glsl_permutation->loc_Texture_Gloss >= 0) R_Mesh_TexBind(2, R_GetTexture(rsurface.texture->glosstexture));
1222 //if (r_glsl_permutation->loc_Texture_Cube >= 0 && permutation & SHADERPERMUTATION_MODE_LIGHTSOURCE) R_Mesh_TexBindCubeMap(3, R_GetTexture(rsurface.rtlight->currentcubemap));
1223 if (r_glsl_permutation->loc_Texture_Attenuation >= 0) R_Mesh_TexBind(10, R_GetTexture(r_shadow_attenuationgradienttexture));
1224 if (r_glsl_permutation->loc_Texture_FogMask >= 0) R_Mesh_TexBind(4, R_GetTexture(r_texture_fogattenuation));
1225 if (r_glsl_permutation->loc_Texture_Pants >= 0) R_Mesh_TexBind(5, R_GetTexture(rsurface.texture->currentskinframe->pants));
1226 if (r_glsl_permutation->loc_Texture_Shirt >= 0) R_Mesh_TexBind(6, R_GetTexture(rsurface.texture->currentskinframe->shirt));
1227 //if (r_glsl_permutation->loc_Texture_Lightmap >= 0) R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
1228 //if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
1229 if (r_glsl_permutation->loc_Texture_Glow >= 0) R_Mesh_TexBind(9, R_GetTexture(rsurface.texture->currentskinframe->glow));
1230 if (r_glsl_permutation->loc_Texture_Refraction >= 0) R_Mesh_TexBind(11, R_GetTexture(r_texture_white)); // changed per surface
1231 if (r_glsl_permutation->loc_Texture_Reflection >= 0) R_Mesh_TexBind(12, R_GetTexture(r_texture_white)); // changed per surface
1232 if (r_glsl_permutation->loc_GlowScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_GlowScale, r_hdr_glowintensity.value);
1233 if (r_glsl_permutation->loc_ContrastBoostCoeff >= 0)
1235 // The formula used is actually:
1236 // color.rgb *= SceneBrightness;
1237 // color.rgb *= ContrastBoost / ((ContrastBoost - 1) * color.rgb + 1);
1238 // I simplify that to
1239 // color.rgb *= [[SceneBrightness * ContrastBoost]];
1240 // color.rgb /= [[(ContrastBoost - 1) / ContrastBoost]] * color.rgb + 1;
1242 // color.rgb = [[SceneBrightness * ContrastBoost]] / ([[(ContrastBoost - 1) * SceneBrightness]] + 1 / color.rgb);
1243 // and do [[calculations]] here in the engine
1244 qglUniform1fARB(r_glsl_permutation->loc_ContrastBoostCoeff, (r_glsl_contrastboost.value - 1) * r_view.colorscale);
1245 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_view.colorscale * r_glsl_contrastboost.value);
1248 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_view.colorscale);
1249 if (r_glsl_permutation->loc_FogColor >= 0)
1251 // additive passes are only darkened by fog, not tinted
1252 if (rsurface.rtlight || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD))
1253 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
1255 qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
1257 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.modelorg[0], rsurface.modelorg[1], rsurface.modelorg[2]);
1258 if (r_glsl_permutation->loc_Color_Pants >= 0)
1260 if (rsurface.texture->currentskinframe->pants)
1261 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
1263 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
1265 if (r_glsl_permutation->loc_Color_Shirt >= 0)
1267 if (rsurface.texture->currentskinframe->shirt)
1268 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
1270 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
1272 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, r_refdef.fograngerecip);
1273 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower);
1274 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
1275 if (r_glsl_permutation->loc_DistortScaleRefractReflect >= 0) qglUniform4fARB(r_glsl_permutation->loc_DistortScaleRefractReflect, r_glsl_water_refractdistort.value, r_glsl_water_refractdistort.value, r_glsl_water_reflectdistort.value, r_glsl_water_reflectdistort.value);
1276 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]);
1277 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]);
1278 if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_RefractColor, r_glsl_water_refractcolor_r.value, r_glsl_water_refractcolor_g.value, r_glsl_water_refractcolor_b.value);
1279 if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_ReflectColor, r_glsl_water_reflectcolor_r.value, r_glsl_water_reflectcolor_g.value, r_glsl_water_reflectcolor_b.value);
1284 void R_SwitchSurfaceShader(int permutation)
1286 if (r_glsl_permutation != r_glsl_permutations + (permutation & SHADERPERMUTATION_MASK))
1288 r_glsl_permutation = r_glsl_permutations + (permutation & SHADERPERMUTATION_MASK);
1290 qglUseProgramObjectARB(r_glsl_permutation->program);
1295 #define SKINFRAME_HASH 1024
1299 int loadsequence; // incremented each level change
1300 memexpandablearray_t array;
1301 skinframe_t *hash[SKINFRAME_HASH];
1305 void R_SkinFrame_PrepareForPurge(void)
1307 r_skinframe.loadsequence++;
1308 // wrap it without hitting zero
1309 if (r_skinframe.loadsequence >= 200)
1310 r_skinframe.loadsequence = 1;
1313 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
1317 // mark the skinframe as used for the purging code
1318 skinframe->loadsequence = r_skinframe.loadsequence;
1321 void R_SkinFrame_Purge(void)
1325 for (i = 0;i < SKINFRAME_HASH;i++)
1327 for (s = r_skinframe.hash[i];s;s = s->next)
1329 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
1331 if (s->base == r_texture_notexture) s->base = NULL;
1332 if (s->nmap == r_texture_blanknormalmap)s->nmap = NULL;
1333 if (s->merged == s->base) s->merged = NULL;
1334 if (s->stain ) R_FreeTexture(s->stain );s->stain = NULL;
1335 if (s->merged) R_FreeTexture(s->merged);s->merged = NULL;
1336 if (s->base ) R_FreeTexture(s->base );s->base = NULL;
1337 if (s->pants ) R_FreeTexture(s->pants );s->pants = NULL;
1338 if (s->shirt ) R_FreeTexture(s->shirt );s->shirt = NULL;
1339 if (s->nmap ) R_FreeTexture(s->nmap );s->nmap = NULL;
1340 if (s->gloss ) R_FreeTexture(s->gloss );s->gloss = NULL;
1341 if (s->glow ) R_FreeTexture(s->glow );s->glow = NULL;
1342 if (s->fog ) R_FreeTexture(s->fog );s->fog = NULL;
1343 s->loadsequence = 0;
1349 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
1353 char basename[MAX_QPATH];
1355 Image_StripImageExtension(name, basename, sizeof(basename));
1357 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
1358 for (item = r_skinframe.hash[hashindex];item;item = item->next)
1359 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
1365 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
1366 memset(item, 0, sizeof(*item));
1367 strlcpy(item->basename, basename, sizeof(item->basename));
1368 item->textureflags = textureflags;
1369 item->comparewidth = comparewidth;
1370 item->compareheight = compareheight;
1371 item->comparecrc = comparecrc;
1372 item->next = r_skinframe.hash[hashindex];
1373 r_skinframe.hash[hashindex] = item;
1375 R_SkinFrame_MarkUsed(item);
1379 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
1381 // FIXME: it should be possible to disable loading various layers using
1382 // cvars, to prevent wasted loading time and memory usage if the user does
1384 qboolean loadnormalmap = true;
1385 qboolean loadgloss = true;
1386 qboolean loadpantsandshirt = true;
1387 qboolean loadglow = true;
1389 unsigned char *pixels;
1390 unsigned char *bumppixels;
1391 unsigned char *basepixels = NULL;
1392 int basepixels_width;
1393 int basepixels_height;
1394 skinframe_t *skinframe;
1396 if (cls.state == ca_dedicated)
1399 // return an existing skinframe if already loaded
1400 // if loading of the first image fails, don't make a new skinframe as it
1401 // would cause all future lookups of this to be missing
1402 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
1403 if (skinframe && skinframe->base)
1406 basepixels = loadimagepixels(name, complain, 0, 0);
1407 if (basepixels == NULL)
1410 // we've got some pixels to store, so really allocate this new texture now
1412 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
1413 skinframe->stain = NULL;
1414 skinframe->merged = NULL;
1415 skinframe->base = r_texture_notexture;
1416 skinframe->pants = NULL;
1417 skinframe->shirt = NULL;
1418 skinframe->nmap = r_texture_blanknormalmap;
1419 skinframe->gloss = NULL;
1420 skinframe->glow = NULL;
1421 skinframe->fog = NULL;
1423 basepixels_width = image_width;
1424 basepixels_height = image_height;
1425 skinframe->base = R_LoadTexture2D (r_main_texturepool, skinframe->basename, basepixels_width, basepixels_height, basepixels, TEXTYPE_RGBA, skinframe->textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), NULL);
1427 if (textureflags & TEXF_ALPHA)
1429 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
1430 if (basepixels[j] < 255)
1432 if (j < basepixels_width * basepixels_height * 4)
1434 // has transparent pixels
1435 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
1436 for (j = 0;j < image_width * image_height * 4;j += 4)
1441 pixels[j+3] = basepixels[j+3];
1443 skinframe->fog = R_LoadTexture2D (r_main_texturepool, va("%s_mask", skinframe->basename), image_width, image_height, pixels, TEXTYPE_RGBA, skinframe->textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), NULL);
1448 // _norm is the name used by tenebrae and has been adopted as standard
1451 if ((pixels = loadimagepixels(va("%s_norm", skinframe->basename), false, 0, 0)) != NULL)
1453 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_RGBA, skinframe->textureflags & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), NULL);
1457 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixels(va("%s_bump", skinframe->basename), false, 0, 0)) != NULL)
1459 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
1460 Image_HeightmapToNormalmap(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
1461 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_RGBA, skinframe->textureflags & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), NULL);
1463 Mem_Free(bumppixels);
1465 else if (r_shadow_bumpscale_basetexture.value > 0)
1467 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
1468 Image_HeightmapToNormalmap(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
1469 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), basepixels_width, basepixels_height, pixels, TEXTYPE_RGBA, skinframe->textureflags & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), NULL);
1473 // _luma is supported for tenebrae compatibility
1474 // (I think it's a very stupid name, but oh well)
1475 // _glow is the preferred name
1476 if (loadglow && ((pixels = loadimagepixels(va("%s_glow", skinframe->basename), false, 0, 0)) != NULL || (pixels = loadimagepixels(va("%s_luma", skinframe->basename), false, 0, 0)) != NULL)) {skinframe->glow = R_LoadTexture2D (r_main_texturepool, va("%s_glow", skinframe->basename), image_width, image_height, pixels, TEXTYPE_RGBA, skinframe->textureflags & (gl_texturecompression_glow.integer ? ~0 : ~TEXF_COMPRESS), NULL);Mem_Free(pixels);pixels = NULL;}
1477 if (loadgloss && (pixels = loadimagepixels(va("%s_gloss", skinframe->basename), false, 0, 0)) != NULL) {skinframe->gloss = R_LoadTexture2D (r_main_texturepool, va("%s_gloss", skinframe->basename), image_width, image_height, pixels, TEXTYPE_RGBA, skinframe->textureflags & (gl_texturecompression_gloss.integer ? ~0 : ~TEXF_COMPRESS), NULL);Mem_Free(pixels);pixels = NULL;}
1478 if (loadpantsandshirt && (pixels = loadimagepixels(va("%s_pants", skinframe->basename), false, 0, 0)) != NULL) {skinframe->pants = R_LoadTexture2D (r_main_texturepool, va("%s_pants", skinframe->basename), image_width, image_height, pixels, TEXTYPE_RGBA, skinframe->textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), NULL);Mem_Free(pixels);pixels = NULL;}
1479 if (loadpantsandshirt && (pixels = loadimagepixels(va("%s_shirt", skinframe->basename), false, 0, 0)) != NULL) {skinframe->shirt = R_LoadTexture2D (r_main_texturepool, va("%s_shirt", skinframe->basename), image_width, image_height, pixels, TEXTYPE_RGBA, skinframe->textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), NULL);Mem_Free(pixels);pixels = NULL;}
1482 Mem_Free(basepixels);
1487 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)
1492 for (i = 0;i < width*height;i++)
1493 if (((unsigned char *)&palette[in[i]])[3] > 0)
1495 if (i == width*height)
1498 return R_LoadTexture2D (r_main_texturepool, name, width, height, in, TEXTYPE_PALETTE, textureflags, palette);
1501 skinframe_t *R_SkinFrame_LoadInternal(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height, int bitsperpixel, const unsigned int *palette, const unsigned int *alphapalette)
1504 unsigned char *temp1, *temp2;
1505 skinframe_t *skinframe;
1507 if (cls.state == ca_dedicated)
1510 // if already loaded just return it, otherwise make a new skinframe
1511 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*bitsperpixel/8) : 0, true);
1512 if (skinframe && skinframe->base)
1515 skinframe->stain = NULL;
1516 skinframe->merged = NULL;
1517 skinframe->base = r_texture_notexture;
1518 skinframe->pants = NULL;
1519 skinframe->shirt = NULL;
1520 skinframe->nmap = r_texture_blanknormalmap;
1521 skinframe->gloss = NULL;
1522 skinframe->glow = NULL;
1523 skinframe->fog = NULL;
1525 // if no data was provided, then clearly the caller wanted to get a blank skinframe
1529 if (bitsperpixel == 32)
1531 if (r_shadow_bumpscale_basetexture.value > 0)
1533 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
1534 temp2 = temp1 + width * height * 4;
1535 Image_HeightmapToNormalmap(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
1536 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_RGBA, skinframe->textureflags | TEXF_ALPHA, NULL);
1539 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_RGBA, skinframe->textureflags, NULL);
1540 if (textureflags & TEXF_ALPHA)
1542 for (i = 3;i < width * height * 4;i += 4)
1543 if (skindata[i] < 255)
1545 if (i < width * height * 4)
1547 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
1548 memcpy(fogpixels, skindata, width * height * 4);
1549 for (i = 0;i < width * height * 4;i += 4)
1550 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
1551 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_RGBA, skinframe->textureflags, NULL);
1552 Mem_Free(fogpixels);
1556 else if (bitsperpixel == 8)
1558 if (r_shadow_bumpscale_basetexture.value > 0)
1560 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
1561 temp2 = temp1 + width * height * 4;
1562 if (bitsperpixel == 32)
1563 Image_HeightmapToNormalmap(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
1566 // use either a custom palette or the quake palette
1567 Image_Copy8bitRGBA(skindata, temp1, width * height, palette ? palette : palette_complete);
1568 Image_HeightmapToNormalmap(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
1570 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_RGBA, skinframe->textureflags | TEXF_ALPHA, NULL);
1573 // use either a custom palette, or the quake palette
1574 skinframe->base = skinframe->merged = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_merged", skinframe->basename), palette ? palette : (loadglowtexture ? palette_nofullbrights : ((skinframe->textureflags & TEXF_ALPHA) ? palette_transparent : palette_complete)), skinframe->textureflags, true); // all
1575 if (!palette && loadglowtexture)
1576 skinframe->glow = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_glow", skinframe->basename), palette_onlyfullbrights, skinframe->textureflags, false); // glow
1577 if (!palette && loadpantsandshirt)
1579 skinframe->pants = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_pants", skinframe->basename), palette_pantsaswhite, skinframe->textureflags, false); // pants
1580 skinframe->shirt = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_shirt", skinframe->basename), palette_shirtaswhite, skinframe->textureflags, false); // shirt
1582 if (skinframe->pants || skinframe->shirt)
1583 skinframe->base = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_nospecial", skinframe->basename),loadglowtexture ? palette_nocolormapnofullbrights : palette_nocolormap, skinframe->textureflags, false); // no special colors
1584 if (textureflags & TEXF_ALPHA)
1586 // if not using a custom alphapalette, use the quake one
1588 alphapalette = palette_alpha;
1589 for (i = 0;i < width * height;i++)
1590 if (((unsigned char *)alphapalette)[skindata[i]*4+3] < 255)
1592 if (i < width * height)
1593 skinframe->fog = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_fog", skinframe->basename), alphapalette, skinframe->textureflags, true); // fog mask
1600 skinframe_t *R_SkinFrame_LoadMissing(void)
1602 skinframe_t *skinframe;
1604 if (cls.state == ca_dedicated)
1607 skinframe = R_SkinFrame_Find("missing", TEXF_PRECACHE, 0, 0, 0, true);
1608 skinframe->stain = NULL;
1609 skinframe->merged = NULL;
1610 skinframe->base = r_texture_notexture;
1611 skinframe->pants = NULL;
1612 skinframe->shirt = NULL;
1613 skinframe->nmap = r_texture_blanknormalmap;
1614 skinframe->gloss = NULL;
1615 skinframe->glow = NULL;
1616 skinframe->fog = NULL;
1621 void gl_main_start(void)
1626 r = (-1.0/256.0) * (FOGMASKTABLEWIDTH * FOGMASKTABLEWIDTH);
1627 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
1629 alpha = 1 - exp(r / ((double)x*(double)x));
1630 if (x == FOGMASKTABLEWIDTH - 1)
1632 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
1635 memset(r_qwskincache, 0, sizeof(r_qwskincache));
1636 memset(r_qwskincache_skinframe, 0, sizeof(r_qwskincache_skinframe));
1638 // set up r_skinframe loading system for textures
1639 memset(&r_skinframe, 0, sizeof(r_skinframe));
1640 r_skinframe.loadsequence = 1;
1641 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
1643 r_main_texturepool = R_AllocTexturePool();
1644 R_BuildBlankTextures();
1646 if (gl_texturecubemap)
1649 R_BuildNormalizationCube();
1651 R_BuildFogTexture();
1652 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
1653 memset(&r_waterstate, 0, sizeof(r_waterstate));
1654 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
1655 memset(&r_svbsp, 0, sizeof (r_svbsp));
1658 void gl_main_shutdown(void)
1660 memset(r_qwskincache, 0, sizeof(r_qwskincache));
1661 memset(r_qwskincache_skinframe, 0, sizeof(r_qwskincache_skinframe));
1663 // clear out the r_skinframe state
1664 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
1665 memset(&r_skinframe, 0, sizeof(r_skinframe));
1668 Mem_Free(r_svbsp.nodes);
1669 memset(&r_svbsp, 0, sizeof (r_svbsp));
1670 R_FreeTexturePool(&r_main_texturepool);
1671 r_texture_blanknormalmap = NULL;
1672 r_texture_white = NULL;
1673 r_texture_grey128 = NULL;
1674 r_texture_black = NULL;
1675 r_texture_whitecube = NULL;
1676 r_texture_normalizationcube = NULL;
1677 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
1678 memset(&r_waterstate, 0, sizeof(r_waterstate));
1682 extern void CL_ParseEntityLump(char *entitystring);
1683 void gl_main_newmap(void)
1685 // FIXME: move this code to client
1687 char *entities, entname[MAX_QPATH];
1690 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
1691 l = (int)strlen(entname) - 4;
1692 if (l >= 0 && !strcmp(entname + l, ".bsp"))
1694 memcpy(entname + l, ".ent", 5);
1695 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
1697 CL_ParseEntityLump(entities);
1702 if (cl.worldmodel->brush.entities)
1703 CL_ParseEntityLump(cl.worldmodel->brush.entities);
1707 void GL_Main_Init(void)
1709 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
1711 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
1712 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
1713 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
1714 if (gamemode == GAME_NEHAHRA)
1716 Cvar_RegisterVariable (&gl_fogenable);
1717 Cvar_RegisterVariable (&gl_fogdensity);
1718 Cvar_RegisterVariable (&gl_fogred);
1719 Cvar_RegisterVariable (&gl_foggreen);
1720 Cvar_RegisterVariable (&gl_fogblue);
1721 Cvar_RegisterVariable (&gl_fogstart);
1722 Cvar_RegisterVariable (&gl_fogend);
1724 Cvar_RegisterVariable(&r_depthfirst);
1725 Cvar_RegisterVariable(&r_nearclip);
1726 Cvar_RegisterVariable(&r_showbboxes);
1727 Cvar_RegisterVariable(&r_showsurfaces);
1728 Cvar_RegisterVariable(&r_showtris);
1729 Cvar_RegisterVariable(&r_shownormals);
1730 Cvar_RegisterVariable(&r_showlighting);
1731 Cvar_RegisterVariable(&r_showshadowvolumes);
1732 Cvar_RegisterVariable(&r_showcollisionbrushes);
1733 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
1734 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
1735 Cvar_RegisterVariable(&r_showdisabledepthtest);
1736 Cvar_RegisterVariable(&r_drawportals);
1737 Cvar_RegisterVariable(&r_drawentities);
1738 Cvar_RegisterVariable(&r_cullentities_trace);
1739 Cvar_RegisterVariable(&r_cullentities_trace_samples);
1740 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
1741 Cvar_RegisterVariable(&r_cullentities_trace_delay);
1742 Cvar_RegisterVariable(&r_drawviewmodel);
1743 Cvar_RegisterVariable(&r_speeds);
1744 Cvar_RegisterVariable(&r_fullbrights);
1745 Cvar_RegisterVariable(&r_wateralpha);
1746 Cvar_RegisterVariable(&r_dynamic);
1747 Cvar_RegisterVariable(&r_fullbright);
1748 Cvar_RegisterVariable(&r_shadows);
1749 Cvar_RegisterVariable(&r_shadows_throwdistance);
1750 Cvar_RegisterVariable(&r_q1bsp_skymasking);
1751 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
1752 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
1753 Cvar_RegisterVariable(&r_textureunits);
1754 Cvar_RegisterVariable(&r_glsl);
1755 Cvar_RegisterVariable(&r_glsl_offsetmapping);
1756 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
1757 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
1758 Cvar_RegisterVariable(&r_glsl_water);
1759 Cvar_RegisterVariable(&r_glsl_water_resolutionmultiplier);
1760 Cvar_RegisterVariable(&r_glsl_water_clippingplanebias);
1761 Cvar_RegisterVariable(&r_glsl_water_refractcolor_r);
1762 Cvar_RegisterVariable(&r_glsl_water_refractcolor_g);
1763 Cvar_RegisterVariable(&r_glsl_water_refractcolor_b);
1764 Cvar_RegisterVariable(&r_glsl_water_reflectcolor_r);
1765 Cvar_RegisterVariable(&r_glsl_water_reflectcolor_g);
1766 Cvar_RegisterVariable(&r_glsl_water_reflectcolor_b);
1767 Cvar_RegisterVariable(&r_glsl_water_refractdistort);
1768 Cvar_RegisterVariable(&r_glsl_water_reflectdistort);
1769 Cvar_RegisterVariable(&r_glsl_deluxemapping);
1770 Cvar_RegisterVariable(&r_lerpsprites);
1771 Cvar_RegisterVariable(&r_lerpmodels);
1772 Cvar_RegisterVariable(&r_waterscroll);
1773 Cvar_RegisterVariable(&r_bloom);
1774 Cvar_RegisterVariable(&r_bloom_colorscale);
1775 Cvar_RegisterVariable(&r_bloom_brighten);
1776 Cvar_RegisterVariable(&r_bloom_blur);
1777 Cvar_RegisterVariable(&r_bloom_resolution);
1778 Cvar_RegisterVariable(&r_bloom_colorexponent);
1779 Cvar_RegisterVariable(&r_bloom_colorsubtract);
1780 Cvar_RegisterVariable(&r_hdr);
1781 Cvar_RegisterVariable(&r_hdr_scenebrightness);
1782 Cvar_RegisterVariable(&r_glsl_contrastboost);
1783 Cvar_RegisterVariable(&r_hdr_glowintensity);
1784 Cvar_RegisterVariable(&r_hdr_range);
1785 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
1786 Cvar_RegisterVariable(&developer_texturelogging);
1787 Cvar_RegisterVariable(&gl_lightmaps);
1788 Cvar_RegisterVariable(&r_test);
1789 Cvar_RegisterVariable(&r_batchmode);
1790 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
1791 Cvar_SetValue("r_fullbrights", 0);
1792 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
1795 extern void R_Textures_Init(void);
1796 extern void GL_Draw_Init(void);
1797 extern void GL_Main_Init(void);
1798 extern void R_Shadow_Init(void);
1799 extern void R_Sky_Init(void);
1800 extern void GL_Surf_Init(void);
1801 extern void R_Light_Init(void);
1802 extern void R_Particles_Init(void);
1803 extern void R_Explosion_Init(void);
1804 extern void gl_backend_init(void);
1805 extern void Sbar_Init(void);
1806 extern void R_LightningBeams_Init(void);
1807 extern void Mod_RenderInit(void);
1809 void Render_Init(void)
1822 R_LightningBeams_Init();
1831 extern char *ENGINE_EXTENSIONS;
1834 VID_CheckExtensions();
1836 // LordHavoc: report supported extensions
1837 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
1839 // clear to black (loading plaque will be seen over this)
1841 qglClearColor(0,0,0,1);CHECKGLERROR
1842 qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
1845 int R_CullBox(const vec3_t mins, const vec3_t maxs)
1849 for (i = 0;i < r_view.numfrustumplanes;i++)
1851 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
1854 p = r_view.frustum + i;
1859 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1863 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1867 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1871 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1875 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1879 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1883 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1887 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1895 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
1899 for (i = 0;i < numplanes;i++)
1906 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1910 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1914 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1918 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1922 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1926 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1930 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1934 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1942 //==================================================================================
1944 static void R_UpdateEntityLighting(entity_render_t *ent)
1946 vec3_t tempdiffusenormal;
1948 // fetch the lighting from the worldmodel data
1949 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));
1950 VectorClear(ent->modellight_diffuse);
1951 VectorClear(tempdiffusenormal);
1952 if ((ent->flags & RENDER_LIGHT) && r_refdef.worldmodel && r_refdef.worldmodel->brush.LightPoint)
1955 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
1956 r_refdef.worldmodel->brush.LightPoint(r_refdef.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
1959 VectorSet(ent->modellight_ambient, 1, 1, 1);
1961 // move the light direction into modelspace coordinates for lighting code
1962 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
1963 if(VectorLength2(ent->modellight_lightdir) > 0)
1965 VectorNormalize(ent->modellight_lightdir);
1969 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
1972 // scale ambient and directional light contributions according to rendering variables
1973 ent->modellight_ambient[0] *= ent->colormod[0] * r_refdef.lightmapintensity;
1974 ent->modellight_ambient[1] *= ent->colormod[1] * r_refdef.lightmapintensity;
1975 ent->modellight_ambient[2] *= ent->colormod[2] * r_refdef.lightmapintensity;
1976 ent->modellight_diffuse[0] *= ent->colormod[0] * r_refdef.lightmapintensity;
1977 ent->modellight_diffuse[1] *= ent->colormod[1] * r_refdef.lightmapintensity;
1978 ent->modellight_diffuse[2] *= ent->colormod[2] * r_refdef.lightmapintensity;
1981 static void R_View_UpdateEntityVisible (void)
1984 entity_render_t *ent;
1986 if (!r_drawentities.integer)
1989 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : ((chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL : RENDER_EXTERIORMODEL);
1990 if (r_refdef.worldmodel && r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs)
1992 // worldmodel can check visibility
1993 for (i = 0;i < r_refdef.numentities;i++)
1995 ent = r_refdef.entities[i];
1996 r_viewcache.entityvisible[i] = !(ent->flags & renderimask) && !R_CullBox(ent->mins, ent->maxs) && ((ent->effects & EF_NODEPTHTEST) || (ent->flags & RENDER_VIEWMODEL) || r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs(r_refdef.worldmodel, r_viewcache.world_leafvisible, ent->mins, ent->maxs));
1998 if(r_cullentities_trace.integer)
2000 for (i = 0;i < r_refdef.numentities;i++)
2002 ent = r_refdef.entities[i];
2003 if(r_viewcache.entityvisible[i] && !(ent->effects & EF_NODEPTHTEST) && !(ent->flags & RENDER_VIEWMODEL) && !(ent->model && (ent->model->name[0] == '*')))
2005 if(Mod_CanSeeBox_Trace(r_cullentities_trace_samples.integer, r_cullentities_trace_enlarge.value, r_refdef.worldmodel, r_view.origin, ent->mins, ent->maxs))
2006 ent->last_trace_visibility = realtime;
2007 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
2008 r_viewcache.entityvisible[i] = 0;
2015 // no worldmodel or it can't check visibility
2016 for (i = 0;i < r_refdef.numentities;i++)
2018 ent = r_refdef.entities[i];
2019 r_viewcache.entityvisible[i] = !(ent->flags & renderimask) && !R_CullBox(ent->mins, ent->maxs);
2023 // update entity lighting (even on hidden entities for r_shadows)
2024 for (i = 0;i < r_refdef.numentities;i++)
2025 R_UpdateEntityLighting(r_refdef.entities[i]);
2028 // only used if skyrendermasked, and normally returns false
2029 int R_DrawBrushModelsSky (void)
2032 entity_render_t *ent;
2034 if (!r_drawentities.integer)
2038 for (i = 0;i < r_refdef.numentities;i++)
2040 if (!r_viewcache.entityvisible[i])
2042 ent = r_refdef.entities[i];
2043 if (!ent->model || !ent->model->DrawSky)
2045 ent->model->DrawSky(ent);
2051 static void R_DrawNoModel(entity_render_t *ent);
2052 static void R_DrawModels(void)
2055 entity_render_t *ent;
2057 if (!r_drawentities.integer)
2060 for (i = 0;i < r_refdef.numentities;i++)
2062 if (!r_viewcache.entityvisible[i])
2064 ent = r_refdef.entities[i];
2065 r_refdef.stats.entities++;
2066 if (ent->model && ent->model->Draw != NULL)
2067 ent->model->Draw(ent);
2073 static void R_DrawModelsDepth(void)
2076 entity_render_t *ent;
2078 if (!r_drawentities.integer)
2081 for (i = 0;i < r_refdef.numentities;i++)
2083 if (!r_viewcache.entityvisible[i])
2085 ent = r_refdef.entities[i];
2086 r_refdef.stats.entities++;
2087 if (ent->model && ent->model->DrawDepth != NULL)
2088 ent->model->DrawDepth(ent);
2092 static void R_DrawModelsAddWaterPlanes(void)
2095 entity_render_t *ent;
2097 if (!r_drawentities.integer)
2100 for (i = 0;i < r_refdef.numentities;i++)
2102 if (!r_viewcache.entityvisible[i])
2104 ent = r_refdef.entities[i];
2105 r_refdef.stats.entities++;
2106 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
2107 ent->model->DrawAddWaterPlanes(ent);
2111 static void R_View_SetFrustum(void)
2114 double slopex, slopey;
2116 // break apart the view matrix into vectors for various purposes
2117 Matrix4x4_ToVectors(&r_view.matrix, r_view.forward, r_view.left, r_view.up, r_view.origin);
2118 VectorNegate(r_view.left, r_view.right);
2121 r_view.frustum[0].normal[0] = 0 - 1.0 / r_view.frustum_x;
2122 r_view.frustum[0].normal[1] = 0 - 0;
2123 r_view.frustum[0].normal[2] = -1 - 0;
2124 r_view.frustum[1].normal[0] = 0 + 1.0 / r_view.frustum_x;
2125 r_view.frustum[1].normal[1] = 0 + 0;
2126 r_view.frustum[1].normal[2] = -1 + 0;
2127 r_view.frustum[2].normal[0] = 0 - 0;
2128 r_view.frustum[2].normal[1] = 0 - 1.0 / r_view.frustum_y;
2129 r_view.frustum[2].normal[2] = -1 - 0;
2130 r_view.frustum[3].normal[0] = 0 + 0;
2131 r_view.frustum[3].normal[1] = 0 + 1.0 / r_view.frustum_y;
2132 r_view.frustum[3].normal[2] = -1 + 0;
2136 zNear = r_refdef.nearclip;
2137 nudge = 1.0 - 1.0 / (1<<23);
2138 r_view.frustum[4].normal[0] = 0 - 0;
2139 r_view.frustum[4].normal[1] = 0 - 0;
2140 r_view.frustum[4].normal[2] = -1 - -nudge;
2141 r_view.frustum[4].dist = 0 - -2 * zNear * nudge;
2142 r_view.frustum[5].normal[0] = 0 + 0;
2143 r_view.frustum[5].normal[1] = 0 + 0;
2144 r_view.frustum[5].normal[2] = -1 + -nudge;
2145 r_view.frustum[5].dist = 0 + -2 * zNear * nudge;
2151 r_view.frustum[0].normal[0] = m[3] - m[0];
2152 r_view.frustum[0].normal[1] = m[7] - m[4];
2153 r_view.frustum[0].normal[2] = m[11] - m[8];
2154 r_view.frustum[0].dist = m[15] - m[12];
2156 r_view.frustum[1].normal[0] = m[3] + m[0];
2157 r_view.frustum[1].normal[1] = m[7] + m[4];
2158 r_view.frustum[1].normal[2] = m[11] + m[8];
2159 r_view.frustum[1].dist = m[15] + m[12];
2161 r_view.frustum[2].normal[0] = m[3] - m[1];
2162 r_view.frustum[2].normal[1] = m[7] - m[5];
2163 r_view.frustum[2].normal[2] = m[11] - m[9];
2164 r_view.frustum[2].dist = m[15] - m[13];
2166 r_view.frustum[3].normal[0] = m[3] + m[1];
2167 r_view.frustum[3].normal[1] = m[7] + m[5];
2168 r_view.frustum[3].normal[2] = m[11] + m[9];
2169 r_view.frustum[3].dist = m[15] + m[13];
2171 r_view.frustum[4].normal[0] = m[3] - m[2];
2172 r_view.frustum[4].normal[1] = m[7] - m[6];
2173 r_view.frustum[4].normal[2] = m[11] - m[10];
2174 r_view.frustum[4].dist = m[15] - m[14];
2176 r_view.frustum[5].normal[0] = m[3] + m[2];
2177 r_view.frustum[5].normal[1] = m[7] + m[6];
2178 r_view.frustum[5].normal[2] = m[11] + m[10];
2179 r_view.frustum[5].dist = m[15] + m[14];
2184 if (r_view.useperspective)
2186 slopex = 1.0 / r_view.frustum_x;
2187 slopey = 1.0 / r_view.frustum_y;
2188 VectorMA(r_view.forward, -slopex, r_view.left, r_view.frustum[0].normal);
2189 VectorMA(r_view.forward, slopex, r_view.left, r_view.frustum[1].normal);
2190 VectorMA(r_view.forward, -slopey, r_view.up , r_view.frustum[2].normal);
2191 VectorMA(r_view.forward, slopey, r_view.up , r_view.frustum[3].normal);
2192 VectorCopy(r_view.forward, r_view.frustum[4].normal);
2194 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
2195 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, -1024 * slopex, r_view.left, -1024 * slopey, r_view.up, r_view.frustumcorner[0]);
2196 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, 1024 * slopex, r_view.left, -1024 * slopey, r_view.up, r_view.frustumcorner[1]);
2197 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, -1024 * slopex, r_view.left, 1024 * slopey, r_view.up, r_view.frustumcorner[2]);
2198 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, 1024 * slopex, r_view.left, 1024 * slopey, r_view.up, r_view.frustumcorner[3]);
2200 r_view.frustum[0].dist = DotProduct (r_view.origin, r_view.frustum[0].normal);
2201 r_view.frustum[1].dist = DotProduct (r_view.origin, r_view.frustum[1].normal);
2202 r_view.frustum[2].dist = DotProduct (r_view.origin, r_view.frustum[2].normal);
2203 r_view.frustum[3].dist = DotProduct (r_view.origin, r_view.frustum[3].normal);
2204 r_view.frustum[4].dist = DotProduct (r_view.origin, r_view.frustum[4].normal) + r_refdef.nearclip;
2208 VectorScale(r_view.left, -r_view.ortho_x, r_view.frustum[0].normal);
2209 VectorScale(r_view.left, r_view.ortho_x, r_view.frustum[1].normal);
2210 VectorScale(r_view.up, -r_view.ortho_y, r_view.frustum[2].normal);
2211 VectorScale(r_view.up, r_view.ortho_y, r_view.frustum[3].normal);
2212 VectorCopy(r_view.forward, r_view.frustum[4].normal);
2213 r_view.frustum[0].dist = DotProduct (r_view.origin, r_view.frustum[0].normal) + r_view.ortho_x;
2214 r_view.frustum[1].dist = DotProduct (r_view.origin, r_view.frustum[1].normal) + r_view.ortho_x;
2215 r_view.frustum[2].dist = DotProduct (r_view.origin, r_view.frustum[2].normal) + r_view.ortho_y;
2216 r_view.frustum[3].dist = DotProduct (r_view.origin, r_view.frustum[3].normal) + r_view.ortho_y;
2217 r_view.frustum[4].dist = DotProduct (r_view.origin, r_view.frustum[4].normal) + r_refdef.nearclip;
2219 r_view.numfrustumplanes = 5;
2221 if (r_view.useclipplane)
2223 r_view.numfrustumplanes = 6;
2224 r_view.frustum[5] = r_view.clipplane;
2227 for (i = 0;i < r_view.numfrustumplanes;i++)
2228 PlaneClassify(r_view.frustum + i);
2230 // LordHavoc: note to all quake engine coders, Quake had a special case
2231 // for 90 degrees which assumed a square view (wrong), so I removed it,
2232 // Quake2 has it disabled as well.
2234 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
2235 //RotatePointAroundVector( r_view.frustum[0].normal, r_view.up, r_view.forward, -(90 - r_refdef.fov_x / 2));
2236 //r_view.frustum[0].dist = DotProduct (r_view.origin, frustum[0].normal);
2237 //PlaneClassify(&frustum[0]);
2239 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
2240 //RotatePointAroundVector( r_view.frustum[1].normal, r_view.up, r_view.forward, (90 - r_refdef.fov_x / 2));
2241 //r_view.frustum[1].dist = DotProduct (r_view.origin, frustum[1].normal);
2242 //PlaneClassify(&frustum[1]);
2244 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
2245 //RotatePointAroundVector( r_view.frustum[2].normal, r_view.left, r_view.forward, -(90 - r_refdef.fov_y / 2));
2246 //r_view.frustum[2].dist = DotProduct (r_view.origin, frustum[2].normal);
2247 //PlaneClassify(&frustum[2]);
2249 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
2250 //RotatePointAroundVector( r_view.frustum[3].normal, r_view.left, r_view.forward, (90 - r_refdef.fov_y / 2));
2251 //r_view.frustum[3].dist = DotProduct (r_view.origin, frustum[3].normal);
2252 //PlaneClassify(&frustum[3]);
2255 //VectorCopy(r_view.forward, r_view.frustum[4].normal);
2256 //r_view.frustum[4].dist = DotProduct (r_view.origin, frustum[4].normal) + r_nearclip.value;
2257 //PlaneClassify(&frustum[4]);
2260 void R_View_Update(void)
2262 R_View_SetFrustum();
2263 R_View_WorldVisibility(r_view.useclipplane);
2264 R_View_UpdateEntityVisible();
2267 void R_SetupView(void)
2269 if (!r_view.useperspective)
2270 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);
2271 else if (r_refdef.rtworldshadows || r_refdef.rtdlightshadows)
2272 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_view.frustum_x, r_view.frustum_y, r_refdef.nearclip);
2274 GL_SetupView_Mode_Perspective(r_view.frustum_x, r_view.frustum_y, r_refdef.nearclip, r_refdef.farclip);
2276 GL_SetupView_Orientation_FromEntity(&r_view.matrix);
2278 if (r_view.useclipplane)
2280 // LordHavoc: couldn't figure out how to make this approach the
2281 vec_t dist = r_view.clipplane.dist - r_glsl_water_clippingplanebias.value;
2282 vec_t viewdist = DotProduct(r_view.origin, r_view.clipplane.normal);
2283 if (viewdist < r_view.clipplane.dist + r_glsl_water_clippingplanebias.value)
2284 dist = r_view.clipplane.dist;
2285 GL_SetupView_ApplyCustomNearClipPlane(r_view.clipplane.normal[0], r_view.clipplane.normal[1], r_view.clipplane.normal[2], dist);
2289 void R_ResetViewRendering2D(void)
2291 if (gl_support_fragment_shader)
2293 qglUseProgramObjectARB(0);CHECKGLERROR
2298 // GL is weird because it's bottom to top, r_view.y is top to bottom
2299 qglViewport(r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
2300 GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
2301 GL_Scissor(r_view.x, r_view.y, r_view.width, r_view.height);
2302 GL_Color(1, 1, 1, 1);
2303 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
2304 GL_BlendFunc(GL_ONE, GL_ZERO);
2305 GL_AlphaTest(false);
2306 GL_ScissorTest(false);
2307 GL_DepthMask(false);
2308 GL_DepthRange(0, 1);
2309 GL_DepthTest(false);
2310 R_Mesh_Matrix(&identitymatrix);
2311 R_Mesh_ResetTextureState();
2312 GL_PolygonOffset(0, 0);
2313 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
2314 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
2315 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
2316 qglStencilMask(~0);CHECKGLERROR
2317 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
2318 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
2319 GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
2322 void R_ResetViewRendering3D(void)
2324 if (gl_support_fragment_shader)
2326 qglUseProgramObjectARB(0);CHECKGLERROR
2331 // GL is weird because it's bottom to top, r_view.y is top to bottom
2332 qglViewport(r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
2334 GL_Scissor(r_view.x, r_view.y, r_view.width, r_view.height);
2335 GL_Color(1, 1, 1, 1);
2336 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
2337 GL_BlendFunc(GL_ONE, GL_ZERO);
2338 GL_AlphaTest(false);
2339 GL_ScissorTest(true);
2341 GL_DepthRange(0, 1);
2343 R_Mesh_Matrix(&identitymatrix);
2344 R_Mesh_ResetTextureState();
2345 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
2346 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
2347 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
2348 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
2349 qglStencilMask(~0);CHECKGLERROR
2350 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
2351 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
2352 GL_CullFace(r_view.cullface_back);
2356 R_Bloom_SetupShader(
2358 "// written by Forest 'LordHavoc' Hale\n"
2360 "// common definitions between vertex shader and fragment shader:\n"
2362 "#ifdef __GLSL_CG_DATA_TYPES\n"
2363 "#define myhalf half\n"
2364 "#define myhvec2 hvec2\n"
2365 "#define myhvec3 hvec3\n"
2366 "#define myhvec4 hvec4\n"
2368 "#define myhalf float\n"
2369 "#define myhvec2 vec2\n"
2370 "#define myhvec3 vec3\n"
2371 "#define myhvec4 vec4\n"
2374 "varying vec2 ScreenTexCoord;\n"
2375 "varying vec2 BloomTexCoord;\n"
2380 "// vertex shader specific:\n"
2381 "#ifdef VERTEX_SHADER\n"
2385 " ScreenTexCoord = vec2(gl_MultiTexCoord0);\n"
2386 " BloomTexCoord = vec2(gl_MultiTexCoord1);\n"
2387 " // transform vertex to camera space, using ftransform to match non-VS\n"
2389 " gl_Position = ftransform();\n"
2392 "#endif // VERTEX_SHADER\n"
2397 "// fragment shader specific:\n"
2398 "#ifdef FRAGMENT_SHADER\n"
2403 " myhvec3 color = myhvec3(texture2D(Texture_Screen, ScreenTexCoord));\n"
2404 " for (x = -BLUR_X;x <= BLUR_X;x++)
2405 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2406 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2407 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2408 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2410 " gl_FragColor = vec4(color);\n"
2413 "#endif // FRAGMENT_SHADER\n"
2416 void R_RenderScene(qboolean addwaterplanes);
2418 static void R_Water_StartFrame(void)
2421 int texturewidth, textureheight;
2422 r_waterstate_waterplane_t *p;
2424 r_waterstate.maxwaterplanes = 0;
2426 // set waterwidth and waterheight to the water resolution that will be
2427 // used (often less than the screen resolution for faster rendering)
2428 r_waterstate.waterwidth = (int)bound(1, r_view.width * r_glsl_water_resolutionmultiplier.value, r_view.width);
2429 r_waterstate.waterheight = (int)bound(1, r_view.height * r_glsl_water_resolutionmultiplier.value, r_view.height);
2431 // calculate desired texture sizes
2432 if (gl_support_arb_texture_non_power_of_two)
2434 texturewidth = r_waterstate.waterwidth;
2435 textureheight = r_waterstate.waterheight;
2439 for (texturewidth = 1;texturewidth < r_waterstate.waterwidth ;texturewidth *= 2);
2440 for (textureheight = 1;textureheight < r_waterstate.waterheight;textureheight *= 2);
2443 if (!r_glsl_water.integer)
2444 texturewidth = textureheight = 0;
2446 // allocate textures as needed
2447 if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight)
2449 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
2451 if (p->texture_refraction)
2452 R_FreeTexture(p->texture_refraction);
2453 p->texture_refraction = NULL;
2454 if (p->texture_reflection)
2455 R_FreeTexture(p->texture_reflection);
2456 p->texture_reflection = NULL;
2458 r_waterstate.texturewidth = texturewidth;
2459 r_waterstate.textureheight = textureheight;
2462 if ((!texturewidth && !textureheight) || texturewidth > gl_max_texture_size || textureheight > gl_max_texture_size)
2464 // can't use water if the parameters are too weird
2465 // can't use water if the card does not support the texture size
2466 memset(&r_waterstate, 0, sizeof(r_waterstate));
2470 r_waterstate.enabled = true;
2472 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
2474 // set up variables that will be used in shader setup
2475 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
2476 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
2477 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
2478 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
2481 static void R_Water_AddWaterPlane(msurface_t *surface)
2483 int triangleindex, planeindex;
2489 r_waterstate_waterplane_t *p;
2490 // just use the first triangle with a valid normal for any decisions
2491 VectorClear(normal);
2492 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
2494 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
2495 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
2496 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
2497 TriangleNormal(vert[0], vert[1], vert[2], normal);
2498 if (VectorLength2(normal) >= 0.001)
2501 // now find the center of this surface
2502 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles*3;triangleindex++, e++)
2504 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
2505 VectorAdd(center, vert[0], center);
2507 f = 1.0 / surface->num_triangles*3;
2508 VectorScale(center, f, center);
2510 // find a matching plane if there is one
2511 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
2512 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
2514 if (planeindex >= r_waterstate.maxwaterplanes)
2515 return; // nothing we can do, out of planes
2517 // if this triangle does not fit any known plane rendered this frame, add one
2518 if (planeindex >= r_waterstate.numwaterplanes)
2520 // store the new plane
2521 r_waterstate.numwaterplanes++;
2522 VectorCopy(normal, p->plane.normal);
2523 VectorNormalize(p->plane.normal);
2524 p->plane.dist = DotProduct(vert[0], p->plane.normal);
2525 PlaneClassify(&p->plane);
2526 // flip the plane if it does not face the viewer
2527 if (PlaneDiff(r_view.origin, &p->plane) < 0)
2529 VectorNegate(p->plane.normal, p->plane.normal);
2530 p->plane.dist *= -1;
2531 PlaneClassify(&p->plane);
2533 // clear materialflags and pvs
2534 p->materialflags = 0;
2535 p->pvsvalid = false;
2537 // merge this surface's materialflags into the waterplane
2538 p->materialflags |= surface->texture->currentframe->currentmaterialflags;
2539 // merge this surface's PVS into the waterplane
2540 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION) && r_refdef.worldmodel && r_refdef.worldmodel->brush.FatPVS)
2542 r_refdef.worldmodel->brush.FatPVS(r_refdef.worldmodel, r_view.origin, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
2547 static void R_Water_ProcessPlanes(void)
2549 r_view_t originalview;
2551 r_waterstate_waterplane_t *p;
2553 // make sure enough textures are allocated
2554 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
2556 if (p->materialflags & MATERIALFLAG_WATERSHADER)
2558 if (!p->texture_refraction)
2559 p->texture_refraction = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_refraction", planeindex), r_waterstate.texturewidth, r_waterstate.textureheight, NULL, TEXTYPE_RGBA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
2560 if (!p->texture_refraction)
2564 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
2566 if (!p->texture_reflection)
2567 p->texture_reflection = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_reflection", planeindex), r_waterstate.texturewidth, r_waterstate.textureheight, NULL, TEXTYPE_RGBA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
2568 if (!p->texture_reflection)
2574 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
2576 originalview = r_view;
2577 r_view.showdebug = false;
2578 r_view.width = r_waterstate.waterwidth;
2579 r_view.height = r_waterstate.waterheight;
2580 r_view.useclipplane = true;
2581 r_waterstate.renderingscene = true;
2583 // render the normal view scene and copy into texture
2584 // (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)
2585 if (p->materialflags & MATERIALFLAG_WATERSHADER)
2587 r_view.clipplane = p->plane;
2588 VectorNegate(r_view.clipplane.normal, r_view.clipplane.normal);
2589 r_view.clipplane.dist = -r_view.clipplane.dist;
2590 PlaneClassify(&r_view.clipplane);
2592 R_RenderScene(false);
2594 // copy view into the screen texture
2595 R_Mesh_TexBind(0, R_GetTexture(p->texture_refraction));
2596 GL_ActiveTexture(0);
2598 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
2601 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
2603 // render reflected scene and copy into texture
2604 Matrix4x4_Reflect(&r_view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
2605 r_view.clipplane = p->plane;
2606 // reverse the cullface settings for this render
2607 r_view.cullface_front = GL_FRONT;
2608 r_view.cullface_back = GL_BACK;
2609 if (r_refdef.worldmodel && r_refdef.worldmodel->brush.num_pvsclusterbytes)
2611 r_view.usecustompvs = true;
2613 memcpy(r_viewcache.world_pvsbits, p->pvsbits, r_refdef.worldmodel->brush.num_pvsclusterbytes);
2615 memset(r_viewcache.world_pvsbits, 0xFF, r_refdef.worldmodel->brush.num_pvsclusterbytes);
2618 R_ResetViewRendering3D();
2621 R_RenderScene(false);
2623 R_Mesh_TexBind(0, R_GetTexture(p->texture_reflection));
2624 GL_ActiveTexture(0);
2626 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
2628 R_ResetViewRendering3D();
2632 r_view = originalview;
2633 r_waterstate.renderingscene = false;
2637 r_view = originalview;
2638 r_waterstate.renderingscene = false;
2639 Cvar_SetValueQuick(&r_glsl_water, 0);
2640 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_glsl_water.\n");
2644 void R_Bloom_StartFrame(void)
2646 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
2648 // set bloomwidth and bloomheight to the bloom resolution that will be
2649 // used (often less than the screen resolution for faster rendering)
2650 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_view.width);
2651 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_view.height / r_view.width;
2652 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_view.height);
2654 // calculate desired texture sizes
2655 if (gl_support_arb_texture_non_power_of_two)
2657 screentexturewidth = r_view.width;
2658 screentextureheight = r_view.height;
2659 bloomtexturewidth = r_bloomstate.bloomwidth;
2660 bloomtextureheight = r_bloomstate.bloomheight;
2664 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
2665 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
2666 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
2667 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
2672 screentexturewidth = screentextureheight = 0;
2674 else if (r_bloom.integer)
2679 screentexturewidth = screentextureheight = 0;
2680 bloomtexturewidth = bloomtextureheight = 0;
2683 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)
2685 // can't use bloom if the parameters are too weird
2686 // can't use bloom if the card does not support the texture size
2687 if (r_bloomstate.texture_screen)
2688 R_FreeTexture(r_bloomstate.texture_screen);
2689 if (r_bloomstate.texture_bloom)
2690 R_FreeTexture(r_bloomstate.texture_bloom);
2691 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
2695 r_bloomstate.enabled = true;
2696 r_bloomstate.hdr = r_hdr.integer != 0;
2698 // allocate textures as needed
2699 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
2701 if (r_bloomstate.texture_screen)
2702 R_FreeTexture(r_bloomstate.texture_screen);
2703 r_bloomstate.texture_screen = NULL;
2704 r_bloomstate.screentexturewidth = screentexturewidth;
2705 r_bloomstate.screentextureheight = screentextureheight;
2706 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
2707 r_bloomstate.texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, TEXTYPE_RGBA, TEXF_FORCENEAREST | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
2709 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
2711 if (r_bloomstate.texture_bloom)
2712 R_FreeTexture(r_bloomstate.texture_bloom);
2713 r_bloomstate.texture_bloom = NULL;
2714 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
2715 r_bloomstate.bloomtextureheight = bloomtextureheight;
2716 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
2717 r_bloomstate.texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", r_bloomstate.bloomtexturewidth, r_bloomstate.bloomtextureheight, NULL, TEXTYPE_RGBA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
2720 // set up a texcoord array for the full resolution screen image
2721 // (we have to keep this around to copy back during final render)
2722 r_bloomstate.screentexcoord2f[0] = 0;
2723 r_bloomstate.screentexcoord2f[1] = (float)r_view.height / (float)r_bloomstate.screentextureheight;
2724 r_bloomstate.screentexcoord2f[2] = (float)r_view.width / (float)r_bloomstate.screentexturewidth;
2725 r_bloomstate.screentexcoord2f[3] = (float)r_view.height / (float)r_bloomstate.screentextureheight;
2726 r_bloomstate.screentexcoord2f[4] = (float)r_view.width / (float)r_bloomstate.screentexturewidth;
2727 r_bloomstate.screentexcoord2f[5] = 0;
2728 r_bloomstate.screentexcoord2f[6] = 0;
2729 r_bloomstate.screentexcoord2f[7] = 0;
2731 // set up a texcoord array for the reduced resolution bloom image
2732 // (which will be additive blended over the screen image)
2733 r_bloomstate.bloomtexcoord2f[0] = 0;
2734 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
2735 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
2736 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
2737 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
2738 r_bloomstate.bloomtexcoord2f[5] = 0;
2739 r_bloomstate.bloomtexcoord2f[6] = 0;
2740 r_bloomstate.bloomtexcoord2f[7] = 0;
2743 void R_Bloom_CopyScreenTexture(float colorscale)
2745 r_refdef.stats.bloom++;
2747 R_ResetViewRendering2D();
2748 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
2749 R_Mesh_ColorPointer(NULL, 0, 0);
2750 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
2751 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
2753 // copy view into the screen texture
2754 GL_ActiveTexture(0);
2756 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
2757 r_refdef.stats.bloom_copypixels += r_view.width * r_view.height;
2759 // now scale it down to the bloom texture size
2761 qglViewport(r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
2762 GL_BlendFunc(GL_ONE, GL_ZERO);
2763 GL_Color(colorscale, colorscale, colorscale, 1);
2764 // TODO: optimize with multitexture or GLSL
2765 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2766 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2768 // we now have a bloom image in the framebuffer
2769 // copy it into the bloom image texture for later processing
2770 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2771 GL_ActiveTexture(0);
2773 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
2774 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2777 void R_Bloom_CopyHDRTexture(void)
2779 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2780 GL_ActiveTexture(0);
2782 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
2783 r_refdef.stats.bloom_copypixels += r_view.width * r_view.height;
2786 void R_Bloom_MakeTexture(void)
2789 float xoffset, yoffset, r, brighten;
2791 r_refdef.stats.bloom++;
2793 R_ResetViewRendering2D();
2794 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
2795 R_Mesh_ColorPointer(NULL, 0, 0);
2797 // we have a bloom image in the framebuffer
2799 qglViewport(r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
2801 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
2804 r = bound(0, r_bloom_colorexponent.value / x, 1);
2805 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
2806 GL_Color(r, r, r, 1);
2807 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2808 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
2809 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2810 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2812 // copy the vertically blurred bloom view to a texture
2813 GL_ActiveTexture(0);
2815 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
2816 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2819 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
2820 brighten = r_bloom_brighten.value;
2822 brighten *= r_hdr_range.value;
2823 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2824 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
2826 for (dir = 0;dir < 2;dir++)
2828 // blend on at multiple vertical offsets to achieve a vertical blur
2829 // TODO: do offset blends using GLSL
2830 GL_BlendFunc(GL_ONE, GL_ZERO);
2831 for (x = -range;x <= range;x++)
2833 if (!dir){xoffset = 0;yoffset = x;}
2834 else {xoffset = x;yoffset = 0;}
2835 xoffset /= (float)r_bloomstate.bloomtexturewidth;
2836 yoffset /= (float)r_bloomstate.bloomtextureheight;
2837 // compute a texcoord array with the specified x and y offset
2838 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
2839 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
2840 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
2841 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
2842 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
2843 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
2844 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
2845 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
2846 // this r value looks like a 'dot' particle, fading sharply to
2847 // black at the edges
2848 // (probably not realistic but looks good enough)
2849 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
2850 //r = (dir ? 1.0f : brighten)/(range*2+1);
2851 r = (dir ? 1.0f : brighten)/(range*2+1)*(1 - x*x/(float)(range*range));
2852 GL_Color(r, r, r, 1);
2853 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2854 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2855 GL_BlendFunc(GL_ONE, GL_ONE);
2858 // copy the vertically blurred bloom view to a texture
2859 GL_ActiveTexture(0);
2861 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
2862 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2865 // apply subtract last
2866 // (just like it would be in a GLSL shader)
2867 if (r_bloom_colorsubtract.value > 0 && gl_support_ext_blend_subtract)
2869 GL_BlendFunc(GL_ONE, GL_ZERO);
2870 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2871 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
2872 GL_Color(1, 1, 1, 1);
2873 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2874 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2876 GL_BlendFunc(GL_ONE, GL_ONE);
2877 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
2878 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2879 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
2880 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
2881 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2882 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2883 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
2885 // copy the darkened bloom view to a texture
2886 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2887 GL_ActiveTexture(0);
2889 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
2890 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2894 void R_HDR_RenderBloomTexture(void)
2896 int oldwidth, oldheight;
2898 oldwidth = r_view.width;
2899 oldheight = r_view.height;
2900 r_view.width = r_bloomstate.bloomwidth;
2901 r_view.height = r_bloomstate.bloomheight;
2903 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
2904 // TODO: add exposure compensation features
2905 // TODO: add fp16 framebuffer support
2907 r_view.showdebug = false;
2908 r_view.colorscale = r_bloom_colorscale.value * r_hdr_scenebrightness.value;
2910 r_view.colorscale /= r_hdr_range.value;
2911 r_waterstate.numwaterplanes = 0;
2912 R_RenderScene(r_waterstate.enabled);
2913 r_view.showdebug = true;
2915 R_ResetViewRendering2D();
2917 R_Bloom_CopyHDRTexture();
2918 R_Bloom_MakeTexture();
2920 R_ResetViewRendering3D();
2923 if (r_timereport_active)
2924 R_TimeReport("clear");
2927 // restore the view settings
2928 r_view.width = oldwidth;
2929 r_view.height = oldheight;
2932 static void R_BlendView(void)
2934 if (r_bloomstate.enabled && r_bloomstate.hdr)
2936 // render high dynamic range bloom effect
2937 // the bloom texture was made earlier this render, so we just need to
2938 // blend it onto the screen...
2939 R_ResetViewRendering2D();
2940 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
2941 R_Mesh_ColorPointer(NULL, 0, 0);
2942 GL_Color(1, 1, 1, 1);
2943 GL_BlendFunc(GL_ONE, GL_ONE);
2944 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2945 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
2946 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2947 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
2949 else if (r_bloomstate.enabled)
2951 // render simple bloom effect
2952 // copy the screen and shrink it and darken it for the bloom process
2953 R_Bloom_CopyScreenTexture(r_bloom_colorscale.value);
2954 // make the bloom texture
2955 R_Bloom_MakeTexture();
2956 // put the original screen image back in place and blend the bloom
2958 R_ResetViewRendering2D();
2959 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
2960 R_Mesh_ColorPointer(NULL, 0, 0);
2961 GL_Color(1, 1, 1, 1);
2962 GL_BlendFunc(GL_ONE, GL_ZERO);
2963 // do both in one pass if possible
2964 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2965 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
2966 if (r_textureunits.integer >= 2 && gl_combine.integer)
2968 R_Mesh_TexCombine(1, GL_ADD, GL_ADD, 1, 1);
2969 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_screen));
2970 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.screentexcoord2f, 0, 0);
2974 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2975 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
2976 // now blend on the bloom texture
2977 GL_BlendFunc(GL_ONE, GL_ONE);
2978 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
2979 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
2981 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2982 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
2984 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
2986 // apply a color tint to the whole view
2987 R_ResetViewRendering2D();
2988 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
2989 R_Mesh_ColorPointer(NULL, 0, 0);
2990 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2991 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
2992 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2996 void R_RenderScene(qboolean addwaterplanes);
2998 matrix4x4_t r_waterscrollmatrix;
3000 void R_UpdateVariables(void)
3004 r_refdef.farclip = 4096;
3005 if (r_refdef.worldmodel)
3006 r_refdef.farclip += VectorDistance(r_refdef.worldmodel->normalmins, r_refdef.worldmodel->normalmaxs);
3007 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
3009 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
3010 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
3011 r_refdef.polygonfactor = 0;
3012 r_refdef.polygonoffset = 0;
3013 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
3014 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
3016 r_refdef.rtworld = r_shadow_realtime_world.integer;
3017 r_refdef.rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
3018 r_refdef.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
3019 r_refdef.rtdlightshadows = r_refdef.rtdlight && r_shadow_realtime_dlight_shadows.integer && gl_stencil;
3020 r_refdef.lightmapintensity = r_refdef.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
3021 if (r_showsurfaces.integer)
3023 r_refdef.rtworld = false;
3024 r_refdef.rtworldshadows = false;
3025 r_refdef.rtdlight = false;
3026 r_refdef.rtdlightshadows = false;
3027 r_refdef.lightmapintensity = 0;
3030 if (gamemode == GAME_NEHAHRA)
3032 if (gl_fogenable.integer)
3034 r_refdef.oldgl_fogenable = true;
3035 r_refdef.fog_density = gl_fogdensity.value;
3036 r_refdef.fog_red = gl_fogred.value;
3037 r_refdef.fog_green = gl_foggreen.value;
3038 r_refdef.fog_blue = gl_fogblue.value;
3040 else if (r_refdef.oldgl_fogenable)
3042 r_refdef.oldgl_fogenable = false;
3043 r_refdef.fog_density = 0;
3044 r_refdef.fog_red = 0;
3045 r_refdef.fog_green = 0;
3046 r_refdef.fog_blue = 0;
3049 if (r_refdef.fog_density)
3051 r_refdef.fogcolor[0] = bound(0.0f, r_refdef.fog_red , 1.0f);
3052 r_refdef.fogcolor[1] = bound(0.0f, r_refdef.fog_green, 1.0f);
3053 r_refdef.fogcolor[2] = bound(0.0f, r_refdef.fog_blue , 1.0f);
3055 if (r_refdef.fog_density)
3057 r_refdef.fogenabled = true;
3058 // this is the point where the fog reaches 0.9986 alpha, which we
3059 // consider a good enough cutoff point for the texture
3060 // (0.9986 * 256 == 255.6)
3061 r_refdef.fogrange = 400 / r_refdef.fog_density;
3062 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
3063 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
3064 // fog color was already set
3067 r_refdef.fogenabled = false;
3075 void R_RenderView(void)
3077 if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
3078 return; //Host_Error ("R_RenderView: NULL worldmodel");
3080 R_Shadow_UpdateWorldLightSelection();
3082 R_Bloom_StartFrame();
3083 R_Water_StartFrame();
3086 if (r_timereport_active)
3087 R_TimeReport("setup");
3089 R_ResetViewRendering3D();
3092 if (r_timereport_active)
3093 R_TimeReport("clear");
3095 r_view.showdebug = true;
3097 // this produces a bloom texture to be used in R_BlendView() later
3099 R_HDR_RenderBloomTexture();
3101 r_view.colorscale = r_hdr_scenebrightness.value;
3102 r_waterstate.numwaterplanes = 0;
3103 R_RenderScene(r_waterstate.enabled);
3106 if (r_timereport_active)
3107 R_TimeReport("blendview");
3109 GL_Scissor(0, 0, vid.width, vid.height);
3110 GL_ScissorTest(false);
3114 extern void R_DrawLightningBeams (void);
3115 extern void VM_CL_AddPolygonsToMeshQueue (void);
3116 extern void R_DrawPortals (void);
3117 extern cvar_t cl_locs_show;
3118 static void R_DrawLocs(void);
3119 static void R_DrawEntityBBoxes(void);
3120 void R_RenderScene(qboolean addwaterplanes)
3124 R_ResetViewRendering3D();
3127 if (r_timereport_active)
3128 R_TimeReport("watervisibility");
3130 if (cl.csqc_vidvars.drawworld && r_refdef.worldmodel && r_refdef.worldmodel->DrawAddWaterPlanes)
3132 r_refdef.worldmodel->DrawAddWaterPlanes(r_refdef.worldentity);
3133 if (r_timereport_active)
3134 R_TimeReport("waterworld");
3137 // don't let sound skip if going slow
3138 if (r_refdef.extraupdate)
3141 R_DrawModelsAddWaterPlanes();
3142 if (r_timereport_active)
3143 R_TimeReport("watermodels");
3145 R_Water_ProcessPlanes();
3146 if (r_timereport_active)
3147 R_TimeReport("waterscenes");
3150 R_ResetViewRendering3D();
3152 // don't let sound skip if going slow
3153 if (r_refdef.extraupdate)
3156 R_MeshQueue_BeginScene();
3161 if (r_timereport_active)
3162 R_TimeReport("visibility");
3164 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);
3166 if (cl.csqc_vidvars.drawworld)
3168 // don't let sound skip if going slow
3169 if (r_refdef.extraupdate)
3172 if (r_refdef.worldmodel && r_refdef.worldmodel->DrawSky)
3174 r_refdef.worldmodel->DrawSky(r_refdef.worldentity);
3175 if (r_timereport_active)
3176 R_TimeReport("worldsky");
3179 if (R_DrawBrushModelsSky() && r_timereport_active)
3180 R_TimeReport("bmodelsky");
3183 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.worldmodel && r_refdef.worldmodel->DrawDepth)
3185 r_refdef.worldmodel->DrawDepth(r_refdef.worldentity);
3186 if (r_timereport_active)
3187 R_TimeReport("worlddepth");
3189 if (r_depthfirst.integer >= 2)
3191 R_DrawModelsDepth();
3192 if (r_timereport_active)
3193 R_TimeReport("modeldepth");
3196 if (cl.csqc_vidvars.drawworld && r_refdef.worldmodel && r_refdef.worldmodel->Draw)
3198 r_refdef.worldmodel->Draw(r_refdef.worldentity);
3199 if (r_timereport_active)
3200 R_TimeReport("world");
3203 // don't let sound skip if going slow
3204 if (r_refdef.extraupdate)
3208 if (r_timereport_active)
3209 R_TimeReport("models");
3211 // don't let sound skip if going slow
3212 if (r_refdef.extraupdate)
3215 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
3217 R_DrawModelShadows();
3219 R_ResetViewRendering3D();
3221 // don't let sound skip if going slow
3222 if (r_refdef.extraupdate)
3226 R_ShadowVolumeLighting(false);
3227 if (r_timereport_active)
3228 R_TimeReport("rtlights");
3230 // don't let sound skip if going slow
3231 if (r_refdef.extraupdate)
3234 if (cl.csqc_vidvars.drawworld)
3236 R_DrawLightningBeams();
3237 if (r_timereport_active)
3238 R_TimeReport("lightning");
3241 if (r_timereport_active)
3242 R_TimeReport("particles");
3245 if (r_timereport_active)
3246 R_TimeReport("explosions");
3249 if (gl_support_fragment_shader)
3251 qglUseProgramObjectARB(0);CHECKGLERROR
3253 VM_CL_AddPolygonsToMeshQueue();
3255 if (r_view.showdebug)
3257 if (cl_locs_show.integer)
3260 if (r_timereport_active)
3261 R_TimeReport("showlocs");
3264 if (r_drawportals.integer)
3267 if (r_timereport_active)
3268 R_TimeReport("portals");
3271 if (r_showbboxes.value > 0)
3273 R_DrawEntityBBoxes();
3274 if (r_timereport_active)
3275 R_TimeReport("bboxes");
3279 if (gl_support_fragment_shader)
3281 qglUseProgramObjectARB(0);CHECKGLERROR
3283 R_MeshQueue_RenderTransparent();
3284 if (r_timereport_active)
3285 R_TimeReport("drawtrans");
3287 if (gl_support_fragment_shader)
3289 qglUseProgramObjectARB(0);CHECKGLERROR
3292 if (cl.csqc_vidvars.drawworld)
3295 if (r_timereport_active)
3296 R_TimeReport("coronas");
3299 // don't let sound skip if going slow
3300 if (r_refdef.extraupdate)
3303 R_ResetViewRendering2D();
3306 static const int bboxelements[36] =
3316 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
3319 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
3320 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3321 GL_DepthMask(false);
3322 GL_DepthRange(0, 1);
3323 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3324 R_Mesh_Matrix(&identitymatrix);
3325 R_Mesh_ResetTextureState();
3327 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
3328 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
3329 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
3330 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
3331 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
3332 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
3333 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
3334 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
3335 R_FillColors(color4f, 8, cr, cg, cb, ca);
3336 if (r_refdef.fogenabled)
3338 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
3340 f1 = FogPoint_World(v);
3342 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
3343 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
3344 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
3347 R_Mesh_VertexPointer(vertex3f, 0, 0);
3348 R_Mesh_ColorPointer(color4f, 0, 0);
3349 R_Mesh_ResetTextureState();
3350 R_Mesh_Draw(0, 8, 12, bboxelements, 0, 0);
3353 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
3357 prvm_edict_t *edict;
3358 // this function draws bounding boxes of server entities
3362 for (i = 0;i < numsurfaces;i++)
3364 edict = PRVM_EDICT_NUM(surfacelist[i]);
3365 switch ((int)edict->fields.server->solid)
3367 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
3368 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
3369 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
3370 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
3371 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
3372 default: Vector4Set(color, 0, 0, 0, 0.50);break;
3374 color[3] *= r_showbboxes.value;
3375 color[3] = bound(0, color[3], 1);
3376 GL_DepthTest(!r_showdisabledepthtest.integer);
3377 GL_CullFace(r_view.cullface_front);
3378 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
3383 static void R_DrawEntityBBoxes(void)
3386 prvm_edict_t *edict;
3388 // this function draws bounding boxes of server entities
3392 for (i = 0;i < prog->num_edicts;i++)
3394 edict = PRVM_EDICT_NUM(i);
3395 if (edict->priv.server->free)
3397 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
3398 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
3403 int nomodelelements[24] =
3415 float nomodelvertex3f[6*3] =
3425 float nomodelcolor4f[6*4] =
3427 0.0f, 0.0f, 0.5f, 1.0f,
3428 0.0f, 0.0f, 0.5f, 1.0f,
3429 0.0f, 0.5f, 0.0f, 1.0f,
3430 0.0f, 0.5f, 0.0f, 1.0f,
3431 0.5f, 0.0f, 0.0f, 1.0f,
3432 0.5f, 0.0f, 0.0f, 1.0f
3435 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
3440 // this is only called once per entity so numsurfaces is always 1, and
3441 // surfacelist is always {0}, so this code does not handle batches
3442 R_Mesh_Matrix(&ent->matrix);
3444 if (ent->flags & EF_ADDITIVE)
3446 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
3447 GL_DepthMask(false);
3449 else if (ent->alpha < 1)
3451 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3452 GL_DepthMask(false);
3456 GL_BlendFunc(GL_ONE, GL_ZERO);
3459 GL_DepthRange(0, (ent->flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
3460 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3461 GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
3462 GL_CullFace((ent->effects & EF_DOUBLESIDED) ? GL_NONE : r_view.cullface_back);
3463 R_Mesh_VertexPointer(nomodelvertex3f, 0, 0);
3464 if (r_refdef.fogenabled)
3467 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
3468 R_Mesh_ColorPointer(color4f, 0, 0);
3469 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
3470 f1 = FogPoint_World(org);
3472 for (i = 0, c = color4f;i < 6;i++, c += 4)
3474 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
3475 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
3476 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
3480 else if (ent->alpha != 1)
3482 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
3483 R_Mesh_ColorPointer(color4f, 0, 0);
3484 for (i = 0, c = color4f;i < 6;i++, c += 4)
3488 R_Mesh_ColorPointer(nomodelcolor4f, 0, 0);
3489 R_Mesh_ResetTextureState();
3490 R_Mesh_Draw(0, 6, 8, nomodelelements, 0, 0);
3493 void R_DrawNoModel(entity_render_t *ent)
3496 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
3497 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
3498 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
3500 // R_DrawNoModelCallback(ent, 0);
3503 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
3505 vec3_t right1, right2, diff, normal;
3507 VectorSubtract (org2, org1, normal);
3509 // calculate 'right' vector for start
3510 VectorSubtract (r_view.origin, org1, diff);
3511 CrossProduct (normal, diff, right1);
3512 VectorNormalize (right1);
3514 // calculate 'right' vector for end
3515 VectorSubtract (r_view.origin, org2, diff);
3516 CrossProduct (normal, diff, right2);
3517 VectorNormalize (right2);
3519 vert[ 0] = org1[0] + width * right1[0];
3520 vert[ 1] = org1[1] + width * right1[1];
3521 vert[ 2] = org1[2] + width * right1[2];
3522 vert[ 3] = org1[0] - width * right1[0];
3523 vert[ 4] = org1[1] - width * right1[1];
3524 vert[ 5] = org1[2] - width * right1[2];
3525 vert[ 6] = org2[0] - width * right2[0];
3526 vert[ 7] = org2[1] - width * right2[1];
3527 vert[ 8] = org2[2] - width * right2[2];
3528 vert[ 9] = org2[0] + width * right2[0];
3529 vert[10] = org2[1] + width * right2[1];
3530 vert[11] = org2[2] + width * right2[2];
3533 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
3535 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)
3540 if (r_refdef.fogenabled)
3541 fog = FogPoint_World(origin);
3543 R_Mesh_Matrix(&identitymatrix);
3544 GL_BlendFunc(blendfunc1, blendfunc2);
3550 GL_CullFace(r_view.cullface_front);
3553 GL_CullFace(r_view.cullface_back);
3555 GL_DepthMask(false);
3556 GL_DepthRange(0, depthshort ? 0.0625 : 1);
3557 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3558 GL_DepthTest(!depthdisable);
3560 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
3561 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
3562 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
3563 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
3564 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
3565 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
3566 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
3567 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
3568 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
3569 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
3570 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
3571 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
3573 R_Mesh_VertexPointer(vertex3f, 0, 0);
3574 R_Mesh_ColorPointer(NULL, 0, 0);
3575 R_Mesh_ResetTextureState();
3576 R_Mesh_TexBind(0, R_GetTexture(texture));
3577 R_Mesh_TexCoordPointer(0, 2, spritetexcoord2f, 0, 0);
3578 // FIXME: fixed function path can't properly handle r_view.colorscale > 1
3579 GL_Color(cr * fog * r_view.colorscale, cg * fog * r_view.colorscale, cb * fog * r_view.colorscale, ca);
3580 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3582 if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
3584 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
3585 GL_BlendFunc(blendfunc1, GL_ONE);
3587 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);
3588 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3592 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
3597 VectorSet(v, x, y, z);
3598 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
3599 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
3601 if (i == mesh->numvertices)
3603 if (mesh->numvertices < mesh->maxvertices)
3605 VectorCopy(v, vertex3f);
3606 mesh->numvertices++;
3608 return mesh->numvertices;
3614 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
3618 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
3619 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
3620 e = mesh->element3i + mesh->numtriangles * 3;
3621 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
3623 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
3624 if (mesh->numtriangles < mesh->maxtriangles)
3629 mesh->numtriangles++;
3631 element[1] = element[2];
3635 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
3639 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
3640 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
3641 e = mesh->element3i + mesh->numtriangles * 3;
3642 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
3644 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
3645 if (mesh->numtriangles < mesh->maxtriangles)
3650 mesh->numtriangles++;
3652 element[1] = element[2];
3656 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
3657 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
3659 int planenum, planenum2;
3662 mplane_t *plane, *plane2;
3664 double temppoints[2][256*3];
3665 // figure out how large a bounding box we need to properly compute this brush
3667 for (w = 0;w < numplanes;w++)
3668 maxdist = max(maxdist, planes[w].dist);
3669 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
3670 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
3671 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
3675 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
3676 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
3678 if (planenum2 == planenum)
3680 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);
3683 if (tempnumpoints < 3)
3685 // generate elements forming a triangle fan for this polygon
3686 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
3690 static void R_DrawCollisionBrush(const colbrushf_t *brush)
3693 R_Mesh_VertexPointer(brush->points->v, 0, 0);
3694 i = (int)(((size_t)brush) / sizeof(colbrushf_t));
3695 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, 0.2f);
3696 GL_LockArrays(0, brush->numpoints);
3697 R_Mesh_Draw(0, brush->numpoints, brush->numtriangles, brush->elements, 0, 0);
3698 GL_LockArrays(0, 0);
3701 static void R_DrawCollisionSurface(const entity_render_t *ent, const msurface_t *surface)
3704 if (!surface->num_collisiontriangles)
3706 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
3707 i = (int)(((size_t)surface) / sizeof(msurface_t));
3708 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, 0.2f);
3709 GL_LockArrays(0, surface->num_collisionvertices);
3710 R_Mesh_Draw(0, surface->num_collisionvertices, surface->num_collisiontriangles, surface->data_collisionelement3i, 0, 0);
3711 GL_LockArrays(0, 0);
3714 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)
3716 texturelayer_t *layer;
3717 layer = t->currentlayers + t->currentnumlayers++;
3719 layer->depthmask = depthmask;
3720 layer->blendfunc1 = blendfunc1;
3721 layer->blendfunc2 = blendfunc2;
3722 layer->texture = texture;
3723 layer->texmatrix = *matrix;
3724 layer->color[0] = r * r_view.colorscale;
3725 layer->color[1] = g * r_view.colorscale;
3726 layer->color[2] = b * r_view.colorscale;
3727 layer->color[3] = a;
3730 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
3733 index = parms[2] + r_refdef.time * parms[3];
3734 index -= floor(index);
3738 case Q3WAVEFUNC_NONE:
3739 case Q3WAVEFUNC_NOISE:
3740 case Q3WAVEFUNC_COUNT:
3743 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
3744 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
3745 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
3746 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
3747 case Q3WAVEFUNC_TRIANGLE:
3749 f = index - floor(index);
3760 return (float)(parms[0] + parms[1] * f);
3763 void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
3766 model_t *model = ent->model;
3769 q3shaderinfo_layer_tcmod_t *tcmod;
3771 // switch to an alternate material if this is a q1bsp animated material
3773 texture_t *texture = t;
3774 int s = ent->skinnum;
3775 if ((unsigned int)s >= (unsigned int)model->numskins)
3777 if (model->skinscenes)
3779 if (model->skinscenes[s].framecount > 1)
3780 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
3782 s = model->skinscenes[s].firstframe;
3785 t = t + s * model->num_surfaces;
3788 // use an alternate animation if the entity's frame is not 0,
3789 // and only if the texture has an alternate animation
3790 if (ent->frame2 != 0 && t->anim_total[1])
3791 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.time * 5.0f) % t->anim_total[1]) : 0];
3793 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.time * 5.0f) % t->anim_total[0]) : 0];
3795 texture->currentframe = t;
3798 // update currentskinframe to be a qw skin or animation frame
3799 if ((i = ent->entitynumber - 1) >= 0 && i < cl.maxclients)
3801 if (strcmp(r_qwskincache[i], cl.scores[i].qw_skin))
3803 strlcpy(r_qwskincache[i], cl.scores[i].qw_skin, sizeof(r_qwskincache[i]));
3804 Con_DPrintf("loading skins/%s\n", r_qwskincache[i]);
3805 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);
3807 t->currentskinframe = r_qwskincache_skinframe[i];
3808 if (t->currentskinframe == NULL)
3809 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->frame2time)) % t->numskinframes];
3811 else if (t->numskinframes >= 2)
3812 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->frame2time)) % t->numskinframes];
3813 if (t->backgroundnumskinframes >= 2)
3814 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - ent->frame2time)) % t->backgroundnumskinframes];
3816 t->currentmaterialflags = t->basematerialflags;
3817 t->currentalpha = ent->alpha;
3818 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
3820 t->currentalpha *= r_wateralpha.value;
3821 // if rendering refraction/reflection, disable transparency
3822 if (r_waterstate.enabled && (t->currentalpha < 1 || (t->currentmaterialflags & MATERIALFLAG_ALPHA)))
3823 t->currentmaterialflags |= MATERIALFLAG_WATERSHADER;
3825 if (!(ent->flags & RENDER_LIGHT))
3826 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
3827 if (ent->effects & EF_ADDITIVE)
3828 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
3829 else if (t->currentalpha < 1)
3830 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
3831 if (ent->effects & EF_DOUBLESIDED)
3832 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
3833 if (ent->effects & EF_NODEPTHTEST)
3834 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
3835 if (ent->flags & RENDER_VIEWMODEL)
3836 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
3837 if (t->backgroundnumskinframes && !(t->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED))
3838 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
3839 if (t->currentmaterialflags & MATERIALFLAG_WATERSHADER)
3840 t->currentmaterialflags &= ~(MATERIALFLAG_ADD | MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_CUSTOMBLEND);
3842 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && (tcmod->tcmod || i < 1);i++, tcmod++)
3845 switch(tcmod->tcmod)
3849 if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
3850 matrix = r_waterscrollmatrix;
3852 matrix = identitymatrix;
3854 case Q3TCMOD_ENTITYTRANSLATE:
3855 // this is used in Q3 to allow the gamecode to control texcoord
3856 // scrolling on the entity, which is not supported in darkplaces yet.
3857 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
3859 case Q3TCMOD_ROTATE:
3860 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
3861 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.time, 0, 0, 1);
3862 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
3865 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
3867 case Q3TCMOD_SCROLL:
3868 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.time, tcmod->parms[1] * r_refdef.time, 0);
3870 case Q3TCMOD_STRETCH:
3871 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
3872 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
3874 case Q3TCMOD_TRANSFORM:
3875 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
3876 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
3877 VectorSet(tcmat + 6, 0 , 0 , 1);
3878 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
3879 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
3881 case Q3TCMOD_TURBULENT:
3882 // this is handled in the RSurf_PrepareVertices function
3883 matrix = identitymatrix;
3886 // either replace or concatenate the transformation
3888 t->currenttexmatrix = matrix;
3891 matrix4x4_t temp = t->currenttexmatrix;
3892 Matrix4x4_Concat(&t->currenttexmatrix, &matrix, &temp);
3896 t->colormapping = VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f);
3897 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
3898 t->glosstexture = r_texture_black;
3899 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
3900 t->backgroundglosstexture = r_texture_black;
3901 t->specularpower = r_shadow_glossexponent.value;
3902 // TODO: store reference values for these in the texture?
3903 t->specularscale = 0;
3904 if (r_shadow_gloss.integer > 0)
3906 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
3908 if (r_shadow_glossintensity.value > 0)
3910 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
3911 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
3912 t->specularscale = r_shadow_glossintensity.value;
3915 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
3917 t->glosstexture = r_texture_white;
3918 t->backgroundglosstexture = r_texture_white;
3919 t->specularscale = r_shadow_gloss2intensity.value;
3923 // lightmaps mode looks bad with dlights using actual texturing, so turn
3924 // off the colormap and glossmap, but leave the normalmap on as it still
3925 // accurately represents the shading involved
3926 if (gl_lightmaps.integer && !(t->currentmaterialflags & MATERIALFLAG_BLENDED))
3928 t->basetexture = r_texture_white;
3929 t->specularscale = 0;
3932 t->currentpolygonfactor = r_refdef.polygonfactor + t->basepolygonfactor;
3933 t->currentpolygonoffset = r_refdef.polygonoffset + t->basepolygonoffset;
3934 // submodels are biased to avoid z-fighting with world surfaces that they
3935 // may be exactly overlapping (avoids z-fighting artifacts on certain
3936 // doors and things in Quake maps)
3937 if (ent->model->brush.submodel)
3939 t->currentpolygonfactor += r_polygonoffset_submodel_factor.value;
3940 t->currentpolygonoffset += r_polygonoffset_submodel_offset.value;
3943 VectorClear(t->dlightcolor);
3944 t->currentnumlayers = 0;
3945 if (!(t->currentmaterialflags & MATERIALFLAG_NODRAW))
3947 if (!(t->currentmaterialflags & MATERIALFLAG_SKY))
3949 int blendfunc1, blendfunc2, depthmask;
3950 if (t->currentmaterialflags & MATERIALFLAG_ADD)
3952 blendfunc1 = GL_SRC_ALPHA;
3953 blendfunc2 = GL_ONE;
3955 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
3957 blendfunc1 = GL_SRC_ALPHA;
3958 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
3960 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
3962 blendfunc1 = t->customblendfunc[0];
3963 blendfunc2 = t->customblendfunc[1];
3967 blendfunc1 = GL_ONE;
3968 blendfunc2 = GL_ZERO;
3970 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
3971 if (t->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL))
3973 rtexture_t *currentbasetexture;
3975 if (r_refdef.fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED))
3976 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
3977 currentbasetexture = (VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) < (1.0f / 1048576.0f) && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
3978 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
3980 // fullbright is not affected by r_refdef.lightmapintensity
3981 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
3982 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
3983 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);
3984 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
3985 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);
3990 // set the color tint used for lights affecting this surface
3991 VectorSet(t->dlightcolor, ent->colormod[0] * t->currentalpha, ent->colormod[1] * t->currentalpha, ent->colormod[2] * t->currentalpha);
3993 // q3bsp has no lightmap updates, so the lightstylevalue that
3994 // would normally be baked into the lightmap must be
3995 // applied to the color
3996 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
3997 if (ent->model->type == mod_brushq3)
3998 colorscale *= r_refdef.lightstylevalue[0] * (1.0f / 256.0f);
3999 colorscale *= r_refdef.lightmapintensity;
4000 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);
4001 if (r_ambient.value >= (1.0f/64.0f))
4002 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);
4003 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
4005 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);
4006 if (r_ambient.value >= (1.0f/64.0f))
4007 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);
4009 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
4011 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);
4012 if (r_ambient.value >= (1.0f/64.0f))
4013 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);
4016 if (t->currentskinframe->glow != NULL)
4017 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);
4018 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
4020 // if this is opaque use alpha blend which will darken the earlier
4023 // if this is an alpha blended material, all the earlier passes
4024 // were darkened by fog already, so we only need to add the fog
4025 // color ontop through the fog mask texture
4027 // if this is an additive blended material, all the earlier passes
4028 // were darkened by fog already, and we should not add fog color
4029 // (because the background was not darkened, there is no fog color
4030 // that was lost behind it).
4031 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);
4038 void R_UpdateAllTextureInfo(entity_render_t *ent)
4042 for (i = 0;i < ent->model->num_texturesperskin;i++)
4043 R_UpdateTextureInfo(ent, ent->model->data_textures + i);
4046 rsurfacestate_t rsurface;
4048 void R_Mesh_ResizeArrays(int newvertices)
4051 if (rsurface.array_size >= newvertices)
4053 if (rsurface.array_modelvertex3f)
4054 Mem_Free(rsurface.array_modelvertex3f);
4055 rsurface.array_size = (newvertices + 1023) & ~1023;
4056 base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
4057 rsurface.array_modelvertex3f = base + rsurface.array_size * 0;
4058 rsurface.array_modelsvector3f = base + rsurface.array_size * 3;
4059 rsurface.array_modeltvector3f = base + rsurface.array_size * 6;
4060 rsurface.array_modelnormal3f = base + rsurface.array_size * 9;
4061 rsurface.array_deformedvertex3f = base + rsurface.array_size * 12;
4062 rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
4063 rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
4064 rsurface.array_deformednormal3f = base + rsurface.array_size * 21;
4065 rsurface.array_texcoord3f = base + rsurface.array_size * 24;
4066 rsurface.array_color4f = base + rsurface.array_size * 27;
4067 rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
4070 void RSurf_CleanUp(void)
4073 if (rsurface.mode == RSURFMODE_GLSL)
4075 qglUseProgramObjectARB(0);CHECKGLERROR
4077 GL_AlphaTest(false);
4078 rsurface.mode = RSURFMODE_NONE;
4079 rsurface.uselightmaptexture = false;
4080 rsurface.texture = NULL;
4083 void RSurf_ActiveWorldEntity(void)
4085 model_t *model = r_refdef.worldmodel;
4087 if (rsurface.array_size < model->surfmesh.num_vertices)
4088 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
4089 rsurface.matrix = identitymatrix;
4090 rsurface.inversematrix = identitymatrix;
4091 R_Mesh_Matrix(&identitymatrix);
4092 VectorCopy(r_view.origin, rsurface.modelorg);
4093 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
4094 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
4095 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
4096 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
4097 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
4098 rsurface.frameblend[0].frame = 0;
4099 rsurface.frameblend[0].lerp = 1;
4100 rsurface.frameblend[1].frame = 0;
4101 rsurface.frameblend[1].lerp = 0;
4102 rsurface.frameblend[2].frame = 0;
4103 rsurface.frameblend[2].lerp = 0;
4104 rsurface.frameblend[3].frame = 0;
4105 rsurface.frameblend[3].lerp = 0;
4106 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
4107 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
4108 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
4109 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
4110 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
4111 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
4112 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
4113 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
4114 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
4115 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
4116 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
4117 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
4118 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
4119 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
4120 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
4121 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
4122 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
4123 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
4124 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
4125 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
4126 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
4127 rsurface.modelelement3i = model->surfmesh.data_element3i;
4128 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo;
4129 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
4130 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
4131 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
4132 rsurface.modelsurfaces = model->data_surfaces;
4133 rsurface.generatedvertex = false;
4134 rsurface.vertex3f = rsurface.modelvertex3f;
4135 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
4136 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
4137 rsurface.svector3f = rsurface.modelsvector3f;
4138 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
4139 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
4140 rsurface.tvector3f = rsurface.modeltvector3f;
4141 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
4142 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
4143 rsurface.normal3f = rsurface.modelnormal3f;
4144 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
4145 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
4146 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
4149 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4151 model_t *model = ent->model;
4153 if (rsurface.array_size < model->surfmesh.num_vertices)
4154 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
4155 rsurface.matrix = ent->matrix;
4156 rsurface.inversematrix = ent->inversematrix;
4157 R_Mesh_Matrix(&rsurface.matrix);
4158 Matrix4x4_Transform(&rsurface.inversematrix, r_view.origin, rsurface.modelorg);
4159 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
4160 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
4161 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
4162 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
4163 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
4164 rsurface.frameblend[0] = ent->frameblend[0];
4165 rsurface.frameblend[1] = ent->frameblend[1];
4166 rsurface.frameblend[2] = ent->frameblend[2];
4167 rsurface.frameblend[3] = ent->frameblend[3];
4168 if (model->surfmesh.isanimated && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].frame != 0))
4172 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
4173 rsurface.modelsvector3f = rsurface.array_modelsvector3f;
4174 rsurface.modeltvector3f = rsurface.array_modeltvector3f;
4175 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
4176 Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
4178 else if (wantnormals)
4180 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
4181 rsurface.modelsvector3f = NULL;
4182 rsurface.modeltvector3f = NULL;
4183 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
4184 Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
4188 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
4189 rsurface.modelsvector3f = NULL;
4190 rsurface.modeltvector3f = NULL;
4191 rsurface.modelnormal3f = NULL;
4192 Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, NULL, NULL, NULL);
4194 rsurface.modelvertex3f_bufferobject = 0;
4195 rsurface.modelvertex3f_bufferoffset = 0;
4196 rsurface.modelsvector3f_bufferobject = 0;
4197 rsurface.modelsvector3f_bufferoffset = 0;
4198 rsurface.modeltvector3f_bufferobject = 0;
4199 rsurface.modeltvector3f_bufferoffset = 0;
4200 rsurface.modelnormal3f_bufferobject = 0;
4201 rsurface.modelnormal3f_bufferoffset = 0;
4202 rsurface.generatedvertex = true;
4206 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
4207 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
4208 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
4209 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
4210 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
4211 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
4212 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
4213 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
4214 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
4215 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
4216 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
4217 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
4218 rsurface.generatedvertex = false;
4220 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
4221 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
4222 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
4223 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
4224 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
4225 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
4226 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
4227 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
4228 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
4229 rsurface.modelelement3i = model->surfmesh.data_element3i;
4230 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo;
4231 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
4232 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
4233 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
4234 rsurface.modelsurfaces = model->data_surfaces;
4235 rsurface.vertex3f = rsurface.modelvertex3f;
4236 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
4237 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
4238 rsurface.svector3f = rsurface.modelsvector3f;
4239 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
4240 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
4241 rsurface.tvector3f = rsurface.modeltvector3f;
4242 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
4243 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
4244 rsurface.normal3f = rsurface.modelnormal3f;
4245 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
4246 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
4247 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
4250 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
4251 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, msurface_t **texturesurfacelist)
4254 int texturesurfaceindex;
4259 const float *v1, *in_tc;
4261 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
4263 q3shaderinfo_deform_t *deform;
4264 // 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
4265 if (rsurface.generatedvertex)
4267 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
4268 generatenormals = true;
4269 for (i = 0;i < Q3MAXDEFORMS;i++)
4271 if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
4273 generatetangents = true;
4274 generatenormals = true;
4276 if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
4277 generatenormals = true;
4279 if (generatenormals && !rsurface.modelnormal3f)
4281 rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
4282 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
4283 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
4284 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer);
4286 if (generatetangents && !rsurface.modelsvector3f)
4288 rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
4289 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
4290 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
4291 rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
4292 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
4293 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
4294 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);
4297 rsurface.vertex3f = rsurface.modelvertex3f;
4298 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
4299 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
4300 rsurface.svector3f = rsurface.modelsvector3f;
4301 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
4302 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
4303 rsurface.tvector3f = rsurface.modeltvector3f;
4304 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
4305 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
4306 rsurface.normal3f = rsurface.modelnormal3f;
4307 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
4308 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
4309 // if vertices are deformed (sprite flares and things in maps, possibly
4310 // water waves, bulges and other deformations), generate them into
4311 // rsurface.deform* arrays from whatever the rsurface.* arrays point to
4312 // (may be static model data or generated data for an animated model, or
4313 // the previous deform pass)
4314 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
4316 switch (deform->deform)
4319 case Q3DEFORM_PROJECTIONSHADOW:
4320 case Q3DEFORM_TEXT0:
4321 case Q3DEFORM_TEXT1:
4322 case Q3DEFORM_TEXT2:
4323 case Q3DEFORM_TEXT3:
4324 case Q3DEFORM_TEXT4:
4325 case Q3DEFORM_TEXT5:
4326 case Q3DEFORM_TEXT6:
4327 case Q3DEFORM_TEXT7:
4330 case Q3DEFORM_AUTOSPRITE:
4331 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.forward, newforward);
4332 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.right, newright);
4333 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.up, newup);
4334 VectorNormalize(newforward);
4335 VectorNormalize(newright);
4336 VectorNormalize(newup);
4337 // make deformed versions of only the model vertices used by the specified surfaces
4338 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4340 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4341 // a single autosprite surface can contain multiple sprites...
4342 for (j = 0;j < surface->num_vertices - 3;j += 4)
4344 VectorClear(center);
4345 for (i = 0;i < 4;i++)
4346 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
4347 VectorScale(center, 0.25f, center);
4348 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, forward);
4349 VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
4350 VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
4351 for (i = 0;i < 4;i++)
4353 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
4354 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
4357 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);
4358 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);
4360 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4361 rsurface.vertex3f_bufferobject = 0;
4362 rsurface.vertex3f_bufferoffset = 0;
4363 rsurface.svector3f = rsurface.array_deformedsvector3f;
4364 rsurface.svector3f_bufferobject = 0;
4365 rsurface.svector3f_bufferoffset = 0;
4366 rsurface.tvector3f = rsurface.array_deformedtvector3f;
4367 rsurface.tvector3f_bufferobject = 0;
4368 rsurface.tvector3f_bufferoffset = 0;
4369 rsurface.normal3f = rsurface.array_deformednormal3f;
4370 rsurface.normal3f_bufferobject = 0;
4371 rsurface.normal3f_bufferoffset = 0;
4373 case Q3DEFORM_AUTOSPRITE2:
4374 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.forward, newforward);
4375 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.right, newright);
4376 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.up, newup);
4377 VectorNormalize(newforward);
4378 VectorNormalize(newright);
4379 VectorNormalize(newup);
4380 // make deformed versions of only the model vertices used by the specified surfaces
4381 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4383 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4384 const float *v1, *v2;
4394 memset(shortest, 0, sizeof(shortest));
4395 // a single autosprite surface can contain multiple sprites...
4396 for (j = 0;j < surface->num_vertices - 3;j += 4)
4398 VectorClear(center);
4399 for (i = 0;i < 4;i++)
4400 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
4401 VectorScale(center, 0.25f, center);
4402 // find the two shortest edges, then use them to define the
4403 // axis vectors for rotating around the central axis
4404 for (i = 0;i < 6;i++)
4406 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
4407 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
4409 Debug_PolygonBegin(NULL, 0, false, 0);
4410 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
4411 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);
4412 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
4415 l = VectorDistance2(v1, v2);
4416 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
4418 l += (1.0f / 1024.0f);
4419 if (shortest[0].length2 > l || i == 0)
4421 shortest[1] = shortest[0];
4422 shortest[0].length2 = l;
4423 shortest[0].v1 = v1;
4424 shortest[0].v2 = v2;
4426 else if (shortest[1].length2 > l || i == 1)
4428 shortest[1].length2 = l;
4429 shortest[1].v1 = v1;
4430 shortest[1].v2 = v2;
4433 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
4434 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
4436 Debug_PolygonBegin(NULL, 0, false, 0);
4437 Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
4438 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);
4439 Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
4442 // this calculates the right vector from the shortest edge
4443 // and the up vector from the edge midpoints
4444 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
4445 VectorNormalize(right);
4446 VectorSubtract(end, start, up);
4447 VectorNormalize(up);
4448 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
4449 //VectorSubtract(rsurface.modelorg, center, forward);
4450 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.forward, forward);
4451 VectorNegate(forward, forward);
4452 VectorReflect(forward, 0, up, forward);
4453 VectorNormalize(forward);
4454 CrossProduct(up, forward, newright);
4455 VectorNormalize(newright);
4457 Debug_PolygonBegin(NULL, 0, false, 0);
4458 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);
4459 Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
4460 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
4464 Debug_PolygonBegin(NULL, 0, false, 0);
4465 Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
4466 Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
4467 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
4470 // rotate the quad around the up axis vector, this is made
4471 // especially easy by the fact we know the quad is flat,
4472 // so we only have to subtract the center position and
4473 // measure distance along the right vector, and then
4474 // multiply that by the newright vector and add back the
4476 // we also need to subtract the old position to undo the
4477 // displacement from the center, which we do with a
4478 // DotProduct, the subtraction/addition of center is also
4479 // optimized into DotProducts here
4480 l = DotProduct(right, center);
4481 for (i = 0;i < 4;i++)
4483 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
4484 f = DotProduct(right, v1) - l;
4485 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
4488 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);
4489 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);
4491 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4492 rsurface.vertex3f_bufferobject = 0;
4493 rsurface.vertex3f_bufferoffset = 0;
4494 rsurface.svector3f = rsurface.array_deformedsvector3f;
4495 rsurface.svector3f_bufferobject = 0;
4496 rsurface.svector3f_bufferoffset = 0;
4497 rsurface.tvector3f = rsurface.array_deformedtvector3f;
4498 rsurface.tvector3f_bufferobject = 0;
4499 rsurface.tvector3f_bufferoffset = 0;
4500 rsurface.normal3f = rsurface.array_deformednormal3f;
4501 rsurface.normal3f_bufferobject = 0;
4502 rsurface.normal3f_bufferoffset = 0;
4504 case Q3DEFORM_NORMAL:
4505 // deform the normals to make reflections wavey
4506 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4508 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4509 for (j = 0;j < surface->num_vertices;j++)
4512 float *normal = (rsurface.array_deformednormal3f + 3 * surface->num_firstvertex) + j*3;
4513 VectorScale((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
4514 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, normal);
4515 normal[0] += deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.time * deform->parms[1]);
4516 normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.time * deform->parms[1]);
4517 normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.time * deform->parms[1]);
4518 VectorNormalize(normal);
4520 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);
4522 rsurface.svector3f = rsurface.array_deformedsvector3f;
4523 rsurface.svector3f_bufferobject = 0;
4524 rsurface.svector3f_bufferoffset = 0;
4525 rsurface.tvector3f = rsurface.array_deformedtvector3f;
4526 rsurface.tvector3f_bufferobject = 0;
4527 rsurface.tvector3f_bufferoffset = 0;
4528 rsurface.normal3f = rsurface.array_deformednormal3f;
4529 rsurface.normal3f_bufferobject = 0;
4530 rsurface.normal3f_bufferoffset = 0;
4533 // deform vertex array to make wavey water and flags and such
4534 waveparms[0] = deform->waveparms[0];
4535 waveparms[1] = deform->waveparms[1];
4536 waveparms[2] = deform->waveparms[2];
4537 waveparms[3] = deform->waveparms[3];
4538 // this is how a divisor of vertex influence on deformation
4539 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
4540 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
4541 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4543 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4544 for (j = 0;j < surface->num_vertices;j++)
4546 float *vertex = (rsurface.array_deformedvertex3f + 3 * surface->num_firstvertex) + j*3;
4547 VectorCopy((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, vertex);
4548 // if the wavefunc depends on time, evaluate it per-vertex
4551 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
4552 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
4554 VectorMA(vertex, scale, (rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, vertex);
4557 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4558 rsurface.vertex3f_bufferobject = 0;
4559 rsurface.vertex3f_bufferoffset = 0;
4561 case Q3DEFORM_BULGE:
4562 // deform vertex array to make the surface have moving bulges
4563 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4565 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4566 for (j = 0;j < surface->num_vertices;j++)
4568 scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.time * deform->parms[2])) * deform->parms[1];
4569 VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
4572 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4573 rsurface.vertex3f_bufferobject = 0;
4574 rsurface.vertex3f_bufferoffset = 0;
4577 // deform vertex array
4578 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
4579 VectorScale(deform->parms, scale, waveparms);
4580 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4582 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4583 for (j = 0;j < surface->num_vertices;j++)
4584 VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
4586 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4587 rsurface.vertex3f_bufferobject = 0;
4588 rsurface.vertex3f_bufferoffset = 0;
4592 // generate texcoords based on the chosen texcoord source
4593 switch(rsurface.texture->tcgen.tcgen)
4596 case Q3TCGEN_TEXTURE:
4597 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
4598 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordtexture2f_bufferobject;
4599 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
4601 case Q3TCGEN_LIGHTMAP:
4602 rsurface.texcoordtexture2f = rsurface.modeltexcoordlightmap2f;
4603 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
4604 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
4606 case Q3TCGEN_VECTOR:
4607 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4609 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4610 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)
4612 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
4613 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
4616 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
4617 rsurface.texcoordtexture2f_bufferobject = 0;
4618 rsurface.texcoordtexture2f_bufferoffset = 0;
4620 case Q3TCGEN_ENVIRONMENT:
4621 // make environment reflections using a spheremap
4622 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4624 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4625 const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
4626 const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
4627 float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
4628 for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
4630 float l, d, eyedir[3];
4631 VectorSubtract(rsurface.modelorg, vertex, eyedir);
4632 l = 0.5f / VectorLength(eyedir);
4633 d = DotProduct(normal, eyedir)*2;
4634 out_tc[0] = 0.5f + (normal[1]*d - eyedir[1])*l;
4635 out_tc[1] = 0.5f - (normal[2]*d - eyedir[2])*l;
4638 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
4639 rsurface.texcoordtexture2f_bufferobject = 0;
4640 rsurface.texcoordtexture2f_bufferoffset = 0;
4643 // the only tcmod that needs software vertex processing is turbulent, so
4644 // check for it here and apply the changes if needed
4645 // and we only support that as the first one
4646 // (handling a mixture of turbulent and other tcmods would be problematic
4647 // without punting it entirely to a software path)
4648 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
4650 amplitude = rsurface.texture->tcmods[0].parms[1];
4651 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.time * rsurface.texture->tcmods[0].parms[3];
4652 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4654 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4655 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)
4657 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
4658 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
4661 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
4662 rsurface.texcoordtexture2f_bufferobject = 0;
4663 rsurface.texcoordtexture2f_bufferoffset = 0;
4665 rsurface.texcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
4666 rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
4667 rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
4668 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
4671 void RSurf_DrawBatch_Simple(int texturenumsurfaces, msurface_t **texturesurfacelist)
4674 const msurface_t *surface = texturesurfacelist[0];
4675 const msurface_t *surface2;
4680 // TODO: lock all array ranges before render, rather than on each surface
4681 if (texturenumsurfaces == 1)
4683 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
4684 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));
4686 else if (r_batchmode.integer == 2)
4688 #define MAXBATCHTRIANGLES 4096
4689 int batchtriangles = 0;
4690 int batchelements[MAXBATCHTRIANGLES*3];
4691 for (i = 0;i < texturenumsurfaces;i = j)
4693 surface = texturesurfacelist[i];
4695 if (surface->num_triangles > MAXBATCHTRIANGLES)
4697 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));
4700 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
4701 batchtriangles = surface->num_triangles;
4702 firstvertex = surface->num_firstvertex;
4703 endvertex = surface->num_firstvertex + surface->num_vertices;
4704 for (;j < texturenumsurfaces;j++)
4706 surface2 = texturesurfacelist[j];
4707 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
4709 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
4710 batchtriangles += surface2->num_triangles;
4711 firstvertex = min(firstvertex, surface2->num_firstvertex);
4712 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
4714 surface2 = texturesurfacelist[j-1];
4715 numvertices = endvertex - firstvertex;
4716 R_Mesh_Draw(firstvertex, numvertices, batchtriangles, batchelements, 0, 0);
4719 else if (r_batchmode.integer == 1)
4721 for (i = 0;i < texturenumsurfaces;i = j)
4723 surface = texturesurfacelist[i];
4724 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
4725 if (texturesurfacelist[j] != surface2)
4727 surface2 = texturesurfacelist[j-1];
4728 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
4729 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
4730 GL_LockArrays(surface->num_firstvertex, numvertices);
4731 R_Mesh_Draw(surface->num_firstvertex, numvertices, numtriangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
4736 for (i = 0;i < texturenumsurfaces;i++)
4738 surface = texturesurfacelist[i];
4739 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
4740 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));
4745 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit, int refractiontexunit, int reflectiontexunit)
4747 int i, planeindex, vertexindex;
4751 r_waterstate_waterplane_t *p, *bestp;
4752 msurface_t *surface;
4753 if (r_waterstate.renderingscene)
4755 for (i = 0;i < texturenumsurfaces;i++)
4757 surface = texturesurfacelist[i];
4758 if (lightmaptexunit >= 0)
4759 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
4760 if (deluxemaptexunit >= 0)
4761 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
4762 // pick the closest matching water plane
4765 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
4768 for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
4770 Matrix4x4_Transform(&rsurface.matrix, v, vert);
4771 d += fabs(PlaneDiff(vert, &p->plane));
4773 if (bestd > d || !bestp)
4781 if (refractiontexunit >= 0)
4782 R_Mesh_TexBind(refractiontexunit, R_GetTexture(bestp->texture_refraction));
4783 if (reflectiontexunit >= 0)
4784 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(bestp->texture_reflection));
4788 if (refractiontexunit >= 0)
4789 R_Mesh_TexBind(refractiontexunit, R_GetTexture(r_texture_black));
4790 if (reflectiontexunit >= 0)
4791 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(r_texture_black));
4793 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
4794 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));
4798 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit)
4802 const msurface_t *surface = texturesurfacelist[0];
4803 const msurface_t *surface2;
4808 // TODO: lock all array ranges before render, rather than on each surface
4809 if (texturenumsurfaces == 1)
4811 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
4812 if (deluxemaptexunit >= 0)
4813 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
4814 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
4815 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));
4817 else if (r_batchmode.integer == 2)
4819 #define MAXBATCHTRIANGLES 4096
4820 int batchtriangles = 0;
4821 int batchelements[MAXBATCHTRIANGLES*3];
4822 for (i = 0;i < texturenumsurfaces;i = j)
4824 surface = texturesurfacelist[i];
4825 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
4826 if (deluxemaptexunit >= 0)
4827 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
4829 if (surface->num_triangles > MAXBATCHTRIANGLES)
4831 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));
4834 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
4835 batchtriangles = surface->num_triangles;
4836 firstvertex = surface->num_firstvertex;
4837 endvertex = surface->num_firstvertex + surface->num_vertices;
4838 for (;j < texturenumsurfaces;j++)
4840 surface2 = texturesurfacelist[j];
4841 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
4843 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
4844 batchtriangles += surface2->num_triangles;
4845 firstvertex = min(firstvertex, surface2->num_firstvertex);
4846 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
4848 surface2 = texturesurfacelist[j-1];
4849 numvertices = endvertex - firstvertex;
4850 R_Mesh_Draw(firstvertex, numvertices, batchtriangles, batchelements, 0, 0);
4853 else if (r_batchmode.integer == 1)
4856 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
4857 for (i = 0;i < texturenumsurfaces;i = j)
4859 surface = texturesurfacelist[i];
4860 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
4861 if (texturesurfacelist[j] != surface2)
4863 Con_Printf(" %i", j - i);
4866 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
4868 for (i = 0;i < texturenumsurfaces;i = j)
4870 surface = texturesurfacelist[i];
4871 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
4872 if (deluxemaptexunit >= 0)
4873 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
4874 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
4875 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
4878 Con_Printf(" %i", j - i);
4880 surface2 = texturesurfacelist[j-1];
4881 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
4882 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
4883 GL_LockArrays(surface->num_firstvertex, numvertices);
4884 R_Mesh_Draw(surface->num_firstvertex, numvertices, numtriangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
4892 for (i = 0;i < texturenumsurfaces;i++)
4894 surface = texturesurfacelist[i];
4895 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
4896 if (deluxemaptexunit >= 0)
4897 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
4898 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
4899 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));
4904 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
4907 int texturesurfaceindex;
4908 if (r_showsurfaces.integer == 2)
4910 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4912 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4913 for (j = 0;j < surface->num_triangles;j++)
4915 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_view.colorscale;
4916 GL_Color(f, f, f, 1);
4917 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)));
4923 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4925 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4926 int k = (int)(((size_t)surface) / sizeof(msurface_t));
4927 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);
4928 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
4929 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));
4934 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, msurface_t **texturesurfacelist)
4936 int texturesurfaceindex;
4940 if (rsurface.lightmapcolor4f)
4942 // generate color arrays for the surfaces in this list
4943 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4945 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4946 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)
4948 f = FogPoint_Model(v);
4958 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4960 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4961 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)
4963 f = FogPoint_Model(v);
4971 rsurface.lightmapcolor4f = rsurface.array_color4f;
4972 rsurface.lightmapcolor4f_bufferobject = 0;
4973 rsurface.lightmapcolor4f_bufferoffset = 0;
4976 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a)
4978 int texturesurfaceindex;
4981 if (!rsurface.lightmapcolor4f)
4983 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4985 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4986 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)
4994 rsurface.lightmapcolor4f = rsurface.array_color4f;
4995 rsurface.lightmapcolor4f_bufferobject = 0;
4996 rsurface.lightmapcolor4f_bufferoffset = 0;
4999 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5002 rsurface.lightmapcolor4f = NULL;
5003 rsurface.lightmapcolor4f_bufferobject = 0;
5004 rsurface.lightmapcolor4f_bufferoffset = 0;
5005 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5006 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5007 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5008 GL_Color(r, g, b, a);
5009 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 0, -1);
5012 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5014 // TODO: optimize applyfog && applycolor case
5015 // just apply fog if necessary, and tint the fog color array if necessary
5016 rsurface.lightmapcolor4f = NULL;
5017 rsurface.lightmapcolor4f_bufferobject = 0;
5018 rsurface.lightmapcolor4f_bufferoffset = 0;
5019 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5020 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5021 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5022 GL_Color(r, g, b, a);
5023 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5026 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5028 int texturesurfaceindex;
5032 if (texturesurfacelist[0]->lightmapinfo && texturesurfacelist[0]->lightmapinfo->stainsamples)
5034 // generate color arrays for the surfaces in this list
5035 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5037 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5038 for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
5040 if (surface->lightmapinfo->samples)
5042 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
5043 float scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
5044 VectorScale(lm, scale, c);
5045 if (surface->lightmapinfo->styles[1] != 255)
5047 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
5049 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
5050 VectorMA(c, scale, lm, c);
5051 if (surface->lightmapinfo->styles[2] != 255)
5054 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
5055 VectorMA(c, scale, lm, c);
5056 if (surface->lightmapinfo->styles[3] != 255)
5059 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
5060 VectorMA(c, scale, lm, c);
5070 rsurface.lightmapcolor4f = rsurface.array_color4f;
5071 rsurface.lightmapcolor4f_bufferobject = 0;
5072 rsurface.lightmapcolor4f_bufferoffset = 0;
5076 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
5077 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
5078 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
5080 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5081 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5082 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5083 GL_Color(r, g, b, a);
5084 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5087 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5089 int texturesurfaceindex;
5093 vec3_t ambientcolor;
5094 vec3_t diffusecolor;
5098 VectorCopy(rsurface.modellight_lightdir, lightdir);
5099 ambientcolor[0] = rsurface.modellight_ambient[0] * r * 0.5f;
5100 ambientcolor[1] = rsurface.modellight_ambient[1] * g * 0.5f;
5101 ambientcolor[2] = rsurface.modellight_ambient[2] * b * 0.5f;
5102 diffusecolor[0] = rsurface.modellight_diffuse[0] * r * 0.5f;
5103 diffusecolor[1] = rsurface.modellight_diffuse[1] * g * 0.5f;
5104 diffusecolor[2] = rsurface.modellight_diffuse[2] * b * 0.5f;
5105 if (VectorLength2(diffusecolor) > 0)
5107 // generate color arrays for the surfaces in this list
5108 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5110 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5111 int numverts = surface->num_vertices;
5112 v = rsurface.vertex3f + 3 * surface->num_firstvertex;
5113 c2 = rsurface.normal3f + 3 * surface->num_firstvertex;
5114 c = rsurface.array_color4f + 4 * surface->num_firstvertex;
5115 // q3-style directional shading
5116 for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
5118 if ((f = DotProduct(c2, lightdir)) > 0)
5119 VectorMA(ambientcolor, f, diffusecolor, c);
5121 VectorCopy(ambientcolor, c);
5130 rsurface.lightmapcolor4f = rsurface.array_color4f;
5131 rsurface.lightmapcolor4f_bufferobject = 0;
5132 rsurface.lightmapcolor4f_bufferoffset = 0;
5136 r = ambientcolor[0];
5137 g = ambientcolor[1];
5138 b = ambientcolor[2];
5139 rsurface.lightmapcolor4f = NULL;
5140 rsurface.lightmapcolor4f_bufferobject = 0;
5141 rsurface.lightmapcolor4f_bufferoffset = 0;
5143 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5144 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5145 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5146 GL_Color(r, g, b, a);
5147 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5150 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
5152 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5153 GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset);
5154 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
5155 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_view.cullface_back);
5156 if (rsurface.mode != RSURFMODE_SHOWSURFACES)
5158 rsurface.mode = RSURFMODE_SHOWSURFACES;
5160 GL_BlendFunc(GL_ONE, GL_ZERO);
5161 R_Mesh_ColorPointer(NULL, 0, 0);
5162 R_Mesh_ResetTextureState();
5164 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
5165 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
5168 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, msurface_t **texturesurfacelist)
5170 // transparent sky would be ridiculous
5171 if ((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED))
5173 if (rsurface.mode != RSURFMODE_SKY)
5175 if (rsurface.mode == RSURFMODE_GLSL)
5177 qglUseProgramObjectARB(0);CHECKGLERROR
5179 rsurface.mode = RSURFMODE_SKY;
5183 skyrendernow = false;
5185 // restore entity matrix
5186 R_Mesh_Matrix(&rsurface.matrix);
5188 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5189 GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset);
5190 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
5191 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_view.cullface_back);
5193 // LordHavoc: HalfLife maps have freaky skypolys so don't use
5194 // skymasking on them, and Quake3 never did sky masking (unlike
5195 // software Quake and software Quake2), so disable the sky masking
5196 // in Quake3 maps as it causes problems with q3map2 sky tricks,
5197 // and skymasking also looks very bad when noclipping outside the
5198 // level, so don't use it then either.
5199 if (r_refdef.worldmodel && r_refdef.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_viewcache.world_novis)
5201 GL_Color(r_refdef.fogcolor[0] * r_view.colorscale, r_refdef.fogcolor[1] * r_view.colorscale, r_refdef.fogcolor[2] * r_view.colorscale, 1);
5202 R_Mesh_ColorPointer(NULL, 0, 0);
5203 R_Mesh_ResetTextureState();
5204 if (skyrendermasked)
5206 // depth-only (masking)
5207 GL_ColorMask(0,0,0,0);
5208 // just to make sure that braindead drivers don't draw
5209 // anything despite that colormask...
5210 GL_BlendFunc(GL_ZERO, GL_ONE);
5215 GL_BlendFunc(GL_ONE, GL_ZERO);
5217 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
5218 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5219 if (skyrendermasked)
5220 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
5224 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, msurface_t **texturesurfacelist)
5226 if (rsurface.mode != RSURFMODE_GLSL)
5228 rsurface.mode = RSURFMODE_GLSL;
5229 R_Mesh_ResetTextureState();
5232 R_SetupSurfaceShader(vec3_origin, rsurface.lightmode == 2, 1, 1, rsurface.texture->specularscale);
5233 if (!r_glsl_permutation)
5236 if (rsurface.lightmode == 2)
5237 RSurf_PrepareVerticesForBatch(true, r_glsl_permutation->loc_Texture_Normal >= 0, texturenumsurfaces, texturesurfacelist);
5239 RSurf_PrepareVerticesForBatch(r_glsl_permutation->loc_Texture_Normal >= 0, r_glsl_permutation->loc_Texture_Normal >= 0, texturenumsurfaces, texturesurfacelist);
5240 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
5241 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
5242 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
5243 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
5244 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
5246 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]);
5247 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
5249 R_Mesh_TexBind(7, R_GetTexture(r_texture_grey128));
5250 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
5251 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
5252 R_Mesh_ColorPointer(NULL, 0, 0);
5254 else if (rsurface.uselightmaptexture)
5256 R_Mesh_TexBind(7, R_GetTexture(texturesurfacelist[0]->lightmaptexture));
5257 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
5258 R_Mesh_TexBind(8, R_GetTexture(texturesurfacelist[0]->deluxemaptexture));
5259 R_Mesh_ColorPointer(NULL, 0, 0);
5263 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
5264 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
5265 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
5266 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
5269 if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
5271 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
5272 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist, 7, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? 8 : -1, 11, 12);
5273 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5274 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist, 7, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? 8 : -1, -1, 12);
5276 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 7, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? 8 : -1);
5280 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
5281 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist, -1, -1, 11, 12);
5282 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5283 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist, -1, -1, -1, 12);
5285 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5287 if (rsurface.texture->backgroundnumskinframes && !(rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED))
5292 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, msurface_t **texturesurfacelist)
5294 // OpenGL 1.3 path - anything not completely ancient
5295 int texturesurfaceindex;
5296 qboolean applycolor;
5300 const texturelayer_t *layer;
5301 if (rsurface.mode != RSURFMODE_MULTIPASS)
5302 rsurface.mode = RSURFMODE_MULTIPASS;
5303 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
5304 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
5307 int layertexrgbscale;
5308 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5310 if (layerindex == 0)
5314 GL_AlphaTest(false);
5315 qglDepthFunc(GL_EQUAL);CHECKGLERROR
5318 GL_DepthMask(layer->depthmask);
5319 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
5320 if ((layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2) && (gl_combine.integer || layer->depthmask))
5322 layertexrgbscale = 4;
5323 VectorScale(layer->color, 0.25f, layercolor);
5325 else if ((layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1) && (gl_combine.integer || layer->depthmask))
5327 layertexrgbscale = 2;
5328 VectorScale(layer->color, 0.5f, layercolor);
5332 layertexrgbscale = 1;
5333 VectorScale(layer->color, 1.0f, layercolor);
5335 layercolor[3] = layer->color[3];
5336 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
5337 R_Mesh_ColorPointer(NULL, 0, 0);
5338 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
5339 switch (layer->type)
5341 case TEXTURELAYERTYPE_LITTEXTURE:
5342 memset(&m, 0, sizeof(m));
5343 m.tex[0] = R_GetTexture(r_texture_white);
5344 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
5345 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
5346 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
5347 m.tex[1] = R_GetTexture(layer->texture);
5348 m.texmatrix[1] = layer->texmatrix;
5349 m.texrgbscale[1] = layertexrgbscale;
5350 m.pointer_texcoord[1] = rsurface.texcoordtexture2f;
5351 m.pointer_texcoord_bufferobject[1] = rsurface.texcoordtexture2f_bufferobject;
5352 m.pointer_texcoord_bufferoffset[1] = rsurface.texcoordtexture2f_bufferoffset;
5353 R_Mesh_TextureState(&m);
5354 if (rsurface.lightmode == 2)
5355 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
5356 else if (rsurface.uselightmaptexture)
5357 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
5359 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
5361 case TEXTURELAYERTYPE_TEXTURE:
5362 memset(&m, 0, sizeof(m));
5363 m.tex[0] = R_GetTexture(layer->texture);
5364 m.texmatrix[0] = layer->texmatrix;
5365 m.texrgbscale[0] = layertexrgbscale;
5366 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5367 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5368 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5369 R_Mesh_TextureState(&m);
5370 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
5372 case TEXTURELAYERTYPE_FOG:
5373 memset(&m, 0, sizeof(m));
5374 m.texrgbscale[0] = layertexrgbscale;
5377 m.tex[0] = R_GetTexture(layer->texture);
5378 m.texmatrix[0] = layer->texmatrix;
5379 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5380 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5381 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5383 R_Mesh_TextureState(&m);
5384 // generate a color array for the fog pass
5385 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
5386 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5390 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5391 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)
5393 f = 1 - FogPoint_Model(v);
5394 c[0] = layercolor[0];
5395 c[1] = layercolor[1];
5396 c[2] = layercolor[2];
5397 c[3] = f * layercolor[3];
5400 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5403 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
5405 GL_LockArrays(0, 0);
5408 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5410 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
5411 GL_AlphaTest(false);
5415 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, msurface_t **texturesurfacelist)
5417 // OpenGL 1.1 - crusty old voodoo path
5418 int texturesurfaceindex;
5422 const texturelayer_t *layer;
5423 if (rsurface.mode != RSURFMODE_MULTIPASS)
5424 rsurface.mode = RSURFMODE_MULTIPASS;
5425 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
5426 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
5428 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5430 if (layerindex == 0)
5434 GL_AlphaTest(false);
5435 qglDepthFunc(GL_EQUAL);CHECKGLERROR
5438 GL_DepthMask(layer->depthmask);
5439 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
5440 R_Mesh_ColorPointer(NULL, 0, 0);
5441 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
5442 switch (layer->type)
5444 case TEXTURELAYERTYPE_LITTEXTURE:
5445 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
5447 // two-pass lit texture with 2x rgbscale
5448 // first the lightmap pass
5449 memset(&m, 0, sizeof(m));
5450 m.tex[0] = R_GetTexture(r_texture_white);
5451 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
5452 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
5453 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
5454 R_Mesh_TextureState(&m);
5455 if (rsurface.lightmode == 2)
5456 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5457 else if (rsurface.uselightmaptexture)
5458 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5460 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5461 GL_LockArrays(0, 0);
5462 // then apply the texture to it
5463 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
5464 memset(&m, 0, sizeof(m));
5465 m.tex[0] = R_GetTexture(layer->texture);
5466 m.texmatrix[0] = layer->texmatrix;
5467 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5468 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5469 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5470 R_Mesh_TextureState(&m);
5471 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);
5475 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
5476 memset(&m, 0, sizeof(m));
5477 m.tex[0] = R_GetTexture(layer->texture);
5478 m.texmatrix[0] = layer->texmatrix;
5479 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5480 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5481 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5482 R_Mesh_TextureState(&m);
5483 if (rsurface.lightmode == 2)
5484 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);
5486 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);
5489 case TEXTURELAYERTYPE_TEXTURE:
5490 // singletexture unlit texture with transparency support
5491 memset(&m, 0, sizeof(m));
5492 m.tex[0] = R_GetTexture(layer->texture);
5493 m.texmatrix[0] = layer->texmatrix;
5494 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5495 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5496 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5497 R_Mesh_TextureState(&m);
5498 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);
5500 case TEXTURELAYERTYPE_FOG:
5501 // singletexture fogging
5502 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
5505 memset(&m, 0, sizeof(m));
5506 m.tex[0] = R_GetTexture(layer->texture);
5507 m.texmatrix[0] = layer->texmatrix;
5508 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5509 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5510 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5511 R_Mesh_TextureState(&m);
5514 R_Mesh_ResetTextureState();
5515 // generate a color array for the fog pass
5516 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5520 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5521 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)
5523 f = 1 - FogPoint_Model(v);
5524 c[0] = layer->color[0];
5525 c[1] = layer->color[1];
5526 c[2] = layer->color[2];
5527 c[3] = f * layer->color[3];
5530 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5533 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
5535 GL_LockArrays(0, 0);
5538 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5540 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
5541 GL_AlphaTest(false);
5545 static void R_DrawTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly)
5547 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW)
5549 rsurface.rtlight = NULL;
5553 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
5555 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
5557 if (rsurface.mode != RSURFMODE_MULTIPASS)
5558 rsurface.mode = RSURFMODE_MULTIPASS;
5559 if (r_depthfirst.integer == 3)
5561 int i = (int)(texturesurfacelist[0] - rsurface.modelsurfaces);
5562 if (!r_view.showdebug)
5563 GL_Color(0, 0, 0, 1);
5565 GL_Color(((i >> 6) & 7) / 7.0f, ((i >> 3) & 7) / 7.0f, (i & 7) / 7.0f,1);
5569 GL_ColorMask(0,0,0,0);
5572 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5573 GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset);
5574 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_view.cullface_back);
5576 GL_BlendFunc(GL_ONE, GL_ZERO);
5578 GL_AlphaTest(false);
5579 R_Mesh_ColorPointer(NULL, 0, 0);
5580 R_Mesh_ResetTextureState();
5581 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
5582 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5583 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
5584 r_refdef.stats.entities_surfaces += texturenumsurfaces;
5586 else if (r_depthfirst.integer == 3)
5588 else if (!r_view.showdebug && (r_showsurfaces.integer || gl_lightmaps.integer))
5590 GL_Color(0, 0, 0, 1);
5591 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5593 else if (r_showsurfaces.integer)
5595 if (rsurface.mode != RSURFMODE_MULTIPASS)
5596 rsurface.mode = RSURFMODE_MULTIPASS;
5597 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5598 GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset);
5600 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_view.cullface_back);
5601 GL_BlendFunc(GL_ONE, GL_ZERO);
5602 GL_DepthMask(writedepth);
5604 GL_AlphaTest(false);
5605 R_Mesh_ColorPointer(NULL, 0, 0);
5606 R_Mesh_ResetTextureState();
5607 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
5608 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
5609 r_refdef.stats.entities_surfaces += texturenumsurfaces;
5611 else if (gl_lightmaps.integer)
5614 if (rsurface.mode != RSURFMODE_MULTIPASS)
5615 rsurface.mode = RSURFMODE_MULTIPASS;
5616 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5618 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_view.cullface_back);
5619 GL_BlendFunc(GL_ONE, GL_ZERO);
5620 GL_DepthMask(writedepth);
5622 GL_AlphaTest(false);
5623 // use lightmode 0 (fullbright or lightmap) or 2 (model lighting)
5624 rsurface.lightmode = ((rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT) || rsurface.modeltexcoordlightmap2f != NULL) ? 0 : 2;
5625 R_Mesh_ColorPointer(NULL, 0, 0);
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 R_Mesh_TextureState(&m);
5632 RSurf_PrepareVerticesForBatch(rsurface.lightmode == 2, false, texturenumsurfaces, texturesurfacelist);
5633 if (rsurface.lightmode == 2)
5634 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5635 else if (rsurface.uselightmaptexture)
5636 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5638 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5639 r_refdef.stats.entities_surfaces += texturenumsurfaces;
5641 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
5643 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
5644 r_refdef.stats.entities_surfaces += texturenumsurfaces;
5646 else if (rsurface.texture->currentnumlayers)
5648 // write depth for anything we skipped on the depth-only pass earlier
5649 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5651 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5652 GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset);
5653 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
5654 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_view.cullface_back);
5655 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5656 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
5657 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5658 // use lightmode 0 (fullbright or lightmap) or 2 (model lighting)
5659 rsurface.lightmode = ((rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT) || rsurface.modeltexcoordlightmap2f != NULL) ? 0 : 2;
5660 if (r_glsl.integer && gl_support_fragment_shader)
5661 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist);
5662 else if (gl_combine.integer && r_textureunits.integer >= 2)
5663 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist);
5665 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist);
5666 r_refdef.stats.entities_surfaces += texturenumsurfaces;
5669 GL_LockArrays(0, 0);
5672 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
5675 int texturenumsurfaces, endsurface;
5677 msurface_t *surface;
5678 msurface_t *texturesurfacelist[1024];
5680 // if the model is static it doesn't matter what value we give for
5681 // wantnormals and wanttangents, so this logic uses only rules applicable
5682 // to a model, knowing that they are meaningless otherwise
5683 if (ent == r_refdef.worldentity)
5684 RSurf_ActiveWorldEntity();
5685 else if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
5686 RSurf_ActiveModelEntity(ent, false, false);
5688 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
5690 for (i = 0;i < numsurfaces;i = j)
5693 surface = rsurface.modelsurfaces + surfacelist[i];
5694 texture = surface->texture;
5695 R_UpdateTextureInfo(ent, texture);
5696 rsurface.texture = texture->currentframe;
5697 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
5698 // scan ahead until we find a different texture
5699 endsurface = min(i + 1024, numsurfaces);
5700 texturenumsurfaces = 0;
5701 texturesurfacelist[texturenumsurfaces++] = surface;
5702 for (;j < endsurface;j++)
5704 surface = rsurface.modelsurfaces + surfacelist[j];
5705 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
5707 texturesurfacelist[texturenumsurfaces++] = surface;
5709 // render the range of surfaces
5710 R_DrawTextureSurfaceList(texturenumsurfaces, texturesurfacelist, true, false);
5716 void R_QueueSurfaceList(entity_render_t *ent, int numsurfaces, msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes)
5719 vec3_t tempcenter, center;
5721 // if we're rendering water textures (extra scene renders), use a separate loop to avoid burdening the main one
5724 for (i = 0;i < numsurfaces;i++)
5725 if (surfacelist[i]->texture->currentframe->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5726 R_Water_AddWaterPlane(surfacelist[i]);
5729 // break the surface list down into batches by texture and use of lightmapping
5730 for (i = 0;i < numsurfaces;i = j)
5733 // texture is the base texture pointer, rsurface.texture is the
5734 // current frame/skin the texture is directing us to use (for example
5735 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
5736 // use skin 1 instead)
5737 texture = surfacelist[i]->texture;
5738 rsurface.texture = texture->currentframe;
5739 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
5740 if (!(rsurface.texture->currentmaterialflags & flagsmask))
5742 // if this texture is not the kind we want, skip ahead to the next one
5743 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
5747 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
5749 // transparent surfaces get pushed off into the transparent queue
5750 const msurface_t *surface = surfacelist[i];
5753 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
5754 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
5755 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
5756 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
5757 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_view.origin : center, R_DrawSurface_TransparentCallback, ent, surface - rsurface.modelsurfaces, rsurface.rtlight);
5761 // simply scan ahead until we find a different texture or lightmap state
5762 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
5764 // render the range of surfaces
5765 R_DrawTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly);
5770 float locboxvertex3f[6*4*3] =
5772 1,0,1, 1,0,0, 1,1,0, 1,1,1,
5773 0,1,1, 0,1,0, 0,0,0, 0,0,1,
5774 1,1,1, 1,1,0, 0,1,0, 0,1,1,
5775 0,0,1, 0,0,0, 1,0,0, 1,0,1,
5776 0,0,1, 1,0,1, 1,1,1, 0,1,1,
5777 1,0,0, 0,0,0, 0,1,0, 1,1,0
5780 int locboxelement3i[6*2*3] =
5790 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
5793 cl_locnode_t *loc = (cl_locnode_t *)ent;
5795 float vertex3f[6*4*3];
5797 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5798 GL_DepthMask(false);
5799 GL_DepthRange(0, 1);
5800 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5802 GL_CullFace(GL_NONE);
5803 R_Mesh_Matrix(&identitymatrix);
5805 R_Mesh_VertexPointer(vertex3f, 0, 0);
5806 R_Mesh_ColorPointer(NULL, 0, 0);
5807 R_Mesh_ResetTextureState();
5810 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_view.colorscale,
5811 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_view.colorscale,
5812 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_view.colorscale,
5813 surfacelist[0] < 0 ? 0.5f : 0.125f);
5815 if (VectorCompare(loc->mins, loc->maxs))
5817 VectorSet(size, 2, 2, 2);
5818 VectorMA(loc->mins, -0.5f, size, mins);
5822 VectorCopy(loc->mins, mins);
5823 VectorSubtract(loc->maxs, loc->mins, size);
5826 for (i = 0;i < 6*4*3;)
5827 for (j = 0;j < 3;j++, i++)
5828 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
5830 R_Mesh_Draw(0, 6*4, 6*2, locboxelement3i, 0, 0);
5833 void R_DrawLocs(void)
5836 cl_locnode_t *loc, *nearestloc;
5838 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
5839 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
5841 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
5842 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
5846 void R_DrawCollisionBrushes(entity_render_t *ent)
5850 msurface_t *surface;
5851 model_t *model = ent->model;
5852 if (!model->brush.num_brushes)
5855 R_Mesh_ColorPointer(NULL, 0, 0);
5856 R_Mesh_ResetTextureState();
5857 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
5858 GL_DepthMask(false);
5859 GL_DepthRange(0, 1);
5860 GL_DepthTest(!r_showdisabledepthtest.integer);
5861 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
5862 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
5863 if (brush->colbrushf && brush->colbrushf->numtriangles)
5864 R_DrawCollisionBrush(brush->colbrushf);
5865 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
5866 if (surface->num_collisiontriangles)
5867 R_DrawCollisionSurface(ent, surface);
5868 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5871 void R_DrawTrianglesAndNormals(entity_render_t *ent, qboolean drawtris, qboolean drawnormals, int flagsmask)
5874 const int *elements;
5875 msurface_t *surface;
5876 model_t *model = ent->model;
5879 GL_DepthRange(0, 1);
5880 GL_DepthTest(!r_showdisabledepthtest.integer);
5881 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5883 GL_BlendFunc(GL_ONE, GL_ZERO);
5884 R_Mesh_ColorPointer(NULL, 0, 0);
5885 R_Mesh_ResetTextureState();
5886 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
5888 if (ent == r_refdef.worldentity && !r_viewcache.world_surfacevisible[j])
5890 rsurface.texture = surface->texture->currentframe;
5891 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
5893 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
5896 if (!rsurface.texture->currentlayers->depthmask)
5897 GL_Color(r_showtris.value * r_view.colorscale, 0, 0, 1);
5898 else if (ent == r_refdef.worldentity)
5899 GL_Color(r_showtris.value * r_view.colorscale, r_showtris.value * r_view.colorscale, r_showtris.value * r_view.colorscale, 1);
5901 GL_Color(0, r_showtris.value * r_view.colorscale, 0, 1);
5902 elements = (ent->model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
5905 for (k = 0;k < surface->num_triangles;k++, elements += 3)
5907 #define GLVERTEXELEMENT(n) qglVertex3f(rsurface.vertex3f[elements[n]*3+0], rsurface.vertex3f[elements[n]*3+1], rsurface.vertex3f[elements[n]*3+2])
5908 GLVERTEXELEMENT(0);GLVERTEXELEMENT(1);
5909 GLVERTEXELEMENT(1);GLVERTEXELEMENT(2);
5910 GLVERTEXELEMENT(2);GLVERTEXELEMENT(0);
5917 GL_Color(r_shownormals.value * r_view.colorscale, 0, 0, 1);
5919 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
5921 VectorCopy(rsurface.vertex3f + l * 3, v);
5922 qglVertex3f(v[0], v[1], v[2]);
5923 VectorMA(v, 8, rsurface.svector3f + l * 3, v);
5924 qglVertex3f(v[0], v[1], v[2]);
5928 GL_Color(0, 0, r_shownormals.value * r_view.colorscale, 1);
5930 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
5932 VectorCopy(rsurface.vertex3f + l * 3, v);
5933 qglVertex3f(v[0], v[1], v[2]);
5934 VectorMA(v, 8, rsurface.tvector3f + l * 3, v);
5935 qglVertex3f(v[0], v[1], v[2]);
5939 GL_Color(0, r_shownormals.value * r_view.colorscale, 0, 1);
5941 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
5943 VectorCopy(rsurface.vertex3f + l * 3, v);
5944 qglVertex3f(v[0], v[1], v[2]);
5945 VectorMA(v, 8, rsurface.normal3f + l * 3, v);
5946 qglVertex3f(v[0], v[1], v[2]);
5953 rsurface.texture = NULL;
5956 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
5957 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes)
5959 int i, j, endj, f, flagsmask;
5960 int counttriangles = 0;
5961 msurface_t *surface, **surfacechain;
5963 model_t *model = r_refdef.worldmodel;
5964 const int maxsurfacelist = 1024;
5965 int numsurfacelist = 0;
5966 msurface_t *surfacelist[1024];
5970 RSurf_ActiveWorldEntity();
5972 // update light styles
5973 if (!skysurfaces && !depthonly && !addwaterplanes && model->brushq1.light_styleupdatechains)
5975 for (i = 0;i < model->brushq1.light_styles;i++)
5977 if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
5979 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
5980 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
5981 for (;(surface = *surfacechain);surfacechain++)
5982 surface->cached_dlight = true;
5987 R_UpdateAllTextureInfo(r_refdef.worldentity);
5988 flagsmask = addwaterplanes ? (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION) : (skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL));
5991 rsurface.uselightmaptexture = false;
5992 rsurface.texture = NULL;
5994 j = model->firstmodelsurface;
5995 endj = j + model->nummodelsurfaces;
5998 // quickly skip over non-visible surfaces
5999 for (;j < endj && !r_viewcache.world_surfacevisible[j];j++)
6001 // quickly iterate over visible surfaces
6002 for (;j < endj && r_viewcache.world_surfacevisible[j];j++)
6004 // process this surface
6005 surface = model->data_surfaces + j;
6006 // if this surface fits the criteria, add it to the list
6007 if (surface->num_triangles)
6009 // if lightmap parameters changed, rebuild lightmap texture
6010 if (surface->cached_dlight)
6011 R_BuildLightMap(r_refdef.worldentity, surface);
6012 // add face to draw list
6013 surfacelist[numsurfacelist++] = surface;
6014 counttriangles += surface->num_triangles;
6015 if (numsurfacelist >= maxsurfacelist)
6017 R_QueueSurfaceList(r_refdef.worldentity, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
6024 R_QueueSurfaceList(r_refdef.worldentity, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
6025 r_refdef.stats.entities_triangles += counttriangles;
6028 if (r_view.showdebug)
6030 if (r_showcollisionbrushes.integer && !skysurfaces && !addwaterplanes && !depthonly)
6031 R_DrawCollisionBrushes(r_refdef.worldentity);
6033 if ((r_showtris.integer || r_shownormals.integer) && !addwaterplanes && !depthonly)
6034 R_DrawTrianglesAndNormals(r_refdef.worldentity, r_showtris.integer, r_shownormals.integer, flagsmask);
6038 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes)
6040 int i, f, flagsmask;
6041 int counttriangles = 0;
6042 msurface_t *surface, *endsurface, **surfacechain;
6044 model_t *model = ent->model;
6045 const int maxsurfacelist = 1024;
6046 int numsurfacelist = 0;
6047 msurface_t *surfacelist[1024];
6051 // if the model is static it doesn't matter what value we give for
6052 // wantnormals and wanttangents, so this logic uses only rules applicable
6053 // to a model, knowing that they are meaningless otherwise
6054 if (ent == r_refdef.worldentity)
6055 RSurf_ActiveWorldEntity();
6056 else if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
6057 RSurf_ActiveModelEntity(ent, false, false);
6059 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader && !depthonly);
6061 // update light styles
6062 if (!skysurfaces && !depthonly && !addwaterplanes && model->brushq1.light_styleupdatechains)
6064 for (i = 0;i < model->brushq1.light_styles;i++)
6066 if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
6068 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
6069 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
6070 for (;(surface = *surfacechain);surfacechain++)
6071 surface->cached_dlight = true;
6076 R_UpdateAllTextureInfo(ent);
6077 flagsmask = addwaterplanes ? (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION) : (skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL));
6080 rsurface.uselightmaptexture = false;
6081 rsurface.texture = NULL;
6083 surface = model->data_surfaces + model->firstmodelsurface;
6084 endsurface = surface + model->nummodelsurfaces;
6085 for (;surface < endsurface;surface++)
6087 // if this surface fits the criteria, add it to the list
6088 if (surface->num_triangles)
6090 // if lightmap parameters changed, rebuild lightmap texture
6091 if (surface->cached_dlight)
6092 R_BuildLightMap(ent, surface);
6093 // add face to draw list
6094 surfacelist[numsurfacelist++] = surface;
6095 counttriangles += surface->num_triangles;
6096 if (numsurfacelist >= maxsurfacelist)
6098 R_QueueSurfaceList(ent, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
6104 R_QueueSurfaceList(ent, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
6105 r_refdef.stats.entities_triangles += counttriangles;
6108 if (r_view.showdebug)
6110 if (r_showcollisionbrushes.integer && !skysurfaces && !addwaterplanes && !depthonly)
6111 R_DrawCollisionBrushes(ent);
6113 if ((r_showtris.integer || r_shownormals.integer) && !addwaterplanes && !depthonly)
6114 R_DrawTrianglesAndNormals(ent, r_showtris.integer, r_shownormals.integer, flagsmask);