2 Copyright (C) 1996-1997 Id Software, Inc.
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
27 mempool_t *r_main_mempool;
28 rtexturepool_t *r_main_texturepool;
35 r_viewcache_t r_viewcache;
37 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "1", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
38 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
39 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%, 10 = 100%)"};
40 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
41 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
42 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
43 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
44 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
45 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
46 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
47 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
48 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
49 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
50 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
51 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
52 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
53 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling"};
54 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
55 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
56 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
57 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
58 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
59 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
60 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
61 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this)"};
62 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
63 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
64 cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
65 cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "2", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
67 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
68 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
69 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
70 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
71 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
72 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
73 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
75 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of hardware texture units reported by driver (note: setting this to 1 turns off gl_combine)"};
77 cvar_t r_glsl = {CVAR_SAVE, "r_glsl", "1", "enables use of OpenGL 2.0 pixel shaders for lighting"};
78 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
79 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
80 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
81 cvar_t r_glsl_deluxemapping = {CVAR_SAVE, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"};
82 cvar_t r_glsl_contrastboost = {CVAR_SAVE, "r_glsl_contrastboost", "1", "by how much to multiply the contrast in dark areas (1 is no change)"};
84 cvar_t r_water = {CVAR_SAVE, "r_water", "0", "whether to use reflections and refraction on water surfaces (note: r_wateralpha must be set below 1)"};
85 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
86 cvar_t r_water_resolutionmultiplier = {CVAR_SAVE, "r_water_resolutionmultiplier", "0.5", "multiplier for screen resolution when rendering refracted/reflected scenes, 1 is full quality, lower values are faster"};
87 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
88 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
90 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1", "enables animation smoothing on sprites (requires r_lerpmodels 1)"};
91 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
92 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
94 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
95 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
96 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
97 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
98 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
99 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
100 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
102 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
103 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
104 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
105 cvar_t r_hdr_range = {CVAR_SAVE, "r_hdr_range", "4", "how much dynamic range to render bloom with (equivilant to multiplying r_bloom_brighten by this value and dividing r_bloom_colorscale by this value)"};
107 cvar_t r_smoothnormals_areaweighting = {0, "r_smoothnormals_areaweighting", "1", "uses significantly faster (and supposedly higher quality) area-weighted vertex normals and tangent vectors rather than summing normalized triangle normals and tangents"};
109 cvar_t developer_texturelogging = {0, "developer_texturelogging", "0", "produces a textures.log file containing names of skins and map textures the engine tried to load"};
111 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
113 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
114 cvar_t r_batchmode = {0, "r_batchmode", "1", "selects method of rendering multiple surfaces with one driver call (values are 0, 1, 2, etc...)"};
116 extern qboolean v_flipped_state;
118 typedef struct r_glsl_bloomshader_s
121 int loc_Texture_Bloom;
123 r_glsl_bloomshader_t;
125 static struct r_bloomstate_s
130 int bloomwidth, bloomheight;
132 int screentexturewidth, screentextureheight;
133 rtexture_t *texture_screen;
135 int bloomtexturewidth, bloomtextureheight;
136 rtexture_t *texture_bloom;
138 r_glsl_bloomshader_t *shader;
140 // arrays for rendering the screen passes
141 float screentexcoord2f[8];
142 float bloomtexcoord2f[8];
143 float offsettexcoord2f[8];
147 typedef struct r_waterstate_waterplane_s
149 rtexture_t *texture_refraction;
150 rtexture_t *texture_reflection;
152 int materialflags; // combined flags of all water surfaces on this plane
153 unsigned char pvsbits[(32768+7)>>3]; // FIXME: buffer overflow on huge maps
156 r_waterstate_waterplane_t;
158 #define MAX_WATERPLANES 16
160 static struct r_waterstate_s
164 qboolean renderingscene; // true while rendering a refraction or reflection texture, disables water surfaces
166 int waterwidth, waterheight;
167 int texturewidth, textureheight;
169 int maxwaterplanes; // same as MAX_WATERPLANES
171 r_waterstate_waterplane_t waterplanes[MAX_WATERPLANES];
173 float screenscale[2];
174 float screencenter[2];
178 // shadow volume bsp struct with automatically growing nodes buffer
181 rtexture_t *r_texture_blanknormalmap;
182 rtexture_t *r_texture_white;
183 rtexture_t *r_texture_grey128;
184 rtexture_t *r_texture_black;
185 rtexture_t *r_texture_notexture;
186 rtexture_t *r_texture_whitecube;
187 rtexture_t *r_texture_normalizationcube;
188 rtexture_t *r_texture_fogattenuation;
189 //rtexture_t *r_texture_fogintensity;
191 // information about each possible shader permutation
192 r_glsl_permutation_t r_glsl_permutations[SHADERPERMUTATION_MAX];
193 // currently selected permutation
194 r_glsl_permutation_t *r_glsl_permutation;
196 char r_qwskincache[MAX_SCOREBOARD][MAX_QPATH];
197 skinframe_t *r_qwskincache_skinframe[MAX_SCOREBOARD];
199 // vertex coordinates for a quad that covers the screen exactly
200 const static float r_screenvertex3f[12] =
208 extern void R_DrawModelShadows(void);
210 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
213 for (i = 0;i < verts;i++)
224 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
227 for (i = 0;i < verts;i++)
237 // FIXME: move this to client?
240 if (gamemode == GAME_NEHAHRA)
242 Cvar_Set("gl_fogenable", "0");
243 Cvar_Set("gl_fogdensity", "0.2");
244 Cvar_Set("gl_fogred", "0.3");
245 Cvar_Set("gl_foggreen", "0.3");
246 Cvar_Set("gl_fogblue", "0.3");
248 r_refdef.fog_density = r_refdef.fog_red = r_refdef.fog_green = r_refdef.fog_blue = 0.0f;
251 float FogPoint_World(const vec3_t p)
253 int fogmasktableindex = (int)(VectorDistance((p), r_view.origin) * r_refdef.fogmasktabledistmultiplier);
254 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
257 float FogPoint_Model(const vec3_t p)
259 int fogmasktableindex = (int)(VectorDistance((p), rsurface.modelorg) * r_refdef.fogmasktabledistmultiplier);
260 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
263 static void R_BuildBlankTextures(void)
265 unsigned char data[4];
266 data[0] = 128; // normal X
267 data[1] = 128; // normal Y
268 data[2] = 255; // normal Z
269 data[3] = 128; // height
270 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
275 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
280 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
285 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
288 static void R_BuildNoTexture(void)
291 unsigned char pix[16][16][4];
292 // this makes a light grey/dark grey checkerboard texture
293 for (y = 0;y < 16;y++)
295 for (x = 0;x < 16;x++)
297 if ((y < 8) ^ (x < 8))
313 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_RGBA, TEXF_MIPMAP, NULL);
316 static void R_BuildWhiteCube(void)
318 unsigned char data[6*1*1*4];
319 data[ 0] = 255;data[ 1] = 255;data[ 2] = 255;data[ 3] = 255;
320 data[ 4] = 255;data[ 5] = 255;data[ 6] = 255;data[ 7] = 255;
321 data[ 8] = 255;data[ 9] = 255;data[10] = 255;data[11] = 255;
322 data[12] = 255;data[13] = 255;data[14] = 255;data[15] = 255;
323 data[16] = 255;data[17] = 255;data[18] = 255;data[19] = 255;
324 data[20] = 255;data[21] = 255;data[22] = 255;data[23] = 255;
325 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
328 static void R_BuildNormalizationCube(void)
332 vec_t s, t, intensity;
334 unsigned char data[6][NORMSIZE][NORMSIZE][4];
335 for (side = 0;side < 6;side++)
337 for (y = 0;y < NORMSIZE;y++)
339 for (x = 0;x < NORMSIZE;x++)
341 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
342 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
377 intensity = 127.0f / sqrt(DotProduct(v, v));
378 data[side][y][x][0] = (unsigned char)(128.0f + intensity * v[0]);
379 data[side][y][x][1] = (unsigned char)(128.0f + intensity * v[1]);
380 data[side][y][x][2] = (unsigned char)(128.0f + intensity * v[2]);
381 data[side][y][x][3] = 255;
385 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, &data[0][0][0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
388 static void R_BuildFogTexture(void)
392 unsigned char data1[FOGWIDTH][4];
393 //unsigned char data2[FOGWIDTH][4];
394 for (x = 0;x < FOGWIDTH;x++)
396 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
401 //data2[x][0] = 255 - b;
402 //data2[x][1] = 255 - b;
403 //data2[x][2] = 255 - b;
406 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
407 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
410 static const char *builtinshaderstring =
411 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
412 "// written by Forest 'LordHavoc' Hale\n"
414 "// common definitions between vertex shader and fragment shader:\n"
416 "#ifdef __GLSL_CG_DATA_TYPES\n"
417 "# define myhalf half\n"
418 "# define myhvec2 hvec2\n"
419 "# define myhvec3 hvec3\n"
420 "# define myhvec4 hvec4\n"
422 "# define myhalf float\n"
423 "# define myhvec2 vec2\n"
424 "# define myhvec3 vec3\n"
425 "# define myhvec4 vec4\n"
428 "varying vec2 TexCoord;\n"
429 "varying vec2 TexCoordLightmap;\n"
431 "//#ifdef MODE_LIGHTSOURCE\n"
432 "varying vec3 CubeVector;\n"
435 "//#ifdef MODE_LIGHTSOURCE\n"
436 "varying vec3 LightVector;\n"
438 "//# ifdef MODE_LIGHTDIRECTION\n"
439 "//varying vec3 LightVector;\n"
443 "varying vec3 EyeVector;\n"
445 "varying vec3 EyeVectorModelSpace;\n"
448 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
449 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
450 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
452 "//#ifdef USEWATER\n"
453 "varying vec4 ModelViewProjectionPosition;\n"
455 "//# ifdef USEREFLECTION\n"
456 "//varying vec4 ModelViewProjectionPosition;\n"
464 "// vertex shader specific:\n"
465 "#ifdef VERTEX_SHADER\n"
467 "uniform vec3 LightPosition;\n"
468 "uniform vec3 EyePosition;\n"
469 "uniform vec3 LightDir;\n"
471 "// TODO: get rid of tangentt (texcoord2) and use a crossproduct to regenerate it from tangents (texcoord1) and normal (texcoord3)\n"
475 " gl_FrontColor = gl_Color;\n"
476 " // copy the surface texcoord\n"
477 " TexCoord = vec2(gl_TextureMatrix[0] * gl_MultiTexCoord0);\n"
478 "#ifndef MODE_LIGHTSOURCE\n"
479 "# ifndef MODE_LIGHTDIRECTION\n"
480 " TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
484 "#ifdef MODE_LIGHTSOURCE\n"
485 " // transform vertex position into light attenuation/cubemap space\n"
486 " // (-1 to +1 across the light box)\n"
487 " CubeVector = vec3(gl_TextureMatrix[3] * gl_Vertex);\n"
489 " // transform unnormalized light direction into tangent space\n"
490 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
491 " // normalize it per pixel)\n"
492 " vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
493 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
494 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
495 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
498 "#ifdef MODE_LIGHTDIRECTION\n"
499 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
500 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
501 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
504 " // transform unnormalized eye direction into tangent space\n"
506 " vec3 EyeVectorModelSpace;\n"
508 " EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
509 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
510 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
511 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
513 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
514 " VectorS = gl_MultiTexCoord1.xyz;\n"
515 " VectorT = gl_MultiTexCoord2.xyz;\n"
516 " VectorR = gl_MultiTexCoord3.xyz;\n"
519 "//#if defined(USEWATER) || defined(USEREFLECTION)\n"
520 "// ModelViewProjectionPosition = gl_Vertex * gl_ModelViewProjectionMatrix;\n"
521 "// //ModelViewProjectionPosition_svector = (gl_Vertex + vec4(gl_MultiTexCoord1.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
522 "// //ModelViewProjectionPosition_tvector = (gl_Vertex + vec4(gl_MultiTexCoord2.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
525 "// transform vertex to camera space, using ftransform to match non-VS\n"
527 " gl_Position = ftransform();\n"
530 " ModelViewProjectionPosition = gl_Position;\n"
532 "# ifdef USEREFLECTION\n"
533 " ModelViewProjectionPosition = gl_Position;\n"
538 "#endif // VERTEX_SHADER\n"
543 "// fragment shader specific:\n"
544 "#ifdef FRAGMENT_SHADER\n"
546 "// 13 textures, we can only use up to 16 on DX9-class hardware\n"
547 "uniform sampler2D Texture_Normal;\n"
548 "uniform sampler2D Texture_Color;\n"
549 "uniform sampler2D Texture_Gloss;\n"
550 "uniform samplerCube Texture_Cube;\n"
551 "uniform sampler2D Texture_Attenuation;\n"
552 "uniform sampler2D Texture_FogMask;\n"
553 "uniform sampler2D Texture_Pants;\n"
554 "uniform sampler2D Texture_Shirt;\n"
555 "uniform sampler2D Texture_Lightmap;\n"
556 "uniform sampler2D Texture_Deluxemap;\n"
557 "uniform sampler2D Texture_Glow;\n"
558 "uniform sampler2D Texture_Reflection;\n"
559 "uniform sampler2D Texture_Refraction;\n"
561 "uniform myhvec3 LightColor;\n"
562 "uniform myhvec3 AmbientColor;\n"
563 "uniform myhvec3 DiffuseColor;\n"
564 "uniform myhvec3 SpecularColor;\n"
565 "uniform myhvec3 Color_Pants;\n"
566 "uniform myhvec3 Color_Shirt;\n"
567 "uniform myhvec3 FogColor;\n"
569 "//#ifdef USEWATER\n"
570 "uniform vec4 DistortScaleRefractReflect;\n"
571 "uniform vec4 ScreenScaleRefractReflect;\n"
572 "uniform vec4 ScreenCenterRefractReflect;\n"
573 "uniform myhvec3 RefractColor;\n"
574 "uniform myhvec3 ReflectColor;\n"
575 "uniform myhalf ReflectFactor;\n"
576 "uniform myhalf ReflectOffset;\n"
578 "//# ifdef USEREFLECTION\n"
579 "//uniform vec4 DistortScaleRefractReflect;\n"
580 "//uniform vec4 ScreenScaleRefractReflect;\n"
581 "//uniform vec4 ScreenCenterRefractReflect;\n"
582 "//uniform myhvec3 ReflectColor;\n"
586 "uniform myhalf GlowScale;\n"
587 "uniform myhalf SceneBrightness;\n"
588 "#ifdef USECONTRASTBOOST\n"
589 "uniform myhalf ContrastBoostCoeff;\n"
592 "uniform float OffsetMapping_Scale;\n"
593 "uniform float OffsetMapping_Bias;\n"
594 "uniform float FogRangeRecip;\n"
596 "uniform myhalf AmbientScale;\n"
597 "uniform myhalf DiffuseScale;\n"
598 "uniform myhalf SpecularScale;\n"
599 "uniform myhalf SpecularPower;\n"
601 "#ifdef USEOFFSETMAPPING\n"
602 "vec2 OffsetMapping(vec2 TexCoord)\n"
604 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
605 " // 14 sample relief mapping: linear search and then binary search\n"
606 " // this basically steps forward a small amount repeatedly until it finds\n"
607 " // itself inside solid, then jitters forward and back using decreasing\n"
608 " // amounts to find the impact\n"
609 " //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
610 " //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
611 " vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
612 " vec3 RT = vec3(TexCoord, 1);\n"
613 " OffsetVector *= 0.1;\n"
614 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
615 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
616 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\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) - 0.5);\n"
624 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5 - 0.25);\n"
625 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25 - 0.125);\n"
626 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125 - 0.0625);\n"
627 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
630 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
631 " // this basically moves forward the full distance, and then backs up based\n"
632 " // on height of samples\n"
633 " //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
634 " //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
635 " vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
636 " TexCoord += OffsetVector;\n"
637 " OffsetVector *= 0.333;\n"
638 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
639 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
640 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
641 " return TexCoord;\n"
648 "#ifdef USEOFFSETMAPPING\n"
649 " // apply offsetmapping\n"
650 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
651 "#define TexCoord TexCoordOffset\n"
654 " // combine the diffuse textures (base, pants, shirt)\n"
655 " myhvec4 color = myhvec4(texture2D(Texture_Color, TexCoord));\n"
656 "#ifdef USECOLORMAPPING\n"
657 " color.rgb += myhvec3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhvec3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
663 "#ifdef MODE_LIGHTSOURCE\n"
666 " // calculate surface normal, light normal, and specular normal\n"
667 " // compute color intensity for the two textures (colormap and glossmap)\n"
668 " // scale by light color and attenuation as efficiently as possible\n"
669 " // (do as much scalar math as possible rather than vector math)\n"
670 "# ifdef USESPECULAR\n"
671 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
672 " myhvec3 diffusenormal = myhvec3(normalize(LightVector));\n"
673 " myhvec3 specularnormal = normalize(diffusenormal + myhvec3(normalize(EyeVector)));\n"
675 " // calculate directional shading\n"
676 " 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"
678 "# ifdef USEDIFFUSE\n"
679 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
680 " myhvec3 diffusenormal = myhvec3(normalize(LightVector));\n"
682 " // calculate directional shading\n"
683 " 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"
685 " // calculate directionless shading\n"
686 " color.rgb = color.rgb * LightColor * myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
690 "# ifdef USECUBEFILTER\n"
691 " // apply light cubemap filter\n"
692 " //color.rgb *= normalize(CubeVector) * 0.5 + 0.5;//vec3(textureCube(Texture_Cube, CubeVector));\n"
693 " color.rgb *= myhvec3(textureCube(Texture_Cube, CubeVector));\n"
695 " color *= myhvec4(gl_Color);\n"
696 "#endif // MODE_LIGHTSOURCE\n"
701 "#ifdef MODE_LIGHTDIRECTION\n"
702 " // directional model lighting\n"
704 " // get the surface normal and light normal\n"
705 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
706 " myhvec3 diffusenormal = myhvec3(LightVector);\n"
708 " // calculate directional shading\n"
709 " color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
710 "# ifdef USESPECULAR\n"
711 " myhvec3 specularnormal = normalize(diffusenormal + myhvec3(normalize(EyeVector)));\n"
712 " color.rgb += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
714 " color *= myhvec4(gl_Color);\n"
715 "#endif // MODE_LIGHTDIRECTION\n"
720 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
721 " // deluxemap lightmapping using light vectors in modelspace (evil q3map2)\n"
723 " // get the surface normal and light normal\n"
724 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
726 " myhvec3 diffusenormal_modelspace = myhvec3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - myhvec3(0.5);\n"
727 " myhvec3 diffusenormal = normalize(myhvec3(dot(diffusenormal_modelspace, myhvec3(VectorS)), dot(diffusenormal_modelspace, myhvec3(VectorT)), dot(diffusenormal_modelspace, myhvec3(VectorR))));\n"
728 " // calculate directional shading\n"
729 " myhvec3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0)));\n"
730 "# ifdef USESPECULAR\n"
731 " myhvec3 specularnormal = myhvec3(normalize(diffusenormal + myhvec3(normalize(EyeVector))));\n"
732 " tempcolor += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
735 " // apply lightmap color\n"
736 " color.rgb = myhvec4(tempcolor,1) * myhvec4(texture2D(Texture_Lightmap, TexCoordLightmap)) * myhvec4(gl_Color) + myhvec4(color.rgb * AmbientScale, 0);\n"
737 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
742 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
743 " // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
745 " // get the surface normal and light normal\n"
746 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
748 " myhvec3 diffusenormal = normalize(myhvec3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - myhvec3(0.5));\n"
749 " // calculate directional shading\n"
750 " myhvec3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0)));\n"
751 "# ifdef USESPECULAR\n"
752 " myhvec3 specularnormal = myhvec3(normalize(diffusenormal + myhvec3(normalize(EyeVector))));\n"
753 " tempcolor += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
756 " // apply lightmap color\n"
757 " color = myhvec4(tempcolor, 1) * myhvec4(texture2D(Texture_Lightmap, TexCoordLightmap)) * myhvec4(gl_Color) + myhvec4(color.rgb * AmbientScale, 0);\n"
758 "#endif // MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
763 "#ifdef MODE_LIGHTMAP\n"
764 " // apply lightmap color\n"
765 " color *= myhvec4(texture2D(Texture_Lightmap, TexCoordLightmap)) * myhvec4(gl_Color) * myhvec4(myhvec3(DiffuseScale), 1) + myhvec4(myhvec3(AmbientScale), 0);\n"
766 "#endif // MODE_LIGHTMAP\n"
775 "#ifdef MODE_LIGHTSOURCE\n"
777 " color.rgb *= color.a;\n"
781 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
782 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
783 " vec4 ScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect + vec3(normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5))).xyxy * DistortScaleRefractReflect;\n"
784 " myhalf Fresnel = myhalf(pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0)) * ReflectFactor + ReflectOffset;\n"
785 " color.rgb = mix(mix(myhvec3(texture2D(Texture_Refraction, ScreenTexCoord.xy)) * RefractColor, myhvec3(texture2D(Texture_Reflection, ScreenTexCoord.zw)) * ReflectColor, Fresnel), color.rgb, color.a);\n"
787 "# ifdef USEREFLECTION\n"
788 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
789 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
790 " vec4 ScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect + vec3(normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5))).xyxy * DistortScaleRefractReflect;\n"
791 " color.rgb += myhvec3(texture2D(Texture_Reflection, ScreenTexCoord.zw)) * ReflectColor;\n"
797 " color.rgb += myhvec3(texture2D(Texture_Glow, TexCoord)) * GlowScale;\n"
802 " color.rgb = mix(FogColor, color.rgb, myhalf(texture2D(Texture_FogMask, myhvec2(length(EyeVectorModelSpace)*FogRangeRecip, 0.0))));\n"
805 "#ifdef USECONTRASTBOOST\n"
806 " color.rgb = color.rgb * SceneBrightness / (ContrastBoostCoeff * color.rgb + myhvec3(1, 1, 1));\n"
808 " color.rgb *= SceneBrightness;\n"
811 " gl_FragColor = vec4(color);\n"
814 "#endif // FRAGMENT_SHADER\n"
817 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
818 const char *permutationinfo[][2] =
820 {"#define MODE_LIGHTMAP\n", " lightmap"},
821 {"#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
822 {"#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
823 {"#define MODE_LIGHTDIRECTION\n", " lightdirection"},
824 {"#define MODE_LIGHTSOURCE\n", " lightsource"},
825 {"#define USEWATER\n", " water"},
826 {"#define USEREFLECTION\n", " reflection"},
827 {"#define USEGLOW\n", " glow"},
828 {"#define USEFOG\n", " fog"},
829 {"#define USECOLORMAPPING\n", " colormapping"},
830 {"#define USEDIFFUSE\n", " diffuse"},
831 {"#define USECONTRASTBOOST\n", " contrastboost"},
832 {"#define USESPECULAR\n", " specular"},
833 {"#define USECUBEFILTER\n", " cubefilter"},
834 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
835 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
839 void R_GLSL_CompilePermutation(const char *filename, int permutation)
842 qboolean shaderfound;
843 r_glsl_permutation_t *p = r_glsl_permutations + (permutation & SHADERPERMUTATION_MASK);
844 int vertstrings_count;
845 int geomstrings_count;
846 int fragstrings_count;
848 const char *vertstrings_list[32+1];
849 const char *geomstrings_list[32+1];
850 const char *fragstrings_list[32+1];
851 char permutationname[256];
856 vertstrings_list[0] = "#define VERTEX_SHADER\n";
857 geomstrings_list[0] = "#define GEOMETRY_SHADER\n";
858 fragstrings_list[0] = "#define FRAGMENT_SHADER\n";
859 vertstrings_count = 1;
860 geomstrings_count = 1;
861 fragstrings_count = 1;
862 permutationname[0] = 0;
863 for (i = 0;permutationinfo[i][0];i++)
865 if (permutation & (1<<i))
867 vertstrings_list[vertstrings_count++] = permutationinfo[i][0];
868 geomstrings_list[geomstrings_count++] = permutationinfo[i][0];
869 fragstrings_list[fragstrings_count++] = permutationinfo[i][0];
870 strlcat(permutationname, permutationinfo[i][1], sizeof(permutationname));
874 // keep line numbers correct
875 vertstrings_list[vertstrings_count++] = "\n";
876 geomstrings_list[geomstrings_count++] = "\n";
877 fragstrings_list[fragstrings_count++] = "\n";
880 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
884 Con_DPrintf("GLSL shader text for \"%s\" loaded from disk\n", filename);
885 vertstrings_list[vertstrings_count++] = shaderstring;
886 geomstrings_list[geomstrings_count++] = shaderstring;
887 fragstrings_list[fragstrings_count++] = shaderstring;
890 else if (!strcmp(filename, "glsl/default.glsl"))
892 Con_DPrintf("GLSL shader text for \"%s\" loaded from engine\n", filename);
893 vertstrings_list[vertstrings_count++] = builtinshaderstring;
894 geomstrings_list[geomstrings_count++] = builtinshaderstring;
895 fragstrings_list[fragstrings_count++] = builtinshaderstring;
898 // clear any lists that are not needed by this shader
899 if (!(permutation & SHADERPERMUTATION_USES_VERTEXSHADER))
900 vertstrings_count = 0;
901 if (!(permutation & SHADERPERMUTATION_USES_GEOMETRYSHADER))
902 geomstrings_count = 0;
903 if (!(permutation & SHADERPERMUTATION_USES_FRAGMENTSHADER))
904 fragstrings_count = 0;
905 // compile the shader program
906 if (shaderfound && vertstrings_count + geomstrings_count + fragstrings_count)
907 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
911 qglUseProgramObjectARB(p->program);CHECKGLERROR
912 // look up all the uniform variable names we care about, so we don't
913 // have to look them up every time we set them
914 p->loc_Texture_Normal = qglGetUniformLocationARB(p->program, "Texture_Normal");
915 p->loc_Texture_Color = qglGetUniformLocationARB(p->program, "Texture_Color");
916 p->loc_Texture_Gloss = qglGetUniformLocationARB(p->program, "Texture_Gloss");
917 p->loc_Texture_Cube = qglGetUniformLocationARB(p->program, "Texture_Cube");
918 p->loc_Texture_Attenuation = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
919 p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
920 p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
921 p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
922 p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
923 p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
924 p->loc_Texture_Glow = qglGetUniformLocationARB(p->program, "Texture_Glow");
925 p->loc_Texture_Refraction = qglGetUniformLocationARB(p->program, "Texture_Refraction");
926 p->loc_Texture_Reflection = qglGetUniformLocationARB(p->program, "Texture_Reflection");
927 p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
928 p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
929 p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
930 p->loc_LightColor = qglGetUniformLocationARB(p->program, "LightColor");
931 p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants");
932 p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt");
933 p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip");
934 p->loc_AmbientScale = qglGetUniformLocationARB(p->program, "AmbientScale");
935 p->loc_DiffuseScale = qglGetUniformLocationARB(p->program, "DiffuseScale");
936 p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
937 p->loc_SpecularScale = qglGetUniformLocationARB(p->program, "SpecularScale");
938 p->loc_GlowScale = qglGetUniformLocationARB(p->program, "GlowScale");
939 p->loc_SceneBrightness = qglGetUniformLocationARB(p->program, "SceneBrightness");
940 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
941 p->loc_AmbientColor = qglGetUniformLocationARB(p->program, "AmbientColor");
942 p->loc_DiffuseColor = qglGetUniformLocationARB(p->program, "DiffuseColor");
943 p->loc_SpecularColor = qglGetUniformLocationARB(p->program, "SpecularColor");
944 p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
945 p->loc_ContrastBoostCoeff = qglGetUniformLocationARB(p->program, "ContrastBoostCoeff");
946 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
947 p->loc_ScreenScaleRefractReflect = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
948 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
949 p->loc_RefractColor = qglGetUniformLocationARB(p->program, "RefractColor");
950 p->loc_ReflectColor = qglGetUniformLocationARB(p->program, "ReflectColor");
951 p->loc_ReflectFactor = qglGetUniformLocationARB(p->program, "ReflectFactor");
952 p->loc_ReflectOffset = qglGetUniformLocationARB(p->program, "ReflectOffset");
953 // initialize the samplers to refer to the texture units we use
954 if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal, 0);
955 if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color, 1);
956 if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss, 2);
957 if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube, 3);
958 if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask, 4);
959 if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants, 5);
960 if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt, 6);
961 if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap, 7);
962 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap, 8);
963 if (p->loc_Texture_Glow >= 0) qglUniform1iARB(p->loc_Texture_Glow, 9);
964 if (p->loc_Texture_Attenuation >= 0) qglUniform1iARB(p->loc_Texture_Attenuation, 10);
965 if (p->loc_Texture_Refraction >= 0) qglUniform1iARB(p->loc_Texture_Refraction, 11);
966 if (p->loc_Texture_Reflection >= 0) qglUniform1iARB(p->loc_Texture_Reflection, 12);
968 qglUseProgramObjectARB(0);CHECKGLERROR
971 Con_Printf("permutation%s failed for shader %s, some features may not work properly!\n", permutationname, filename);
973 Mem_Free(shaderstring);
976 void R_GLSL_Restart_f(void)
979 for (i = 0;i < SHADERPERMUTATION_MAX;i++)
980 if (r_glsl_permutations[i].program)
981 GL_Backend_FreeProgram(r_glsl_permutations[i].program);
982 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
985 void R_GLSL_DumpShader_f(void)
989 qfile_t *file = FS_Open("glsl/default.glsl", "w", false, false);
992 Con_Printf("failed to write to glsl/default.glsl\n");
996 FS_Print(file, "// The engine may define the following macros:\n");
997 FS_Print(file, "// #define VERTEX_SHADER\n// #define GEOMETRY_SHADER\n// #define FRAGMENT_SHADER\n");
998 for (i = 0;permutationinfo[i][0];i++)
999 FS_Printf(file, "// %s", permutationinfo[i][0]);
1000 FS_Print(file, "\n");
1001 FS_Print(file, builtinshaderstring);
1004 Con_Printf("glsl/default.glsl written\n");
1007 extern rtexture_t *r_shadow_attenuationgradienttexture;
1008 extern rtexture_t *r_shadow_attenuation2dtexture;
1009 extern rtexture_t *r_shadow_attenuation3dtexture;
1010 int R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale)
1012 // select a permutation of the lighting shader appropriate to this
1013 // combination of texture, entity, light source, and fogging, only use the
1014 // minimum features necessary to avoid wasting rendering time in the
1015 // fragment shader on features that are not being used
1016 const char *shaderfilename = NULL;
1017 unsigned int permutation = 0;
1019 r_glsl_permutation = NULL;
1020 // TODO: implement geometry-shader based shadow volumes someday
1021 if (rsurface.rtlight)
1024 shaderfilename = "glsl/default.glsl";
1025 permutation = SHADERPERMUTATION_MODE_LIGHTSOURCE | SHADERPERMUTATION_USES_VERTEXSHADER | SHADERPERMUTATION_USES_FRAGMENTSHADER;
1026 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
1027 permutation |= SHADERPERMUTATION_CUBEFILTER;
1028 if (diffusescale > 0)
1029 permutation |= SHADERPERMUTATION_DIFFUSE;
1030 if (specularscale > 0)
1031 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
1032 if (r_refdef.fogenabled)
1033 permutation |= SHADERPERMUTATION_FOG;
1034 if (rsurface.texture->colormapping)
1035 permutation |= SHADERPERMUTATION_COLORMAPPING;
1036 if (r_glsl_offsetmapping.integer)
1038 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
1039 if (r_glsl_offsetmapping_reliefmapping.integer)
1040 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
1042 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1043 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1044 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
1045 permutation |= SHADERPERMUTATION_WATER;
1046 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1047 permutation |= SHADERPERMUTATION_REFLECTION;
1049 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
1051 // bright unshaded geometry
1052 shaderfilename = "glsl/default.glsl";
1053 permutation = SHADERPERMUTATION_USES_VERTEXSHADER | SHADERPERMUTATION_USES_FRAGMENTSHADER;
1054 permutation |= SHADERPERMUTATION_MODE_LIGHTMAP;
1055 if (rsurface.texture->currentskinframe->glow)
1056 permutation |= SHADERPERMUTATION_GLOW;
1057 if (r_refdef.fogenabled)
1058 permutation |= SHADERPERMUTATION_FOG;
1059 if (rsurface.texture->colormapping)
1060 permutation |= SHADERPERMUTATION_COLORMAPPING;
1061 if (r_glsl_offsetmapping.integer)
1063 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
1064 if (r_glsl_offsetmapping_reliefmapping.integer)
1065 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
1067 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1068 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1069 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
1070 permutation |= SHADERPERMUTATION_WATER;
1071 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1072 permutation |= SHADERPERMUTATION_REFLECTION;
1074 else if (modellighting)
1076 // directional model lighting
1077 shaderfilename = "glsl/default.glsl";
1078 permutation = SHADERPERMUTATION_USES_VERTEXSHADER | SHADERPERMUTATION_USES_FRAGMENTSHADER;
1079 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTION;
1080 if (rsurface.texture->currentskinframe->glow)
1081 permutation |= SHADERPERMUTATION_GLOW;
1082 if (specularscale > 0)
1083 permutation |= SHADERPERMUTATION_SPECULAR;
1084 if (r_refdef.fogenabled)
1085 permutation |= SHADERPERMUTATION_FOG;
1086 if (rsurface.texture->colormapping)
1087 permutation |= SHADERPERMUTATION_COLORMAPPING;
1088 if (r_glsl_offsetmapping.integer)
1090 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
1091 if (r_glsl_offsetmapping_reliefmapping.integer)
1092 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
1094 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1095 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1096 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
1097 permutation |= SHADERPERMUTATION_WATER;
1098 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1099 permutation |= SHADERPERMUTATION_REFLECTION;
1104 shaderfilename = "glsl/default.glsl";
1105 permutation = SHADERPERMUTATION_USES_VERTEXSHADER | SHADERPERMUTATION_USES_FRAGMENTSHADER;
1106 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.worldmodel && r_refdef.worldmodel->brushq3.deluxemapping)
1108 // deluxemapping (light direction texture)
1109 if (rsurface.uselightmaptexture && r_refdef.worldmodel && r_refdef.worldmodel->brushq3.deluxemapping && r_refdef.worldmodel->brushq3.deluxemapping_modelspace)
1110 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_MODELSPACE;
1112 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
1113 if (specularscale > 0)
1114 permutation |= SHADERPERMUTATION_SPECULAR;
1116 else if (r_glsl_deluxemapping.integer >= 2)
1118 // fake deluxemapping (uniform light direction in tangentspace)
1119 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
1120 if (specularscale > 0)
1121 permutation |= SHADERPERMUTATION_SPECULAR;
1125 // ordinary lightmapping
1126 permutation |= SHADERPERMUTATION_MODE_LIGHTMAP;
1128 if (rsurface.texture->currentskinframe->glow)
1129 permutation |= SHADERPERMUTATION_GLOW;
1130 if (r_refdef.fogenabled)
1131 permutation |= SHADERPERMUTATION_FOG;
1132 if (rsurface.texture->colormapping)
1133 permutation |= SHADERPERMUTATION_COLORMAPPING;
1134 if (r_glsl_offsetmapping.integer)
1136 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
1137 if (r_glsl_offsetmapping_reliefmapping.integer)
1138 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
1140 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1141 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1142 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
1143 permutation |= SHADERPERMUTATION_WATER;
1144 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1145 permutation |= SHADERPERMUTATION_REFLECTION;
1147 if (!r_glsl_permutations[permutation & SHADERPERMUTATION_MASK].program)
1149 if (!r_glsl_permutations[permutation & SHADERPERMUTATION_MASK].compiled)
1150 R_GLSL_CompilePermutation(shaderfilename, permutation);
1151 if (!r_glsl_permutations[permutation & SHADERPERMUTATION_MASK].program)
1153 // remove features until we find a valid permutation
1155 for (i = (SHADERPERMUTATION_MAX >> 1);;i>>=1)
1159 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");
1160 Cvar_SetValueQuick(&r_glsl, 0);
1161 return 0; // no bit left to clear
1163 // reduce i more quickly whenever it would not remove any bits
1164 if (!(permutation & i))
1167 if (!r_glsl_permutations[permutation & SHADERPERMUTATION_MASK].compiled)
1168 R_GLSL_CompilePermutation(shaderfilename, permutation);
1169 if (r_glsl_permutations[permutation & SHADERPERMUTATION_MASK].program)
1174 r_glsl_permutation = r_glsl_permutations + (permutation & SHADERPERMUTATION_MASK);
1176 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
1177 R_Mesh_TexMatrix(0, &rsurface.texture->currenttexmatrix);
1178 if (permutation & SHADERPERMUTATION_MODE_LIGHTSOURCE)
1180 if (r_glsl_permutation->loc_Texture_Cube >= 0 && rsurface.rtlight) R_Mesh_TexBindCubeMap(3, R_GetTexture(rsurface.rtlight->currentcubemap));
1181 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
1182 if (permutation & SHADERPERMUTATION_DIFFUSE)
1184 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
1185 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, ambientscale);
1186 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, diffusescale);
1187 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, specularscale);
1191 // ambient only is simpler
1192 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0] * ambientscale, lightcolorbase[1] * ambientscale, lightcolorbase[2] * ambientscale);
1193 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, 1);
1194 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, 0);
1195 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, 0);
1198 else if (permutation & SHADERPERMUTATION_MODE_LIGHTDIRECTION)
1200 if (r_glsl_permutation->loc_AmbientColor >= 0)
1201 qglUniform3fARB(r_glsl_permutation->loc_AmbientColor, rsurface.modellight_ambient[0] * ambientscale, rsurface.modellight_ambient[1] * ambientscale, rsurface.modellight_ambient[2] * ambientscale);
1202 if (r_glsl_permutation->loc_DiffuseColor >= 0)
1203 qglUniform3fARB(r_glsl_permutation->loc_DiffuseColor, rsurface.modellight_diffuse[0] * diffusescale, rsurface.modellight_diffuse[1] * diffusescale, rsurface.modellight_diffuse[2] * diffusescale);
1204 if (r_glsl_permutation->loc_SpecularColor >= 0)
1205 qglUniform3fARB(r_glsl_permutation->loc_SpecularColor, rsurface.modellight_diffuse[0] * specularscale, rsurface.modellight_diffuse[1] * specularscale, rsurface.modellight_diffuse[2] * specularscale);
1206 if (r_glsl_permutation->loc_LightDir >= 0)
1207 qglUniform3fARB(r_glsl_permutation->loc_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
1211 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_ambient.value * 2.0f / 128.0f);
1212 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_refdef.lightmapintensity * 2.0f);
1213 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, r_refdef.lightmapintensity * specularscale * 2.0f);
1215 nmap = rsurface.texture->currentskinframe->nmap;
1216 if (gl_lightmaps.integer)
1217 nmap = r_texture_blanknormalmap;
1218 if (r_glsl_permutation->loc_Texture_Normal >= 0) R_Mesh_TexBind(0, R_GetTexture(nmap));
1219 if (r_glsl_permutation->loc_Texture_Color >= 0) R_Mesh_TexBind(1, R_GetTexture(rsurface.texture->basetexture));
1220 if (r_glsl_permutation->loc_Texture_Gloss >= 0) R_Mesh_TexBind(2, R_GetTexture(rsurface.texture->glosstexture));
1221 //if (r_glsl_permutation->loc_Texture_Cube >= 0 && permutation & SHADERPERMUTATION_MODE_LIGHTSOURCE) R_Mesh_TexBindCubeMap(3, R_GetTexture(rsurface.rtlight->currentcubemap));
1222 if (r_glsl_permutation->loc_Texture_Attenuation >= 0) R_Mesh_TexBind(10, R_GetTexture(r_shadow_attenuationgradienttexture));
1223 if (r_glsl_permutation->loc_Texture_FogMask >= 0) R_Mesh_TexBind(4, R_GetTexture(r_texture_fogattenuation));
1224 if (r_glsl_permutation->loc_Texture_Pants >= 0) R_Mesh_TexBind(5, R_GetTexture(rsurface.texture->currentskinframe->pants));
1225 if (r_glsl_permutation->loc_Texture_Shirt >= 0) R_Mesh_TexBind(6, R_GetTexture(rsurface.texture->currentskinframe->shirt));
1226 //if (r_glsl_permutation->loc_Texture_Lightmap >= 0) R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
1227 //if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
1228 if (r_glsl_permutation->loc_Texture_Glow >= 0) R_Mesh_TexBind(9, R_GetTexture(rsurface.texture->currentskinframe->glow));
1229 if (r_glsl_permutation->loc_Texture_Refraction >= 0) R_Mesh_TexBind(11, R_GetTexture(r_texture_white)); // changed per surface
1230 if (r_glsl_permutation->loc_Texture_Reflection >= 0) R_Mesh_TexBind(12, R_GetTexture(r_texture_white)); // changed per surface
1231 if (r_glsl_permutation->loc_GlowScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_GlowScale, r_hdr_glowintensity.value);
1232 if (r_glsl_permutation->loc_ContrastBoostCoeff >= 0)
1234 // The formula used is actually:
1235 // color.rgb *= SceneBrightness;
1236 // color.rgb *= ContrastBoost / ((ContrastBoost - 1) * color.rgb + 1);
1237 // I simplify that to
1238 // color.rgb *= [[SceneBrightness * ContrastBoost]];
1239 // color.rgb /= [[(ContrastBoost - 1) / ContrastBoost]] * color.rgb + 1;
1241 // color.rgb = [[SceneBrightness * ContrastBoost]] / ([[(ContrastBoost - 1) * SceneBrightness]] + 1 / color.rgb);
1242 // and do [[calculations]] here in the engine
1243 qglUniform1fARB(r_glsl_permutation->loc_ContrastBoostCoeff, (r_glsl_contrastboost.value - 1) * r_view.colorscale);
1244 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_view.colorscale * r_glsl_contrastboost.value);
1247 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_view.colorscale);
1248 if (r_glsl_permutation->loc_FogColor >= 0)
1250 // additive passes are only darkened by fog, not tinted
1251 if (rsurface.rtlight || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD))
1252 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
1254 qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
1256 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.modelorg[0], rsurface.modelorg[1], rsurface.modelorg[2]);
1257 if (r_glsl_permutation->loc_Color_Pants >= 0)
1259 if (rsurface.texture->currentskinframe->pants)
1260 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
1262 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
1264 if (r_glsl_permutation->loc_Color_Shirt >= 0)
1266 if (rsurface.texture->currentskinframe->shirt)
1267 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
1269 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
1271 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, r_refdef.fograngerecip);
1272 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower);
1273 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
1274 if (r_glsl_permutation->loc_DistortScaleRefractReflect >= 0) qglUniform4fARB(r_glsl_permutation->loc_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value, r_water_reflectdistort.value);
1275 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]);
1276 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]);
1277 if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform3fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor);
1278 if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform3fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor);
1279 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->refractmax - rsurface.texture->refractmin);
1280 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, 1 - rsurface.texture->refractmax);
1285 void R_SwitchSurfaceShader(int permutation)
1287 if (r_glsl_permutation != r_glsl_permutations + (permutation & SHADERPERMUTATION_MASK))
1289 r_glsl_permutation = r_glsl_permutations + (permutation & SHADERPERMUTATION_MASK);
1291 qglUseProgramObjectARB(r_glsl_permutation->program);
1296 #define SKINFRAME_HASH 1024
1300 int loadsequence; // incremented each level change
1301 memexpandablearray_t array;
1302 skinframe_t *hash[SKINFRAME_HASH];
1306 void R_SkinFrame_PrepareForPurge(void)
1308 r_skinframe.loadsequence++;
1309 // wrap it without hitting zero
1310 if (r_skinframe.loadsequence >= 200)
1311 r_skinframe.loadsequence = 1;
1314 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
1318 // mark the skinframe as used for the purging code
1319 skinframe->loadsequence = r_skinframe.loadsequence;
1322 void R_SkinFrame_Purge(void)
1326 for (i = 0;i < SKINFRAME_HASH;i++)
1328 for (s = r_skinframe.hash[i];s;s = s->next)
1330 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
1332 if (s->base == r_texture_notexture) s->base = NULL;
1333 if (s->nmap == r_texture_blanknormalmap)s->nmap = NULL;
1334 if (s->merged == s->base) s->merged = NULL;
1335 if (s->stain ) R_FreeTexture(s->stain );s->stain = NULL;
1336 if (s->merged) R_FreeTexture(s->merged);s->merged = NULL;
1337 if (s->base ) R_FreeTexture(s->base );s->base = NULL;
1338 if (s->pants ) R_FreeTexture(s->pants );s->pants = NULL;
1339 if (s->shirt ) R_FreeTexture(s->shirt );s->shirt = NULL;
1340 if (s->nmap ) R_FreeTexture(s->nmap );s->nmap = NULL;
1341 if (s->gloss ) R_FreeTexture(s->gloss );s->gloss = NULL;
1342 if (s->glow ) R_FreeTexture(s->glow );s->glow = NULL;
1343 if (s->fog ) R_FreeTexture(s->fog );s->fog = NULL;
1344 s->loadsequence = 0;
1350 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
1354 char basename[MAX_QPATH];
1356 Image_StripImageExtension(name, basename, sizeof(basename));
1358 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
1359 for (item = r_skinframe.hash[hashindex];item;item = item->next)
1360 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
1366 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
1367 memset(item, 0, sizeof(*item));
1368 strlcpy(item->basename, basename, sizeof(item->basename));
1369 item->textureflags = textureflags;
1370 item->comparewidth = comparewidth;
1371 item->compareheight = compareheight;
1372 item->comparecrc = comparecrc;
1373 item->next = r_skinframe.hash[hashindex];
1374 r_skinframe.hash[hashindex] = item;
1376 R_SkinFrame_MarkUsed(item);
1380 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
1382 // FIXME: it should be possible to disable loading various layers using
1383 // cvars, to prevent wasted loading time and memory usage if the user does
1385 qboolean loadnormalmap = true;
1386 qboolean loadgloss = true;
1387 qboolean loadpantsandshirt = true;
1388 qboolean loadglow = true;
1390 unsigned char *pixels;
1391 unsigned char *bumppixels;
1392 unsigned char *basepixels = NULL;
1393 int basepixels_width;
1394 int basepixels_height;
1395 skinframe_t *skinframe;
1397 if (cls.state == ca_dedicated)
1400 // return an existing skinframe if already loaded
1401 // if loading of the first image fails, don't make a new skinframe as it
1402 // would cause all future lookups of this to be missing
1403 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
1404 if (skinframe && skinframe->base)
1407 basepixels = loadimagepixels(name, complain, 0, 0);
1408 if (basepixels == NULL)
1411 // we've got some pixels to store, so really allocate this new texture now
1413 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
1414 skinframe->stain = NULL;
1415 skinframe->merged = NULL;
1416 skinframe->base = r_texture_notexture;
1417 skinframe->pants = NULL;
1418 skinframe->shirt = NULL;
1419 skinframe->nmap = r_texture_blanknormalmap;
1420 skinframe->gloss = NULL;
1421 skinframe->glow = NULL;
1422 skinframe->fog = NULL;
1424 basepixels_width = image_width;
1425 basepixels_height = image_height;
1426 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);
1428 if (textureflags & TEXF_ALPHA)
1430 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
1431 if (basepixels[j] < 255)
1433 if (j < basepixels_width * basepixels_height * 4)
1435 // has transparent pixels
1436 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
1437 for (j = 0;j < image_width * image_height * 4;j += 4)
1442 pixels[j+3] = basepixels[j+3];
1444 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);
1449 // _norm is the name used by tenebrae and has been adopted as standard
1452 if ((pixels = loadimagepixels(va("%s_norm", skinframe->basename), false, 0, 0)) != NULL)
1454 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);
1458 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixels(va("%s_bump", skinframe->basename), false, 0, 0)) != NULL)
1460 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
1461 Image_HeightmapToNormalmap(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
1462 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);
1464 Mem_Free(bumppixels);
1466 else if (r_shadow_bumpscale_basetexture.value > 0)
1468 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
1469 Image_HeightmapToNormalmap(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
1470 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);
1474 // _luma is supported for tenebrae compatibility
1475 // (I think it's a very stupid name, but oh well)
1476 // _glow is the preferred name
1477 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;}
1478 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;}
1479 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;}
1480 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;}
1483 Mem_Free(basepixels);
1488 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)
1493 for (i = 0;i < width*height;i++)
1494 if (((unsigned char *)&palette[in[i]])[3] > 0)
1496 if (i == width*height)
1499 return R_LoadTexture2D (r_main_texturepool, name, width, height, in, TEXTYPE_PALETTE, textureflags, palette);
1502 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)
1505 unsigned char *temp1, *temp2;
1506 skinframe_t *skinframe;
1508 if (cls.state == ca_dedicated)
1511 // if already loaded just return it, otherwise make a new skinframe
1512 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*bitsperpixel/8) : 0, true);
1513 if (skinframe && skinframe->base)
1516 skinframe->stain = NULL;
1517 skinframe->merged = NULL;
1518 skinframe->base = r_texture_notexture;
1519 skinframe->pants = NULL;
1520 skinframe->shirt = NULL;
1521 skinframe->nmap = r_texture_blanknormalmap;
1522 skinframe->gloss = NULL;
1523 skinframe->glow = NULL;
1524 skinframe->fog = NULL;
1526 // if no data was provided, then clearly the caller wanted to get a blank skinframe
1530 if (bitsperpixel == 32)
1532 if (r_shadow_bumpscale_basetexture.value > 0)
1534 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
1535 temp2 = temp1 + width * height * 4;
1536 Image_HeightmapToNormalmap(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
1537 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_RGBA, skinframe->textureflags | TEXF_ALPHA, NULL);
1540 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_RGBA, skinframe->textureflags, NULL);
1541 if (textureflags & TEXF_ALPHA)
1543 for (i = 3;i < width * height * 4;i += 4)
1544 if (skindata[i] < 255)
1546 if (i < width * height * 4)
1548 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
1549 memcpy(fogpixels, skindata, width * height * 4);
1550 for (i = 0;i < width * height * 4;i += 4)
1551 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
1552 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_RGBA, skinframe->textureflags, NULL);
1553 Mem_Free(fogpixels);
1557 else if (bitsperpixel == 8)
1559 if (r_shadow_bumpscale_basetexture.value > 0)
1561 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
1562 temp2 = temp1 + width * height * 4;
1563 if (bitsperpixel == 32)
1564 Image_HeightmapToNormalmap(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
1567 // use either a custom palette or the quake palette
1568 Image_Copy8bitRGBA(skindata, temp1, width * height, palette ? palette : palette_complete);
1569 Image_HeightmapToNormalmap(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
1571 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_RGBA, skinframe->textureflags | TEXF_ALPHA, NULL);
1574 // use either a custom palette, or the quake palette
1575 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
1576 if (!palette && loadglowtexture)
1577 skinframe->glow = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_glow", skinframe->basename), palette_onlyfullbrights, skinframe->textureflags, false); // glow
1578 if (!palette && loadpantsandshirt)
1580 skinframe->pants = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_pants", skinframe->basename), palette_pantsaswhite, skinframe->textureflags, false); // pants
1581 skinframe->shirt = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_shirt", skinframe->basename), palette_shirtaswhite, skinframe->textureflags, false); // shirt
1583 if (skinframe->pants || skinframe->shirt)
1584 skinframe->base = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_nospecial", skinframe->basename),loadglowtexture ? palette_nocolormapnofullbrights : palette_nocolormap, skinframe->textureflags, false); // no special colors
1585 if (textureflags & TEXF_ALPHA)
1587 // if not using a custom alphapalette, use the quake one
1589 alphapalette = palette_alpha;
1590 for (i = 0;i < width * height;i++)
1591 if (((unsigned char *)alphapalette)[skindata[i]*4+3] < 255)
1593 if (i < width * height)
1594 skinframe->fog = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_fog", skinframe->basename), alphapalette, skinframe->textureflags, true); // fog mask
1601 skinframe_t *R_SkinFrame_LoadMissing(void)
1603 skinframe_t *skinframe;
1605 if (cls.state == ca_dedicated)
1608 skinframe = R_SkinFrame_Find("missing", TEXF_PRECACHE, 0, 0, 0, true);
1609 skinframe->stain = NULL;
1610 skinframe->merged = NULL;
1611 skinframe->base = r_texture_notexture;
1612 skinframe->pants = NULL;
1613 skinframe->shirt = NULL;
1614 skinframe->nmap = r_texture_blanknormalmap;
1615 skinframe->gloss = NULL;
1616 skinframe->glow = NULL;
1617 skinframe->fog = NULL;
1622 void gl_main_start(void)
1627 r = (-1.0/256.0) * (FOGMASKTABLEWIDTH * FOGMASKTABLEWIDTH);
1628 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
1630 alpha = 1 - exp(r / ((double)x*(double)x));
1631 if (x == FOGMASKTABLEWIDTH - 1)
1633 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
1636 memset(r_qwskincache, 0, sizeof(r_qwskincache));
1637 memset(r_qwskincache_skinframe, 0, sizeof(r_qwskincache_skinframe));
1639 // set up r_skinframe loading system for textures
1640 memset(&r_skinframe, 0, sizeof(r_skinframe));
1641 r_skinframe.loadsequence = 1;
1642 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
1644 r_main_texturepool = R_AllocTexturePool();
1645 R_BuildBlankTextures();
1647 if (gl_texturecubemap)
1650 R_BuildNormalizationCube();
1652 R_BuildFogTexture();
1653 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
1654 memset(&r_waterstate, 0, sizeof(r_waterstate));
1655 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
1656 memset(&r_svbsp, 0, sizeof (r_svbsp));
1659 void gl_main_shutdown(void)
1661 memset(r_qwskincache, 0, sizeof(r_qwskincache));
1662 memset(r_qwskincache_skinframe, 0, sizeof(r_qwskincache_skinframe));
1664 // clear out the r_skinframe state
1665 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
1666 memset(&r_skinframe, 0, sizeof(r_skinframe));
1669 Mem_Free(r_svbsp.nodes);
1670 memset(&r_svbsp, 0, sizeof (r_svbsp));
1671 R_FreeTexturePool(&r_main_texturepool);
1672 r_texture_blanknormalmap = NULL;
1673 r_texture_white = NULL;
1674 r_texture_grey128 = NULL;
1675 r_texture_black = NULL;
1676 r_texture_whitecube = NULL;
1677 r_texture_normalizationcube = NULL;
1678 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
1679 memset(&r_waterstate, 0, sizeof(r_waterstate));
1683 extern void CL_ParseEntityLump(char *entitystring);
1684 void gl_main_newmap(void)
1686 // FIXME: move this code to client
1688 char *entities, entname[MAX_QPATH];
1691 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
1692 l = (int)strlen(entname) - 4;
1693 if (l >= 0 && !strcmp(entname + l, ".bsp"))
1695 memcpy(entname + l, ".ent", 5);
1696 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
1698 CL_ParseEntityLump(entities);
1703 if (cl.worldmodel->brush.entities)
1704 CL_ParseEntityLump(cl.worldmodel->brush.entities);
1708 void GL_Main_Init(void)
1710 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
1712 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
1713 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
1714 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
1715 if (gamemode == GAME_NEHAHRA)
1717 Cvar_RegisterVariable (&gl_fogenable);
1718 Cvar_RegisterVariable (&gl_fogdensity);
1719 Cvar_RegisterVariable (&gl_fogred);
1720 Cvar_RegisterVariable (&gl_foggreen);
1721 Cvar_RegisterVariable (&gl_fogblue);
1722 Cvar_RegisterVariable (&gl_fogstart);
1723 Cvar_RegisterVariable (&gl_fogend);
1725 Cvar_RegisterVariable(&r_depthfirst);
1726 Cvar_RegisterVariable(&r_nearclip);
1727 Cvar_RegisterVariable(&r_showbboxes);
1728 Cvar_RegisterVariable(&r_showsurfaces);
1729 Cvar_RegisterVariable(&r_showtris);
1730 Cvar_RegisterVariable(&r_shownormals);
1731 Cvar_RegisterVariable(&r_showlighting);
1732 Cvar_RegisterVariable(&r_showshadowvolumes);
1733 Cvar_RegisterVariable(&r_showcollisionbrushes);
1734 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
1735 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
1736 Cvar_RegisterVariable(&r_showdisabledepthtest);
1737 Cvar_RegisterVariable(&r_drawportals);
1738 Cvar_RegisterVariable(&r_drawentities);
1739 Cvar_RegisterVariable(&r_cullentities_trace);
1740 Cvar_RegisterVariable(&r_cullentities_trace_samples);
1741 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
1742 Cvar_RegisterVariable(&r_cullentities_trace_delay);
1743 Cvar_RegisterVariable(&r_drawviewmodel);
1744 Cvar_RegisterVariable(&r_speeds);
1745 Cvar_RegisterVariable(&r_fullbrights);
1746 Cvar_RegisterVariable(&r_wateralpha);
1747 Cvar_RegisterVariable(&r_dynamic);
1748 Cvar_RegisterVariable(&r_fullbright);
1749 Cvar_RegisterVariable(&r_shadows);
1750 Cvar_RegisterVariable(&r_shadows_throwdistance);
1751 Cvar_RegisterVariable(&r_q1bsp_skymasking);
1752 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
1753 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
1754 Cvar_RegisterVariable(&r_textureunits);
1755 Cvar_RegisterVariable(&r_glsl);
1756 Cvar_RegisterVariable(&r_glsl_offsetmapping);
1757 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
1758 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
1759 Cvar_RegisterVariable(&r_glsl_deluxemapping);
1760 Cvar_RegisterVariable(&r_water);
1761 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
1762 Cvar_RegisterVariable(&r_water_clippingplanebias);
1763 Cvar_RegisterVariable(&r_water_refractdistort);
1764 Cvar_RegisterVariable(&r_water_reflectdistort);
1765 Cvar_RegisterVariable(&r_lerpsprites);
1766 Cvar_RegisterVariable(&r_lerpmodels);
1767 Cvar_RegisterVariable(&r_waterscroll);
1768 Cvar_RegisterVariable(&r_bloom);
1769 Cvar_RegisterVariable(&r_bloom_colorscale);
1770 Cvar_RegisterVariable(&r_bloom_brighten);
1771 Cvar_RegisterVariable(&r_bloom_blur);
1772 Cvar_RegisterVariable(&r_bloom_resolution);
1773 Cvar_RegisterVariable(&r_bloom_colorexponent);
1774 Cvar_RegisterVariable(&r_bloom_colorsubtract);
1775 Cvar_RegisterVariable(&r_hdr);
1776 Cvar_RegisterVariable(&r_hdr_scenebrightness);
1777 Cvar_RegisterVariable(&r_glsl_contrastboost);
1778 Cvar_RegisterVariable(&r_hdr_glowintensity);
1779 Cvar_RegisterVariable(&r_hdr_range);
1780 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
1781 Cvar_RegisterVariable(&developer_texturelogging);
1782 Cvar_RegisterVariable(&gl_lightmaps);
1783 Cvar_RegisterVariable(&r_test);
1784 Cvar_RegisterVariable(&r_batchmode);
1785 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
1786 Cvar_SetValue("r_fullbrights", 0);
1787 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
1790 extern void R_Textures_Init(void);
1791 extern void GL_Draw_Init(void);
1792 extern void GL_Main_Init(void);
1793 extern void R_Shadow_Init(void);
1794 extern void R_Sky_Init(void);
1795 extern void GL_Surf_Init(void);
1796 extern void R_Light_Init(void);
1797 extern void R_Particles_Init(void);
1798 extern void R_Explosion_Init(void);
1799 extern void gl_backend_init(void);
1800 extern void Sbar_Init(void);
1801 extern void R_LightningBeams_Init(void);
1802 extern void Mod_RenderInit(void);
1804 void Render_Init(void)
1817 R_LightningBeams_Init();
1826 extern char *ENGINE_EXTENSIONS;
1829 VID_CheckExtensions();
1831 // LordHavoc: report supported extensions
1832 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
1834 // clear to black (loading plaque will be seen over this)
1836 qglClearColor(0,0,0,1);CHECKGLERROR
1837 qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
1840 int R_CullBox(const vec3_t mins, const vec3_t maxs)
1844 for (i = 0;i < r_view.numfrustumplanes;i++)
1846 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
1849 p = r_view.frustum + i;
1854 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1858 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1862 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1866 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1870 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1874 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1878 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1882 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1890 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
1894 for (i = 0;i < numplanes;i++)
1901 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1905 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1909 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1913 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1917 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1921 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1925 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1929 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1937 //==================================================================================
1939 static void R_UpdateEntityLighting(entity_render_t *ent)
1941 vec3_t tempdiffusenormal;
1943 // fetch the lighting from the worldmodel data
1944 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));
1945 VectorClear(ent->modellight_diffuse);
1946 VectorClear(tempdiffusenormal);
1947 if ((ent->flags & RENDER_LIGHT) && r_refdef.worldmodel && r_refdef.worldmodel->brush.LightPoint)
1950 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
1951 r_refdef.worldmodel->brush.LightPoint(r_refdef.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
1954 VectorSet(ent->modellight_ambient, 1, 1, 1);
1956 // move the light direction into modelspace coordinates for lighting code
1957 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
1958 if(VectorLength2(ent->modellight_lightdir) > 0)
1960 VectorNormalize(ent->modellight_lightdir);
1964 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
1967 // scale ambient and directional light contributions according to rendering variables
1968 ent->modellight_ambient[0] *= ent->colormod[0] * r_refdef.lightmapintensity;
1969 ent->modellight_ambient[1] *= ent->colormod[1] * r_refdef.lightmapintensity;
1970 ent->modellight_ambient[2] *= ent->colormod[2] * r_refdef.lightmapintensity;
1971 ent->modellight_diffuse[0] *= ent->colormod[0] * r_refdef.lightmapintensity;
1972 ent->modellight_diffuse[1] *= ent->colormod[1] * r_refdef.lightmapintensity;
1973 ent->modellight_diffuse[2] *= ent->colormod[2] * r_refdef.lightmapintensity;
1976 static void R_View_UpdateEntityVisible (void)
1979 entity_render_t *ent;
1981 if (!r_drawentities.integer)
1984 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : ((chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL : RENDER_EXTERIORMODEL);
1985 if (r_refdef.worldmodel && r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs)
1987 // worldmodel can check visibility
1988 for (i = 0;i < r_refdef.numentities;i++)
1990 ent = r_refdef.entities[i];
1991 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));
1993 if(r_cullentities_trace.integer)
1995 for (i = 0;i < r_refdef.numentities;i++)
1997 ent = r_refdef.entities[i];
1998 if(r_viewcache.entityvisible[i] && !(ent->effects & EF_NODEPTHTEST) && !(ent->flags & RENDER_VIEWMODEL) && !(ent->model && (ent->model->name[0] == '*')))
2000 if(Mod_CanSeeBox_Trace(r_cullentities_trace_samples.integer, r_cullentities_trace_enlarge.value, r_refdef.worldmodel, r_view.origin, ent->mins, ent->maxs))
2001 ent->last_trace_visibility = realtime;
2002 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
2003 r_viewcache.entityvisible[i] = 0;
2010 // no worldmodel or it can't check visibility
2011 for (i = 0;i < r_refdef.numentities;i++)
2013 ent = r_refdef.entities[i];
2014 r_viewcache.entityvisible[i] = !(ent->flags & renderimask) && !R_CullBox(ent->mins, ent->maxs);
2018 // update entity lighting (even on hidden entities for r_shadows)
2019 for (i = 0;i < r_refdef.numentities;i++)
2020 R_UpdateEntityLighting(r_refdef.entities[i]);
2023 // only used if skyrendermasked, and normally returns false
2024 int R_DrawBrushModelsSky (void)
2027 entity_render_t *ent;
2029 if (!r_drawentities.integer)
2033 for (i = 0;i < r_refdef.numentities;i++)
2035 if (!r_viewcache.entityvisible[i])
2037 ent = r_refdef.entities[i];
2038 if (!ent->model || !ent->model->DrawSky)
2040 ent->model->DrawSky(ent);
2046 static void R_DrawNoModel(entity_render_t *ent);
2047 static void R_DrawModels(void)
2050 entity_render_t *ent;
2052 if (!r_drawentities.integer)
2055 for (i = 0;i < r_refdef.numentities;i++)
2057 if (!r_viewcache.entityvisible[i])
2059 ent = r_refdef.entities[i];
2060 r_refdef.stats.entities++;
2061 if (ent->model && ent->model->Draw != NULL)
2062 ent->model->Draw(ent);
2068 static void R_DrawModelsDepth(void)
2071 entity_render_t *ent;
2073 if (!r_drawentities.integer)
2076 for (i = 0;i < r_refdef.numentities;i++)
2078 if (!r_viewcache.entityvisible[i])
2080 ent = r_refdef.entities[i];
2081 r_refdef.stats.entities++;
2082 if (ent->model && ent->model->DrawDepth != NULL)
2083 ent->model->DrawDepth(ent);
2087 static void R_DrawModelsDebug(void)
2090 entity_render_t *ent;
2092 if (!r_drawentities.integer)
2095 for (i = 0;i < r_refdef.numentities;i++)
2097 if (!r_viewcache.entityvisible[i])
2099 ent = r_refdef.entities[i];
2100 r_refdef.stats.entities++;
2101 if (ent->model && ent->model->DrawDebug != NULL)
2102 ent->model->DrawDebug(ent);
2106 static void R_DrawModelsAddWaterPlanes(void)
2109 entity_render_t *ent;
2111 if (!r_drawentities.integer)
2114 for (i = 0;i < r_refdef.numentities;i++)
2116 if (!r_viewcache.entityvisible[i])
2118 ent = r_refdef.entities[i];
2119 r_refdef.stats.entities++;
2120 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
2121 ent->model->DrawAddWaterPlanes(ent);
2125 static void R_View_SetFrustum(void)
2128 double slopex, slopey;
2130 // break apart the view matrix into vectors for various purposes
2131 Matrix4x4_ToVectors(&r_view.matrix, r_view.forward, r_view.left, r_view.up, r_view.origin);
2132 VectorNegate(r_view.left, r_view.right);
2135 r_view.frustum[0].normal[0] = 0 - 1.0 / r_view.frustum_x;
2136 r_view.frustum[0].normal[1] = 0 - 0;
2137 r_view.frustum[0].normal[2] = -1 - 0;
2138 r_view.frustum[1].normal[0] = 0 + 1.0 / r_view.frustum_x;
2139 r_view.frustum[1].normal[1] = 0 + 0;
2140 r_view.frustum[1].normal[2] = -1 + 0;
2141 r_view.frustum[2].normal[0] = 0 - 0;
2142 r_view.frustum[2].normal[1] = 0 - 1.0 / r_view.frustum_y;
2143 r_view.frustum[2].normal[2] = -1 - 0;
2144 r_view.frustum[3].normal[0] = 0 + 0;
2145 r_view.frustum[3].normal[1] = 0 + 1.0 / r_view.frustum_y;
2146 r_view.frustum[3].normal[2] = -1 + 0;
2150 zNear = r_refdef.nearclip;
2151 nudge = 1.0 - 1.0 / (1<<23);
2152 r_view.frustum[4].normal[0] = 0 - 0;
2153 r_view.frustum[4].normal[1] = 0 - 0;
2154 r_view.frustum[4].normal[2] = -1 - -nudge;
2155 r_view.frustum[4].dist = 0 - -2 * zNear * nudge;
2156 r_view.frustum[5].normal[0] = 0 + 0;
2157 r_view.frustum[5].normal[1] = 0 + 0;
2158 r_view.frustum[5].normal[2] = -1 + -nudge;
2159 r_view.frustum[5].dist = 0 + -2 * zNear * nudge;
2165 r_view.frustum[0].normal[0] = m[3] - m[0];
2166 r_view.frustum[0].normal[1] = m[7] - m[4];
2167 r_view.frustum[0].normal[2] = m[11] - m[8];
2168 r_view.frustum[0].dist = m[15] - m[12];
2170 r_view.frustum[1].normal[0] = m[3] + m[0];
2171 r_view.frustum[1].normal[1] = m[7] + m[4];
2172 r_view.frustum[1].normal[2] = m[11] + m[8];
2173 r_view.frustum[1].dist = m[15] + m[12];
2175 r_view.frustum[2].normal[0] = m[3] - m[1];
2176 r_view.frustum[2].normal[1] = m[7] - m[5];
2177 r_view.frustum[2].normal[2] = m[11] - m[9];
2178 r_view.frustum[2].dist = m[15] - m[13];
2180 r_view.frustum[3].normal[0] = m[3] + m[1];
2181 r_view.frustum[3].normal[1] = m[7] + m[5];
2182 r_view.frustum[3].normal[2] = m[11] + m[9];
2183 r_view.frustum[3].dist = m[15] + m[13];
2185 r_view.frustum[4].normal[0] = m[3] - m[2];
2186 r_view.frustum[4].normal[1] = m[7] - m[6];
2187 r_view.frustum[4].normal[2] = m[11] - m[10];
2188 r_view.frustum[4].dist = m[15] - m[14];
2190 r_view.frustum[5].normal[0] = m[3] + m[2];
2191 r_view.frustum[5].normal[1] = m[7] + m[6];
2192 r_view.frustum[5].normal[2] = m[11] + m[10];
2193 r_view.frustum[5].dist = m[15] + m[14];
2198 if (r_view.useperspective)
2200 slopex = 1.0 / r_view.frustum_x;
2201 slopey = 1.0 / r_view.frustum_y;
2202 VectorMA(r_view.forward, -slopex, r_view.left, r_view.frustum[0].normal);
2203 VectorMA(r_view.forward, slopex, r_view.left, r_view.frustum[1].normal);
2204 VectorMA(r_view.forward, -slopey, r_view.up , r_view.frustum[2].normal);
2205 VectorMA(r_view.forward, slopey, r_view.up , r_view.frustum[3].normal);
2206 VectorCopy(r_view.forward, r_view.frustum[4].normal);
2208 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
2209 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, -1024 * slopex, r_view.left, -1024 * slopey, r_view.up, r_view.frustumcorner[0]);
2210 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, 1024 * slopex, r_view.left, -1024 * slopey, r_view.up, r_view.frustumcorner[1]);
2211 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, -1024 * slopex, r_view.left, 1024 * slopey, r_view.up, r_view.frustumcorner[2]);
2212 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, 1024 * slopex, r_view.left, 1024 * slopey, r_view.up, r_view.frustumcorner[3]);
2214 r_view.frustum[0].dist = DotProduct (r_view.origin, r_view.frustum[0].normal);
2215 r_view.frustum[1].dist = DotProduct (r_view.origin, r_view.frustum[1].normal);
2216 r_view.frustum[2].dist = DotProduct (r_view.origin, r_view.frustum[2].normal);
2217 r_view.frustum[3].dist = DotProduct (r_view.origin, r_view.frustum[3].normal);
2218 r_view.frustum[4].dist = DotProduct (r_view.origin, r_view.frustum[4].normal) + r_refdef.nearclip;
2222 VectorScale(r_view.left, -r_view.ortho_x, r_view.frustum[0].normal);
2223 VectorScale(r_view.left, r_view.ortho_x, r_view.frustum[1].normal);
2224 VectorScale(r_view.up, -r_view.ortho_y, r_view.frustum[2].normal);
2225 VectorScale(r_view.up, r_view.ortho_y, r_view.frustum[3].normal);
2226 VectorCopy(r_view.forward, r_view.frustum[4].normal);
2227 r_view.frustum[0].dist = DotProduct (r_view.origin, r_view.frustum[0].normal) + r_view.ortho_x;
2228 r_view.frustum[1].dist = DotProduct (r_view.origin, r_view.frustum[1].normal) + r_view.ortho_x;
2229 r_view.frustum[2].dist = DotProduct (r_view.origin, r_view.frustum[2].normal) + r_view.ortho_y;
2230 r_view.frustum[3].dist = DotProduct (r_view.origin, r_view.frustum[3].normal) + r_view.ortho_y;
2231 r_view.frustum[4].dist = DotProduct (r_view.origin, r_view.frustum[4].normal) + r_refdef.nearclip;
2233 r_view.numfrustumplanes = 5;
2235 if (r_view.useclipplane)
2237 r_view.numfrustumplanes = 6;
2238 r_view.frustum[5] = r_view.clipplane;
2241 for (i = 0;i < r_view.numfrustumplanes;i++)
2242 PlaneClassify(r_view.frustum + i);
2244 // LordHavoc: note to all quake engine coders, Quake had a special case
2245 // for 90 degrees which assumed a square view (wrong), so I removed it,
2246 // Quake2 has it disabled as well.
2248 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
2249 //RotatePointAroundVector( r_view.frustum[0].normal, r_view.up, r_view.forward, -(90 - r_refdef.fov_x / 2));
2250 //r_view.frustum[0].dist = DotProduct (r_view.origin, frustum[0].normal);
2251 //PlaneClassify(&frustum[0]);
2253 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
2254 //RotatePointAroundVector( r_view.frustum[1].normal, r_view.up, r_view.forward, (90 - r_refdef.fov_x / 2));
2255 //r_view.frustum[1].dist = DotProduct (r_view.origin, frustum[1].normal);
2256 //PlaneClassify(&frustum[1]);
2258 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
2259 //RotatePointAroundVector( r_view.frustum[2].normal, r_view.left, r_view.forward, -(90 - r_refdef.fov_y / 2));
2260 //r_view.frustum[2].dist = DotProduct (r_view.origin, frustum[2].normal);
2261 //PlaneClassify(&frustum[2]);
2263 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
2264 //RotatePointAroundVector( r_view.frustum[3].normal, r_view.left, r_view.forward, (90 - r_refdef.fov_y / 2));
2265 //r_view.frustum[3].dist = DotProduct (r_view.origin, frustum[3].normal);
2266 //PlaneClassify(&frustum[3]);
2269 //VectorCopy(r_view.forward, r_view.frustum[4].normal);
2270 //r_view.frustum[4].dist = DotProduct (r_view.origin, frustum[4].normal) + r_nearclip.value;
2271 //PlaneClassify(&frustum[4]);
2274 void R_View_Update(void)
2276 R_View_SetFrustum();
2277 R_View_WorldVisibility(r_view.useclipplane);
2278 R_View_UpdateEntityVisible();
2281 void R_SetupView(void)
2283 if (!r_view.useperspective)
2284 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);
2285 else if (r_refdef.rtworldshadows || r_refdef.rtdlightshadows)
2286 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_view.frustum_x, r_view.frustum_y, r_refdef.nearclip);
2288 GL_SetupView_Mode_Perspective(r_view.frustum_x, r_view.frustum_y, r_refdef.nearclip, r_refdef.farclip);
2290 GL_SetupView_Orientation_FromEntity(&r_view.matrix);
2292 if (r_view.useclipplane)
2294 // LordHavoc: couldn't figure out how to make this approach the
2295 vec_t dist = r_view.clipplane.dist - r_water_clippingplanebias.value;
2296 vec_t viewdist = DotProduct(r_view.origin, r_view.clipplane.normal);
2297 if (viewdist < r_view.clipplane.dist + r_water_clippingplanebias.value)
2298 dist = r_view.clipplane.dist;
2299 GL_SetupView_ApplyCustomNearClipPlane(r_view.clipplane.normal[0], r_view.clipplane.normal[1], r_view.clipplane.normal[2], dist);
2303 void R_ResetViewRendering2D(void)
2305 if (gl_support_fragment_shader)
2307 qglUseProgramObjectARB(0);CHECKGLERROR
2312 // GL is weird because it's bottom to top, r_view.y is top to bottom
2313 qglViewport(r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
2314 GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
2315 GL_Scissor(r_view.x, r_view.y, r_view.width, r_view.height);
2316 GL_Color(1, 1, 1, 1);
2317 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
2318 GL_BlendFunc(GL_ONE, GL_ZERO);
2319 GL_AlphaTest(false);
2320 GL_ScissorTest(false);
2321 GL_DepthMask(false);
2322 GL_DepthRange(0, 1);
2323 GL_DepthTest(false);
2324 R_Mesh_Matrix(&identitymatrix);
2325 R_Mesh_ResetTextureState();
2326 GL_PolygonOffset(0, 0);
2327 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
2328 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
2329 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
2330 qglStencilMask(~0);CHECKGLERROR
2331 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
2332 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
2333 GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
2336 void R_ResetViewRendering3D(void)
2338 if (gl_support_fragment_shader)
2340 qglUseProgramObjectARB(0);CHECKGLERROR
2345 // GL is weird because it's bottom to top, r_view.y is top to bottom
2346 qglViewport(r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
2348 GL_Scissor(r_view.x, r_view.y, r_view.width, r_view.height);
2349 GL_Color(1, 1, 1, 1);
2350 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
2351 GL_BlendFunc(GL_ONE, GL_ZERO);
2352 GL_AlphaTest(false);
2353 GL_ScissorTest(true);
2355 GL_DepthRange(0, 1);
2357 R_Mesh_Matrix(&identitymatrix);
2358 R_Mesh_ResetTextureState();
2359 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
2360 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
2361 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
2362 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
2363 qglStencilMask(~0);CHECKGLERROR
2364 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
2365 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
2366 GL_CullFace(r_view.cullface_back);
2370 R_Bloom_SetupShader(
2372 "// written by Forest 'LordHavoc' Hale\n"
2374 "// common definitions between vertex shader and fragment shader:\n"
2376 "#ifdef __GLSL_CG_DATA_TYPES\n"
2377 "#define myhalf half\n"
2378 "#define myhvec2 hvec2\n"
2379 "#define myhvec3 hvec3\n"
2380 "#define myhvec4 hvec4\n"
2382 "#define myhalf float\n"
2383 "#define myhvec2 vec2\n"
2384 "#define myhvec3 vec3\n"
2385 "#define myhvec4 vec4\n"
2388 "varying vec2 ScreenTexCoord;\n"
2389 "varying vec2 BloomTexCoord;\n"
2394 "// vertex shader specific:\n"
2395 "#ifdef VERTEX_SHADER\n"
2399 " ScreenTexCoord = vec2(gl_MultiTexCoord0);\n"
2400 " BloomTexCoord = vec2(gl_MultiTexCoord1);\n"
2401 " // transform vertex to camera space, using ftransform to match non-VS\n"
2403 " gl_Position = ftransform();\n"
2406 "#endif // VERTEX_SHADER\n"
2411 "// fragment shader specific:\n"
2412 "#ifdef FRAGMENT_SHADER\n"
2417 " myhvec3 color = myhvec3(texture2D(Texture_Screen, ScreenTexCoord));\n"
2418 " for (x = -BLUR_X;x <= BLUR_X;x++)
2419 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2420 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2421 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2422 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2424 " gl_FragColor = vec4(color);\n"
2427 "#endif // FRAGMENT_SHADER\n"
2430 void R_RenderScene(qboolean addwaterplanes);
2432 static void R_Water_StartFrame(void)
2435 int waterwidth, waterheight, texturewidth, textureheight;
2436 r_waterstate_waterplane_t *p;
2438 // set waterwidth and waterheight to the water resolution that will be
2439 // used (often less than the screen resolution for faster rendering)
2440 waterwidth = (int)bound(1, r_view.width * r_water_resolutionmultiplier.value, r_view.width);
2441 waterheight = (int)bound(1, r_view.height * r_water_resolutionmultiplier.value, r_view.height);
2443 // calculate desired texture sizes
2444 // can't use water if the card does not support the texture size
2445 if (!r_water.integer || waterwidth > gl_max_texture_size || waterheight > gl_max_texture_size)
2446 texturewidth = textureheight = waterwidth = waterheight = 0;
2447 else if (gl_support_arb_texture_non_power_of_two)
2449 texturewidth = waterwidth;
2450 textureheight = waterheight;
2454 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
2455 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
2458 // allocate textures as needed
2459 if (r_waterstate.waterwidth != waterwidth || r_waterstate.waterheight != waterheight || r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight)
2461 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
2462 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
2464 if (p->texture_refraction)
2465 R_FreeTexture(p->texture_refraction);
2466 p->texture_refraction = NULL;
2467 if (p->texture_reflection)
2468 R_FreeTexture(p->texture_reflection);
2469 p->texture_reflection = NULL;
2471 memset(&r_waterstate, 0, sizeof(r_waterstate));
2472 r_waterstate.waterwidth = waterwidth;
2473 r_waterstate.waterheight = waterheight;
2474 r_waterstate.texturewidth = texturewidth;
2475 r_waterstate.textureheight = textureheight;
2478 if (r_waterstate.waterwidth)
2480 r_waterstate.enabled = true;
2482 // set up variables that will be used in shader setup
2483 r_waterstate.screenscale[0] = 0.5f * (float)waterwidth / (float)texturewidth;
2484 r_waterstate.screenscale[1] = 0.5f * (float)waterheight / (float)textureheight;
2485 r_waterstate.screencenter[0] = 0.5f * (float)waterwidth / (float)texturewidth;
2486 r_waterstate.screencenter[1] = 0.5f * (float)waterheight / (float)textureheight;
2489 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
2490 r_waterstate.numwaterplanes = 0;
2493 static void R_Water_AddWaterPlane(msurface_t *surface)
2495 int triangleindex, planeindex;
2501 r_waterstate_waterplane_t *p;
2502 // just use the first triangle with a valid normal for any decisions
2503 VectorClear(normal);
2504 VectorClear(center);
2505 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
2507 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
2508 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
2509 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
2510 TriangleNormal(vert[0], vert[1], vert[2], normal);
2511 if (VectorLength2(normal) >= 0.001)
2514 // now find the center of this surface
2515 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles*3;triangleindex++, e++)
2517 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
2518 VectorAdd(center, vert[0], center);
2520 f = 1.0 / surface->num_triangles*3;
2521 VectorScale(center, f, center);
2523 // find a matching plane if there is one
2524 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
2525 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
2527 if (planeindex >= r_waterstate.maxwaterplanes)
2528 return; // nothing we can do, out of planes
2530 // if this triangle does not fit any known plane rendered this frame, add one
2531 if (planeindex >= r_waterstate.numwaterplanes)
2533 // store the new plane
2534 r_waterstate.numwaterplanes++;
2535 VectorCopy(normal, p->plane.normal);
2536 VectorNormalize(p->plane.normal);
2537 p->plane.dist = DotProduct(vert[0], p->plane.normal);
2538 PlaneClassify(&p->plane);
2539 // flip the plane if it does not face the viewer
2540 if (PlaneDiff(r_view.origin, &p->plane) < 0)
2542 VectorNegate(p->plane.normal, p->plane.normal);
2543 p->plane.dist *= -1;
2544 PlaneClassify(&p->plane);
2546 // clear materialflags and pvs
2547 p->materialflags = 0;
2548 p->pvsvalid = false;
2550 // merge this surface's materialflags into the waterplane
2551 p->materialflags |= surface->texture->currentframe->currentmaterialflags;
2552 // merge this surface's PVS into the waterplane
2553 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION) && r_refdef.worldmodel && r_refdef.worldmodel->brush.FatPVS)
2555 r_refdef.worldmodel->brush.FatPVS(r_refdef.worldmodel, r_view.origin, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
2560 static void R_Water_ProcessPlanes(void)
2562 r_view_t originalview;
2564 r_waterstate_waterplane_t *p;
2566 originalview = r_view;
2568 // make sure enough textures are allocated
2569 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
2571 if (p->materialflags & MATERIALFLAG_WATERSHADER)
2573 if (!p->texture_refraction)
2574 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);
2575 if (!p->texture_refraction)
2579 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
2581 if (!p->texture_reflection)
2582 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);
2583 if (!p->texture_reflection)
2589 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
2591 r_view.showdebug = false;
2592 r_view.width = r_waterstate.waterwidth;
2593 r_view.height = r_waterstate.waterheight;
2594 r_view.useclipplane = true;
2595 r_waterstate.renderingscene = true;
2597 // render the normal view scene and copy into texture
2598 // (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)
2599 if (p->materialflags & MATERIALFLAG_WATERSHADER)
2601 r_view.clipplane = p->plane;
2602 VectorNegate(r_view.clipplane.normal, r_view.clipplane.normal);
2603 r_view.clipplane.dist = -r_view.clipplane.dist;
2604 PlaneClassify(&r_view.clipplane);
2606 R_RenderScene(false);
2608 // copy view into the screen texture
2609 R_Mesh_TexBind(0, R_GetTexture(p->texture_refraction));
2610 GL_ActiveTexture(0);
2612 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
2615 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
2617 // render reflected scene and copy into texture
2618 Matrix4x4_Reflect(&r_view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
2619 r_view.clipplane = p->plane;
2620 // reverse the cullface settings for this render
2621 r_view.cullface_front = GL_FRONT;
2622 r_view.cullface_back = GL_BACK;
2623 if (r_refdef.worldmodel && r_refdef.worldmodel->brush.num_pvsclusterbytes)
2625 r_view.usecustompvs = true;
2627 memcpy(r_viewcache.world_pvsbits, p->pvsbits, r_refdef.worldmodel->brush.num_pvsclusterbytes);
2629 memset(r_viewcache.world_pvsbits, 0xFF, r_refdef.worldmodel->brush.num_pvsclusterbytes);
2632 R_ResetViewRendering3D();
2635 R_RenderScene(false);
2637 R_Mesh_TexBind(0, R_GetTexture(p->texture_reflection));
2638 GL_ActiveTexture(0);
2640 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
2642 R_ResetViewRendering3D();
2646 r_view = originalview;
2647 r_waterstate.renderingscene = false;
2651 r_view = originalview;
2652 r_waterstate.renderingscene = false;
2653 Cvar_SetValueQuick(&r_water, 0);
2654 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
2658 void R_Bloom_StartFrame(void)
2660 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
2662 // set bloomwidth and bloomheight to the bloom resolution that will be
2663 // used (often less than the screen resolution for faster rendering)
2664 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_view.width);
2665 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_view.height / r_view.width;
2666 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_view.height);
2668 // calculate desired texture sizes
2669 if (gl_support_arb_texture_non_power_of_two)
2671 screentexturewidth = r_view.width;
2672 screentextureheight = r_view.height;
2673 bloomtexturewidth = r_bloomstate.bloomwidth;
2674 bloomtextureheight = r_bloomstate.bloomheight;
2678 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
2679 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
2680 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
2681 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
2686 screentexturewidth = screentextureheight = 0;
2688 else if (r_bloom.integer)
2693 screentexturewidth = screentextureheight = 0;
2694 bloomtexturewidth = bloomtextureheight = 0;
2697 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)
2699 // can't use bloom if the parameters are too weird
2700 // can't use bloom if the card does not support the texture size
2701 if (r_bloomstate.texture_screen)
2702 R_FreeTexture(r_bloomstate.texture_screen);
2703 if (r_bloomstate.texture_bloom)
2704 R_FreeTexture(r_bloomstate.texture_bloom);
2705 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
2709 r_bloomstate.enabled = true;
2710 r_bloomstate.hdr = r_hdr.integer != 0;
2712 // allocate textures as needed
2713 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
2715 if (r_bloomstate.texture_screen)
2716 R_FreeTexture(r_bloomstate.texture_screen);
2717 r_bloomstate.texture_screen = NULL;
2718 r_bloomstate.screentexturewidth = screentexturewidth;
2719 r_bloomstate.screentextureheight = screentextureheight;
2720 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
2721 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);
2723 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
2725 if (r_bloomstate.texture_bloom)
2726 R_FreeTexture(r_bloomstate.texture_bloom);
2727 r_bloomstate.texture_bloom = NULL;
2728 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
2729 r_bloomstate.bloomtextureheight = bloomtextureheight;
2730 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
2731 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);
2734 // set up a texcoord array for the full resolution screen image
2735 // (we have to keep this around to copy back during final render)
2736 r_bloomstate.screentexcoord2f[0] = 0;
2737 r_bloomstate.screentexcoord2f[1] = (float)r_view.height / (float)r_bloomstate.screentextureheight;
2738 r_bloomstate.screentexcoord2f[2] = (float)r_view.width / (float)r_bloomstate.screentexturewidth;
2739 r_bloomstate.screentexcoord2f[3] = (float)r_view.height / (float)r_bloomstate.screentextureheight;
2740 r_bloomstate.screentexcoord2f[4] = (float)r_view.width / (float)r_bloomstate.screentexturewidth;
2741 r_bloomstate.screentexcoord2f[5] = 0;
2742 r_bloomstate.screentexcoord2f[6] = 0;
2743 r_bloomstate.screentexcoord2f[7] = 0;
2745 // set up a texcoord array for the reduced resolution bloom image
2746 // (which will be additive blended over the screen image)
2747 r_bloomstate.bloomtexcoord2f[0] = 0;
2748 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
2749 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
2750 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
2751 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
2752 r_bloomstate.bloomtexcoord2f[5] = 0;
2753 r_bloomstate.bloomtexcoord2f[6] = 0;
2754 r_bloomstate.bloomtexcoord2f[7] = 0;
2757 void R_Bloom_CopyScreenTexture(float colorscale)
2759 r_refdef.stats.bloom++;
2761 R_ResetViewRendering2D();
2762 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
2763 R_Mesh_ColorPointer(NULL, 0, 0);
2764 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
2765 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
2767 // copy view into the screen texture
2768 GL_ActiveTexture(0);
2770 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
2771 r_refdef.stats.bloom_copypixels += r_view.width * r_view.height;
2773 // now scale it down to the bloom texture size
2775 qglViewport(r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
2776 GL_BlendFunc(GL_ONE, GL_ZERO);
2777 GL_Color(colorscale, colorscale, colorscale, 1);
2778 // TODO: optimize with multitexture or GLSL
2779 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2780 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2782 // we now have a bloom image in the framebuffer
2783 // copy it into the bloom image texture for later processing
2784 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2785 GL_ActiveTexture(0);
2787 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
2788 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2791 void R_Bloom_CopyHDRTexture(void)
2793 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2794 GL_ActiveTexture(0);
2796 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
2797 r_refdef.stats.bloom_copypixels += r_view.width * r_view.height;
2800 void R_Bloom_MakeTexture(void)
2803 float xoffset, yoffset, r, brighten;
2805 r_refdef.stats.bloom++;
2807 R_ResetViewRendering2D();
2808 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
2809 R_Mesh_ColorPointer(NULL, 0, 0);
2811 // we have a bloom image in the framebuffer
2813 qglViewport(r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
2815 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
2818 r = bound(0, r_bloom_colorexponent.value / x, 1);
2819 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
2820 GL_Color(r, r, r, 1);
2821 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2822 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
2823 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2824 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2826 // copy the vertically blurred bloom view to a texture
2827 GL_ActiveTexture(0);
2829 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
2830 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2833 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
2834 brighten = r_bloom_brighten.value;
2836 brighten *= r_hdr_range.value;
2837 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2838 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
2840 for (dir = 0;dir < 2;dir++)
2842 // blend on at multiple vertical offsets to achieve a vertical blur
2843 // TODO: do offset blends using GLSL
2844 GL_BlendFunc(GL_ONE, GL_ZERO);
2845 for (x = -range;x <= range;x++)
2847 if (!dir){xoffset = 0;yoffset = x;}
2848 else {xoffset = x;yoffset = 0;}
2849 xoffset /= (float)r_bloomstate.bloomtexturewidth;
2850 yoffset /= (float)r_bloomstate.bloomtextureheight;
2851 // compute a texcoord array with the specified x and y offset
2852 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
2853 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
2854 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
2855 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
2856 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
2857 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
2858 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
2859 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
2860 // this r value looks like a 'dot' particle, fading sharply to
2861 // black at the edges
2862 // (probably not realistic but looks good enough)
2863 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
2864 //r = (dir ? 1.0f : brighten)/(range*2+1);
2865 r = (dir ? 1.0f : brighten)/(range*2+1)*(1 - x*x/(float)(range*range));
2866 GL_Color(r, r, r, 1);
2867 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2868 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2869 GL_BlendFunc(GL_ONE, GL_ONE);
2872 // copy the vertically blurred bloom view to a texture
2873 GL_ActiveTexture(0);
2875 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
2876 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2879 // apply subtract last
2880 // (just like it would be in a GLSL shader)
2881 if (r_bloom_colorsubtract.value > 0 && gl_support_ext_blend_subtract)
2883 GL_BlendFunc(GL_ONE, GL_ZERO);
2884 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2885 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
2886 GL_Color(1, 1, 1, 1);
2887 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2888 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2890 GL_BlendFunc(GL_ONE, GL_ONE);
2891 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
2892 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2893 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
2894 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
2895 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2896 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2897 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
2899 // copy the darkened bloom view to a texture
2900 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2901 GL_ActiveTexture(0);
2903 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
2904 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2908 void R_HDR_RenderBloomTexture(void)
2910 int oldwidth, oldheight;
2912 oldwidth = r_view.width;
2913 oldheight = r_view.height;
2914 r_view.width = r_bloomstate.bloomwidth;
2915 r_view.height = r_bloomstate.bloomheight;
2917 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
2918 // TODO: add exposure compensation features
2919 // TODO: add fp16 framebuffer support
2921 r_view.showdebug = false;
2922 r_view.colorscale = r_bloom_colorscale.value * r_hdr_scenebrightness.value;
2924 r_view.colorscale /= r_hdr_range.value;
2925 r_waterstate.numwaterplanes = 0;
2926 R_RenderScene(r_waterstate.enabled);
2927 r_view.showdebug = true;
2929 R_ResetViewRendering2D();
2931 R_Bloom_CopyHDRTexture();
2932 R_Bloom_MakeTexture();
2934 R_ResetViewRendering3D();
2937 if (r_timereport_active)
2938 R_TimeReport("clear");
2941 // restore the view settings
2942 r_view.width = oldwidth;
2943 r_view.height = oldheight;
2946 static void R_BlendView(void)
2948 if (r_bloomstate.enabled && r_bloomstate.hdr)
2950 // render high dynamic range bloom effect
2951 // the bloom texture was made earlier this render, so we just need to
2952 // blend it onto the screen...
2953 R_ResetViewRendering2D();
2954 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
2955 R_Mesh_ColorPointer(NULL, 0, 0);
2956 GL_Color(1, 1, 1, 1);
2957 GL_BlendFunc(GL_ONE, GL_ONE);
2958 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2959 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
2960 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2961 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
2963 else if (r_bloomstate.enabled)
2965 // render simple bloom effect
2966 // copy the screen and shrink it and darken it for the bloom process
2967 R_Bloom_CopyScreenTexture(r_bloom_colorscale.value);
2968 // make the bloom texture
2969 R_Bloom_MakeTexture();
2970 // put the original screen image back in place and blend the bloom
2972 R_ResetViewRendering2D();
2973 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
2974 R_Mesh_ColorPointer(NULL, 0, 0);
2975 GL_Color(1, 1, 1, 1);
2976 GL_BlendFunc(GL_ONE, GL_ZERO);
2977 // do both in one pass if possible
2978 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2979 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
2980 if (r_textureunits.integer >= 2 && gl_combine.integer)
2982 R_Mesh_TexCombine(1, GL_ADD, GL_ADD, 1, 1);
2983 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_screen));
2984 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.screentexcoord2f, 0, 0);
2988 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2989 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
2990 // now blend on the bloom texture
2991 GL_BlendFunc(GL_ONE, GL_ONE);
2992 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
2993 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
2995 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2996 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
2998 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
3000 // apply a color tint to the whole view
3001 R_ResetViewRendering2D();
3002 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3003 R_Mesh_ColorPointer(NULL, 0, 0);
3004 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3005 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
3006 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3010 void R_RenderScene(qboolean addwaterplanes);
3012 matrix4x4_t r_waterscrollmatrix;
3014 void R_UpdateVariables(void)
3018 r_refdef.farclip = 4096;
3019 if (r_refdef.worldmodel)
3020 r_refdef.farclip += VectorDistance(r_refdef.worldmodel->normalmins, r_refdef.worldmodel->normalmaxs);
3021 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
3023 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
3024 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
3025 r_refdef.polygonfactor = 0;
3026 r_refdef.polygonoffset = 0;
3027 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
3028 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
3030 r_refdef.rtworld = r_shadow_realtime_world.integer;
3031 r_refdef.rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
3032 r_refdef.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
3033 r_refdef.rtdlightshadows = r_refdef.rtdlight && r_shadow_realtime_dlight_shadows.integer && gl_stencil;
3034 r_refdef.lightmapintensity = r_refdef.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
3035 if (r_showsurfaces.integer)
3037 r_refdef.rtworld = false;
3038 r_refdef.rtworldshadows = false;
3039 r_refdef.rtdlight = false;
3040 r_refdef.rtdlightshadows = false;
3041 r_refdef.lightmapintensity = 0;
3044 if (gamemode == GAME_NEHAHRA)
3046 if (gl_fogenable.integer)
3048 r_refdef.oldgl_fogenable = true;
3049 r_refdef.fog_density = gl_fogdensity.value;
3050 r_refdef.fog_red = gl_fogred.value;
3051 r_refdef.fog_green = gl_foggreen.value;
3052 r_refdef.fog_blue = gl_fogblue.value;
3054 else if (r_refdef.oldgl_fogenable)
3056 r_refdef.oldgl_fogenable = false;
3057 r_refdef.fog_density = 0;
3058 r_refdef.fog_red = 0;
3059 r_refdef.fog_green = 0;
3060 r_refdef.fog_blue = 0;
3063 if (r_refdef.fog_density)
3065 r_refdef.fogcolor[0] = bound(0.0f, r_refdef.fog_red , 1.0f);
3066 r_refdef.fogcolor[1] = bound(0.0f, r_refdef.fog_green, 1.0f);
3067 r_refdef.fogcolor[2] = bound(0.0f, r_refdef.fog_blue , 1.0f);
3069 if (r_refdef.fog_density)
3071 r_refdef.fogenabled = true;
3072 // this is the point where the fog reaches 0.9986 alpha, which we
3073 // consider a good enough cutoff point for the texture
3074 // (0.9986 * 256 == 255.6)
3075 r_refdef.fogrange = 400 / r_refdef.fog_density;
3076 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
3077 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
3078 // fog color was already set
3081 r_refdef.fogenabled = false;
3089 void R_RenderView(void)
3091 if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
3092 return; //Host_Error ("R_RenderView: NULL worldmodel");
3094 R_Shadow_UpdateWorldLightSelection();
3096 R_Bloom_StartFrame();
3097 R_Water_StartFrame();
3100 if (r_timereport_active)
3101 R_TimeReport("setup");
3103 R_ResetViewRendering3D();
3106 if (r_timereport_active)
3107 R_TimeReport("clear");
3109 r_view.showdebug = true;
3111 // this produces a bloom texture to be used in R_BlendView() later
3113 R_HDR_RenderBloomTexture();
3115 r_view.colorscale = r_hdr_scenebrightness.value;
3116 r_waterstate.numwaterplanes = 0;
3117 R_RenderScene(r_waterstate.enabled);
3120 if (r_timereport_active)
3121 R_TimeReport("blendview");
3123 GL_Scissor(0, 0, vid.width, vid.height);
3124 GL_ScissorTest(false);
3128 extern void R_DrawLightningBeams (void);
3129 extern void VM_CL_AddPolygonsToMeshQueue (void);
3130 extern void R_DrawPortals (void);
3131 extern cvar_t cl_locs_show;
3132 static void R_DrawLocs(void);
3133 static void R_DrawEntityBBoxes(void);
3134 void R_RenderScene(qboolean addwaterplanes)
3138 R_ResetViewRendering3D();
3141 if (r_timereport_active)
3142 R_TimeReport("watervisibility");
3144 if (cl.csqc_vidvars.drawworld && r_refdef.worldmodel && r_refdef.worldmodel->DrawAddWaterPlanes)
3146 r_refdef.worldmodel->DrawAddWaterPlanes(r_refdef.worldentity);
3147 if (r_timereport_active)
3148 R_TimeReport("waterworld");
3151 // don't let sound skip if going slow
3152 if (r_refdef.extraupdate)
3155 R_DrawModelsAddWaterPlanes();
3156 if (r_timereport_active)
3157 R_TimeReport("watermodels");
3159 R_Water_ProcessPlanes();
3160 if (r_timereport_active)
3161 R_TimeReport("waterscenes");
3164 R_ResetViewRendering3D();
3166 // don't let sound skip if going slow
3167 if (r_refdef.extraupdate)
3170 R_MeshQueue_BeginScene();
3175 if (r_timereport_active)
3176 R_TimeReport("visibility");
3178 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);
3180 if (cl.csqc_vidvars.drawworld)
3182 // don't let sound skip if going slow
3183 if (r_refdef.extraupdate)
3186 if (r_refdef.worldmodel && r_refdef.worldmodel->DrawSky)
3188 r_refdef.worldmodel->DrawSky(r_refdef.worldentity);
3189 if (r_timereport_active)
3190 R_TimeReport("worldsky");
3193 if (R_DrawBrushModelsSky() && r_timereport_active)
3194 R_TimeReport("bmodelsky");
3197 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.worldmodel && r_refdef.worldmodel->DrawDepth)
3199 r_refdef.worldmodel->DrawDepth(r_refdef.worldentity);
3200 if (r_timereport_active)
3201 R_TimeReport("worlddepth");
3203 if (r_depthfirst.integer >= 2)
3205 R_DrawModelsDepth();
3206 if (r_timereport_active)
3207 R_TimeReport("modeldepth");
3210 if (cl.csqc_vidvars.drawworld && r_refdef.worldmodel && r_refdef.worldmodel->Draw)
3212 r_refdef.worldmodel->Draw(r_refdef.worldentity);
3213 if (r_timereport_active)
3214 R_TimeReport("world");
3217 // don't let sound skip if going slow
3218 if (r_refdef.extraupdate)
3222 if (r_timereport_active)
3223 R_TimeReport("models");
3225 // don't let sound skip if going slow
3226 if (r_refdef.extraupdate)
3229 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
3231 R_DrawModelShadows();
3233 R_ResetViewRendering3D();
3235 // don't let sound skip if going slow
3236 if (r_refdef.extraupdate)
3240 R_ShadowVolumeLighting(false);
3241 if (r_timereport_active)
3242 R_TimeReport("rtlights");
3244 // don't let sound skip if going slow
3245 if (r_refdef.extraupdate)
3248 if (cl.csqc_vidvars.drawworld)
3250 R_DrawLightningBeams();
3251 if (r_timereport_active)
3252 R_TimeReport("lightning");
3255 if (r_timereport_active)
3256 R_TimeReport("particles");
3259 if (r_timereport_active)
3260 R_TimeReport("explosions");
3263 if (gl_support_fragment_shader)
3265 qglUseProgramObjectARB(0);CHECKGLERROR
3267 VM_CL_AddPolygonsToMeshQueue();
3269 if (r_view.showdebug)
3271 if (cl_locs_show.integer)
3274 if (r_timereport_active)
3275 R_TimeReport("showlocs");
3278 if (r_drawportals.integer)
3281 if (r_timereport_active)
3282 R_TimeReport("portals");
3285 if (r_showbboxes.value > 0)
3287 R_DrawEntityBBoxes();
3288 if (r_timereport_active)
3289 R_TimeReport("bboxes");
3293 if (gl_support_fragment_shader)
3295 qglUseProgramObjectARB(0);CHECKGLERROR
3297 R_MeshQueue_RenderTransparent();
3298 if (r_timereport_active)
3299 R_TimeReport("drawtrans");
3301 if (gl_support_fragment_shader)
3303 qglUseProgramObjectARB(0);CHECKGLERROR
3306 if (r_view.showdebug && r_refdef.worldmodel && r_refdef.worldmodel->DrawDebug && (r_showtris.value > 0 || r_shownormals.value > 0 || r_showcollisionbrushes.value > 0))
3308 r_refdef.worldmodel->DrawDebug(r_refdef.worldentity);
3309 if (r_timereport_active)
3310 R_TimeReport("worlddebug");
3311 R_DrawModelsDebug();
3312 if (r_timereport_active)
3313 R_TimeReport("modeldebug");
3316 if (gl_support_fragment_shader)
3318 qglUseProgramObjectARB(0);CHECKGLERROR
3321 if (cl.csqc_vidvars.drawworld)
3324 if (r_timereport_active)
3325 R_TimeReport("coronas");
3328 // don't let sound skip if going slow
3329 if (r_refdef.extraupdate)
3332 R_ResetViewRendering2D();
3335 static const int bboxelements[36] =
3345 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
3348 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
3349 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3350 GL_DepthMask(false);
3351 GL_DepthRange(0, 1);
3352 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3353 R_Mesh_Matrix(&identitymatrix);
3354 R_Mesh_ResetTextureState();
3356 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
3357 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
3358 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
3359 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
3360 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
3361 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
3362 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
3363 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
3364 R_FillColors(color4f, 8, cr, cg, cb, ca);
3365 if (r_refdef.fogenabled)
3367 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
3369 f1 = FogPoint_World(v);
3371 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
3372 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
3373 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
3376 R_Mesh_VertexPointer(vertex3f, 0, 0);
3377 R_Mesh_ColorPointer(color4f, 0, 0);
3378 R_Mesh_ResetTextureState();
3379 R_Mesh_Draw(0, 8, 12, bboxelements, 0, 0);
3382 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
3386 prvm_edict_t *edict;
3387 // this function draws bounding boxes of server entities
3391 for (i = 0;i < numsurfaces;i++)
3393 edict = PRVM_EDICT_NUM(surfacelist[i]);
3394 switch ((int)edict->fields.server->solid)
3396 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
3397 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
3398 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
3399 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
3400 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
3401 default: Vector4Set(color, 0, 0, 0, 0.50);break;
3403 color[3] *= r_showbboxes.value;
3404 color[3] = bound(0, color[3], 1);
3405 GL_DepthTest(!r_showdisabledepthtest.integer);
3406 GL_CullFace(r_view.cullface_front);
3407 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
3412 static void R_DrawEntityBBoxes(void)
3415 prvm_edict_t *edict;
3417 // this function draws bounding boxes of server entities
3421 for (i = 0;i < prog->num_edicts;i++)
3423 edict = PRVM_EDICT_NUM(i);
3424 if (edict->priv.server->free)
3426 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
3427 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
3432 int nomodelelements[24] =
3444 float nomodelvertex3f[6*3] =
3454 float nomodelcolor4f[6*4] =
3456 0.0f, 0.0f, 0.5f, 1.0f,
3457 0.0f, 0.0f, 0.5f, 1.0f,
3458 0.0f, 0.5f, 0.0f, 1.0f,
3459 0.0f, 0.5f, 0.0f, 1.0f,
3460 0.5f, 0.0f, 0.0f, 1.0f,
3461 0.5f, 0.0f, 0.0f, 1.0f
3464 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
3469 // this is only called once per entity so numsurfaces is always 1, and
3470 // surfacelist is always {0}, so this code does not handle batches
3471 R_Mesh_Matrix(&ent->matrix);
3473 if (ent->flags & EF_ADDITIVE)
3475 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
3476 GL_DepthMask(false);
3478 else if (ent->alpha < 1)
3480 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3481 GL_DepthMask(false);
3485 GL_BlendFunc(GL_ONE, GL_ZERO);
3488 GL_DepthRange(0, (ent->flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
3489 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3490 GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
3491 GL_CullFace((ent->effects & EF_DOUBLESIDED) ? GL_NONE : r_view.cullface_back);
3492 R_Mesh_VertexPointer(nomodelvertex3f, 0, 0);
3493 if (r_refdef.fogenabled)
3496 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
3497 R_Mesh_ColorPointer(color4f, 0, 0);
3498 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
3499 f1 = FogPoint_World(org);
3501 for (i = 0, c = color4f;i < 6;i++, c += 4)
3503 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
3504 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
3505 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
3509 else if (ent->alpha != 1)
3511 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
3512 R_Mesh_ColorPointer(color4f, 0, 0);
3513 for (i = 0, c = color4f;i < 6;i++, c += 4)
3517 R_Mesh_ColorPointer(nomodelcolor4f, 0, 0);
3518 R_Mesh_ResetTextureState();
3519 R_Mesh_Draw(0, 6, 8, nomodelelements, 0, 0);
3522 void R_DrawNoModel(entity_render_t *ent)
3525 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
3526 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
3527 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
3529 // R_DrawNoModelCallback(ent, 0);
3532 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
3534 vec3_t right1, right2, diff, normal;
3536 VectorSubtract (org2, org1, normal);
3538 // calculate 'right' vector for start
3539 VectorSubtract (r_view.origin, org1, diff);
3540 CrossProduct (normal, diff, right1);
3541 VectorNormalize (right1);
3543 // calculate 'right' vector for end
3544 VectorSubtract (r_view.origin, org2, diff);
3545 CrossProduct (normal, diff, right2);
3546 VectorNormalize (right2);
3548 vert[ 0] = org1[0] + width * right1[0];
3549 vert[ 1] = org1[1] + width * right1[1];
3550 vert[ 2] = org1[2] + width * right1[2];
3551 vert[ 3] = org1[0] - width * right1[0];
3552 vert[ 4] = org1[1] - width * right1[1];
3553 vert[ 5] = org1[2] - width * right1[2];
3554 vert[ 6] = org2[0] - width * right2[0];
3555 vert[ 7] = org2[1] - width * right2[1];
3556 vert[ 8] = org2[2] - width * right2[2];
3557 vert[ 9] = org2[0] + width * right2[0];
3558 vert[10] = org2[1] + width * right2[1];
3559 vert[11] = org2[2] + width * right2[2];
3562 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
3564 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)
3569 if (r_refdef.fogenabled)
3570 fog = FogPoint_World(origin);
3572 R_Mesh_Matrix(&identitymatrix);
3573 GL_BlendFunc(blendfunc1, blendfunc2);
3579 GL_CullFace(r_view.cullface_front);
3582 GL_CullFace(r_view.cullface_back);
3584 GL_DepthMask(false);
3585 GL_DepthRange(0, depthshort ? 0.0625 : 1);
3586 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3587 GL_DepthTest(!depthdisable);
3589 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
3590 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
3591 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
3592 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
3593 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
3594 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
3595 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
3596 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
3597 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
3598 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
3599 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
3600 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
3602 R_Mesh_VertexPointer(vertex3f, 0, 0);
3603 R_Mesh_ColorPointer(NULL, 0, 0);
3604 R_Mesh_ResetTextureState();
3605 R_Mesh_TexBind(0, R_GetTexture(texture));
3606 R_Mesh_TexCoordPointer(0, 2, spritetexcoord2f, 0, 0);
3607 // FIXME: fixed function path can't properly handle r_view.colorscale > 1
3608 GL_Color(cr * fog * r_view.colorscale, cg * fog * r_view.colorscale, cb * fog * r_view.colorscale, ca);
3609 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3611 if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
3613 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
3614 GL_BlendFunc(blendfunc1, GL_ONE);
3616 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);
3617 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3621 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
3626 VectorSet(v, x, y, z);
3627 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
3628 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
3630 if (i == mesh->numvertices)
3632 if (mesh->numvertices < mesh->maxvertices)
3634 VectorCopy(v, vertex3f);
3635 mesh->numvertices++;
3637 return mesh->numvertices;
3643 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
3647 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
3648 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
3649 e = mesh->element3i + mesh->numtriangles * 3;
3650 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
3652 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
3653 if (mesh->numtriangles < mesh->maxtriangles)
3658 mesh->numtriangles++;
3660 element[1] = element[2];
3664 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
3668 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
3669 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
3670 e = mesh->element3i + mesh->numtriangles * 3;
3671 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
3673 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
3674 if (mesh->numtriangles < mesh->maxtriangles)
3679 mesh->numtriangles++;
3681 element[1] = element[2];
3685 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
3686 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
3688 int planenum, planenum2;
3691 mplane_t *plane, *plane2;
3693 double temppoints[2][256*3];
3694 // figure out how large a bounding box we need to properly compute this brush
3696 for (w = 0;w < numplanes;w++)
3697 maxdist = max(maxdist, planes[w].dist);
3698 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
3699 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
3700 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
3704 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
3705 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
3707 if (planenum2 == planenum)
3709 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);
3712 if (tempnumpoints < 3)
3714 // generate elements forming a triangle fan for this polygon
3715 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
3719 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)
3721 texturelayer_t *layer;
3722 layer = t->currentlayers + t->currentnumlayers++;
3724 layer->depthmask = depthmask;
3725 layer->blendfunc1 = blendfunc1;
3726 layer->blendfunc2 = blendfunc2;
3727 layer->texture = texture;
3728 layer->texmatrix = *matrix;
3729 layer->color[0] = r * r_view.colorscale;
3730 layer->color[1] = g * r_view.colorscale;
3731 layer->color[2] = b * r_view.colorscale;
3732 layer->color[3] = a;
3735 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
3738 index = parms[2] + r_refdef.time * parms[3];
3739 index -= floor(index);
3743 case Q3WAVEFUNC_NONE:
3744 case Q3WAVEFUNC_NOISE:
3745 case Q3WAVEFUNC_COUNT:
3748 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
3749 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
3750 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
3751 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
3752 case Q3WAVEFUNC_TRIANGLE:
3754 f = index - floor(index);
3765 return (float)(parms[0] + parms[1] * f);
3768 void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
3771 model_t *model = ent->model;
3774 q3shaderinfo_layer_tcmod_t *tcmod;
3776 // switch to an alternate material if this is a q1bsp animated material
3778 texture_t *texture = t;
3779 int s = ent->skinnum;
3780 if ((unsigned int)s >= (unsigned int)model->numskins)
3782 if (model->skinscenes)
3784 if (model->skinscenes[s].framecount > 1)
3785 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
3787 s = model->skinscenes[s].firstframe;
3790 t = t + s * model->num_surfaces;
3793 // use an alternate animation if the entity's frame is not 0,
3794 // and only if the texture has an alternate animation
3795 if (ent->frame2 != 0 && t->anim_total[1])
3796 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.time * 5.0f) % t->anim_total[1]) : 0];
3798 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.time * 5.0f) % t->anim_total[0]) : 0];
3800 texture->currentframe = t;
3803 // update currentskinframe to be a qw skin or animation frame
3804 if ((i = ent->entitynumber - 1) >= 0 && i < cl.maxclients)
3806 if (strcmp(r_qwskincache[i], cl.scores[i].qw_skin))
3808 strlcpy(r_qwskincache[i], cl.scores[i].qw_skin, sizeof(r_qwskincache[i]));
3809 Con_DPrintf("loading skins/%s\n", r_qwskincache[i]);
3810 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);
3812 t->currentskinframe = r_qwskincache_skinframe[i];
3813 if (t->currentskinframe == NULL)
3814 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->frame2time)) % t->numskinframes];
3816 else if (t->numskinframes >= 2)
3817 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->frame2time)) % t->numskinframes];
3818 if (t->backgroundnumskinframes >= 2)
3819 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - ent->frame2time)) % t->backgroundnumskinframes];
3821 t->currentmaterialflags = t->basematerialflags;
3822 t->currentalpha = ent->alpha;
3823 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
3825 t->currentalpha *= r_wateralpha.value;
3827 * FIXME what is this supposed to do?
3828 // if rendering refraction/reflection, disable transparency
3829 if (r_waterstate.enabled && (t->currentalpha < 1 || (t->currentmaterialflags & MATERIALFLAG_ALPHA)))
3830 t->currentmaterialflags |= MATERIALFLAG_WATERSHADER;
3833 if(!r_waterstate.enabled)
3835 t->currentmaterialflags &= ~MATERIALFLAG_WATERSHADER;
3836 t->currentmaterialflags &= ~MATERIALFLAG_REFLECTION;
3838 if (!(ent->flags & RENDER_LIGHT))
3839 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
3840 if (ent->effects & EF_ADDITIVE)
3841 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
3842 else if (t->currentalpha < 1)
3843 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
3844 if (ent->effects & EF_DOUBLESIDED)
3845 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
3846 if (ent->effects & EF_NODEPTHTEST)
3847 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
3848 if (ent->flags & RENDER_VIEWMODEL)
3849 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
3850 if (t->backgroundnumskinframes && !(t->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED))
3851 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
3852 if (t->currentmaterialflags & MATERIALFLAG_WATERSHADER)
3853 t->currentmaterialflags &= ~(MATERIALFLAG_ADD | MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_CUSTOMBLEND);
3855 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && (tcmod->tcmod || i < 1);i++, tcmod++)
3858 switch(tcmod->tcmod)
3862 if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
3863 matrix = r_waterscrollmatrix;
3865 matrix = identitymatrix;
3867 case Q3TCMOD_ENTITYTRANSLATE:
3868 // this is used in Q3 to allow the gamecode to control texcoord
3869 // scrolling on the entity, which is not supported in darkplaces yet.
3870 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
3872 case Q3TCMOD_ROTATE:
3873 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
3874 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.time, 0, 0, 1);
3875 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
3878 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
3880 case Q3TCMOD_SCROLL:
3881 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.time, tcmod->parms[1] * r_refdef.time, 0);
3883 case Q3TCMOD_STRETCH:
3884 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
3885 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
3887 case Q3TCMOD_TRANSFORM:
3888 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
3889 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
3890 VectorSet(tcmat + 6, 0 , 0 , 1);
3891 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
3892 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
3894 case Q3TCMOD_TURBULENT:
3895 // this is handled in the RSurf_PrepareVertices function
3896 matrix = identitymatrix;
3899 // either replace or concatenate the transformation
3901 t->currenttexmatrix = matrix;
3904 matrix4x4_t temp = t->currenttexmatrix;
3905 Matrix4x4_Concat(&t->currenttexmatrix, &matrix, &temp);
3909 t->colormapping = VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f);
3910 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
3911 t->glosstexture = r_texture_black;
3912 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
3913 t->backgroundglosstexture = r_texture_black;
3914 t->specularpower = r_shadow_glossexponent.value;
3915 // TODO: store reference values for these in the texture?
3916 t->specularscale = 0;
3917 if (r_shadow_gloss.integer > 0)
3919 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
3921 if (r_shadow_glossintensity.value > 0)
3923 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
3924 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
3925 t->specularscale = r_shadow_glossintensity.value;
3928 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
3930 t->glosstexture = r_texture_white;
3931 t->backgroundglosstexture = r_texture_white;
3932 t->specularscale = r_shadow_gloss2intensity.value;
3936 // lightmaps mode looks bad with dlights using actual texturing, so turn
3937 // off the colormap and glossmap, but leave the normalmap on as it still
3938 // accurately represents the shading involved
3939 if (gl_lightmaps.integer && !(t->currentmaterialflags & MATERIALFLAG_BLENDED))
3941 t->basetexture = r_texture_white;
3942 t->specularscale = 0;
3945 t->currentpolygonfactor = r_refdef.polygonfactor + t->basepolygonfactor;
3946 t->currentpolygonoffset = r_refdef.polygonoffset + t->basepolygonoffset;
3947 // submodels are biased to avoid z-fighting with world surfaces that they
3948 // may be exactly overlapping (avoids z-fighting artifacts on certain
3949 // doors and things in Quake maps)
3950 if (ent->model->brush.submodel)
3952 t->currentpolygonfactor += r_polygonoffset_submodel_factor.value;
3953 t->currentpolygonoffset += r_polygonoffset_submodel_offset.value;
3956 VectorClear(t->dlightcolor);
3957 t->currentnumlayers = 0;
3958 if (!(t->currentmaterialflags & MATERIALFLAG_NODRAW))
3960 if (!(t->currentmaterialflags & MATERIALFLAG_SKY))
3962 int blendfunc1, blendfunc2, depthmask;
3963 if (t->currentmaterialflags & MATERIALFLAG_ADD)
3965 blendfunc1 = GL_SRC_ALPHA;
3966 blendfunc2 = GL_ONE;
3968 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
3970 blendfunc1 = GL_SRC_ALPHA;
3971 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
3973 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
3975 blendfunc1 = t->customblendfunc[0];
3976 blendfunc2 = t->customblendfunc[1];
3980 blendfunc1 = GL_ONE;
3981 blendfunc2 = GL_ZERO;
3983 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
3984 if (t->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL))
3986 rtexture_t *currentbasetexture;
3988 if (r_refdef.fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED))
3989 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
3990 currentbasetexture = (VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) < (1.0f / 1048576.0f) && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
3991 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
3993 // fullbright is not affected by r_refdef.lightmapintensity
3994 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
3995 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
3996 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);
3997 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
3998 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);
4003 // set the color tint used for lights affecting this surface
4004 VectorSet(t->dlightcolor, ent->colormod[0] * t->currentalpha, ent->colormod[1] * t->currentalpha, ent->colormod[2] * t->currentalpha);
4006 // q3bsp has no lightmap updates, so the lightstylevalue that
4007 // would normally be baked into the lightmap must be
4008 // applied to the color
4009 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
4010 if (ent->model->type == mod_brushq3)
4011 colorscale *= r_refdef.lightstylevalue[0] * (1.0f / 256.0f);
4012 colorscale *= r_refdef.lightmapintensity;
4013 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);
4014 if (r_ambient.value >= (1.0f/64.0f))
4015 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);
4016 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
4018 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);
4019 if (r_ambient.value >= (1.0f/64.0f))
4020 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);
4022 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
4024 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);
4025 if (r_ambient.value >= (1.0f/64.0f))
4026 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);
4029 if (t->currentskinframe->glow != NULL)
4030 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);
4031 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
4033 // if this is opaque use alpha blend which will darken the earlier
4036 // if this is an alpha blended material, all the earlier passes
4037 // were darkened by fog already, so we only need to add the fog
4038 // color ontop through the fog mask texture
4040 // if this is an additive blended material, all the earlier passes
4041 // were darkened by fog already, and we should not add fog color
4042 // (because the background was not darkened, there is no fog color
4043 // that was lost behind it).
4044 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);
4051 void R_UpdateAllTextureInfo(entity_render_t *ent)
4055 for (i = 0;i < ent->model->num_texturesperskin;i++)
4056 R_UpdateTextureInfo(ent, ent->model->data_textures + i);
4059 rsurfacestate_t rsurface;
4061 void R_Mesh_ResizeArrays(int newvertices)
4064 if (rsurface.array_size >= newvertices)
4066 if (rsurface.array_modelvertex3f)
4067 Mem_Free(rsurface.array_modelvertex3f);
4068 rsurface.array_size = (newvertices + 1023) & ~1023;
4069 base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
4070 rsurface.array_modelvertex3f = base + rsurface.array_size * 0;
4071 rsurface.array_modelsvector3f = base + rsurface.array_size * 3;
4072 rsurface.array_modeltvector3f = base + rsurface.array_size * 6;
4073 rsurface.array_modelnormal3f = base + rsurface.array_size * 9;
4074 rsurface.array_deformedvertex3f = base + rsurface.array_size * 12;
4075 rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
4076 rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
4077 rsurface.array_deformednormal3f = base + rsurface.array_size * 21;
4078 rsurface.array_texcoord3f = base + rsurface.array_size * 24;
4079 rsurface.array_color4f = base + rsurface.array_size * 27;
4080 rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
4083 void RSurf_CleanUp(void)
4086 if (rsurface.mode == RSURFMODE_GLSL)
4088 qglUseProgramObjectARB(0);CHECKGLERROR
4090 GL_AlphaTest(false);
4091 rsurface.mode = RSURFMODE_NONE;
4092 rsurface.uselightmaptexture = false;
4093 rsurface.texture = NULL;
4096 void RSurf_ActiveWorldEntity(void)
4098 model_t *model = r_refdef.worldmodel;
4100 if (rsurface.array_size < model->surfmesh.num_vertices)
4101 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
4102 rsurface.matrix = identitymatrix;
4103 rsurface.inversematrix = identitymatrix;
4104 R_Mesh_Matrix(&identitymatrix);
4105 VectorCopy(r_view.origin, rsurface.modelorg);
4106 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
4107 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
4108 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
4109 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
4110 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
4111 rsurface.frameblend[0].frame = 0;
4112 rsurface.frameblend[0].lerp = 1;
4113 rsurface.frameblend[1].frame = 0;
4114 rsurface.frameblend[1].lerp = 0;
4115 rsurface.frameblend[2].frame = 0;
4116 rsurface.frameblend[2].lerp = 0;
4117 rsurface.frameblend[3].frame = 0;
4118 rsurface.frameblend[3].lerp = 0;
4119 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
4120 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
4121 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
4122 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
4123 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
4124 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
4125 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
4126 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
4127 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
4128 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
4129 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
4130 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
4131 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
4132 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
4133 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
4134 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
4135 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
4136 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
4137 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
4138 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
4139 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
4140 rsurface.modelelement3i = model->surfmesh.data_element3i;
4141 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo;
4142 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
4143 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
4144 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
4145 rsurface.modelsurfaces = model->data_surfaces;
4146 rsurface.generatedvertex = false;
4147 rsurface.vertex3f = rsurface.modelvertex3f;
4148 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
4149 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
4150 rsurface.svector3f = rsurface.modelsvector3f;
4151 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
4152 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
4153 rsurface.tvector3f = rsurface.modeltvector3f;
4154 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
4155 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
4156 rsurface.normal3f = rsurface.modelnormal3f;
4157 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
4158 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
4159 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
4162 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4164 model_t *model = ent->model;
4166 if (rsurface.array_size < model->surfmesh.num_vertices)
4167 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
4168 rsurface.matrix = ent->matrix;
4169 rsurface.inversematrix = ent->inversematrix;
4170 R_Mesh_Matrix(&rsurface.matrix);
4171 Matrix4x4_Transform(&rsurface.inversematrix, r_view.origin, rsurface.modelorg);
4172 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
4173 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
4174 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
4175 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
4176 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
4177 rsurface.frameblend[0] = ent->frameblend[0];
4178 rsurface.frameblend[1] = ent->frameblend[1];
4179 rsurface.frameblend[2] = ent->frameblend[2];
4180 rsurface.frameblend[3] = ent->frameblend[3];
4181 if (model->surfmesh.isanimated && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].frame != 0))
4185 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
4186 rsurface.modelsvector3f = rsurface.array_modelsvector3f;
4187 rsurface.modeltvector3f = rsurface.array_modeltvector3f;
4188 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
4189 Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
4191 else if (wantnormals)
4193 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
4194 rsurface.modelsvector3f = NULL;
4195 rsurface.modeltvector3f = NULL;
4196 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
4197 Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
4201 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
4202 rsurface.modelsvector3f = NULL;
4203 rsurface.modeltvector3f = NULL;
4204 rsurface.modelnormal3f = NULL;
4205 Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, NULL, NULL, NULL);
4207 rsurface.modelvertex3f_bufferobject = 0;
4208 rsurface.modelvertex3f_bufferoffset = 0;
4209 rsurface.modelsvector3f_bufferobject = 0;
4210 rsurface.modelsvector3f_bufferoffset = 0;
4211 rsurface.modeltvector3f_bufferobject = 0;
4212 rsurface.modeltvector3f_bufferoffset = 0;
4213 rsurface.modelnormal3f_bufferobject = 0;
4214 rsurface.modelnormal3f_bufferoffset = 0;
4215 rsurface.generatedvertex = true;
4219 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
4220 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
4221 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
4222 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
4223 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
4224 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
4225 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
4226 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
4227 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
4228 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
4229 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
4230 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
4231 rsurface.generatedvertex = false;
4233 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
4234 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
4235 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
4236 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
4237 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
4238 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
4239 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
4240 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
4241 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
4242 rsurface.modelelement3i = model->surfmesh.data_element3i;
4243 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo;
4244 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
4245 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
4246 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
4247 rsurface.modelsurfaces = model->data_surfaces;
4248 rsurface.vertex3f = rsurface.modelvertex3f;
4249 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
4250 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
4251 rsurface.svector3f = rsurface.modelsvector3f;
4252 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
4253 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
4254 rsurface.tvector3f = rsurface.modeltvector3f;
4255 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
4256 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
4257 rsurface.normal3f = rsurface.modelnormal3f;
4258 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
4259 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
4260 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
4263 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
4264 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, msurface_t **texturesurfacelist)
4267 int texturesurfaceindex;
4272 const float *v1, *in_tc;
4274 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
4276 q3shaderinfo_deform_t *deform;
4277 // 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
4278 if (rsurface.generatedvertex)
4280 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
4281 generatenormals = true;
4282 for (i = 0;i < Q3MAXDEFORMS;i++)
4284 if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
4286 generatetangents = true;
4287 generatenormals = true;
4289 if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
4290 generatenormals = true;
4292 if (generatenormals && !rsurface.modelnormal3f)
4294 rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
4295 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
4296 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
4297 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer);
4299 if (generatetangents && !rsurface.modelsvector3f)
4301 rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
4302 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
4303 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
4304 rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
4305 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
4306 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
4307 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);
4310 rsurface.vertex3f = rsurface.modelvertex3f;
4311 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
4312 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
4313 rsurface.svector3f = rsurface.modelsvector3f;
4314 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
4315 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
4316 rsurface.tvector3f = rsurface.modeltvector3f;
4317 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
4318 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
4319 rsurface.normal3f = rsurface.modelnormal3f;
4320 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
4321 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
4322 // if vertices are deformed (sprite flares and things in maps, possibly
4323 // water waves, bulges and other deformations), generate them into
4324 // rsurface.deform* arrays from whatever the rsurface.* arrays point to
4325 // (may be static model data or generated data for an animated model, or
4326 // the previous deform pass)
4327 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
4329 switch (deform->deform)
4332 case Q3DEFORM_PROJECTIONSHADOW:
4333 case Q3DEFORM_TEXT0:
4334 case Q3DEFORM_TEXT1:
4335 case Q3DEFORM_TEXT2:
4336 case Q3DEFORM_TEXT3:
4337 case Q3DEFORM_TEXT4:
4338 case Q3DEFORM_TEXT5:
4339 case Q3DEFORM_TEXT6:
4340 case Q3DEFORM_TEXT7:
4343 case Q3DEFORM_AUTOSPRITE:
4344 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.forward, newforward);
4345 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.right, newright);
4346 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.up, newup);
4347 VectorNormalize(newforward);
4348 VectorNormalize(newright);
4349 VectorNormalize(newup);
4350 // make deformed versions of only the model vertices used by the specified surfaces
4351 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4353 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4354 // a single autosprite surface can contain multiple sprites...
4355 for (j = 0;j < surface->num_vertices - 3;j += 4)
4357 VectorClear(center);
4358 for (i = 0;i < 4;i++)
4359 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
4360 VectorScale(center, 0.25f, center);
4361 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, forward);
4362 VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
4363 VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
4364 for (i = 0;i < 4;i++)
4366 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
4367 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
4370 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);
4371 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);
4373 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4374 rsurface.vertex3f_bufferobject = 0;
4375 rsurface.vertex3f_bufferoffset = 0;
4376 rsurface.svector3f = rsurface.array_deformedsvector3f;
4377 rsurface.svector3f_bufferobject = 0;
4378 rsurface.svector3f_bufferoffset = 0;
4379 rsurface.tvector3f = rsurface.array_deformedtvector3f;
4380 rsurface.tvector3f_bufferobject = 0;
4381 rsurface.tvector3f_bufferoffset = 0;
4382 rsurface.normal3f = rsurface.array_deformednormal3f;
4383 rsurface.normal3f_bufferobject = 0;
4384 rsurface.normal3f_bufferoffset = 0;
4386 case Q3DEFORM_AUTOSPRITE2:
4387 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.forward, newforward);
4388 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.right, newright);
4389 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.up, newup);
4390 VectorNormalize(newforward);
4391 VectorNormalize(newright);
4392 VectorNormalize(newup);
4393 // make deformed versions of only the model vertices used by the specified surfaces
4394 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4396 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4397 const float *v1, *v2;
4407 memset(shortest, 0, sizeof(shortest));
4408 // a single autosprite surface can contain multiple sprites...
4409 for (j = 0;j < surface->num_vertices - 3;j += 4)
4411 VectorClear(center);
4412 for (i = 0;i < 4;i++)
4413 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
4414 VectorScale(center, 0.25f, center);
4415 // find the two shortest edges, then use them to define the
4416 // axis vectors for rotating around the central axis
4417 for (i = 0;i < 6;i++)
4419 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
4420 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
4422 Debug_PolygonBegin(NULL, 0, false, 0);
4423 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
4424 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);
4425 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
4428 l = VectorDistance2(v1, v2);
4429 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
4431 l += (1.0f / 1024.0f);
4432 if (shortest[0].length2 > l || i == 0)
4434 shortest[1] = shortest[0];
4435 shortest[0].length2 = l;
4436 shortest[0].v1 = v1;
4437 shortest[0].v2 = v2;
4439 else if (shortest[1].length2 > l || i == 1)
4441 shortest[1].length2 = l;
4442 shortest[1].v1 = v1;
4443 shortest[1].v2 = v2;
4446 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
4447 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
4449 Debug_PolygonBegin(NULL, 0, false, 0);
4450 Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
4451 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);
4452 Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
4455 // this calculates the right vector from the shortest edge
4456 // and the up vector from the edge midpoints
4457 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
4458 VectorNormalize(right);
4459 VectorSubtract(end, start, up);
4460 VectorNormalize(up);
4461 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
4462 //VectorSubtract(rsurface.modelorg, center, forward);
4463 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.forward, forward);
4464 VectorNegate(forward, forward);
4465 VectorReflect(forward, 0, up, forward);
4466 VectorNormalize(forward);
4467 CrossProduct(up, forward, newright);
4468 VectorNormalize(newright);
4470 Debug_PolygonBegin(NULL, 0, false, 0);
4471 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);
4472 Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
4473 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
4477 Debug_PolygonBegin(NULL, 0, false, 0);
4478 Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
4479 Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
4480 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
4483 // rotate the quad around the up axis vector, this is made
4484 // especially easy by the fact we know the quad is flat,
4485 // so we only have to subtract the center position and
4486 // measure distance along the right vector, and then
4487 // multiply that by the newright vector and add back the
4489 // we also need to subtract the old position to undo the
4490 // displacement from the center, which we do with a
4491 // DotProduct, the subtraction/addition of center is also
4492 // optimized into DotProducts here
4493 l = DotProduct(right, center);
4494 for (i = 0;i < 4;i++)
4496 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
4497 f = DotProduct(right, v1) - l;
4498 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
4501 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);
4502 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);
4504 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4505 rsurface.vertex3f_bufferobject = 0;
4506 rsurface.vertex3f_bufferoffset = 0;
4507 rsurface.svector3f = rsurface.array_deformedsvector3f;
4508 rsurface.svector3f_bufferobject = 0;
4509 rsurface.svector3f_bufferoffset = 0;
4510 rsurface.tvector3f = rsurface.array_deformedtvector3f;
4511 rsurface.tvector3f_bufferobject = 0;
4512 rsurface.tvector3f_bufferoffset = 0;
4513 rsurface.normal3f = rsurface.array_deformednormal3f;
4514 rsurface.normal3f_bufferobject = 0;
4515 rsurface.normal3f_bufferoffset = 0;
4517 case Q3DEFORM_NORMAL:
4518 // deform the normals to make reflections wavey
4519 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4521 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4522 for (j = 0;j < surface->num_vertices;j++)
4525 float *normal = (rsurface.array_deformednormal3f + 3 * surface->num_firstvertex) + j*3;
4526 VectorScale((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
4527 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, normal);
4528 normal[0] += deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.time * deform->parms[1]);
4529 normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.time * deform->parms[1]);
4530 normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.time * deform->parms[1]);
4531 VectorNormalize(normal);
4533 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);
4535 rsurface.svector3f = rsurface.array_deformedsvector3f;
4536 rsurface.svector3f_bufferobject = 0;
4537 rsurface.svector3f_bufferoffset = 0;
4538 rsurface.tvector3f = rsurface.array_deformedtvector3f;
4539 rsurface.tvector3f_bufferobject = 0;
4540 rsurface.tvector3f_bufferoffset = 0;
4541 rsurface.normal3f = rsurface.array_deformednormal3f;
4542 rsurface.normal3f_bufferobject = 0;
4543 rsurface.normal3f_bufferoffset = 0;
4546 // deform vertex array to make wavey water and flags and such
4547 waveparms[0] = deform->waveparms[0];
4548 waveparms[1] = deform->waveparms[1];
4549 waveparms[2] = deform->waveparms[2];
4550 waveparms[3] = deform->waveparms[3];
4551 // this is how a divisor of vertex influence on deformation
4552 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
4553 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
4554 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4556 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4557 for (j = 0;j < surface->num_vertices;j++)
4559 float *vertex = (rsurface.array_deformedvertex3f + 3 * surface->num_firstvertex) + j*3;
4560 VectorCopy((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, vertex);
4561 // if the wavefunc depends on time, evaluate it per-vertex
4564 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
4565 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
4567 VectorMA(vertex, scale, (rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, vertex);
4570 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4571 rsurface.vertex3f_bufferobject = 0;
4572 rsurface.vertex3f_bufferoffset = 0;
4574 case Q3DEFORM_BULGE:
4575 // deform vertex array to make the surface have moving bulges
4576 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4578 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4579 for (j = 0;j < surface->num_vertices;j++)
4581 scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.time * deform->parms[2])) * deform->parms[1];
4582 VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
4585 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4586 rsurface.vertex3f_bufferobject = 0;
4587 rsurface.vertex3f_bufferoffset = 0;
4590 // deform vertex array
4591 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
4592 VectorScale(deform->parms, scale, waveparms);
4593 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4595 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4596 for (j = 0;j < surface->num_vertices;j++)
4597 VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
4599 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4600 rsurface.vertex3f_bufferobject = 0;
4601 rsurface.vertex3f_bufferoffset = 0;
4605 // generate texcoords based on the chosen texcoord source
4606 switch(rsurface.texture->tcgen.tcgen)
4609 case Q3TCGEN_TEXTURE:
4610 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
4611 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordtexture2f_bufferobject;
4612 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
4614 case Q3TCGEN_LIGHTMAP:
4615 rsurface.texcoordtexture2f = rsurface.modeltexcoordlightmap2f;
4616 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
4617 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
4619 case Q3TCGEN_VECTOR:
4620 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4622 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4623 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)
4625 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
4626 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
4629 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
4630 rsurface.texcoordtexture2f_bufferobject = 0;
4631 rsurface.texcoordtexture2f_bufferoffset = 0;
4633 case Q3TCGEN_ENVIRONMENT:
4634 // make environment reflections using a spheremap
4635 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4637 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4638 const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
4639 const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
4640 float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
4641 for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
4643 float l, d, eyedir[3];
4644 VectorSubtract(rsurface.modelorg, vertex, eyedir);
4645 l = 0.5f / VectorLength(eyedir);
4646 d = DotProduct(normal, eyedir)*2;
4647 out_tc[0] = 0.5f + (normal[1]*d - eyedir[1])*l;
4648 out_tc[1] = 0.5f - (normal[2]*d - eyedir[2])*l;
4651 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
4652 rsurface.texcoordtexture2f_bufferobject = 0;
4653 rsurface.texcoordtexture2f_bufferoffset = 0;
4656 // the only tcmod that needs software vertex processing is turbulent, so
4657 // check for it here and apply the changes if needed
4658 // and we only support that as the first one
4659 // (handling a mixture of turbulent and other tcmods would be problematic
4660 // without punting it entirely to a software path)
4661 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
4663 amplitude = rsurface.texture->tcmods[0].parms[1];
4664 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.time * rsurface.texture->tcmods[0].parms[3];
4665 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4667 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4668 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)
4670 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
4671 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
4674 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
4675 rsurface.texcoordtexture2f_bufferobject = 0;
4676 rsurface.texcoordtexture2f_bufferoffset = 0;
4678 rsurface.texcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
4679 rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
4680 rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
4681 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
4684 void RSurf_DrawBatch_Simple(int texturenumsurfaces, msurface_t **texturesurfacelist)
4687 const msurface_t *surface = texturesurfacelist[0];
4688 const msurface_t *surface2;
4693 // TODO: lock all array ranges before render, rather than on each surface
4694 if (texturenumsurfaces == 1)
4696 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
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));
4699 else if (r_batchmode.integer == 2)
4701 #define MAXBATCHTRIANGLES 4096
4702 int batchtriangles = 0;
4703 int batchelements[MAXBATCHTRIANGLES*3];
4704 for (i = 0;i < texturenumsurfaces;i = j)
4706 surface = texturesurfacelist[i];
4708 if (surface->num_triangles > MAXBATCHTRIANGLES)
4710 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));
4713 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
4714 batchtriangles = surface->num_triangles;
4715 firstvertex = surface->num_firstvertex;
4716 endvertex = surface->num_firstvertex + surface->num_vertices;
4717 for (;j < texturenumsurfaces;j++)
4719 surface2 = texturesurfacelist[j];
4720 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
4722 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
4723 batchtriangles += surface2->num_triangles;
4724 firstvertex = min(firstvertex, surface2->num_firstvertex);
4725 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
4727 surface2 = texturesurfacelist[j-1];
4728 numvertices = endvertex - firstvertex;
4729 R_Mesh_Draw(firstvertex, numvertices, batchtriangles, batchelements, 0, 0);
4732 else if (r_batchmode.integer == 1)
4734 for (i = 0;i < texturenumsurfaces;i = j)
4736 surface = texturesurfacelist[i];
4737 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
4738 if (texturesurfacelist[j] != surface2)
4740 surface2 = texturesurfacelist[j-1];
4741 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
4742 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
4743 GL_LockArrays(surface->num_firstvertex, numvertices);
4744 R_Mesh_Draw(surface->num_firstvertex, numvertices, numtriangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
4749 for (i = 0;i < texturenumsurfaces;i++)
4751 surface = texturesurfacelist[i];
4752 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
4753 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));
4758 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit, int refractiontexunit, int reflectiontexunit)
4760 int i, planeindex, vertexindex;
4764 r_waterstate_waterplane_t *p, *bestp;
4765 msurface_t *surface;
4766 if (r_waterstate.renderingscene)
4768 for (i = 0;i < texturenumsurfaces;i++)
4770 surface = texturesurfacelist[i];
4771 if (lightmaptexunit >= 0)
4772 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
4773 if (deluxemaptexunit >= 0)
4774 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
4775 // pick the closest matching water plane
4778 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
4781 for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
4783 Matrix4x4_Transform(&rsurface.matrix, v, vert);
4784 d += fabs(PlaneDiff(vert, &p->plane));
4786 if (bestd > d || !bestp)
4794 if (refractiontexunit >= 0)
4795 R_Mesh_TexBind(refractiontexunit, R_GetTexture(bestp->texture_refraction));
4796 if (reflectiontexunit >= 0)
4797 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(bestp->texture_reflection));
4801 if (refractiontexunit >= 0)
4802 R_Mesh_TexBind(refractiontexunit, R_GetTexture(r_texture_black));
4803 if (reflectiontexunit >= 0)
4804 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(r_texture_black));
4806 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
4807 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));
4811 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit)
4815 const msurface_t *surface = texturesurfacelist[0];
4816 const msurface_t *surface2;
4821 // TODO: lock all array ranges before render, rather than on each surface
4822 if (texturenumsurfaces == 1)
4824 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
4825 if (deluxemaptexunit >= 0)
4826 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
4827 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
4828 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));
4830 else if (r_batchmode.integer == 2)
4832 #define MAXBATCHTRIANGLES 4096
4833 int batchtriangles = 0;
4834 int batchelements[MAXBATCHTRIANGLES*3];
4835 for (i = 0;i < texturenumsurfaces;i = j)
4837 surface = texturesurfacelist[i];
4838 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
4839 if (deluxemaptexunit >= 0)
4840 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
4842 if (surface->num_triangles > MAXBATCHTRIANGLES)
4844 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));
4847 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
4848 batchtriangles = surface->num_triangles;
4849 firstvertex = surface->num_firstvertex;
4850 endvertex = surface->num_firstvertex + surface->num_vertices;
4851 for (;j < texturenumsurfaces;j++)
4853 surface2 = texturesurfacelist[j];
4854 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
4856 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
4857 batchtriangles += surface2->num_triangles;
4858 firstvertex = min(firstvertex, surface2->num_firstvertex);
4859 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
4861 surface2 = texturesurfacelist[j-1];
4862 numvertices = endvertex - firstvertex;
4863 R_Mesh_Draw(firstvertex, numvertices, batchtriangles, batchelements, 0, 0);
4866 else if (r_batchmode.integer == 1)
4869 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
4870 for (i = 0;i < texturenumsurfaces;i = j)
4872 surface = texturesurfacelist[i];
4873 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
4874 if (texturesurfacelist[j] != surface2)
4876 Con_Printf(" %i", j - i);
4879 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
4881 for (i = 0;i < texturenumsurfaces;i = j)
4883 surface = texturesurfacelist[i];
4884 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
4885 if (deluxemaptexunit >= 0)
4886 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
4887 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
4888 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
4891 Con_Printf(" %i", j - i);
4893 surface2 = texturesurfacelist[j-1];
4894 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
4895 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
4896 GL_LockArrays(surface->num_firstvertex, numvertices);
4897 R_Mesh_Draw(surface->num_firstvertex, numvertices, numtriangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
4905 for (i = 0;i < texturenumsurfaces;i++)
4907 surface = texturesurfacelist[i];
4908 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
4909 if (deluxemaptexunit >= 0)
4910 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
4911 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
4912 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));
4917 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
4920 int texturesurfaceindex;
4921 if (r_showsurfaces.integer == 2)
4923 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4925 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4926 for (j = 0;j < surface->num_triangles;j++)
4928 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_view.colorscale;
4929 GL_Color(f, f, f, 1);
4930 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)));
4936 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4938 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4939 int k = (int)(((size_t)surface) / sizeof(msurface_t));
4940 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);
4941 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
4942 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));
4947 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, msurface_t **texturesurfacelist)
4949 int texturesurfaceindex;
4953 if (rsurface.lightmapcolor4f)
4955 // generate color arrays for the surfaces in this list
4956 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4958 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4959 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)
4961 f = FogPoint_Model(v);
4971 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4973 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4974 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)
4976 f = FogPoint_Model(v);
4984 rsurface.lightmapcolor4f = rsurface.array_color4f;
4985 rsurface.lightmapcolor4f_bufferobject = 0;
4986 rsurface.lightmapcolor4f_bufferoffset = 0;
4989 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a)
4991 int texturesurfaceindex;
4994 if (!rsurface.lightmapcolor4f)
4996 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4998 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4999 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)
5007 rsurface.lightmapcolor4f = rsurface.array_color4f;
5008 rsurface.lightmapcolor4f_bufferobject = 0;
5009 rsurface.lightmapcolor4f_bufferoffset = 0;
5012 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5015 rsurface.lightmapcolor4f = NULL;
5016 rsurface.lightmapcolor4f_bufferobject = 0;
5017 rsurface.lightmapcolor4f_bufferoffset = 0;
5018 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5019 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5020 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5021 GL_Color(r, g, b, a);
5022 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 0, -1);
5025 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5027 // TODO: optimize applyfog && applycolor case
5028 // just apply fog if necessary, and tint the fog color array if necessary
5029 rsurface.lightmapcolor4f = NULL;
5030 rsurface.lightmapcolor4f_bufferobject = 0;
5031 rsurface.lightmapcolor4f_bufferoffset = 0;
5032 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5033 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5034 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5035 GL_Color(r, g, b, a);
5036 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5039 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5041 int texturesurfaceindex;
5045 if (texturesurfacelist[0]->lightmapinfo && texturesurfacelist[0]->lightmapinfo->stainsamples)
5047 // generate color arrays for the surfaces in this list
5048 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5050 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5051 for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
5053 if (surface->lightmapinfo->samples)
5055 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
5056 float scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
5057 VectorScale(lm, scale, c);
5058 if (surface->lightmapinfo->styles[1] != 255)
5060 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
5062 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
5063 VectorMA(c, scale, lm, c);
5064 if (surface->lightmapinfo->styles[2] != 255)
5067 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
5068 VectorMA(c, scale, lm, c);
5069 if (surface->lightmapinfo->styles[3] != 255)
5072 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
5073 VectorMA(c, scale, lm, c);
5083 rsurface.lightmapcolor4f = rsurface.array_color4f;
5084 rsurface.lightmapcolor4f_bufferobject = 0;
5085 rsurface.lightmapcolor4f_bufferoffset = 0;
5089 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
5090 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
5091 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
5093 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5094 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5095 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5096 GL_Color(r, g, b, a);
5097 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5100 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5102 int texturesurfaceindex;
5106 vec3_t ambientcolor;
5107 vec3_t diffusecolor;
5111 VectorCopy(rsurface.modellight_lightdir, lightdir);
5112 ambientcolor[0] = rsurface.modellight_ambient[0] * r * 0.5f;
5113 ambientcolor[1] = rsurface.modellight_ambient[1] * g * 0.5f;
5114 ambientcolor[2] = rsurface.modellight_ambient[2] * b * 0.5f;
5115 diffusecolor[0] = rsurface.modellight_diffuse[0] * r * 0.5f;
5116 diffusecolor[1] = rsurface.modellight_diffuse[1] * g * 0.5f;
5117 diffusecolor[2] = rsurface.modellight_diffuse[2] * b * 0.5f;
5118 if (VectorLength2(diffusecolor) > 0)
5120 // generate color arrays for the surfaces in this list
5121 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5123 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5124 int numverts = surface->num_vertices;
5125 v = rsurface.vertex3f + 3 * surface->num_firstvertex;
5126 c2 = rsurface.normal3f + 3 * surface->num_firstvertex;
5127 c = rsurface.array_color4f + 4 * surface->num_firstvertex;
5128 // q3-style directional shading
5129 for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
5131 if ((f = DotProduct(c2, lightdir)) > 0)
5132 VectorMA(ambientcolor, f, diffusecolor, c);
5134 VectorCopy(ambientcolor, c);
5143 rsurface.lightmapcolor4f = rsurface.array_color4f;
5144 rsurface.lightmapcolor4f_bufferobject = 0;
5145 rsurface.lightmapcolor4f_bufferoffset = 0;
5149 r = ambientcolor[0];
5150 g = ambientcolor[1];
5151 b = ambientcolor[2];
5152 rsurface.lightmapcolor4f = NULL;
5153 rsurface.lightmapcolor4f_bufferobject = 0;
5154 rsurface.lightmapcolor4f_bufferoffset = 0;
5156 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5157 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5158 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5159 GL_Color(r, g, b, a);
5160 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5163 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
5165 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5166 GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset);
5167 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
5168 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_view.cullface_back);
5169 if (rsurface.mode != RSURFMODE_SHOWSURFACES)
5171 rsurface.mode = RSURFMODE_SHOWSURFACES;
5173 GL_BlendFunc(GL_ONE, GL_ZERO);
5174 R_Mesh_ColorPointer(NULL, 0, 0);
5175 R_Mesh_ResetTextureState();
5177 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
5178 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
5181 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, msurface_t **texturesurfacelist)
5183 // transparent sky would be ridiculous
5184 if ((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED))
5186 if (rsurface.mode != RSURFMODE_SKY)
5188 if (rsurface.mode == RSURFMODE_GLSL)
5190 qglUseProgramObjectARB(0);CHECKGLERROR
5192 rsurface.mode = RSURFMODE_SKY;
5196 skyrendernow = false;
5198 // restore entity matrix
5199 R_Mesh_Matrix(&rsurface.matrix);
5201 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5202 GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset);
5203 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
5204 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_view.cullface_back);
5206 // LordHavoc: HalfLife maps have freaky skypolys so don't use
5207 // skymasking on them, and Quake3 never did sky masking (unlike
5208 // software Quake and software Quake2), so disable the sky masking
5209 // in Quake3 maps as it causes problems with q3map2 sky tricks,
5210 // and skymasking also looks very bad when noclipping outside the
5211 // level, so don't use it then either.
5212 if (r_refdef.worldmodel && r_refdef.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_viewcache.world_novis)
5214 GL_Color(r_refdef.fogcolor[0] * r_view.colorscale, r_refdef.fogcolor[1] * r_view.colorscale, r_refdef.fogcolor[2] * r_view.colorscale, 1);
5215 R_Mesh_ColorPointer(NULL, 0, 0);
5216 R_Mesh_ResetTextureState();
5217 if (skyrendermasked)
5219 // depth-only (masking)
5220 GL_ColorMask(0,0,0,0);
5221 // just to make sure that braindead drivers don't draw
5222 // anything despite that colormask...
5223 GL_BlendFunc(GL_ZERO, GL_ONE);
5228 GL_BlendFunc(GL_ONE, GL_ZERO);
5230 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
5231 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5232 if (skyrendermasked)
5233 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
5237 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, msurface_t **texturesurfacelist)
5239 if (rsurface.mode != RSURFMODE_GLSL)
5241 rsurface.mode = RSURFMODE_GLSL;
5242 R_Mesh_ResetTextureState();
5245 R_SetupSurfaceShader(vec3_origin, rsurface.lightmode == 2, 1, 1, rsurface.texture->specularscale);
5246 if (!r_glsl_permutation)
5249 if (rsurface.lightmode == 2)
5250 RSurf_PrepareVerticesForBatch(true, r_glsl_permutation->loc_Texture_Normal >= 0, texturenumsurfaces, texturesurfacelist);
5252 RSurf_PrepareVerticesForBatch(r_glsl_permutation->loc_Texture_Normal >= 0, r_glsl_permutation->loc_Texture_Normal >= 0, texturenumsurfaces, texturesurfacelist);
5253 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
5254 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
5255 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
5256 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
5257 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
5259 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]);
5260 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
5262 R_Mesh_TexBind(7, R_GetTexture(r_texture_grey128));
5263 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
5264 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
5265 R_Mesh_ColorPointer(NULL, 0, 0);
5267 else if (rsurface.uselightmaptexture)
5269 R_Mesh_TexBind(7, R_GetTexture(texturesurfacelist[0]->lightmaptexture));
5270 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
5271 R_Mesh_TexBind(8, R_GetTexture(texturesurfacelist[0]->deluxemaptexture));
5272 R_Mesh_ColorPointer(NULL, 0, 0);
5276 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
5277 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
5278 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
5279 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
5282 if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
5284 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
5285 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist, 7, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? 8 : -1, 11, 12);
5286 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5287 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist, 7, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? 8 : -1, -1, 12);
5289 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 7, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? 8 : -1);
5293 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
5294 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist, -1, -1, 11, 12);
5295 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5296 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist, -1, -1, -1, 12);
5298 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5300 if (rsurface.texture->backgroundnumskinframes && !(rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED))
5305 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, msurface_t **texturesurfacelist)
5307 // OpenGL 1.3 path - anything not completely ancient
5308 int texturesurfaceindex;
5309 qboolean applycolor;
5313 const texturelayer_t *layer;
5314 if (rsurface.mode != RSURFMODE_MULTIPASS)
5315 rsurface.mode = RSURFMODE_MULTIPASS;
5316 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
5317 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
5320 int layertexrgbscale;
5321 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5323 if (layerindex == 0)
5327 GL_AlphaTest(false);
5328 qglDepthFunc(GL_EQUAL);CHECKGLERROR
5331 GL_DepthMask(layer->depthmask);
5332 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
5333 if ((layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2) && (gl_combine.integer || layer->depthmask))
5335 layertexrgbscale = 4;
5336 VectorScale(layer->color, 0.25f, layercolor);
5338 else if ((layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1) && (gl_combine.integer || layer->depthmask))
5340 layertexrgbscale = 2;
5341 VectorScale(layer->color, 0.5f, layercolor);
5345 layertexrgbscale = 1;
5346 VectorScale(layer->color, 1.0f, layercolor);
5348 layercolor[3] = layer->color[3];
5349 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
5350 R_Mesh_ColorPointer(NULL, 0, 0);
5351 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
5352 switch (layer->type)
5354 case TEXTURELAYERTYPE_LITTEXTURE:
5355 memset(&m, 0, sizeof(m));
5356 m.tex[0] = R_GetTexture(r_texture_white);
5357 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
5358 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
5359 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
5360 m.tex[1] = R_GetTexture(layer->texture);
5361 m.texmatrix[1] = layer->texmatrix;
5362 m.texrgbscale[1] = layertexrgbscale;
5363 m.pointer_texcoord[1] = rsurface.texcoordtexture2f;
5364 m.pointer_texcoord_bufferobject[1] = rsurface.texcoordtexture2f_bufferobject;
5365 m.pointer_texcoord_bufferoffset[1] = rsurface.texcoordtexture2f_bufferoffset;
5366 R_Mesh_TextureState(&m);
5367 if (rsurface.lightmode == 2)
5368 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
5369 else if (rsurface.uselightmaptexture)
5370 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
5372 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
5374 case TEXTURELAYERTYPE_TEXTURE:
5375 memset(&m, 0, sizeof(m));
5376 m.tex[0] = R_GetTexture(layer->texture);
5377 m.texmatrix[0] = layer->texmatrix;
5378 m.texrgbscale[0] = layertexrgbscale;
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;
5382 R_Mesh_TextureState(&m);
5383 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
5385 case TEXTURELAYERTYPE_FOG:
5386 memset(&m, 0, sizeof(m));
5387 m.texrgbscale[0] = layertexrgbscale;
5390 m.tex[0] = R_GetTexture(layer->texture);
5391 m.texmatrix[0] = layer->texmatrix;
5392 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5393 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5394 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5396 R_Mesh_TextureState(&m);
5397 // generate a color array for the fog pass
5398 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
5399 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5403 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5404 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)
5406 f = 1 - FogPoint_Model(v);
5407 c[0] = layercolor[0];
5408 c[1] = layercolor[1];
5409 c[2] = layercolor[2];
5410 c[3] = f * layercolor[3];
5413 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5416 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
5418 GL_LockArrays(0, 0);
5421 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5423 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
5424 GL_AlphaTest(false);
5428 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, msurface_t **texturesurfacelist)
5430 // OpenGL 1.1 - crusty old voodoo path
5431 int texturesurfaceindex;
5435 const texturelayer_t *layer;
5436 if (rsurface.mode != RSURFMODE_MULTIPASS)
5437 rsurface.mode = RSURFMODE_MULTIPASS;
5438 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
5439 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
5441 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5443 if (layerindex == 0)
5447 GL_AlphaTest(false);
5448 qglDepthFunc(GL_EQUAL);CHECKGLERROR
5451 GL_DepthMask(layer->depthmask);
5452 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
5453 R_Mesh_ColorPointer(NULL, 0, 0);
5454 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
5455 switch (layer->type)
5457 case TEXTURELAYERTYPE_LITTEXTURE:
5458 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
5460 // two-pass lit texture with 2x rgbscale
5461 // first the lightmap pass
5462 memset(&m, 0, sizeof(m));
5463 m.tex[0] = R_GetTexture(r_texture_white);
5464 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
5465 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
5466 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
5467 R_Mesh_TextureState(&m);
5468 if (rsurface.lightmode == 2)
5469 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5470 else if (rsurface.uselightmaptexture)
5471 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5473 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5474 GL_LockArrays(0, 0);
5475 // then apply the texture to it
5476 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
5477 memset(&m, 0, sizeof(m));
5478 m.tex[0] = R_GetTexture(layer->texture);
5479 m.texmatrix[0] = layer->texmatrix;
5480 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5481 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5482 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5483 R_Mesh_TextureState(&m);
5484 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);
5488 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
5489 memset(&m, 0, sizeof(m));
5490 m.tex[0] = R_GetTexture(layer->texture);
5491 m.texmatrix[0] = layer->texmatrix;
5492 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5493 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5494 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5495 R_Mesh_TextureState(&m);
5496 if (rsurface.lightmode == 2)
5497 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);
5499 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);
5502 case TEXTURELAYERTYPE_TEXTURE:
5503 // singletexture unlit texture with transparency support
5504 memset(&m, 0, sizeof(m));
5505 m.tex[0] = R_GetTexture(layer->texture);
5506 m.texmatrix[0] = layer->texmatrix;
5507 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5508 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5509 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5510 R_Mesh_TextureState(&m);
5511 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);
5513 case TEXTURELAYERTYPE_FOG:
5514 // singletexture fogging
5515 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
5518 memset(&m, 0, sizeof(m));
5519 m.tex[0] = R_GetTexture(layer->texture);
5520 m.texmatrix[0] = layer->texmatrix;
5521 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5522 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5523 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5524 R_Mesh_TextureState(&m);
5527 R_Mesh_ResetTextureState();
5528 // generate a color array for the fog pass
5529 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5533 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5534 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)
5536 f = 1 - FogPoint_Model(v);
5537 c[0] = layer->color[0];
5538 c[1] = layer->color[1];
5539 c[2] = layer->color[2];
5540 c[3] = f * layer->color[3];
5543 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5546 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
5548 GL_LockArrays(0, 0);
5551 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5553 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
5554 GL_AlphaTest(false);
5558 static void R_DrawTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly)
5560 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW)
5562 rsurface.rtlight = NULL;
5566 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
5568 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
5570 if (rsurface.mode != RSURFMODE_MULTIPASS)
5571 rsurface.mode = RSURFMODE_MULTIPASS;
5572 if (r_depthfirst.integer == 3)
5574 int i = (int)(texturesurfacelist[0] - rsurface.modelsurfaces);
5575 if (!r_view.showdebug)
5576 GL_Color(0, 0, 0, 1);
5578 GL_Color(((i >> 6) & 7) / 7.0f, ((i >> 3) & 7) / 7.0f, (i & 7) / 7.0f,1);
5582 GL_ColorMask(0,0,0,0);
5585 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5586 GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset);
5587 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_view.cullface_back);
5589 GL_BlendFunc(GL_ONE, GL_ZERO);
5591 GL_AlphaTest(false);
5592 R_Mesh_ColorPointer(NULL, 0, 0);
5593 R_Mesh_ResetTextureState();
5594 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
5595 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5596 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
5597 r_refdef.stats.entities_surfaces += texturenumsurfaces;
5599 else if (r_depthfirst.integer == 3)
5601 else if (!r_view.showdebug && (r_showsurfaces.integer || gl_lightmaps.integer))
5603 GL_Color(0, 0, 0, 1);
5604 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5606 else if (r_showsurfaces.integer)
5608 if (rsurface.mode != RSURFMODE_MULTIPASS)
5609 rsurface.mode = RSURFMODE_MULTIPASS;
5610 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5611 GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset);
5613 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_view.cullface_back);
5614 GL_BlendFunc(GL_ONE, GL_ZERO);
5615 GL_DepthMask(writedepth);
5617 GL_AlphaTest(false);
5618 R_Mesh_ColorPointer(NULL, 0, 0);
5619 R_Mesh_ResetTextureState();
5620 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
5621 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
5622 r_refdef.stats.entities_surfaces += texturenumsurfaces;
5624 else if (gl_lightmaps.integer)
5627 if (rsurface.mode != RSURFMODE_MULTIPASS)
5628 rsurface.mode = RSURFMODE_MULTIPASS;
5629 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5631 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_view.cullface_back);
5632 GL_BlendFunc(GL_ONE, GL_ZERO);
5633 GL_DepthMask(writedepth);
5635 GL_AlphaTest(false);
5636 // use lightmode 0 (fullbright or lightmap) or 2 (model lighting)
5637 rsurface.lightmode = ((rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT) || rsurface.modeltexcoordlightmap2f != NULL) ? 0 : 2;
5638 R_Mesh_ColorPointer(NULL, 0, 0);
5639 memset(&m, 0, sizeof(m));
5640 m.tex[0] = R_GetTexture(r_texture_white);
5641 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
5642 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
5643 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
5644 R_Mesh_TextureState(&m);
5645 RSurf_PrepareVerticesForBatch(rsurface.lightmode == 2, false, texturenumsurfaces, texturesurfacelist);
5646 if (rsurface.lightmode == 2)
5647 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5648 else if (rsurface.uselightmaptexture)
5649 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5651 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5652 r_refdef.stats.entities_surfaces += texturenumsurfaces;
5654 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
5656 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
5657 r_refdef.stats.entities_surfaces += texturenumsurfaces;
5659 else if (rsurface.texture->currentnumlayers)
5661 // write depth for anything we skipped on the depth-only pass earlier
5662 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5664 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5665 GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset);
5666 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
5667 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_view.cullface_back);
5668 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5669 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
5670 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5671 // use lightmode 0 (fullbright or lightmap) or 2 (model lighting)
5672 rsurface.lightmode = ((rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT) || rsurface.modeltexcoordlightmap2f != NULL) ? 0 : 2;
5673 if (r_glsl.integer && gl_support_fragment_shader)
5674 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist);
5675 else if (gl_combine.integer && r_textureunits.integer >= 2)
5676 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist);
5678 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist);
5679 r_refdef.stats.entities_surfaces += texturenumsurfaces;
5682 GL_LockArrays(0, 0);
5685 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
5688 int texturenumsurfaces, endsurface;
5690 msurface_t *surface;
5691 msurface_t *texturesurfacelist[1024];
5693 // if the model is static it doesn't matter what value we give for
5694 // wantnormals and wanttangents, so this logic uses only rules applicable
5695 // to a model, knowing that they are meaningless otherwise
5696 if (ent == r_refdef.worldentity)
5697 RSurf_ActiveWorldEntity();
5698 else if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
5699 RSurf_ActiveModelEntity(ent, false, false);
5701 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
5703 for (i = 0;i < numsurfaces;i = j)
5706 surface = rsurface.modelsurfaces + surfacelist[i];
5707 texture = surface->texture;
5708 R_UpdateTextureInfo(ent, texture);
5709 rsurface.texture = texture->currentframe;
5710 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
5711 // scan ahead until we find a different texture
5712 endsurface = min(i + 1024, numsurfaces);
5713 texturenumsurfaces = 0;
5714 texturesurfacelist[texturenumsurfaces++] = surface;
5715 for (;j < endsurface;j++)
5717 surface = rsurface.modelsurfaces + surfacelist[j];
5718 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
5720 texturesurfacelist[texturenumsurfaces++] = surface;
5722 // render the range of surfaces
5723 R_DrawTextureSurfaceList(texturenumsurfaces, texturesurfacelist, true, false);
5729 void R_QueueSurfaceList(entity_render_t *ent, int numsurfaces, msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes)
5732 vec3_t tempcenter, center;
5734 // if we're rendering water textures (extra scene renders), use a separate loop to avoid burdening the main one
5737 for (i = 0;i < numsurfaces;i++)
5738 if (surfacelist[i]->texture->currentframe->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5739 R_Water_AddWaterPlane(surfacelist[i]);
5742 // break the surface list down into batches by texture and use of lightmapping
5743 for (i = 0;i < numsurfaces;i = j)
5746 // texture is the base texture pointer, rsurface.texture is the
5747 // current frame/skin the texture is directing us to use (for example
5748 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
5749 // use skin 1 instead)
5750 texture = surfacelist[i]->texture;
5751 rsurface.texture = texture->currentframe;
5752 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
5753 if (!(rsurface.texture->currentmaterialflags & flagsmask))
5755 // if this texture is not the kind we want, skip ahead to the next one
5756 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
5760 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
5762 // transparent surfaces get pushed off into the transparent queue
5763 const msurface_t *surface = surfacelist[i];
5766 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
5767 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
5768 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
5769 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
5770 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_view.origin : center, R_DrawSurface_TransparentCallback, ent, surface - rsurface.modelsurfaces, rsurface.rtlight);
5774 // simply scan ahead until we find a different texture or lightmap state
5775 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
5777 // render the range of surfaces
5778 R_DrawTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly);
5783 float locboxvertex3f[6*4*3] =
5785 1,0,1, 1,0,0, 1,1,0, 1,1,1,
5786 0,1,1, 0,1,0, 0,0,0, 0,0,1,
5787 1,1,1, 1,1,0, 0,1,0, 0,1,1,
5788 0,0,1, 0,0,0, 1,0,0, 1,0,1,
5789 0,0,1, 1,0,1, 1,1,1, 0,1,1,
5790 1,0,0, 0,0,0, 0,1,0, 1,1,0
5793 int locboxelement3i[6*2*3] =
5803 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
5806 cl_locnode_t *loc = (cl_locnode_t *)ent;
5808 float vertex3f[6*4*3];
5810 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5811 GL_DepthMask(false);
5812 GL_DepthRange(0, 1);
5813 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5815 GL_CullFace(GL_NONE);
5816 R_Mesh_Matrix(&identitymatrix);
5818 R_Mesh_VertexPointer(vertex3f, 0, 0);
5819 R_Mesh_ColorPointer(NULL, 0, 0);
5820 R_Mesh_ResetTextureState();
5823 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_view.colorscale,
5824 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_view.colorscale,
5825 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_view.colorscale,
5826 surfacelist[0] < 0 ? 0.5f : 0.125f);
5828 if (VectorCompare(loc->mins, loc->maxs))
5830 VectorSet(size, 2, 2, 2);
5831 VectorMA(loc->mins, -0.5f, size, mins);
5835 VectorCopy(loc->mins, mins);
5836 VectorSubtract(loc->maxs, loc->mins, size);
5839 for (i = 0;i < 6*4*3;)
5840 for (j = 0;j < 3;j++, i++)
5841 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
5843 R_Mesh_Draw(0, 6*4, 6*2, locboxelement3i, 0, 0);
5846 void R_DrawLocs(void)
5849 cl_locnode_t *loc, *nearestloc;
5851 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
5852 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
5854 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
5855 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
5859 void R_DrawDebugModel(entity_render_t *ent)
5861 int i, j, k, l, flagsmask;
5862 const int *elements;
5864 msurface_t *surface;
5865 model_t *model = ent->model;
5868 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WATER | MATERIALFLAG_WALL;
5870 R_Mesh_ColorPointer(NULL, 0, 0);
5871 R_Mesh_ResetTextureState();
5872 GL_DepthRange(0, 1);
5873 GL_DepthTest(!r_showdisabledepthtest.integer);
5874 GL_DepthMask(false);
5875 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5877 if (r_showcollisionbrushes.value > 0 && model->brush.num_brushes)
5879 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
5880 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
5882 if (brush->colbrushf && brush->colbrushf->numtriangles)
5884 R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
5885 GL_Color((i & 31) * (1.0f / 32.0f) * r_view.colorscale, ((i >> 5) & 31) * (1.0f / 32.0f) * r_view.colorscale, ((i >> 10) & 31) * (1.0f / 32.0f) * r_view.colorscale, r_showcollisionbrushes.value);
5886 R_Mesh_Draw(0, brush->colbrushf->numpoints, brush->colbrushf->numtriangles, brush->colbrushf->elements, 0, 0);
5889 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
5891 if (surface->num_collisiontriangles)
5893 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
5894 GL_Color((i & 31) * (1.0f / 32.0f) * r_view.colorscale, ((i >> 5) & 31) * (1.0f / 32.0f) * r_view.colorscale, ((i >> 10) & 31) * (1.0f / 32.0f) * r_view.colorscale, r_showcollisionbrushes.value);
5895 R_Mesh_Draw(0, surface->num_collisionvertices, surface->num_collisiontriangles, surface->data_collisionelement3i, 0, 0);
5900 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5902 if (r_showtris.integer || r_shownormals.integer)
5904 if (r_showdisabledepthtest.integer)
5906 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5907 GL_DepthMask(false);
5911 GL_BlendFunc(GL_ONE, GL_ZERO);
5914 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
5916 if (ent == r_refdef.worldentity && !r_viewcache.world_surfacevisible[j])
5918 rsurface.texture = surface->texture->currentframe;
5919 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
5921 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
5922 if (r_showtris.value > 0)
5924 if (!rsurface.texture->currentlayers->depthmask)
5925 GL_Color(r_view.colorscale, 0, 0, r_showtris.value);
5926 else if (ent == r_refdef.worldentity)
5927 GL_Color(r_view.colorscale, r_view.colorscale, r_view.colorscale, r_showtris.value);
5929 GL_Color(0, r_view.colorscale, 0, r_showtris.value);
5930 elements = (ent->model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
5933 for (k = 0;k < surface->num_triangles;k++, elements += 3)
5935 #define GLVERTEXELEMENT(n) qglVertex3f(rsurface.vertex3f[elements[n]*3+0], rsurface.vertex3f[elements[n]*3+1], rsurface.vertex3f[elements[n]*3+2])
5936 GLVERTEXELEMENT(0);GLVERTEXELEMENT(1);
5937 GLVERTEXELEMENT(1);GLVERTEXELEMENT(2);
5938 GLVERTEXELEMENT(2);GLVERTEXELEMENT(0);
5943 if (r_shownormals.value > 0)
5945 GL_Color(r_view.colorscale, 0, 0, r_shownormals.value);
5947 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
5949 VectorCopy(rsurface.vertex3f + l * 3, v);
5950 qglVertex3f(v[0], v[1], v[2]);
5951 VectorMA(v, 8, rsurface.svector3f + l * 3, v);
5952 qglVertex3f(v[0], v[1], v[2]);
5956 GL_Color(0, 0, r_view.colorscale, r_shownormals.value);
5958 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
5960 VectorCopy(rsurface.vertex3f + l * 3, v);
5961 qglVertex3f(v[0], v[1], v[2]);
5962 VectorMA(v, 8, rsurface.tvector3f + l * 3, v);
5963 qglVertex3f(v[0], v[1], v[2]);
5967 GL_Color(0, r_view.colorscale, 0, r_shownormals.value);
5969 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
5971 VectorCopy(rsurface.vertex3f + l * 3, v);
5972 qglVertex3f(v[0], v[1], v[2]);
5973 VectorMA(v, 8, rsurface.normal3f + l * 3, v);
5974 qglVertex3f(v[0], v[1], v[2]);
5981 rsurface.texture = NULL;
5985 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
5986 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes, qboolean debug)
5988 int i, j, endj, f, flagsmask;
5989 int counttriangles = 0;
5990 msurface_t *surface, **surfacechain;
5992 model_t *model = r_refdef.worldmodel;
5993 const int maxsurfacelist = 1024;
5994 int numsurfacelist = 0;
5995 msurface_t *surfacelist[1024];
5999 RSurf_ActiveWorldEntity();
6001 // update light styles
6002 if (!skysurfaces && !depthonly && !addwaterplanes && model->brushq1.light_styleupdatechains)
6004 for (i = 0;i < model->brushq1.light_styles;i++)
6006 if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
6008 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
6009 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
6010 for (;(surface = *surfacechain);surfacechain++)
6011 surface->cached_dlight = true;
6016 R_UpdateAllTextureInfo(r_refdef.worldentity);
6017 flagsmask = addwaterplanes ? (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION) : (skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL));
6021 R_DrawDebugModel(r_refdef.worldentity);
6027 rsurface.uselightmaptexture = false;
6028 rsurface.texture = NULL;
6030 j = model->firstmodelsurface;
6031 endj = j + model->nummodelsurfaces;
6034 // quickly skip over non-visible surfaces
6035 for (;j < endj && !r_viewcache.world_surfacevisible[j];j++)
6037 // quickly iterate over visible surfaces
6038 for (;j < endj && r_viewcache.world_surfacevisible[j];j++)
6040 // process this surface
6041 surface = model->data_surfaces + j;
6042 // if this surface fits the criteria, add it to the list
6043 if (surface->num_triangles)
6045 // if lightmap parameters changed, rebuild lightmap texture
6046 if (surface->cached_dlight)
6047 R_BuildLightMap(r_refdef.worldentity, surface);
6048 // add face to draw list
6049 surfacelist[numsurfacelist++] = surface;
6050 counttriangles += surface->num_triangles;
6051 if (numsurfacelist >= maxsurfacelist)
6053 R_QueueSurfaceList(r_refdef.worldentity, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
6060 R_QueueSurfaceList(r_refdef.worldentity, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
6061 r_refdef.stats.entities_triangles += counttriangles;
6065 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes, qboolean debug)
6067 int i, f, flagsmask;
6068 int counttriangles = 0;
6069 msurface_t *surface, *endsurface, **surfacechain;
6071 model_t *model = ent->model;
6072 const int maxsurfacelist = 1024;
6073 int numsurfacelist = 0;
6074 msurface_t *surfacelist[1024];
6078 // if the model is static it doesn't matter what value we give for
6079 // wantnormals and wanttangents, so this logic uses only rules applicable
6080 // to a model, knowing that they are meaningless otherwise
6081 if (ent == r_refdef.worldentity)
6082 RSurf_ActiveWorldEntity();
6083 else if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
6084 RSurf_ActiveModelEntity(ent, false, false);
6086 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader && !depthonly);
6088 // update light styles
6089 if (!skysurfaces && !depthonly && !addwaterplanes && model->brushq1.light_styleupdatechains)
6091 for (i = 0;i < model->brushq1.light_styles;i++)
6093 if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
6095 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
6096 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
6097 for (;(surface = *surfacechain);surfacechain++)
6098 surface->cached_dlight = true;
6103 R_UpdateAllTextureInfo(ent);
6104 flagsmask = addwaterplanes ? (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION) : (skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL));
6108 R_DrawDebugModel(ent);
6114 rsurface.uselightmaptexture = false;
6115 rsurface.texture = NULL;
6117 surface = model->data_surfaces + model->firstmodelsurface;
6118 endsurface = surface + model->nummodelsurfaces;
6119 for (;surface < endsurface;surface++)
6121 // if this surface fits the criteria, add it to the list
6122 if (surface->num_triangles)
6124 // if lightmap parameters changed, rebuild lightmap texture
6125 if (surface->cached_dlight)
6126 R_BuildLightMap(ent, surface);
6127 // add face to draw list
6128 surfacelist[numsurfacelist++] = surface;
6129 counttriangles += surface->num_triangles;
6130 if (numsurfacelist >= maxsurfacelist)
6132 R_QueueSurfaceList(ent, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
6138 R_QueueSurfaceList(ent, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
6139 r_refdef.stats.entities_triangles += counttriangles;