2 Copyright (C) 1996-1997 Id Software, Inc.
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
27 mempool_t *r_main_mempool;
28 rtexturepool_t *r_main_texturepool;
35 r_viewcache_t r_viewcache;
37 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "1", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
38 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
39 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%, 10 = 100%)"};
40 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
41 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
42 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
43 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
44 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
45 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
46 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
47 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
48 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
49 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
50 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
51 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
52 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
53 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling"};
54 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
55 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
56 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
57 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
58 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
59 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
60 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
61 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this)"};
62 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
63 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
64 cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
65 cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "2", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
67 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
68 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
69 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
70 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
71 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
72 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
73 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
75 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of hardware texture units reported by driver (note: setting this to 1 turns off gl_combine)"};
77 cvar_t r_glsl = {CVAR_SAVE, "r_glsl", "1", "enables use of OpenGL 2.0 pixel shaders for lighting"};
78 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
79 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
80 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
81 cvar_t r_glsl_water = {CVAR_SAVE, "r_glsl_water", "0", "whether to use reflections and refraction on water surfaces (note: r_wateralpha must be set below 1)"};
82 cvar_t r_glsl_water_clippingplanebias = {CVAR_SAVE, "r_glsl_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
83 cvar_t r_glsl_water_resolutionmultiplier = {CVAR_SAVE, "r_glsl_water_resolutionmultiplier", "0.5", "multiplier for screen resolution when rendering refracted/reflected scenes, 1 is full quality, lower values are faster"};
84 cvar_t r_glsl_water_refractdistort = {CVAR_SAVE, "r_glsl_water_refractdistort", "0.01", "how much water refractions shimmer"};
85 cvar_t r_glsl_water_reflectdistort = {CVAR_SAVE, "r_glsl_water_reflectdistort", "0.01", "how much water reflections shimmer"};
86 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)"};
87 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)"};
89 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1", "enables animation smoothing on sprites (requires r_lerpmodels 1)"};
90 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
91 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
93 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
94 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
95 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
96 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
97 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
98 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
99 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
101 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
102 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
103 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
104 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)"};
106 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"};
108 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"};
110 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
112 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
113 cvar_t r_batchmode = {0, "r_batchmode", "1", "selects method of rendering multiple surfaces with one driver call (values are 0, 1, 2, etc...)"};
115 extern qboolean v_flipped_state;
117 typedef struct r_glsl_bloomshader_s
120 int loc_Texture_Bloom;
122 r_glsl_bloomshader_t;
124 static struct r_bloomstate_s
129 int bloomwidth, bloomheight;
131 int screentexturewidth, screentextureheight;
132 rtexture_t *texture_screen;
134 int bloomtexturewidth, bloomtextureheight;
135 rtexture_t *texture_bloom;
137 r_glsl_bloomshader_t *shader;
139 // arrays for rendering the screen passes
140 float screentexcoord2f[8];
141 float bloomtexcoord2f[8];
142 float offsettexcoord2f[8];
146 typedef struct r_waterstate_waterplane_s
148 rtexture_t *texture_refraction;
149 rtexture_t *texture_reflection;
151 int materialflags; // combined flags of all water surfaces on this plane
152 unsigned char pvsbits[(32768+7)>>3]; // FIXME: buffer overflow on huge maps
155 r_waterstate_waterplane_t;
157 #define MAX_WATERPLANES 16
159 static struct r_waterstate_s
163 qboolean renderingscene; // true while rendering a refraction or reflection texture, disables water surfaces
165 int waterwidth, waterheight;
166 int texturewidth, textureheight;
168 int maxwaterplanes; // same as MAX_WATERPLANES
170 r_waterstate_waterplane_t waterplanes[MAX_WATERPLANES];
172 float screenscale[2];
173 float screencenter[2];
177 // shadow volume bsp struct with automatically growing nodes buffer
180 rtexture_t *r_texture_blanknormalmap;
181 rtexture_t *r_texture_white;
182 rtexture_t *r_texture_grey128;
183 rtexture_t *r_texture_black;
184 rtexture_t *r_texture_notexture;
185 rtexture_t *r_texture_whitecube;
186 rtexture_t *r_texture_normalizationcube;
187 rtexture_t *r_texture_fogattenuation;
188 //rtexture_t *r_texture_fogintensity;
190 // information about each possible shader permutation
191 r_glsl_permutation_t r_glsl_permutations[SHADERPERMUTATION_MAX];
192 // currently selected permutation
193 r_glsl_permutation_t *r_glsl_permutation;
195 char r_qwskincache[MAX_SCOREBOARD][MAX_QPATH];
196 skinframe_t *r_qwskincache_skinframe[MAX_SCOREBOARD];
198 // vertex coordinates for a quad that covers the screen exactly
199 const static float r_screenvertex3f[12] =
207 extern void R_DrawModelShadows(void);
209 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
212 for (i = 0;i < verts;i++)
223 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
226 for (i = 0;i < verts;i++)
236 // FIXME: move this to client?
239 if (gamemode == GAME_NEHAHRA)
241 Cvar_Set("gl_fogenable", "0");
242 Cvar_Set("gl_fogdensity", "0.2");
243 Cvar_Set("gl_fogred", "0.3");
244 Cvar_Set("gl_foggreen", "0.3");
245 Cvar_Set("gl_fogblue", "0.3");
247 r_refdef.fog_density = r_refdef.fog_red = r_refdef.fog_green = r_refdef.fog_blue = 0.0f;
250 float FogPoint_World(const vec3_t p)
252 int fogmasktableindex = (int)(VectorDistance((p), r_view.origin) * r_refdef.fogmasktabledistmultiplier);
253 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
256 float FogPoint_Model(const vec3_t p)
258 int fogmasktableindex = (int)(VectorDistance((p), rsurface.modelorg) * r_refdef.fogmasktabledistmultiplier);
259 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
262 static void R_BuildBlankTextures(void)
264 unsigned char data[4];
265 data[0] = 128; // normal X
266 data[1] = 128; // normal Y
267 data[2] = 255; // normal Z
268 data[3] = 128; // height
269 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
274 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
279 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
284 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
287 static void R_BuildNoTexture(void)
290 unsigned char pix[16][16][4];
291 // this makes a light grey/dark grey checkerboard texture
292 for (y = 0;y < 16;y++)
294 for (x = 0;x < 16;x++)
296 if ((y < 8) ^ (x < 8))
312 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_RGBA, TEXF_MIPMAP, NULL);
315 static void R_BuildWhiteCube(void)
317 unsigned char data[6*1*1*4];
318 data[ 0] = 255;data[ 1] = 255;data[ 2] = 255;data[ 3] = 255;
319 data[ 4] = 255;data[ 5] = 255;data[ 6] = 255;data[ 7] = 255;
320 data[ 8] = 255;data[ 9] = 255;data[10] = 255;data[11] = 255;
321 data[12] = 255;data[13] = 255;data[14] = 255;data[15] = 255;
322 data[16] = 255;data[17] = 255;data[18] = 255;data[19] = 255;
323 data[20] = 255;data[21] = 255;data[22] = 255;data[23] = 255;
324 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
327 static void R_BuildNormalizationCube(void)
331 vec_t s, t, intensity;
333 unsigned char data[6][NORMSIZE][NORMSIZE][4];
334 for (side = 0;side < 6;side++)
336 for (y = 0;y < NORMSIZE;y++)
338 for (x = 0;x < NORMSIZE;x++)
340 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
341 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
376 intensity = 127.0f / sqrt(DotProduct(v, v));
377 data[side][y][x][0] = (unsigned char)(128.0f + intensity * v[0]);
378 data[side][y][x][1] = (unsigned char)(128.0f + intensity * v[1]);
379 data[side][y][x][2] = (unsigned char)(128.0f + intensity * v[2]);
380 data[side][y][x][3] = 255;
384 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, &data[0][0][0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
387 static void R_BuildFogTexture(void)
391 unsigned char data1[FOGWIDTH][4];
392 //unsigned char data2[FOGWIDTH][4];
393 for (x = 0;x < FOGWIDTH;x++)
395 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
400 //data2[x][0] = 255 - b;
401 //data2[x][1] = 255 - b;
402 //data2[x][2] = 255 - b;
405 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
406 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
409 static const char *builtinshaderstring =
410 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
411 "// written by Forest 'LordHavoc' Hale\n"
413 "// common definitions between vertex shader and fragment shader:\n"
415 "#ifdef __GLSL_CG_DATA_TYPES\n"
416 "# define myhalf half\n"
417 "# define myhvec2 hvec2\n"
418 "# define myhvec3 hvec3\n"
419 "# define myhvec4 hvec4\n"
421 "# define myhalf float\n"
422 "# define myhvec2 vec2\n"
423 "# define myhvec3 vec3\n"
424 "# define myhvec4 vec4\n"
427 "varying vec2 TexCoord;\n"
428 "varying vec2 TexCoordLightmap;\n"
430 "//#ifdef MODE_LIGHTSOURCE\n"
431 "varying vec3 CubeVector;\n"
434 "//#ifdef MODE_LIGHTSOURCE\n"
435 "varying vec3 LightVector;\n"
437 "//# ifdef MODE_LIGHTDIRECTION\n"
438 "//varying vec3 LightVector;\n"
442 "varying vec3 EyeVector;\n"
444 "varying vec3 EyeVectorModelSpace;\n"
447 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
448 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
449 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
451 "//#ifdef USEWATER\n"
452 "varying vec4 ModelViewProjectionPosition;\n"
454 "//# ifdef USEREFLECTION\n"
455 "//varying vec4 ModelViewProjectionPosition;\n"
463 "// vertex shader specific:\n"
464 "#ifdef VERTEX_SHADER\n"
466 "uniform vec3 LightPosition;\n"
467 "uniform vec3 EyePosition;\n"
468 "uniform vec3 LightDir;\n"
470 "// TODO: get rid of tangentt (texcoord2) and use a crossproduct to regenerate it from tangents (texcoord1) and normal (texcoord3)\n"
474 " gl_FrontColor = gl_Color;\n"
475 " // copy the surface texcoord\n"
476 " TexCoord = vec2(gl_TextureMatrix[0] * gl_MultiTexCoord0);\n"
477 "#ifndef MODE_LIGHTSOURCE\n"
478 "# ifndef MODE_LIGHTDIRECTION\n"
479 " TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
483 "#ifdef MODE_LIGHTSOURCE\n"
484 " // transform vertex position into light attenuation/cubemap space\n"
485 " // (-1 to +1 across the light box)\n"
486 " CubeVector = vec3(gl_TextureMatrix[3] * gl_Vertex);\n"
488 " // transform unnormalized light direction into tangent space\n"
489 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
490 " // normalize it per pixel)\n"
491 " vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
492 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
493 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
494 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
497 "#ifdef MODE_LIGHTDIRECTION\n"
498 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
499 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
500 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
503 " // transform unnormalized eye direction into tangent space\n"
505 " vec3 EyeVectorModelSpace;\n"
507 " EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
508 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
509 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
510 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
512 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
513 " VectorS = gl_MultiTexCoord1.xyz;\n"
514 " VectorT = gl_MultiTexCoord2.xyz;\n"
515 " VectorR = gl_MultiTexCoord3.xyz;\n"
518 "//#if defined(USEWATER) || defined(USEREFLECTION)\n"
519 "// ModelViewProjectionPosition = gl_Vertex * gl_ModelViewProjectionMatrix;\n"
520 "// //ModelViewProjectionPosition_svector = (gl_Vertex + vec4(gl_MultiTexCoord1.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
521 "// //ModelViewProjectionPosition_tvector = (gl_Vertex + vec4(gl_MultiTexCoord2.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
524 "// transform vertex to camera space, using ftransform to match non-VS\n"
526 " gl_Position = ftransform();\n"
529 " ModelViewProjectionPosition = gl_Position;\n"
531 "# ifdef USEREFLECTION\n"
532 " ModelViewProjectionPosition = gl_Position;\n"
537 "#endif // VERTEX_SHADER\n"
542 "// fragment shader specific:\n"
543 "#ifdef FRAGMENT_SHADER\n"
545 "// 13 textures, we can only use up to 16 on DX9-class hardware\n"
546 "uniform sampler2D Texture_Normal;\n"
547 "uniform sampler2D Texture_Color;\n"
548 "uniform sampler2D Texture_Gloss;\n"
549 "uniform samplerCube Texture_Cube;\n"
550 "uniform sampler2D Texture_Attenuation;\n"
551 "uniform sampler2D Texture_FogMask;\n"
552 "uniform sampler2D Texture_Pants;\n"
553 "uniform sampler2D Texture_Shirt;\n"
554 "uniform sampler2D Texture_Lightmap;\n"
555 "uniform sampler2D Texture_Deluxemap;\n"
556 "uniform sampler2D Texture_Glow;\n"
557 "uniform sampler2D Texture_Reflection;\n"
558 "uniform sampler2D Texture_Refraction;\n"
560 "uniform myhvec3 LightColor;\n"
561 "uniform myhvec3 AmbientColor;\n"
562 "uniform myhvec3 DiffuseColor;\n"
563 "uniform myhvec3 SpecularColor;\n"
564 "uniform myhvec3 Color_Pants;\n"
565 "uniform myhvec3 Color_Shirt;\n"
566 "uniform myhvec3 FogColor;\n"
568 "//#ifdef USEWATER\n"
569 "uniform vec4 DistortScaleRefractReflect;\n"
570 "uniform vec4 ScreenScaleRefractReflect;\n"
571 "uniform vec4 ScreenCenterRefractReflect;\n"
572 "uniform myhvec3 RefractColor;\n"
573 "uniform myhvec3 ReflectColor;\n"
574 "uniform myhalf ReflectFactor;\n"
576 "//# ifdef USEREFLECTION\n"
577 "//uniform vec4 DistortScaleRefractReflect;\n"
578 "//uniform vec4 ScreenScaleRefractReflect;\n"
579 "//uniform vec4 ScreenCenterRefractReflect;\n"
580 "//uniform myhvec3 ReflectColor;\n"
584 "uniform myhalf GlowScale;\n"
585 "uniform myhalf SceneBrightness;\n"
586 "#ifdef USECONTRASTBOOST\n"
587 "uniform myhalf ContrastBoostCoeff;\n"
590 "uniform float OffsetMapping_Scale;\n"
591 "uniform float OffsetMapping_Bias;\n"
592 "uniform float FogRangeRecip;\n"
594 "uniform myhalf AmbientScale;\n"
595 "uniform myhalf DiffuseScale;\n"
596 "uniform myhalf SpecularScale;\n"
597 "uniform myhalf SpecularPower;\n"
599 "#ifdef USEOFFSETMAPPING\n"
600 "vec2 OffsetMapping(vec2 TexCoord)\n"
602 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
603 " // 14 sample relief mapping: linear search and then binary search\n"
604 " // this basically steps forward a small amount repeatedly until it finds\n"
605 " // itself inside solid, then jitters forward and back using decreasing\n"
606 " // amounts to find the impact\n"
607 " //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
608 " //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
609 " vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
610 " vec3 RT = vec3(TexCoord, 1);\n"
611 " OffsetVector *= 0.1;\n"
612 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
613 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\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) - 0.5);\n"
622 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5 - 0.25);\n"
623 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25 - 0.125);\n"
624 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125 - 0.0625);\n"
625 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
628 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
629 " // this basically moves forward the full distance, and then backs up based\n"
630 " // on height of samples\n"
631 " //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
632 " //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
633 " vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
634 " TexCoord += OffsetVector;\n"
635 " OffsetVector *= 0.333;\n"
636 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
637 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
638 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
639 " return TexCoord;\n"
646 "#ifdef USEOFFSETMAPPING\n"
647 " // apply offsetmapping\n"
648 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
649 "#define TexCoord TexCoordOffset\n"
652 " // combine the diffuse textures (base, pants, shirt)\n"
653 " myhvec4 color = myhvec4(texture2D(Texture_Color, TexCoord));\n"
654 "#ifdef USECOLORMAPPING\n"
655 " color.rgb += myhvec3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhvec3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
661 "#ifdef MODE_LIGHTSOURCE\n"
664 " // calculate surface normal, light normal, and specular normal\n"
665 " // compute color intensity for the two textures (colormap and glossmap)\n"
666 " // scale by light color and attenuation as efficiently as possible\n"
667 " // (do as much scalar math as possible rather than vector math)\n"
668 "# ifdef USESPECULAR\n"
669 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
670 " myhvec3 diffusenormal = myhvec3(normalize(LightVector));\n"
671 " myhvec3 specularnormal = normalize(diffusenormal + myhvec3(normalize(EyeVector)));\n"
673 " // calculate directional shading\n"
674 " 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"
676 "# ifdef USEDIFFUSE\n"
677 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
678 " myhvec3 diffusenormal = myhvec3(normalize(LightVector));\n"
680 " // calculate directional shading\n"
681 " 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"
683 " // calculate directionless shading\n"
684 " color.rgb = color.rgb * LightColor * myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
688 "# ifdef USECUBEFILTER\n"
689 " // apply light cubemap filter\n"
690 " //color.rgb *= normalize(CubeVector) * 0.5 + 0.5;//vec3(textureCube(Texture_Cube, CubeVector));\n"
691 " color.rgb *= myhvec3(textureCube(Texture_Cube, CubeVector));\n"
693 " color *= myhvec4(gl_Color);\n"
694 "#endif // MODE_LIGHTSOURCE\n"
699 "#ifdef MODE_LIGHTDIRECTION\n"
700 " // directional model lighting\n"
702 " // get the surface normal and light normal\n"
703 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
704 " myhvec3 diffusenormal = myhvec3(LightVector);\n"
706 " // calculate directional shading\n"
707 " color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
708 "# ifdef USESPECULAR\n"
709 " myhvec3 specularnormal = normalize(diffusenormal + myhvec3(normalize(EyeVector)));\n"
710 " color.rgb += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
712 " color *= myhvec4(gl_Color);\n"
713 "#endif // MODE_LIGHTDIRECTION\n"
718 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
719 " // deluxemap lightmapping using light vectors in modelspace (evil q3map2)\n"
721 " // get the surface normal and light normal\n"
722 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
724 " myhvec3 diffusenormal_modelspace = myhvec3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - myhvec3(0.5);\n"
725 " myhvec3 diffusenormal = normalize(myhvec3(dot(diffusenormal_modelspace, myhvec3(VectorS)), dot(diffusenormal_modelspace, myhvec3(VectorT)), dot(diffusenormal_modelspace, myhvec3(VectorR))));\n"
726 " // calculate directional shading\n"
727 " myhvec3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0)));\n"
728 "# ifdef USESPECULAR\n"
729 " myhvec3 specularnormal = myhvec3(normalize(diffusenormal + myhvec3(normalize(EyeVector))));\n"
730 " tempcolor += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
733 " // apply lightmap color\n"
734 " color.rgb = myhvec4(tempcolor,1) * myhvec4(texture2D(Texture_Lightmap, TexCoordLightmap)) * myhvec4(gl_Color) + myhvec4(color.rgb * AmbientScale, 0);\n"
735 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
740 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
741 " // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
743 " // get the surface normal and light normal\n"
744 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
746 " myhvec3 diffusenormal = normalize(myhvec3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - myhvec3(0.5));\n"
747 " // calculate directional shading\n"
748 " myhvec3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0)));\n"
749 "# ifdef USESPECULAR\n"
750 " myhvec3 specularnormal = myhvec3(normalize(diffusenormal + myhvec3(normalize(EyeVector))));\n"
751 " tempcolor += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
754 " // apply lightmap color\n"
755 " color = myhvec4(tempcolor, 1) * myhvec4(texture2D(Texture_Lightmap, TexCoordLightmap)) * myhvec4(gl_Color) + myhvec4(color.rgb * AmbientScale, 0);\n"
756 "#endif // MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
761 "#ifdef MODE_LIGHTMAP\n"
762 " // apply lightmap color\n"
763 " color *= myhvec4(texture2D(Texture_Lightmap, TexCoordLightmap)) * myhvec4(gl_Color) * myhvec4(myhvec3(DiffuseScale), 1) + myhvec4(myhvec3(AmbientScale), 0);\n"
764 "#endif // MODE_LIGHTMAP\n"
773 "#ifdef MODE_LIGHTSOURCE\n"
775 " color.rgb *= color.a;\n"
779 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
780 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
781 " vec4 ScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect + vec3(normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5))).xyxy * DistortScaleRefractReflect;\n"
782 " myhalf Fresnel = myhalf(pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0)) * ReflectFactor;\n"
783 " color.rgb = mix(mix(myhvec3(texture2D(Texture_Refraction, ScreenTexCoord.xy)) * RefractColor, myhvec3(texture2D(Texture_Reflection, ScreenTexCoord.zw)) * ReflectColor, Fresnel), color.rgb, color.a);\n"
785 "# ifdef USEREFLECTION\n"
786 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
787 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
788 " vec4 ScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect + vec3(normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5))).xyxy * DistortScaleRefractReflect;\n"
789 " color.rgb = mix(color.rgb, myhvec3(texture2D(Texture_Reflection, ScreenTexCoord.zw)), ReflectFactor);\n"
795 " color.rgb += myhvec3(texture2D(Texture_Glow, TexCoord)) * GlowScale;\n"
800 " color.rgb = mix(FogColor, color.rgb, myhalf(texture2D(Texture_FogMask, myhvec2(length(EyeVectorModelSpace)*FogRangeRecip, 0.0))));\n"
803 "#ifdef USECONTRASTBOOST\n"
804 " color.rgb = color.rgb * SceneBrightness / (ContrastBoostCoeff * color.rgb + myhvec3(1, 1, 1));\n"
806 " color.rgb *= SceneBrightness;\n"
809 " gl_FragColor = vec4(color);\n"
812 "#endif // FRAGMENT_SHADER\n"
815 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
816 const char *permutationinfo[][2] =
818 {"#define MODE_LIGHTMAP\n", " lightmap"},
819 {"#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
820 {"#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
821 {"#define MODE_LIGHTDIRECTION\n", " lightdirection"},
822 {"#define MODE_LIGHTSOURCE\n", " lightsource"},
823 {"#define USEWATER\n", " water"},
824 {"#define USEREFLECTION\n", " reflection"},
825 {"#define USEGLOW\n", " glow"},
826 {"#define USEFOG\n", " fog"},
827 {"#define USECOLORMAPPING\n", " colormapping"},
828 {"#define USEDIFFUSE\n", " diffuse"},
829 {"#define USECONTRASTBOOST\n", " contrastboost"},
830 {"#define USESPECULAR\n", " specular"},
831 {"#define USECUBEFILTER\n", " cubefilter"},
832 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
833 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
837 void R_GLSL_CompilePermutation(const char *filename, int permutation)
840 qboolean shaderfound;
841 r_glsl_permutation_t *p = r_glsl_permutations + (permutation & SHADERPERMUTATION_MASK);
842 int vertstrings_count;
843 int geomstrings_count;
844 int fragstrings_count;
846 const char *vertstrings_list[32+1];
847 const char *geomstrings_list[32+1];
848 const char *fragstrings_list[32+1];
849 char permutationname[256];
854 vertstrings_list[0] = "#define VERTEX_SHADER\n";
855 geomstrings_list[0] = "#define GEOMETRY_SHADER\n";
856 fragstrings_list[0] = "#define FRAGMENT_SHADER\n";
857 vertstrings_count = 1;
858 geomstrings_count = 1;
859 fragstrings_count = 1;
860 permutationname[0] = 0;
861 for (i = 0;permutationinfo[i][0];i++)
863 if (permutation & (1<<i))
865 vertstrings_list[vertstrings_count++] = permutationinfo[i][0];
866 geomstrings_list[geomstrings_count++] = permutationinfo[i][0];
867 fragstrings_list[fragstrings_count++] = permutationinfo[i][0];
868 strlcat(permutationname, permutationinfo[i][1], sizeof(permutationname));
872 // keep line numbers correct
873 vertstrings_list[vertstrings_count++] = "\n";
874 geomstrings_list[geomstrings_count++] = "\n";
875 fragstrings_list[fragstrings_count++] = "\n";
878 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
882 Con_DPrintf("GLSL shader text for \"%s\" loaded from disk\n", filename);
883 vertstrings_list[vertstrings_count++] = shaderstring;
884 geomstrings_list[geomstrings_count++] = shaderstring;
885 fragstrings_list[fragstrings_count++] = shaderstring;
888 else if (!strcmp(filename, "glsl/default.glsl"))
890 Con_DPrintf("GLSL shader text for \"%s\" loaded from engine\n", filename);
891 vertstrings_list[vertstrings_count++] = builtinshaderstring;
892 geomstrings_list[geomstrings_count++] = builtinshaderstring;
893 fragstrings_list[fragstrings_count++] = builtinshaderstring;
896 // clear any lists that are not needed by this shader
897 if (!(permutation & SHADERPERMUTATION_USES_VERTEXSHADER))
898 vertstrings_count = 0;
899 if (!(permutation & SHADERPERMUTATION_USES_GEOMETRYSHADER))
900 geomstrings_count = 0;
901 if (!(permutation & SHADERPERMUTATION_USES_FRAGMENTSHADER))
902 fragstrings_count = 0;
903 // compile the shader program
904 if (shaderfound && vertstrings_count + geomstrings_count + fragstrings_count)
905 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
909 qglUseProgramObjectARB(p->program);CHECKGLERROR
910 // look up all the uniform variable names we care about, so we don't
911 // have to look them up every time we set them
912 p->loc_Texture_Normal = qglGetUniformLocationARB(p->program, "Texture_Normal");
913 p->loc_Texture_Color = qglGetUniformLocationARB(p->program, "Texture_Color");
914 p->loc_Texture_Gloss = qglGetUniformLocationARB(p->program, "Texture_Gloss");
915 p->loc_Texture_Cube = qglGetUniformLocationARB(p->program, "Texture_Cube");
916 p->loc_Texture_Attenuation = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
917 p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
918 p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
919 p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
920 p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
921 p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
922 p->loc_Texture_Glow = qglGetUniformLocationARB(p->program, "Texture_Glow");
923 p->loc_Texture_Refraction = qglGetUniformLocationARB(p->program, "Texture_Refraction");
924 p->loc_Texture_Reflection = qglGetUniformLocationARB(p->program, "Texture_Reflection");
925 p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
926 p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
927 p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
928 p->loc_LightColor = qglGetUniformLocationARB(p->program, "LightColor");
929 p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants");
930 p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt");
931 p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip");
932 p->loc_AmbientScale = qglGetUniformLocationARB(p->program, "AmbientScale");
933 p->loc_DiffuseScale = qglGetUniformLocationARB(p->program, "DiffuseScale");
934 p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
935 p->loc_SpecularScale = qglGetUniformLocationARB(p->program, "SpecularScale");
936 p->loc_GlowScale = qglGetUniformLocationARB(p->program, "GlowScale");
937 p->loc_SceneBrightness = qglGetUniformLocationARB(p->program, "SceneBrightness");
938 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
939 p->loc_AmbientColor = qglGetUniformLocationARB(p->program, "AmbientColor");
940 p->loc_DiffuseColor = qglGetUniformLocationARB(p->program, "DiffuseColor");
941 p->loc_SpecularColor = qglGetUniformLocationARB(p->program, "SpecularColor");
942 p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
943 p->loc_ContrastBoostCoeff = qglGetUniformLocationARB(p->program, "ContrastBoostCoeff");
944 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
945 p->loc_ScreenScaleRefractReflect = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
946 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
947 p->loc_RefractColor = qglGetUniformLocationARB(p->program, "RefractColor");
948 p->loc_ReflectColor = qglGetUniformLocationARB(p->program, "ReflectColor");
949 p->loc_ReflectFactor = qglGetUniformLocationARB(p->program, "ReflectFactor");
950 // initialize the samplers to refer to the texture units we use
951 if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal, 0);
952 if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color, 1);
953 if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss, 2);
954 if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube, 3);
955 if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask, 4);
956 if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants, 5);
957 if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt, 6);
958 if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap, 7);
959 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap, 8);
960 if (p->loc_Texture_Glow >= 0) qglUniform1iARB(p->loc_Texture_Glow, 9);
961 if (p->loc_Texture_Attenuation >= 0) qglUniform1iARB(p->loc_Texture_Attenuation, 10);
962 if (p->loc_Texture_Refraction >= 0) qglUniform1iARB(p->loc_Texture_Refraction, 11);
963 if (p->loc_Texture_Reflection >= 0) qglUniform1iARB(p->loc_Texture_Reflection, 12);
965 qglUseProgramObjectARB(0);CHECKGLERROR
968 Con_Printf("permutation%s failed for shader %s, some features may not work properly!\n", permutationname, filename);
970 Mem_Free(shaderstring);
973 void R_GLSL_Restart_f(void)
976 for (i = 0;i < SHADERPERMUTATION_MAX;i++)
977 if (r_glsl_permutations[i].program)
978 GL_Backend_FreeProgram(r_glsl_permutations[i].program);
979 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
982 void R_GLSL_DumpShader_f(void)
986 qfile_t *file = FS_Open("glsl/default.glsl", "w", false, false);
989 Con_Printf("failed to write to glsl/default.glsl\n");
993 FS_Print(file, "// The engine may define the following macros:\n");
994 FS_Print(file, "// #define VERTEX_SHADER\n// #define GEOMETRY_SHADER\n// #define FRAGMENT_SHADER\n");
995 for (i = 0;permutationinfo[i][0];i++)
996 FS_Printf(file, "// %s", permutationinfo[i][0]);
997 FS_Print(file, "\n");
998 FS_Print(file, builtinshaderstring);
1001 Con_Printf("glsl/default.glsl written\n");
1004 extern rtexture_t *r_shadow_attenuationgradienttexture;
1005 extern rtexture_t *r_shadow_attenuation2dtexture;
1006 extern rtexture_t *r_shadow_attenuation3dtexture;
1007 int R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale)
1009 // select a permutation of the lighting shader appropriate to this
1010 // combination of texture, entity, light source, and fogging, only use the
1011 // minimum features necessary to avoid wasting rendering time in the
1012 // fragment shader on features that are not being used
1013 const char *shaderfilename = NULL;
1014 unsigned int permutation = 0;
1016 r_glsl_permutation = NULL;
1017 // TODO: implement geometry-shader based shadow volumes someday
1018 if (rsurface.rtlight)
1021 shaderfilename = "glsl/default.glsl";
1022 permutation = SHADERPERMUTATION_MODE_LIGHTSOURCE | SHADERPERMUTATION_USES_VERTEXSHADER | SHADERPERMUTATION_USES_FRAGMENTSHADER;
1023 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
1024 permutation |= SHADERPERMUTATION_CUBEFILTER;
1025 if (diffusescale > 0)
1026 permutation |= SHADERPERMUTATION_DIFFUSE;
1027 if (specularscale > 0)
1028 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
1029 if (r_refdef.fogenabled)
1030 permutation |= SHADERPERMUTATION_FOG;
1031 if (rsurface.texture->colormapping)
1032 permutation |= SHADERPERMUTATION_COLORMAPPING;
1033 if (r_glsl_offsetmapping.integer)
1035 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
1036 if (r_glsl_offsetmapping_reliefmapping.integer)
1037 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
1039 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1040 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1041 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
1042 permutation |= SHADERPERMUTATION_WATER;
1043 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1044 permutation |= SHADERPERMUTATION_REFLECTION;
1046 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
1048 // bright unshaded geometry
1049 shaderfilename = "glsl/default.glsl";
1050 permutation = SHADERPERMUTATION_USES_VERTEXSHADER | SHADERPERMUTATION_USES_FRAGMENTSHADER;
1051 permutation |= SHADERPERMUTATION_MODE_LIGHTMAP;
1052 if (rsurface.texture->currentskinframe->glow)
1053 permutation |= SHADERPERMUTATION_GLOW;
1054 if (r_refdef.fogenabled)
1055 permutation |= SHADERPERMUTATION_FOG;
1056 if (rsurface.texture->colormapping)
1057 permutation |= SHADERPERMUTATION_COLORMAPPING;
1058 if (r_glsl_offsetmapping.integer)
1060 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
1061 if (r_glsl_offsetmapping_reliefmapping.integer)
1062 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
1064 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1065 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1066 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
1067 permutation |= SHADERPERMUTATION_WATER;
1068 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1069 permutation |= SHADERPERMUTATION_REFLECTION;
1071 else if (modellighting)
1073 // directional model lighting
1074 shaderfilename = "glsl/default.glsl";
1075 permutation = SHADERPERMUTATION_USES_VERTEXSHADER | SHADERPERMUTATION_USES_FRAGMENTSHADER;
1076 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTION;
1077 if (rsurface.texture->currentskinframe->glow)
1078 permutation |= SHADERPERMUTATION_GLOW;
1079 if (specularscale > 0)
1080 permutation |= SHADERPERMUTATION_SPECULAR;
1081 if (r_refdef.fogenabled)
1082 permutation |= SHADERPERMUTATION_FOG;
1083 if (rsurface.texture->colormapping)
1084 permutation |= SHADERPERMUTATION_COLORMAPPING;
1085 if (r_glsl_offsetmapping.integer)
1087 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
1088 if (r_glsl_offsetmapping_reliefmapping.integer)
1089 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
1091 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1092 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1093 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
1094 permutation |= SHADERPERMUTATION_WATER;
1095 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1096 permutation |= SHADERPERMUTATION_REFLECTION;
1101 shaderfilename = "glsl/default.glsl";
1102 permutation = SHADERPERMUTATION_USES_VERTEXSHADER | SHADERPERMUTATION_USES_FRAGMENTSHADER;
1103 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.worldmodel && r_refdef.worldmodel->brushq3.deluxemapping)
1105 // deluxemapping (light direction texture)
1106 if (rsurface.uselightmaptexture && r_refdef.worldmodel && r_refdef.worldmodel->brushq3.deluxemapping && r_refdef.worldmodel->brushq3.deluxemapping_modelspace)
1107 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_MODELSPACE;
1109 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
1110 if (specularscale > 0)
1111 permutation |= SHADERPERMUTATION_SPECULAR;
1113 else if (r_glsl_deluxemapping.integer >= 2)
1115 // fake deluxemapping (uniform light direction in tangentspace)
1116 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
1117 if (specularscale > 0)
1118 permutation |= SHADERPERMUTATION_SPECULAR;
1122 // ordinary lightmapping
1123 permutation |= SHADERPERMUTATION_MODE_LIGHTMAP;
1125 if (rsurface.texture->currentskinframe->glow)
1126 permutation |= SHADERPERMUTATION_GLOW;
1127 if (r_refdef.fogenabled)
1128 permutation |= SHADERPERMUTATION_FOG;
1129 if (rsurface.texture->colormapping)
1130 permutation |= SHADERPERMUTATION_COLORMAPPING;
1131 if (r_glsl_offsetmapping.integer)
1133 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
1134 if (r_glsl_offsetmapping_reliefmapping.integer)
1135 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
1137 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1138 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1139 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
1140 permutation |= SHADERPERMUTATION_WATER;
1141 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1142 permutation |= SHADERPERMUTATION_REFLECTION;
1144 if (!r_glsl_permutations[permutation & SHADERPERMUTATION_MASK].program)
1146 if (!r_glsl_permutations[permutation & SHADERPERMUTATION_MASK].compiled)
1147 R_GLSL_CompilePermutation(shaderfilename, permutation);
1148 if (!r_glsl_permutations[permutation & SHADERPERMUTATION_MASK].program)
1150 // remove features until we find a valid permutation
1152 for (i = (SHADERPERMUTATION_MAX >> 1);;i>>=1)
1156 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");
1157 Cvar_SetValueQuick(&r_glsl, 0);
1158 return 0; // no bit left to clear
1160 // reduce i more quickly whenever it would not remove any bits
1161 if (!(permutation & i))
1164 if (!r_glsl_permutations[permutation & SHADERPERMUTATION_MASK].compiled)
1165 R_GLSL_CompilePermutation(shaderfilename, permutation);
1166 if (r_glsl_permutations[permutation & SHADERPERMUTATION_MASK].program)
1171 r_glsl_permutation = r_glsl_permutations + (permutation & SHADERPERMUTATION_MASK);
1173 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
1174 R_Mesh_TexMatrix(0, &rsurface.texture->currenttexmatrix);
1175 if (permutation & SHADERPERMUTATION_MODE_LIGHTSOURCE)
1177 if (r_glsl_permutation->loc_Texture_Cube >= 0 && rsurface.rtlight) R_Mesh_TexBindCubeMap(3, R_GetTexture(rsurface.rtlight->currentcubemap));
1178 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
1179 if (permutation & SHADERPERMUTATION_DIFFUSE)
1181 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
1182 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, ambientscale);
1183 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, diffusescale);
1184 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, specularscale);
1188 // ambient only is simpler
1189 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0] * ambientscale, lightcolorbase[1] * ambientscale, lightcolorbase[2] * ambientscale);
1190 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, 1);
1191 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, 0);
1192 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, 0);
1195 else if (permutation & SHADERPERMUTATION_MODE_LIGHTDIRECTION)
1197 if (r_glsl_permutation->loc_AmbientColor >= 0)
1198 qglUniform3fARB(r_glsl_permutation->loc_AmbientColor, rsurface.modellight_ambient[0] * ambientscale, rsurface.modellight_ambient[1] * ambientscale, rsurface.modellight_ambient[2] * ambientscale);
1199 if (r_glsl_permutation->loc_DiffuseColor >= 0)
1200 qglUniform3fARB(r_glsl_permutation->loc_DiffuseColor, rsurface.modellight_diffuse[0] * diffusescale, rsurface.modellight_diffuse[1] * diffusescale, rsurface.modellight_diffuse[2] * diffusescale);
1201 if (r_glsl_permutation->loc_SpecularColor >= 0)
1202 qglUniform3fARB(r_glsl_permutation->loc_SpecularColor, rsurface.modellight_diffuse[0] * specularscale, rsurface.modellight_diffuse[1] * specularscale, rsurface.modellight_diffuse[2] * specularscale);
1203 if (r_glsl_permutation->loc_LightDir >= 0)
1204 qglUniform3fARB(r_glsl_permutation->loc_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
1208 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_ambient.value * 2.0f / 128.0f);
1209 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_refdef.lightmapintensity * 2.0f);
1210 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, r_refdef.lightmapintensity * specularscale * 2.0f);
1212 nmap = rsurface.texture->currentskinframe->nmap;
1213 if (gl_lightmaps.integer)
1214 nmap = r_texture_blanknormalmap;
1215 if (r_glsl_permutation->loc_Texture_Normal >= 0) R_Mesh_TexBind(0, R_GetTexture(nmap));
1216 if (r_glsl_permutation->loc_Texture_Color >= 0) R_Mesh_TexBind(1, R_GetTexture(rsurface.texture->basetexture));
1217 if (r_glsl_permutation->loc_Texture_Gloss >= 0) R_Mesh_TexBind(2, R_GetTexture(rsurface.texture->glosstexture));
1218 //if (r_glsl_permutation->loc_Texture_Cube >= 0 && permutation & SHADERPERMUTATION_MODE_LIGHTSOURCE) R_Mesh_TexBindCubeMap(3, R_GetTexture(rsurface.rtlight->currentcubemap));
1219 if (r_glsl_permutation->loc_Texture_Attenuation >= 0) R_Mesh_TexBind(10, R_GetTexture(r_shadow_attenuationgradienttexture));
1220 if (r_glsl_permutation->loc_Texture_FogMask >= 0) R_Mesh_TexBind(4, R_GetTexture(r_texture_fogattenuation));
1221 if (r_glsl_permutation->loc_Texture_Pants >= 0) R_Mesh_TexBind(5, R_GetTexture(rsurface.texture->currentskinframe->pants));
1222 if (r_glsl_permutation->loc_Texture_Shirt >= 0) R_Mesh_TexBind(6, R_GetTexture(rsurface.texture->currentskinframe->shirt));
1223 //if (r_glsl_permutation->loc_Texture_Lightmap >= 0) R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
1224 //if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
1225 if (r_glsl_permutation->loc_Texture_Glow >= 0) R_Mesh_TexBind(9, R_GetTexture(rsurface.texture->currentskinframe->glow));
1226 if (r_glsl_permutation->loc_Texture_Refraction >= 0) R_Mesh_TexBind(11, R_GetTexture(r_texture_white)); // changed per surface
1227 if (r_glsl_permutation->loc_Texture_Reflection >= 0) R_Mesh_TexBind(12, R_GetTexture(r_texture_white)); // changed per surface
1228 if (r_glsl_permutation->loc_GlowScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_GlowScale, r_hdr_glowintensity.value);
1229 if (r_glsl_permutation->loc_ContrastBoostCoeff >= 0)
1231 // The formula used is actually:
1232 // color.rgb *= SceneBrightness;
1233 // color.rgb *= ContrastBoost / ((ContrastBoost - 1) * color.rgb + 1);
1234 // I simplify that to
1235 // color.rgb *= [[SceneBrightness * ContrastBoost]];
1236 // color.rgb /= [[(ContrastBoost - 1) / ContrastBoost]] * color.rgb + 1;
1238 // color.rgb = [[SceneBrightness * ContrastBoost]] / ([[(ContrastBoost - 1) * SceneBrightness]] + 1 / color.rgb);
1239 // and do [[calculations]] here in the engine
1240 qglUniform1fARB(r_glsl_permutation->loc_ContrastBoostCoeff, (r_glsl_contrastboost.value - 1) * r_view.colorscale);
1241 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_view.colorscale * r_glsl_contrastboost.value);
1244 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_view.colorscale);
1245 if (r_glsl_permutation->loc_FogColor >= 0)
1247 // additive passes are only darkened by fog, not tinted
1248 if (rsurface.rtlight || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD))
1249 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
1251 qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
1253 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.modelorg[0], rsurface.modelorg[1], rsurface.modelorg[2]);
1254 if (r_glsl_permutation->loc_Color_Pants >= 0)
1256 if (rsurface.texture->currentskinframe->pants)
1257 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
1259 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
1261 if (r_glsl_permutation->loc_Color_Shirt >= 0)
1263 if (rsurface.texture->currentskinframe->shirt)
1264 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
1266 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
1268 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, r_refdef.fograngerecip);
1269 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower);
1270 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
1271 if (r_glsl_permutation->loc_DistortScaleRefractReflect >= 0) qglUniform4fARB(r_glsl_permutation->loc_DistortScaleRefractReflect, r_glsl_water_refractdistort.value * rsurface.texture->refractfactor, r_glsl_water_refractdistort.value * rsurface.texture->refractfactor, r_glsl_water_reflectdistort.value, r_glsl_water_reflectdistort.value);
1272 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]);
1273 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]);
1274 if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform3fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor);
1275 if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform3fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor);
1276 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectfactor);
1281 void R_SwitchSurfaceShader(int permutation)
1283 if (r_glsl_permutation != r_glsl_permutations + (permutation & SHADERPERMUTATION_MASK))
1285 r_glsl_permutation = r_glsl_permutations + (permutation & SHADERPERMUTATION_MASK);
1287 qglUseProgramObjectARB(r_glsl_permutation->program);
1292 #define SKINFRAME_HASH 1024
1296 int loadsequence; // incremented each level change
1297 memexpandablearray_t array;
1298 skinframe_t *hash[SKINFRAME_HASH];
1302 void R_SkinFrame_PrepareForPurge(void)
1304 r_skinframe.loadsequence++;
1305 // wrap it without hitting zero
1306 if (r_skinframe.loadsequence >= 200)
1307 r_skinframe.loadsequence = 1;
1310 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
1314 // mark the skinframe as used for the purging code
1315 skinframe->loadsequence = r_skinframe.loadsequence;
1318 void R_SkinFrame_Purge(void)
1322 for (i = 0;i < SKINFRAME_HASH;i++)
1324 for (s = r_skinframe.hash[i];s;s = s->next)
1326 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
1328 if (s->base == r_texture_notexture) s->base = NULL;
1329 if (s->nmap == r_texture_blanknormalmap)s->nmap = NULL;
1330 if (s->merged == s->base) s->merged = NULL;
1331 if (s->stain ) R_FreeTexture(s->stain );s->stain = NULL;
1332 if (s->merged) R_FreeTexture(s->merged);s->merged = NULL;
1333 if (s->base ) R_FreeTexture(s->base );s->base = NULL;
1334 if (s->pants ) R_FreeTexture(s->pants );s->pants = NULL;
1335 if (s->shirt ) R_FreeTexture(s->shirt );s->shirt = NULL;
1336 if (s->nmap ) R_FreeTexture(s->nmap );s->nmap = NULL;
1337 if (s->gloss ) R_FreeTexture(s->gloss );s->gloss = NULL;
1338 if (s->glow ) R_FreeTexture(s->glow );s->glow = NULL;
1339 if (s->fog ) R_FreeTexture(s->fog );s->fog = NULL;
1340 s->loadsequence = 0;
1346 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
1350 char basename[MAX_QPATH];
1352 Image_StripImageExtension(name, basename, sizeof(basename));
1354 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
1355 for (item = r_skinframe.hash[hashindex];item;item = item->next)
1356 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
1362 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
1363 memset(item, 0, sizeof(*item));
1364 strlcpy(item->basename, basename, sizeof(item->basename));
1365 item->textureflags = textureflags;
1366 item->comparewidth = comparewidth;
1367 item->compareheight = compareheight;
1368 item->comparecrc = comparecrc;
1369 item->next = r_skinframe.hash[hashindex];
1370 r_skinframe.hash[hashindex] = item;
1372 R_SkinFrame_MarkUsed(item);
1376 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
1378 // FIXME: it should be possible to disable loading various layers using
1379 // cvars, to prevent wasted loading time and memory usage if the user does
1381 qboolean loadnormalmap = true;
1382 qboolean loadgloss = true;
1383 qboolean loadpantsandshirt = true;
1384 qboolean loadglow = true;
1386 unsigned char *pixels;
1387 unsigned char *bumppixels;
1388 unsigned char *basepixels = NULL;
1389 int basepixels_width;
1390 int basepixels_height;
1391 skinframe_t *skinframe;
1393 if (cls.state == ca_dedicated)
1396 // return an existing skinframe if already loaded
1397 // if loading of the first image fails, don't make a new skinframe as it
1398 // would cause all future lookups of this to be missing
1399 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
1400 if (skinframe && skinframe->base)
1403 basepixels = loadimagepixels(name, complain, 0, 0);
1404 if (basepixels == NULL)
1407 // we've got some pixels to store, so really allocate this new texture now
1409 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
1410 skinframe->stain = NULL;
1411 skinframe->merged = NULL;
1412 skinframe->base = r_texture_notexture;
1413 skinframe->pants = NULL;
1414 skinframe->shirt = NULL;
1415 skinframe->nmap = r_texture_blanknormalmap;
1416 skinframe->gloss = NULL;
1417 skinframe->glow = NULL;
1418 skinframe->fog = NULL;
1420 basepixels_width = image_width;
1421 basepixels_height = image_height;
1422 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);
1424 if (textureflags & TEXF_ALPHA)
1426 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
1427 if (basepixels[j] < 255)
1429 if (j < basepixels_width * basepixels_height * 4)
1431 // has transparent pixels
1432 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
1433 for (j = 0;j < image_width * image_height * 4;j += 4)
1438 pixels[j+3] = basepixels[j+3];
1440 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);
1445 // _norm is the name used by tenebrae and has been adopted as standard
1448 if ((pixels = loadimagepixels(va("%s_norm", skinframe->basename), false, 0, 0)) != NULL)
1450 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);
1454 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixels(va("%s_bump", skinframe->basename), false, 0, 0)) != NULL)
1456 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
1457 Image_HeightmapToNormalmap(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
1458 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);
1460 Mem_Free(bumppixels);
1462 else if (r_shadow_bumpscale_basetexture.value > 0)
1464 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
1465 Image_HeightmapToNormalmap(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
1466 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);
1470 // _luma is supported for tenebrae compatibility
1471 // (I think it's a very stupid name, but oh well)
1472 // _glow is the preferred name
1473 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;}
1474 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;}
1475 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;}
1476 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;}
1479 Mem_Free(basepixels);
1484 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)
1489 for (i = 0;i < width*height;i++)
1490 if (((unsigned char *)&palette[in[i]])[3] > 0)
1492 if (i == width*height)
1495 return R_LoadTexture2D (r_main_texturepool, name, width, height, in, TEXTYPE_PALETTE, textureflags, palette);
1498 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)
1501 unsigned char *temp1, *temp2;
1502 skinframe_t *skinframe;
1504 if (cls.state == ca_dedicated)
1507 // if already loaded just return it, otherwise make a new skinframe
1508 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*bitsperpixel/8) : 0, true);
1509 if (skinframe && skinframe->base)
1512 skinframe->stain = NULL;
1513 skinframe->merged = NULL;
1514 skinframe->base = r_texture_notexture;
1515 skinframe->pants = NULL;
1516 skinframe->shirt = NULL;
1517 skinframe->nmap = r_texture_blanknormalmap;
1518 skinframe->gloss = NULL;
1519 skinframe->glow = NULL;
1520 skinframe->fog = NULL;
1522 // if no data was provided, then clearly the caller wanted to get a blank skinframe
1526 if (bitsperpixel == 32)
1528 if (r_shadow_bumpscale_basetexture.value > 0)
1530 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
1531 temp2 = temp1 + width * height * 4;
1532 Image_HeightmapToNormalmap(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
1533 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_RGBA, skinframe->textureflags | TEXF_ALPHA, NULL);
1536 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_RGBA, skinframe->textureflags, NULL);
1537 if (textureflags & TEXF_ALPHA)
1539 for (i = 3;i < width * height * 4;i += 4)
1540 if (skindata[i] < 255)
1542 if (i < width * height * 4)
1544 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
1545 memcpy(fogpixels, skindata, width * height * 4);
1546 for (i = 0;i < width * height * 4;i += 4)
1547 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
1548 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_RGBA, skinframe->textureflags, NULL);
1549 Mem_Free(fogpixels);
1553 else if (bitsperpixel == 8)
1555 if (r_shadow_bumpscale_basetexture.value > 0)
1557 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
1558 temp2 = temp1 + width * height * 4;
1559 if (bitsperpixel == 32)
1560 Image_HeightmapToNormalmap(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
1563 // use either a custom palette or the quake palette
1564 Image_Copy8bitRGBA(skindata, temp1, width * height, palette ? palette : palette_complete);
1565 Image_HeightmapToNormalmap(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
1567 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_RGBA, skinframe->textureflags | TEXF_ALPHA, NULL);
1570 // use either a custom palette, or the quake palette
1571 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
1572 if (!palette && loadglowtexture)
1573 skinframe->glow = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_glow", skinframe->basename), palette_onlyfullbrights, skinframe->textureflags, false); // glow
1574 if (!palette && loadpantsandshirt)
1576 skinframe->pants = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_pants", skinframe->basename), palette_pantsaswhite, skinframe->textureflags, false); // pants
1577 skinframe->shirt = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_shirt", skinframe->basename), palette_shirtaswhite, skinframe->textureflags, false); // shirt
1579 if (skinframe->pants || skinframe->shirt)
1580 skinframe->base = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_nospecial", skinframe->basename),loadglowtexture ? palette_nocolormapnofullbrights : palette_nocolormap, skinframe->textureflags, false); // no special colors
1581 if (textureflags & TEXF_ALPHA)
1583 // if not using a custom alphapalette, use the quake one
1585 alphapalette = palette_alpha;
1586 for (i = 0;i < width * height;i++)
1587 if (((unsigned char *)alphapalette)[skindata[i]*4+3] < 255)
1589 if (i < width * height)
1590 skinframe->fog = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_fog", skinframe->basename), alphapalette, skinframe->textureflags, true); // fog mask
1597 skinframe_t *R_SkinFrame_LoadMissing(void)
1599 skinframe_t *skinframe;
1601 if (cls.state == ca_dedicated)
1604 skinframe = R_SkinFrame_Find("missing", TEXF_PRECACHE, 0, 0, 0, true);
1605 skinframe->stain = NULL;
1606 skinframe->merged = NULL;
1607 skinframe->base = r_texture_notexture;
1608 skinframe->pants = NULL;
1609 skinframe->shirt = NULL;
1610 skinframe->nmap = r_texture_blanknormalmap;
1611 skinframe->gloss = NULL;
1612 skinframe->glow = NULL;
1613 skinframe->fog = NULL;
1618 void gl_main_start(void)
1623 r = (-1.0/256.0) * (FOGMASKTABLEWIDTH * FOGMASKTABLEWIDTH);
1624 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
1626 alpha = 1 - exp(r / ((double)x*(double)x));
1627 if (x == FOGMASKTABLEWIDTH - 1)
1629 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
1632 memset(r_qwskincache, 0, sizeof(r_qwskincache));
1633 memset(r_qwskincache_skinframe, 0, sizeof(r_qwskincache_skinframe));
1635 // set up r_skinframe loading system for textures
1636 memset(&r_skinframe, 0, sizeof(r_skinframe));
1637 r_skinframe.loadsequence = 1;
1638 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
1640 r_main_texturepool = R_AllocTexturePool();
1641 R_BuildBlankTextures();
1643 if (gl_texturecubemap)
1646 R_BuildNormalizationCube();
1648 R_BuildFogTexture();
1649 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
1650 memset(&r_waterstate, 0, sizeof(r_waterstate));
1651 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
1652 memset(&r_svbsp, 0, sizeof (r_svbsp));
1655 void gl_main_shutdown(void)
1657 memset(r_qwskincache, 0, sizeof(r_qwskincache));
1658 memset(r_qwskincache_skinframe, 0, sizeof(r_qwskincache_skinframe));
1660 // clear out the r_skinframe state
1661 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
1662 memset(&r_skinframe, 0, sizeof(r_skinframe));
1665 Mem_Free(r_svbsp.nodes);
1666 memset(&r_svbsp, 0, sizeof (r_svbsp));
1667 R_FreeTexturePool(&r_main_texturepool);
1668 r_texture_blanknormalmap = NULL;
1669 r_texture_white = NULL;
1670 r_texture_grey128 = NULL;
1671 r_texture_black = NULL;
1672 r_texture_whitecube = NULL;
1673 r_texture_normalizationcube = NULL;
1674 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
1675 memset(&r_waterstate, 0, sizeof(r_waterstate));
1679 extern void CL_ParseEntityLump(char *entitystring);
1680 void gl_main_newmap(void)
1682 // FIXME: move this code to client
1684 char *entities, entname[MAX_QPATH];
1687 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
1688 l = (int)strlen(entname) - 4;
1689 if (l >= 0 && !strcmp(entname + l, ".bsp"))
1691 memcpy(entname + l, ".ent", 5);
1692 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
1694 CL_ParseEntityLump(entities);
1699 if (cl.worldmodel->brush.entities)
1700 CL_ParseEntityLump(cl.worldmodel->brush.entities);
1704 void GL_Main_Init(void)
1706 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
1708 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
1709 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
1710 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
1711 if (gamemode == GAME_NEHAHRA)
1713 Cvar_RegisterVariable (&gl_fogenable);
1714 Cvar_RegisterVariable (&gl_fogdensity);
1715 Cvar_RegisterVariable (&gl_fogred);
1716 Cvar_RegisterVariable (&gl_foggreen);
1717 Cvar_RegisterVariable (&gl_fogblue);
1718 Cvar_RegisterVariable (&gl_fogstart);
1719 Cvar_RegisterVariable (&gl_fogend);
1721 Cvar_RegisterVariable(&r_depthfirst);
1722 Cvar_RegisterVariable(&r_nearclip);
1723 Cvar_RegisterVariable(&r_showbboxes);
1724 Cvar_RegisterVariable(&r_showsurfaces);
1725 Cvar_RegisterVariable(&r_showtris);
1726 Cvar_RegisterVariable(&r_shownormals);
1727 Cvar_RegisterVariable(&r_showlighting);
1728 Cvar_RegisterVariable(&r_showshadowvolumes);
1729 Cvar_RegisterVariable(&r_showcollisionbrushes);
1730 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
1731 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
1732 Cvar_RegisterVariable(&r_showdisabledepthtest);
1733 Cvar_RegisterVariable(&r_drawportals);
1734 Cvar_RegisterVariable(&r_drawentities);
1735 Cvar_RegisterVariable(&r_cullentities_trace);
1736 Cvar_RegisterVariable(&r_cullentities_trace_samples);
1737 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
1738 Cvar_RegisterVariable(&r_cullentities_trace_delay);
1739 Cvar_RegisterVariable(&r_drawviewmodel);
1740 Cvar_RegisterVariable(&r_speeds);
1741 Cvar_RegisterVariable(&r_fullbrights);
1742 Cvar_RegisterVariable(&r_wateralpha);
1743 Cvar_RegisterVariable(&r_dynamic);
1744 Cvar_RegisterVariable(&r_fullbright);
1745 Cvar_RegisterVariable(&r_shadows);
1746 Cvar_RegisterVariable(&r_shadows_throwdistance);
1747 Cvar_RegisterVariable(&r_q1bsp_skymasking);
1748 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
1749 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
1750 Cvar_RegisterVariable(&r_textureunits);
1751 Cvar_RegisterVariable(&r_glsl);
1752 Cvar_RegisterVariable(&r_glsl_offsetmapping);
1753 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
1754 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
1755 Cvar_RegisterVariable(&r_glsl_water);
1756 Cvar_RegisterVariable(&r_glsl_water_resolutionmultiplier);
1757 Cvar_RegisterVariable(&r_glsl_water_clippingplanebias);
1758 Cvar_RegisterVariable(&r_glsl_water_refractdistort);
1759 Cvar_RegisterVariable(&r_glsl_water_reflectdistort);
1760 Cvar_RegisterVariable(&r_glsl_deluxemapping);
1761 Cvar_RegisterVariable(&r_lerpsprites);
1762 Cvar_RegisterVariable(&r_lerpmodels);
1763 Cvar_RegisterVariable(&r_waterscroll);
1764 Cvar_RegisterVariable(&r_bloom);
1765 Cvar_RegisterVariable(&r_bloom_colorscale);
1766 Cvar_RegisterVariable(&r_bloom_brighten);
1767 Cvar_RegisterVariable(&r_bloom_blur);
1768 Cvar_RegisterVariable(&r_bloom_resolution);
1769 Cvar_RegisterVariable(&r_bloom_colorexponent);
1770 Cvar_RegisterVariable(&r_bloom_colorsubtract);
1771 Cvar_RegisterVariable(&r_hdr);
1772 Cvar_RegisterVariable(&r_hdr_scenebrightness);
1773 Cvar_RegisterVariable(&r_glsl_contrastboost);
1774 Cvar_RegisterVariable(&r_hdr_glowintensity);
1775 Cvar_RegisterVariable(&r_hdr_range);
1776 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
1777 Cvar_RegisterVariable(&developer_texturelogging);
1778 Cvar_RegisterVariable(&gl_lightmaps);
1779 Cvar_RegisterVariable(&r_test);
1780 Cvar_RegisterVariable(&r_batchmode);
1781 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
1782 Cvar_SetValue("r_fullbrights", 0);
1783 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
1786 extern void R_Textures_Init(void);
1787 extern void GL_Draw_Init(void);
1788 extern void GL_Main_Init(void);
1789 extern void R_Shadow_Init(void);
1790 extern void R_Sky_Init(void);
1791 extern void GL_Surf_Init(void);
1792 extern void R_Light_Init(void);
1793 extern void R_Particles_Init(void);
1794 extern void R_Explosion_Init(void);
1795 extern void gl_backend_init(void);
1796 extern void Sbar_Init(void);
1797 extern void R_LightningBeams_Init(void);
1798 extern void Mod_RenderInit(void);
1800 void Render_Init(void)
1813 R_LightningBeams_Init();
1822 extern char *ENGINE_EXTENSIONS;
1825 VID_CheckExtensions();
1827 // LordHavoc: report supported extensions
1828 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
1830 // clear to black (loading plaque will be seen over this)
1832 qglClearColor(0,0,0,1);CHECKGLERROR
1833 qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
1836 int R_CullBox(const vec3_t mins, const vec3_t maxs)
1840 for (i = 0;i < r_view.numfrustumplanes;i++)
1842 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
1845 p = r_view.frustum + i;
1850 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1854 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1858 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1862 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1866 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1870 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1874 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1878 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1886 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
1890 for (i = 0;i < numplanes;i++)
1897 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1901 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1905 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1909 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1913 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1917 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1921 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1925 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1933 //==================================================================================
1935 static void R_UpdateEntityLighting(entity_render_t *ent)
1937 vec3_t tempdiffusenormal;
1939 // fetch the lighting from the worldmodel data
1940 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));
1941 VectorClear(ent->modellight_diffuse);
1942 VectorClear(tempdiffusenormal);
1943 if ((ent->flags & RENDER_LIGHT) && r_refdef.worldmodel && r_refdef.worldmodel->brush.LightPoint)
1946 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
1947 r_refdef.worldmodel->brush.LightPoint(r_refdef.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
1950 VectorSet(ent->modellight_ambient, 1, 1, 1);
1952 // move the light direction into modelspace coordinates for lighting code
1953 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
1954 if(VectorLength2(ent->modellight_lightdir) > 0)
1956 VectorNormalize(ent->modellight_lightdir);
1960 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
1963 // scale ambient and directional light contributions according to rendering variables
1964 ent->modellight_ambient[0] *= ent->colormod[0] * r_refdef.lightmapintensity;
1965 ent->modellight_ambient[1] *= ent->colormod[1] * r_refdef.lightmapintensity;
1966 ent->modellight_ambient[2] *= ent->colormod[2] * r_refdef.lightmapintensity;
1967 ent->modellight_diffuse[0] *= ent->colormod[0] * r_refdef.lightmapintensity;
1968 ent->modellight_diffuse[1] *= ent->colormod[1] * r_refdef.lightmapintensity;
1969 ent->modellight_diffuse[2] *= ent->colormod[2] * r_refdef.lightmapintensity;
1972 static void R_View_UpdateEntityVisible (void)
1975 entity_render_t *ent;
1977 if (!r_drawentities.integer)
1980 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : ((chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL : RENDER_EXTERIORMODEL);
1981 if (r_refdef.worldmodel && r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs)
1983 // worldmodel can check visibility
1984 for (i = 0;i < r_refdef.numentities;i++)
1986 ent = r_refdef.entities[i];
1987 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));
1989 if(r_cullentities_trace.integer)
1991 for (i = 0;i < r_refdef.numentities;i++)
1993 ent = r_refdef.entities[i];
1994 if(r_viewcache.entityvisible[i] && !(ent->effects & EF_NODEPTHTEST) && !(ent->flags & RENDER_VIEWMODEL) && !(ent->model && (ent->model->name[0] == '*')))
1996 if(Mod_CanSeeBox_Trace(r_cullentities_trace_samples.integer, r_cullentities_trace_enlarge.value, r_refdef.worldmodel, r_view.origin, ent->mins, ent->maxs))
1997 ent->last_trace_visibility = realtime;
1998 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
1999 r_viewcache.entityvisible[i] = 0;
2006 // no worldmodel or it can't check visibility
2007 for (i = 0;i < r_refdef.numentities;i++)
2009 ent = r_refdef.entities[i];
2010 r_viewcache.entityvisible[i] = !(ent->flags & renderimask) && !R_CullBox(ent->mins, ent->maxs);
2014 // update entity lighting (even on hidden entities for r_shadows)
2015 for (i = 0;i < r_refdef.numentities;i++)
2016 R_UpdateEntityLighting(r_refdef.entities[i]);
2019 // only used if skyrendermasked, and normally returns false
2020 int R_DrawBrushModelsSky (void)
2023 entity_render_t *ent;
2025 if (!r_drawentities.integer)
2029 for (i = 0;i < r_refdef.numentities;i++)
2031 if (!r_viewcache.entityvisible[i])
2033 ent = r_refdef.entities[i];
2034 if (!ent->model || !ent->model->DrawSky)
2036 ent->model->DrawSky(ent);
2042 static void R_DrawNoModel(entity_render_t *ent);
2043 static void R_DrawModels(void)
2046 entity_render_t *ent;
2048 if (!r_drawentities.integer)
2051 for (i = 0;i < r_refdef.numentities;i++)
2053 if (!r_viewcache.entityvisible[i])
2055 ent = r_refdef.entities[i];
2056 r_refdef.stats.entities++;
2057 if (ent->model && ent->model->Draw != NULL)
2058 ent->model->Draw(ent);
2064 static void R_DrawModelsDepth(void)
2067 entity_render_t *ent;
2069 if (!r_drawentities.integer)
2072 for (i = 0;i < r_refdef.numentities;i++)
2074 if (!r_viewcache.entityvisible[i])
2076 ent = r_refdef.entities[i];
2077 r_refdef.stats.entities++;
2078 if (ent->model && ent->model->DrawDepth != NULL)
2079 ent->model->DrawDepth(ent);
2083 static void R_DrawModelsDebug(void)
2086 entity_render_t *ent;
2088 if (!r_drawentities.integer)
2091 for (i = 0;i < r_refdef.numentities;i++)
2093 if (!r_viewcache.entityvisible[i])
2095 ent = r_refdef.entities[i];
2096 r_refdef.stats.entities++;
2097 if (ent->model && ent->model->DrawDebug != NULL)
2098 ent->model->DrawDebug(ent);
2102 static void R_DrawModelsAddWaterPlanes(void)
2105 entity_render_t *ent;
2107 if (!r_drawentities.integer)
2110 for (i = 0;i < r_refdef.numentities;i++)
2112 if (!r_viewcache.entityvisible[i])
2114 ent = r_refdef.entities[i];
2115 r_refdef.stats.entities++;
2116 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
2117 ent->model->DrawAddWaterPlanes(ent);
2121 static void R_View_SetFrustum(void)
2124 double slopex, slopey;
2126 // break apart the view matrix into vectors for various purposes
2127 Matrix4x4_ToVectors(&r_view.matrix, r_view.forward, r_view.left, r_view.up, r_view.origin);
2128 VectorNegate(r_view.left, r_view.right);
2131 r_view.frustum[0].normal[0] = 0 - 1.0 / r_view.frustum_x;
2132 r_view.frustum[0].normal[1] = 0 - 0;
2133 r_view.frustum[0].normal[2] = -1 - 0;
2134 r_view.frustum[1].normal[0] = 0 + 1.0 / r_view.frustum_x;
2135 r_view.frustum[1].normal[1] = 0 + 0;
2136 r_view.frustum[1].normal[2] = -1 + 0;
2137 r_view.frustum[2].normal[0] = 0 - 0;
2138 r_view.frustum[2].normal[1] = 0 - 1.0 / r_view.frustum_y;
2139 r_view.frustum[2].normal[2] = -1 - 0;
2140 r_view.frustum[3].normal[0] = 0 + 0;
2141 r_view.frustum[3].normal[1] = 0 + 1.0 / r_view.frustum_y;
2142 r_view.frustum[3].normal[2] = -1 + 0;
2146 zNear = r_refdef.nearclip;
2147 nudge = 1.0 - 1.0 / (1<<23);
2148 r_view.frustum[4].normal[0] = 0 - 0;
2149 r_view.frustum[4].normal[1] = 0 - 0;
2150 r_view.frustum[4].normal[2] = -1 - -nudge;
2151 r_view.frustum[4].dist = 0 - -2 * zNear * nudge;
2152 r_view.frustum[5].normal[0] = 0 + 0;
2153 r_view.frustum[5].normal[1] = 0 + 0;
2154 r_view.frustum[5].normal[2] = -1 + -nudge;
2155 r_view.frustum[5].dist = 0 + -2 * zNear * nudge;
2161 r_view.frustum[0].normal[0] = m[3] - m[0];
2162 r_view.frustum[0].normal[1] = m[7] - m[4];
2163 r_view.frustum[0].normal[2] = m[11] - m[8];
2164 r_view.frustum[0].dist = m[15] - m[12];
2166 r_view.frustum[1].normal[0] = m[3] + m[0];
2167 r_view.frustum[1].normal[1] = m[7] + m[4];
2168 r_view.frustum[1].normal[2] = m[11] + m[8];
2169 r_view.frustum[1].dist = m[15] + m[12];
2171 r_view.frustum[2].normal[0] = m[3] - m[1];
2172 r_view.frustum[2].normal[1] = m[7] - m[5];
2173 r_view.frustum[2].normal[2] = m[11] - m[9];
2174 r_view.frustum[2].dist = m[15] - m[13];
2176 r_view.frustum[3].normal[0] = m[3] + m[1];
2177 r_view.frustum[3].normal[1] = m[7] + m[5];
2178 r_view.frustum[3].normal[2] = m[11] + m[9];
2179 r_view.frustum[3].dist = m[15] + m[13];
2181 r_view.frustum[4].normal[0] = m[3] - m[2];
2182 r_view.frustum[4].normal[1] = m[7] - m[6];
2183 r_view.frustum[4].normal[2] = m[11] - m[10];
2184 r_view.frustum[4].dist = m[15] - m[14];
2186 r_view.frustum[5].normal[0] = m[3] + m[2];
2187 r_view.frustum[5].normal[1] = m[7] + m[6];
2188 r_view.frustum[5].normal[2] = m[11] + m[10];
2189 r_view.frustum[5].dist = m[15] + m[14];
2194 if (r_view.useperspective)
2196 slopex = 1.0 / r_view.frustum_x;
2197 slopey = 1.0 / r_view.frustum_y;
2198 VectorMA(r_view.forward, -slopex, r_view.left, r_view.frustum[0].normal);
2199 VectorMA(r_view.forward, slopex, r_view.left, r_view.frustum[1].normal);
2200 VectorMA(r_view.forward, -slopey, r_view.up , r_view.frustum[2].normal);
2201 VectorMA(r_view.forward, slopey, r_view.up , r_view.frustum[3].normal);
2202 VectorCopy(r_view.forward, r_view.frustum[4].normal);
2204 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
2205 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, -1024 * slopex, r_view.left, -1024 * slopey, r_view.up, r_view.frustumcorner[0]);
2206 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, 1024 * slopex, r_view.left, -1024 * slopey, r_view.up, r_view.frustumcorner[1]);
2207 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, -1024 * slopex, r_view.left, 1024 * slopey, r_view.up, r_view.frustumcorner[2]);
2208 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, 1024 * slopex, r_view.left, 1024 * slopey, r_view.up, r_view.frustumcorner[3]);
2210 r_view.frustum[0].dist = DotProduct (r_view.origin, r_view.frustum[0].normal);
2211 r_view.frustum[1].dist = DotProduct (r_view.origin, r_view.frustum[1].normal);
2212 r_view.frustum[2].dist = DotProduct (r_view.origin, r_view.frustum[2].normal);
2213 r_view.frustum[3].dist = DotProduct (r_view.origin, r_view.frustum[3].normal);
2214 r_view.frustum[4].dist = DotProduct (r_view.origin, r_view.frustum[4].normal) + r_refdef.nearclip;
2218 VectorScale(r_view.left, -r_view.ortho_x, r_view.frustum[0].normal);
2219 VectorScale(r_view.left, r_view.ortho_x, r_view.frustum[1].normal);
2220 VectorScale(r_view.up, -r_view.ortho_y, r_view.frustum[2].normal);
2221 VectorScale(r_view.up, r_view.ortho_y, r_view.frustum[3].normal);
2222 VectorCopy(r_view.forward, r_view.frustum[4].normal);
2223 r_view.frustum[0].dist = DotProduct (r_view.origin, r_view.frustum[0].normal) + r_view.ortho_x;
2224 r_view.frustum[1].dist = DotProduct (r_view.origin, r_view.frustum[1].normal) + r_view.ortho_x;
2225 r_view.frustum[2].dist = DotProduct (r_view.origin, r_view.frustum[2].normal) + r_view.ortho_y;
2226 r_view.frustum[3].dist = DotProduct (r_view.origin, r_view.frustum[3].normal) + r_view.ortho_y;
2227 r_view.frustum[4].dist = DotProduct (r_view.origin, r_view.frustum[4].normal) + r_refdef.nearclip;
2229 r_view.numfrustumplanes = 5;
2231 if (r_view.useclipplane)
2233 r_view.numfrustumplanes = 6;
2234 r_view.frustum[5] = r_view.clipplane;
2237 for (i = 0;i < r_view.numfrustumplanes;i++)
2238 PlaneClassify(r_view.frustum + i);
2240 // LordHavoc: note to all quake engine coders, Quake had a special case
2241 // for 90 degrees which assumed a square view (wrong), so I removed it,
2242 // Quake2 has it disabled as well.
2244 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
2245 //RotatePointAroundVector( r_view.frustum[0].normal, r_view.up, r_view.forward, -(90 - r_refdef.fov_x / 2));
2246 //r_view.frustum[0].dist = DotProduct (r_view.origin, frustum[0].normal);
2247 //PlaneClassify(&frustum[0]);
2249 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
2250 //RotatePointAroundVector( r_view.frustum[1].normal, r_view.up, r_view.forward, (90 - r_refdef.fov_x / 2));
2251 //r_view.frustum[1].dist = DotProduct (r_view.origin, frustum[1].normal);
2252 //PlaneClassify(&frustum[1]);
2254 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
2255 //RotatePointAroundVector( r_view.frustum[2].normal, r_view.left, r_view.forward, -(90 - r_refdef.fov_y / 2));
2256 //r_view.frustum[2].dist = DotProduct (r_view.origin, frustum[2].normal);
2257 //PlaneClassify(&frustum[2]);
2259 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
2260 //RotatePointAroundVector( r_view.frustum[3].normal, r_view.left, r_view.forward, (90 - r_refdef.fov_y / 2));
2261 //r_view.frustum[3].dist = DotProduct (r_view.origin, frustum[3].normal);
2262 //PlaneClassify(&frustum[3]);
2265 //VectorCopy(r_view.forward, r_view.frustum[4].normal);
2266 //r_view.frustum[4].dist = DotProduct (r_view.origin, frustum[4].normal) + r_nearclip.value;
2267 //PlaneClassify(&frustum[4]);
2270 void R_View_Update(void)
2272 R_View_SetFrustum();
2273 R_View_WorldVisibility(r_view.useclipplane);
2274 R_View_UpdateEntityVisible();
2277 void R_SetupView(void)
2279 if (!r_view.useperspective)
2280 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);
2281 else if (r_refdef.rtworldshadows || r_refdef.rtdlightshadows)
2282 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_view.frustum_x, r_view.frustum_y, r_refdef.nearclip);
2284 GL_SetupView_Mode_Perspective(r_view.frustum_x, r_view.frustum_y, r_refdef.nearclip, r_refdef.farclip);
2286 GL_SetupView_Orientation_FromEntity(&r_view.matrix);
2288 if (r_view.useclipplane)
2290 // LordHavoc: couldn't figure out how to make this approach the
2291 vec_t dist = r_view.clipplane.dist - r_glsl_water_clippingplanebias.value;
2292 vec_t viewdist = DotProduct(r_view.origin, r_view.clipplane.normal);
2293 if (viewdist < r_view.clipplane.dist + r_glsl_water_clippingplanebias.value)
2294 dist = r_view.clipplane.dist;
2295 GL_SetupView_ApplyCustomNearClipPlane(r_view.clipplane.normal[0], r_view.clipplane.normal[1], r_view.clipplane.normal[2], dist);
2299 void R_ResetViewRendering2D(void)
2301 if (gl_support_fragment_shader)
2303 qglUseProgramObjectARB(0);CHECKGLERROR
2308 // GL is weird because it's bottom to top, r_view.y is top to bottom
2309 qglViewport(r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
2310 GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
2311 GL_Scissor(r_view.x, r_view.y, r_view.width, r_view.height);
2312 GL_Color(1, 1, 1, 1);
2313 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
2314 GL_BlendFunc(GL_ONE, GL_ZERO);
2315 GL_AlphaTest(false);
2316 GL_ScissorTest(false);
2317 GL_DepthMask(false);
2318 GL_DepthRange(0, 1);
2319 GL_DepthTest(false);
2320 R_Mesh_Matrix(&identitymatrix);
2321 R_Mesh_ResetTextureState();
2322 GL_PolygonOffset(0, 0);
2323 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
2324 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
2325 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
2326 qglStencilMask(~0);CHECKGLERROR
2327 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
2328 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
2329 GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
2332 void R_ResetViewRendering3D(void)
2334 if (gl_support_fragment_shader)
2336 qglUseProgramObjectARB(0);CHECKGLERROR
2341 // GL is weird because it's bottom to top, r_view.y is top to bottom
2342 qglViewport(r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
2344 GL_Scissor(r_view.x, r_view.y, r_view.width, r_view.height);
2345 GL_Color(1, 1, 1, 1);
2346 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
2347 GL_BlendFunc(GL_ONE, GL_ZERO);
2348 GL_AlphaTest(false);
2349 GL_ScissorTest(true);
2351 GL_DepthRange(0, 1);
2353 R_Mesh_Matrix(&identitymatrix);
2354 R_Mesh_ResetTextureState();
2355 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
2356 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
2357 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
2358 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
2359 qglStencilMask(~0);CHECKGLERROR
2360 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
2361 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
2362 GL_CullFace(r_view.cullface_back);
2366 R_Bloom_SetupShader(
2368 "// written by Forest 'LordHavoc' Hale\n"
2370 "// common definitions between vertex shader and fragment shader:\n"
2372 "#ifdef __GLSL_CG_DATA_TYPES\n"
2373 "#define myhalf half\n"
2374 "#define myhvec2 hvec2\n"
2375 "#define myhvec3 hvec3\n"
2376 "#define myhvec4 hvec4\n"
2378 "#define myhalf float\n"
2379 "#define myhvec2 vec2\n"
2380 "#define myhvec3 vec3\n"
2381 "#define myhvec4 vec4\n"
2384 "varying vec2 ScreenTexCoord;\n"
2385 "varying vec2 BloomTexCoord;\n"
2390 "// vertex shader specific:\n"
2391 "#ifdef VERTEX_SHADER\n"
2395 " ScreenTexCoord = vec2(gl_MultiTexCoord0);\n"
2396 " BloomTexCoord = vec2(gl_MultiTexCoord1);\n"
2397 " // transform vertex to camera space, using ftransform to match non-VS\n"
2399 " gl_Position = ftransform();\n"
2402 "#endif // VERTEX_SHADER\n"
2407 "// fragment shader specific:\n"
2408 "#ifdef FRAGMENT_SHADER\n"
2413 " myhvec3 color = myhvec3(texture2D(Texture_Screen, ScreenTexCoord));\n"
2414 " for (x = -BLUR_X;x <= BLUR_X;x++)
2415 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2416 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2417 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2418 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2420 " gl_FragColor = vec4(color);\n"
2423 "#endif // FRAGMENT_SHADER\n"
2426 void R_RenderScene(qboolean addwaterplanes);
2428 static void R_Water_StartFrame(void)
2431 int waterwidth, waterheight, texturewidth, textureheight;
2432 r_waterstate_waterplane_t *p;
2434 // set waterwidth and waterheight to the water resolution that will be
2435 // used (often less than the screen resolution for faster rendering)
2436 waterwidth = (int)bound(1, r_view.width * r_glsl_water_resolutionmultiplier.value, r_view.width);
2437 waterheight = (int)bound(1, r_view.height * r_glsl_water_resolutionmultiplier.value, r_view.height);
2439 // calculate desired texture sizes
2440 // can't use water if the card does not support the texture size
2441 if (!r_glsl_water.integer || waterwidth > gl_max_texture_size || waterheight > gl_max_texture_size)
2442 texturewidth = textureheight = waterwidth = waterheight = 0;
2443 else if (gl_support_arb_texture_non_power_of_two)
2445 texturewidth = waterwidth;
2446 textureheight = waterheight;
2450 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
2451 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
2454 // allocate textures as needed
2455 if (r_waterstate.waterwidth != waterwidth || r_waterstate.waterheight != waterheight || r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight)
2457 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
2458 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
2460 if (p->texture_refraction)
2461 R_FreeTexture(p->texture_refraction);
2462 p->texture_refraction = NULL;
2463 if (p->texture_reflection)
2464 R_FreeTexture(p->texture_reflection);
2465 p->texture_reflection = NULL;
2467 memset(&r_waterstate, 0, sizeof(r_waterstate));
2468 r_waterstate.waterwidth = waterwidth;
2469 r_waterstate.waterheight = waterheight;
2470 r_waterstate.texturewidth = texturewidth;
2471 r_waterstate.textureheight = textureheight;
2474 if (r_waterstate.waterwidth)
2476 r_waterstate.enabled = true;
2478 // set up variables that will be used in shader setup
2479 r_waterstate.screenscale[0] = 0.5f * (float)waterwidth / (float)texturewidth;
2480 r_waterstate.screenscale[1] = 0.5f * (float)waterheight / (float)textureheight;
2481 r_waterstate.screencenter[0] = 0.5f * (float)waterwidth / (float)texturewidth;
2482 r_waterstate.screencenter[1] = 0.5f * (float)waterheight / (float)textureheight;
2485 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
2486 r_waterstate.numwaterplanes = 0;
2489 static void R_Water_AddWaterPlane(msurface_t *surface)
2491 int triangleindex, planeindex;
2497 r_waterstate_waterplane_t *p;
2498 // just use the first triangle with a valid normal for any decisions
2499 VectorClear(normal);
2500 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
2502 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
2503 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
2504 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
2505 TriangleNormal(vert[0], vert[1], vert[2], normal);
2506 if (VectorLength2(normal) >= 0.001)
2509 // now find the center of this surface
2510 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles*3;triangleindex++, e++)
2512 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
2513 VectorAdd(center, vert[0], center);
2515 f = 1.0 / surface->num_triangles*3;
2516 VectorScale(center, f, center);
2518 // find a matching plane if there is one
2519 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
2520 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
2522 if (planeindex >= r_waterstate.maxwaterplanes)
2523 return; // nothing we can do, out of planes
2525 // if this triangle does not fit any known plane rendered this frame, add one
2526 if (planeindex >= r_waterstate.numwaterplanes)
2528 // store the new plane
2529 r_waterstate.numwaterplanes++;
2530 VectorCopy(normal, p->plane.normal);
2531 VectorNormalize(p->plane.normal);
2532 p->plane.dist = DotProduct(vert[0], p->plane.normal);
2533 PlaneClassify(&p->plane);
2534 // flip the plane if it does not face the viewer
2535 if (PlaneDiff(r_view.origin, &p->plane) < 0)
2537 VectorNegate(p->plane.normal, p->plane.normal);
2538 p->plane.dist *= -1;
2539 PlaneClassify(&p->plane);
2541 // clear materialflags and pvs
2542 p->materialflags = 0;
2543 p->pvsvalid = false;
2545 // merge this surface's materialflags into the waterplane
2546 p->materialflags |= surface->texture->currentframe->currentmaterialflags;
2547 // merge this surface's PVS into the waterplane
2548 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION) && r_refdef.worldmodel && r_refdef.worldmodel->brush.FatPVS)
2550 r_refdef.worldmodel->brush.FatPVS(r_refdef.worldmodel, r_view.origin, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
2555 static void R_Water_ProcessPlanes(void)
2557 r_view_t originalview;
2559 r_waterstate_waterplane_t *p;
2561 // make sure enough textures are allocated
2562 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
2564 if (p->materialflags & MATERIALFLAG_WATERSHADER)
2566 if (!p->texture_refraction)
2567 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);
2568 if (!p->texture_refraction)
2572 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
2574 if (!p->texture_reflection)
2575 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);
2576 if (!p->texture_reflection)
2582 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
2584 originalview = r_view;
2585 r_view.showdebug = false;
2586 r_view.width = r_waterstate.waterwidth;
2587 r_view.height = r_waterstate.waterheight;
2588 r_view.useclipplane = true;
2589 r_waterstate.renderingscene = true;
2591 // render the normal view scene and copy into texture
2592 // (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)
2593 if (p->materialflags & MATERIALFLAG_WATERSHADER)
2595 r_view.clipplane = p->plane;
2596 VectorNegate(r_view.clipplane.normal, r_view.clipplane.normal);
2597 r_view.clipplane.dist = -r_view.clipplane.dist;
2598 PlaneClassify(&r_view.clipplane);
2600 R_RenderScene(false);
2602 // copy view into the screen texture
2603 R_Mesh_TexBind(0, R_GetTexture(p->texture_refraction));
2604 GL_ActiveTexture(0);
2606 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
2609 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
2611 // render reflected scene and copy into texture
2612 Matrix4x4_Reflect(&r_view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
2613 r_view.clipplane = p->plane;
2614 // reverse the cullface settings for this render
2615 r_view.cullface_front = GL_FRONT;
2616 r_view.cullface_back = GL_BACK;
2617 if (r_refdef.worldmodel && r_refdef.worldmodel->brush.num_pvsclusterbytes)
2619 r_view.usecustompvs = true;
2621 memcpy(r_viewcache.world_pvsbits, p->pvsbits, r_refdef.worldmodel->brush.num_pvsclusterbytes);
2623 memset(r_viewcache.world_pvsbits, 0xFF, r_refdef.worldmodel->brush.num_pvsclusterbytes);
2626 R_ResetViewRendering3D();
2629 R_RenderScene(false);
2631 R_Mesh_TexBind(0, R_GetTexture(p->texture_reflection));
2632 GL_ActiveTexture(0);
2634 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
2636 R_ResetViewRendering3D();
2640 r_view = originalview;
2641 r_waterstate.renderingscene = false;
2645 r_view = originalview;
2646 r_waterstate.renderingscene = false;
2647 Cvar_SetValueQuick(&r_glsl_water, 0);
2648 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_glsl_water.\n");
2652 void R_Bloom_StartFrame(void)
2654 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
2656 // set bloomwidth and bloomheight to the bloom resolution that will be
2657 // used (often less than the screen resolution for faster rendering)
2658 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_view.width);
2659 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_view.height / r_view.width;
2660 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_view.height);
2662 // calculate desired texture sizes
2663 if (gl_support_arb_texture_non_power_of_two)
2665 screentexturewidth = r_view.width;
2666 screentextureheight = r_view.height;
2667 bloomtexturewidth = r_bloomstate.bloomwidth;
2668 bloomtextureheight = r_bloomstate.bloomheight;
2672 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
2673 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
2674 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
2675 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
2680 screentexturewidth = screentextureheight = 0;
2682 else if (r_bloom.integer)
2687 screentexturewidth = screentextureheight = 0;
2688 bloomtexturewidth = bloomtextureheight = 0;
2691 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)
2693 // can't use bloom if the parameters are too weird
2694 // can't use bloom if the card does not support the texture size
2695 if (r_bloomstate.texture_screen)
2696 R_FreeTexture(r_bloomstate.texture_screen);
2697 if (r_bloomstate.texture_bloom)
2698 R_FreeTexture(r_bloomstate.texture_bloom);
2699 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
2703 r_bloomstate.enabled = true;
2704 r_bloomstate.hdr = r_hdr.integer != 0;
2706 // allocate textures as needed
2707 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
2709 if (r_bloomstate.texture_screen)
2710 R_FreeTexture(r_bloomstate.texture_screen);
2711 r_bloomstate.texture_screen = NULL;
2712 r_bloomstate.screentexturewidth = screentexturewidth;
2713 r_bloomstate.screentextureheight = screentextureheight;
2714 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
2715 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);
2717 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
2719 if (r_bloomstate.texture_bloom)
2720 R_FreeTexture(r_bloomstate.texture_bloom);
2721 r_bloomstate.texture_bloom = NULL;
2722 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
2723 r_bloomstate.bloomtextureheight = bloomtextureheight;
2724 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
2725 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);
2728 // set up a texcoord array for the full resolution screen image
2729 // (we have to keep this around to copy back during final render)
2730 r_bloomstate.screentexcoord2f[0] = 0;
2731 r_bloomstate.screentexcoord2f[1] = (float)r_view.height / (float)r_bloomstate.screentextureheight;
2732 r_bloomstate.screentexcoord2f[2] = (float)r_view.width / (float)r_bloomstate.screentexturewidth;
2733 r_bloomstate.screentexcoord2f[3] = (float)r_view.height / (float)r_bloomstate.screentextureheight;
2734 r_bloomstate.screentexcoord2f[4] = (float)r_view.width / (float)r_bloomstate.screentexturewidth;
2735 r_bloomstate.screentexcoord2f[5] = 0;
2736 r_bloomstate.screentexcoord2f[6] = 0;
2737 r_bloomstate.screentexcoord2f[7] = 0;
2739 // set up a texcoord array for the reduced resolution bloom image
2740 // (which will be additive blended over the screen image)
2741 r_bloomstate.bloomtexcoord2f[0] = 0;
2742 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
2743 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
2744 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
2745 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
2746 r_bloomstate.bloomtexcoord2f[5] = 0;
2747 r_bloomstate.bloomtexcoord2f[6] = 0;
2748 r_bloomstate.bloomtexcoord2f[7] = 0;
2751 void R_Bloom_CopyScreenTexture(float colorscale)
2753 r_refdef.stats.bloom++;
2755 R_ResetViewRendering2D();
2756 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
2757 R_Mesh_ColorPointer(NULL, 0, 0);
2758 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
2759 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
2761 // copy view into the screen texture
2762 GL_ActiveTexture(0);
2764 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
2765 r_refdef.stats.bloom_copypixels += r_view.width * r_view.height;
2767 // now scale it down to the bloom texture size
2769 qglViewport(r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
2770 GL_BlendFunc(GL_ONE, GL_ZERO);
2771 GL_Color(colorscale, colorscale, colorscale, 1);
2772 // TODO: optimize with multitexture or GLSL
2773 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2774 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2776 // we now have a bloom image in the framebuffer
2777 // copy it into the bloom image texture for later processing
2778 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2779 GL_ActiveTexture(0);
2781 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
2782 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2785 void R_Bloom_CopyHDRTexture(void)
2787 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2788 GL_ActiveTexture(0);
2790 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
2791 r_refdef.stats.bloom_copypixels += r_view.width * r_view.height;
2794 void R_Bloom_MakeTexture(void)
2797 float xoffset, yoffset, r, brighten;
2799 r_refdef.stats.bloom++;
2801 R_ResetViewRendering2D();
2802 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
2803 R_Mesh_ColorPointer(NULL, 0, 0);
2805 // we have a bloom image in the framebuffer
2807 qglViewport(r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
2809 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
2812 r = bound(0, r_bloom_colorexponent.value / x, 1);
2813 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
2814 GL_Color(r, r, r, 1);
2815 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2816 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
2817 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2818 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2820 // copy the vertically blurred bloom view to a texture
2821 GL_ActiveTexture(0);
2823 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
2824 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2827 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
2828 brighten = r_bloom_brighten.value;
2830 brighten *= r_hdr_range.value;
2831 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2832 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
2834 for (dir = 0;dir < 2;dir++)
2836 // blend on at multiple vertical offsets to achieve a vertical blur
2837 // TODO: do offset blends using GLSL
2838 GL_BlendFunc(GL_ONE, GL_ZERO);
2839 for (x = -range;x <= range;x++)
2841 if (!dir){xoffset = 0;yoffset = x;}
2842 else {xoffset = x;yoffset = 0;}
2843 xoffset /= (float)r_bloomstate.bloomtexturewidth;
2844 yoffset /= (float)r_bloomstate.bloomtextureheight;
2845 // compute a texcoord array with the specified x and y offset
2846 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
2847 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
2848 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
2849 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
2850 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
2851 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
2852 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
2853 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
2854 // this r value looks like a 'dot' particle, fading sharply to
2855 // black at the edges
2856 // (probably not realistic but looks good enough)
2857 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
2858 //r = (dir ? 1.0f : brighten)/(range*2+1);
2859 r = (dir ? 1.0f : brighten)/(range*2+1)*(1 - x*x/(float)(range*range));
2860 GL_Color(r, r, r, 1);
2861 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2862 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2863 GL_BlendFunc(GL_ONE, GL_ONE);
2866 // copy the vertically blurred bloom view to a texture
2867 GL_ActiveTexture(0);
2869 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
2870 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2873 // apply subtract last
2874 // (just like it would be in a GLSL shader)
2875 if (r_bloom_colorsubtract.value > 0 && gl_support_ext_blend_subtract)
2877 GL_BlendFunc(GL_ONE, GL_ZERO);
2878 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2879 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
2880 GL_Color(1, 1, 1, 1);
2881 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2882 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2884 GL_BlendFunc(GL_ONE, GL_ONE);
2885 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
2886 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2887 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
2888 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
2889 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2890 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2891 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
2893 // copy the darkened bloom view to a texture
2894 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2895 GL_ActiveTexture(0);
2897 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
2898 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2902 void R_HDR_RenderBloomTexture(void)
2904 int oldwidth, oldheight;
2906 oldwidth = r_view.width;
2907 oldheight = r_view.height;
2908 r_view.width = r_bloomstate.bloomwidth;
2909 r_view.height = r_bloomstate.bloomheight;
2911 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
2912 // TODO: add exposure compensation features
2913 // TODO: add fp16 framebuffer support
2915 r_view.showdebug = false;
2916 r_view.colorscale = r_bloom_colorscale.value * r_hdr_scenebrightness.value;
2918 r_view.colorscale /= r_hdr_range.value;
2919 r_waterstate.numwaterplanes = 0;
2920 R_RenderScene(r_waterstate.enabled);
2921 r_view.showdebug = true;
2923 R_ResetViewRendering2D();
2925 R_Bloom_CopyHDRTexture();
2926 R_Bloom_MakeTexture();
2928 R_ResetViewRendering3D();
2931 if (r_timereport_active)
2932 R_TimeReport("clear");
2935 // restore the view settings
2936 r_view.width = oldwidth;
2937 r_view.height = oldheight;
2940 static void R_BlendView(void)
2942 if (r_bloomstate.enabled && r_bloomstate.hdr)
2944 // render high dynamic range bloom effect
2945 // the bloom texture was made earlier this render, so we just need to
2946 // blend it onto the screen...
2947 R_ResetViewRendering2D();
2948 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
2949 R_Mesh_ColorPointer(NULL, 0, 0);
2950 GL_Color(1, 1, 1, 1);
2951 GL_BlendFunc(GL_ONE, GL_ONE);
2952 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2953 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
2954 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2955 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
2957 else if (r_bloomstate.enabled)
2959 // render simple bloom effect
2960 // copy the screen and shrink it and darken it for the bloom process
2961 R_Bloom_CopyScreenTexture(r_bloom_colorscale.value);
2962 // make the bloom texture
2963 R_Bloom_MakeTexture();
2964 // put the original screen image back in place and blend the bloom
2966 R_ResetViewRendering2D();
2967 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
2968 R_Mesh_ColorPointer(NULL, 0, 0);
2969 GL_Color(1, 1, 1, 1);
2970 GL_BlendFunc(GL_ONE, GL_ZERO);
2971 // do both in one pass if possible
2972 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2973 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
2974 if (r_textureunits.integer >= 2 && gl_combine.integer)
2976 R_Mesh_TexCombine(1, GL_ADD, GL_ADD, 1, 1);
2977 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_screen));
2978 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.screentexcoord2f, 0, 0);
2982 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2983 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
2984 // now blend on the bloom texture
2985 GL_BlendFunc(GL_ONE, GL_ONE);
2986 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
2987 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
2989 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2990 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
2992 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
2994 // apply a color tint to the whole view
2995 R_ResetViewRendering2D();
2996 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
2997 R_Mesh_ColorPointer(NULL, 0, 0);
2998 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2999 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
3000 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3004 void R_RenderScene(qboolean addwaterplanes);
3006 matrix4x4_t r_waterscrollmatrix;
3008 void R_UpdateVariables(void)
3012 r_refdef.farclip = 4096;
3013 if (r_refdef.worldmodel)
3014 r_refdef.farclip += VectorDistance(r_refdef.worldmodel->normalmins, r_refdef.worldmodel->normalmaxs);
3015 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
3017 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
3018 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
3019 r_refdef.polygonfactor = 0;
3020 r_refdef.polygonoffset = 0;
3021 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
3022 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
3024 r_refdef.rtworld = r_shadow_realtime_world.integer;
3025 r_refdef.rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
3026 r_refdef.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
3027 r_refdef.rtdlightshadows = r_refdef.rtdlight && r_shadow_realtime_dlight_shadows.integer && gl_stencil;
3028 r_refdef.lightmapintensity = r_refdef.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
3029 if (r_showsurfaces.integer)
3031 r_refdef.rtworld = false;
3032 r_refdef.rtworldshadows = false;
3033 r_refdef.rtdlight = false;
3034 r_refdef.rtdlightshadows = false;
3035 r_refdef.lightmapintensity = 0;
3038 if (gamemode == GAME_NEHAHRA)
3040 if (gl_fogenable.integer)
3042 r_refdef.oldgl_fogenable = true;
3043 r_refdef.fog_density = gl_fogdensity.value;
3044 r_refdef.fog_red = gl_fogred.value;
3045 r_refdef.fog_green = gl_foggreen.value;
3046 r_refdef.fog_blue = gl_fogblue.value;
3048 else if (r_refdef.oldgl_fogenable)
3050 r_refdef.oldgl_fogenable = false;
3051 r_refdef.fog_density = 0;
3052 r_refdef.fog_red = 0;
3053 r_refdef.fog_green = 0;
3054 r_refdef.fog_blue = 0;
3057 if (r_refdef.fog_density)
3059 r_refdef.fogcolor[0] = bound(0.0f, r_refdef.fog_red , 1.0f);
3060 r_refdef.fogcolor[1] = bound(0.0f, r_refdef.fog_green, 1.0f);
3061 r_refdef.fogcolor[2] = bound(0.0f, r_refdef.fog_blue , 1.0f);
3063 if (r_refdef.fog_density)
3065 r_refdef.fogenabled = true;
3066 // this is the point where the fog reaches 0.9986 alpha, which we
3067 // consider a good enough cutoff point for the texture
3068 // (0.9986 * 256 == 255.6)
3069 r_refdef.fogrange = 400 / r_refdef.fog_density;
3070 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
3071 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
3072 // fog color was already set
3075 r_refdef.fogenabled = false;
3083 void R_RenderView(void)
3085 if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
3086 return; //Host_Error ("R_RenderView: NULL worldmodel");
3088 R_Shadow_UpdateWorldLightSelection();
3090 R_Bloom_StartFrame();
3091 R_Water_StartFrame();
3094 if (r_timereport_active)
3095 R_TimeReport("setup");
3097 R_ResetViewRendering3D();
3100 if (r_timereport_active)
3101 R_TimeReport("clear");
3103 r_view.showdebug = true;
3105 // this produces a bloom texture to be used in R_BlendView() later
3107 R_HDR_RenderBloomTexture();
3109 r_view.colorscale = r_hdr_scenebrightness.value;
3110 r_waterstate.numwaterplanes = 0;
3111 R_RenderScene(r_waterstate.enabled);
3114 if (r_timereport_active)
3115 R_TimeReport("blendview");
3117 GL_Scissor(0, 0, vid.width, vid.height);
3118 GL_ScissorTest(false);
3122 extern void R_DrawLightningBeams (void);
3123 extern void VM_CL_AddPolygonsToMeshQueue (void);
3124 extern void R_DrawPortals (void);
3125 extern cvar_t cl_locs_show;
3126 static void R_DrawLocs(void);
3127 static void R_DrawEntityBBoxes(void);
3128 void R_RenderScene(qboolean addwaterplanes)
3132 R_ResetViewRendering3D();
3135 if (r_timereport_active)
3136 R_TimeReport("watervisibility");
3138 if (cl.csqc_vidvars.drawworld && r_refdef.worldmodel && r_refdef.worldmodel->DrawAddWaterPlanes)
3140 r_refdef.worldmodel->DrawAddWaterPlanes(r_refdef.worldentity);
3141 if (r_timereport_active)
3142 R_TimeReport("waterworld");
3145 // don't let sound skip if going slow
3146 if (r_refdef.extraupdate)
3149 R_DrawModelsAddWaterPlanes();
3150 if (r_timereport_active)
3151 R_TimeReport("watermodels");
3153 R_Water_ProcessPlanes();
3154 if (r_timereport_active)
3155 R_TimeReport("waterscenes");
3158 R_ResetViewRendering3D();
3160 // don't let sound skip if going slow
3161 if (r_refdef.extraupdate)
3164 R_MeshQueue_BeginScene();
3169 if (r_timereport_active)
3170 R_TimeReport("visibility");
3172 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);
3174 if (cl.csqc_vidvars.drawworld)
3176 // don't let sound skip if going slow
3177 if (r_refdef.extraupdate)
3180 if (r_refdef.worldmodel && r_refdef.worldmodel->DrawSky)
3182 r_refdef.worldmodel->DrawSky(r_refdef.worldentity);
3183 if (r_timereport_active)
3184 R_TimeReport("worldsky");
3187 if (R_DrawBrushModelsSky() && r_timereport_active)
3188 R_TimeReport("bmodelsky");
3191 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.worldmodel && r_refdef.worldmodel->DrawDepth)
3193 r_refdef.worldmodel->DrawDepth(r_refdef.worldentity);
3194 if (r_timereport_active)
3195 R_TimeReport("worlddepth");
3197 if (r_depthfirst.integer >= 2)
3199 R_DrawModelsDepth();
3200 if (r_timereport_active)
3201 R_TimeReport("modeldepth");
3204 if (cl.csqc_vidvars.drawworld && r_refdef.worldmodel && r_refdef.worldmodel->Draw)
3206 r_refdef.worldmodel->Draw(r_refdef.worldentity);
3207 if (r_timereport_active)
3208 R_TimeReport("world");
3211 // don't let sound skip if going slow
3212 if (r_refdef.extraupdate)
3216 if (r_timereport_active)
3217 R_TimeReport("models");
3219 // don't let sound skip if going slow
3220 if (r_refdef.extraupdate)
3223 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
3225 R_DrawModelShadows();
3227 R_ResetViewRendering3D();
3229 // don't let sound skip if going slow
3230 if (r_refdef.extraupdate)
3234 R_ShadowVolumeLighting(false);
3235 if (r_timereport_active)
3236 R_TimeReport("rtlights");
3238 // don't let sound skip if going slow
3239 if (r_refdef.extraupdate)
3242 if (cl.csqc_vidvars.drawworld)
3244 R_DrawLightningBeams();
3245 if (r_timereport_active)
3246 R_TimeReport("lightning");
3249 if (r_timereport_active)
3250 R_TimeReport("particles");
3253 if (r_timereport_active)
3254 R_TimeReport("explosions");
3257 if (gl_support_fragment_shader)
3259 qglUseProgramObjectARB(0);CHECKGLERROR
3261 VM_CL_AddPolygonsToMeshQueue();
3263 if (r_view.showdebug)
3265 if (cl_locs_show.integer)
3268 if (r_timereport_active)
3269 R_TimeReport("showlocs");
3272 if (r_drawportals.integer)
3275 if (r_timereport_active)
3276 R_TimeReport("portals");
3279 if (r_showbboxes.value > 0)
3281 R_DrawEntityBBoxes();
3282 if (r_timereport_active)
3283 R_TimeReport("bboxes");
3287 if (gl_support_fragment_shader)
3289 qglUseProgramObjectARB(0);CHECKGLERROR
3291 R_MeshQueue_RenderTransparent();
3292 if (r_timereport_active)
3293 R_TimeReport("drawtrans");
3295 if (gl_support_fragment_shader)
3297 qglUseProgramObjectARB(0);CHECKGLERROR
3300 if (r_view.showdebug && r_refdef.worldmodel && r_refdef.worldmodel->DrawDebug && (r_showtris.value > 0 || r_shownormals.value > 0 || r_showcollisionbrushes.value > 0))
3302 r_refdef.worldmodel->DrawDebug(r_refdef.worldentity);
3303 if (r_timereport_active)
3304 R_TimeReport("worlddebug");
3305 R_DrawModelsDebug();
3306 if (r_timereport_active)
3307 R_TimeReport("modeldebug");
3310 if (gl_support_fragment_shader)
3312 qglUseProgramObjectARB(0);CHECKGLERROR
3315 if (cl.csqc_vidvars.drawworld)
3318 if (r_timereport_active)
3319 R_TimeReport("coronas");
3322 // don't let sound skip if going slow
3323 if (r_refdef.extraupdate)
3326 R_ResetViewRendering2D();
3329 static const int bboxelements[36] =
3339 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
3342 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
3343 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3344 GL_DepthMask(false);
3345 GL_DepthRange(0, 1);
3346 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3347 R_Mesh_Matrix(&identitymatrix);
3348 R_Mesh_ResetTextureState();
3350 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
3351 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
3352 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
3353 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
3354 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
3355 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
3356 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
3357 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
3358 R_FillColors(color4f, 8, cr, cg, cb, ca);
3359 if (r_refdef.fogenabled)
3361 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
3363 f1 = FogPoint_World(v);
3365 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
3366 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
3367 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
3370 R_Mesh_VertexPointer(vertex3f, 0, 0);
3371 R_Mesh_ColorPointer(color4f, 0, 0);
3372 R_Mesh_ResetTextureState();
3373 R_Mesh_Draw(0, 8, 12, bboxelements, 0, 0);
3376 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
3380 prvm_edict_t *edict;
3381 // this function draws bounding boxes of server entities
3385 for (i = 0;i < numsurfaces;i++)
3387 edict = PRVM_EDICT_NUM(surfacelist[i]);
3388 switch ((int)edict->fields.server->solid)
3390 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
3391 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
3392 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
3393 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
3394 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
3395 default: Vector4Set(color, 0, 0, 0, 0.50);break;
3397 color[3] *= r_showbboxes.value;
3398 color[3] = bound(0, color[3], 1);
3399 GL_DepthTest(!r_showdisabledepthtest.integer);
3400 GL_CullFace(r_view.cullface_front);
3401 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
3406 static void R_DrawEntityBBoxes(void)
3409 prvm_edict_t *edict;
3411 // this function draws bounding boxes of server entities
3415 for (i = 0;i < prog->num_edicts;i++)
3417 edict = PRVM_EDICT_NUM(i);
3418 if (edict->priv.server->free)
3420 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
3421 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
3426 int nomodelelements[24] =
3438 float nomodelvertex3f[6*3] =
3448 float nomodelcolor4f[6*4] =
3450 0.0f, 0.0f, 0.5f, 1.0f,
3451 0.0f, 0.0f, 0.5f, 1.0f,
3452 0.0f, 0.5f, 0.0f, 1.0f,
3453 0.0f, 0.5f, 0.0f, 1.0f,
3454 0.5f, 0.0f, 0.0f, 1.0f,
3455 0.5f, 0.0f, 0.0f, 1.0f
3458 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
3463 // this is only called once per entity so numsurfaces is always 1, and
3464 // surfacelist is always {0}, so this code does not handle batches
3465 R_Mesh_Matrix(&ent->matrix);
3467 if (ent->flags & EF_ADDITIVE)
3469 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
3470 GL_DepthMask(false);
3472 else if (ent->alpha < 1)
3474 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3475 GL_DepthMask(false);
3479 GL_BlendFunc(GL_ONE, GL_ZERO);
3482 GL_DepthRange(0, (ent->flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
3483 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3484 GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
3485 GL_CullFace((ent->effects & EF_DOUBLESIDED) ? GL_NONE : r_view.cullface_back);
3486 R_Mesh_VertexPointer(nomodelvertex3f, 0, 0);
3487 if (r_refdef.fogenabled)
3490 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
3491 R_Mesh_ColorPointer(color4f, 0, 0);
3492 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
3493 f1 = FogPoint_World(org);
3495 for (i = 0, c = color4f;i < 6;i++, c += 4)
3497 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
3498 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
3499 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
3503 else if (ent->alpha != 1)
3505 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
3506 R_Mesh_ColorPointer(color4f, 0, 0);
3507 for (i = 0, c = color4f;i < 6;i++, c += 4)
3511 R_Mesh_ColorPointer(nomodelcolor4f, 0, 0);
3512 R_Mesh_ResetTextureState();
3513 R_Mesh_Draw(0, 6, 8, nomodelelements, 0, 0);
3516 void R_DrawNoModel(entity_render_t *ent)
3519 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
3520 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
3521 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
3523 // R_DrawNoModelCallback(ent, 0);
3526 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
3528 vec3_t right1, right2, diff, normal;
3530 VectorSubtract (org2, org1, normal);
3532 // calculate 'right' vector for start
3533 VectorSubtract (r_view.origin, org1, diff);
3534 CrossProduct (normal, diff, right1);
3535 VectorNormalize (right1);
3537 // calculate 'right' vector for end
3538 VectorSubtract (r_view.origin, org2, diff);
3539 CrossProduct (normal, diff, right2);
3540 VectorNormalize (right2);
3542 vert[ 0] = org1[0] + width * right1[0];
3543 vert[ 1] = org1[1] + width * right1[1];
3544 vert[ 2] = org1[2] + width * right1[2];
3545 vert[ 3] = org1[0] - width * right1[0];
3546 vert[ 4] = org1[1] - width * right1[1];
3547 vert[ 5] = org1[2] - width * right1[2];
3548 vert[ 6] = org2[0] - width * right2[0];
3549 vert[ 7] = org2[1] - width * right2[1];
3550 vert[ 8] = org2[2] - width * right2[2];
3551 vert[ 9] = org2[0] + width * right2[0];
3552 vert[10] = org2[1] + width * right2[1];
3553 vert[11] = org2[2] + width * right2[2];
3556 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
3558 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)
3563 if (r_refdef.fogenabled)
3564 fog = FogPoint_World(origin);
3566 R_Mesh_Matrix(&identitymatrix);
3567 GL_BlendFunc(blendfunc1, blendfunc2);
3573 GL_CullFace(r_view.cullface_front);
3576 GL_CullFace(r_view.cullface_back);
3578 GL_DepthMask(false);
3579 GL_DepthRange(0, depthshort ? 0.0625 : 1);
3580 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3581 GL_DepthTest(!depthdisable);
3583 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
3584 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
3585 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
3586 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
3587 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
3588 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
3589 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
3590 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
3591 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
3592 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
3593 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
3594 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
3596 R_Mesh_VertexPointer(vertex3f, 0, 0);
3597 R_Mesh_ColorPointer(NULL, 0, 0);
3598 R_Mesh_ResetTextureState();
3599 R_Mesh_TexBind(0, R_GetTexture(texture));
3600 R_Mesh_TexCoordPointer(0, 2, spritetexcoord2f, 0, 0);
3601 // FIXME: fixed function path can't properly handle r_view.colorscale > 1
3602 GL_Color(cr * fog * r_view.colorscale, cg * fog * r_view.colorscale, cb * fog * r_view.colorscale, ca);
3603 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3605 if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
3607 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
3608 GL_BlendFunc(blendfunc1, GL_ONE);
3610 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);
3611 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3615 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
3620 VectorSet(v, x, y, z);
3621 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
3622 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
3624 if (i == mesh->numvertices)
3626 if (mesh->numvertices < mesh->maxvertices)
3628 VectorCopy(v, vertex3f);
3629 mesh->numvertices++;
3631 return mesh->numvertices;
3637 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
3641 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
3642 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
3643 e = mesh->element3i + mesh->numtriangles * 3;
3644 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
3646 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
3647 if (mesh->numtriangles < mesh->maxtriangles)
3652 mesh->numtriangles++;
3654 element[1] = element[2];
3658 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
3662 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
3663 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
3664 e = mesh->element3i + mesh->numtriangles * 3;
3665 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
3667 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
3668 if (mesh->numtriangles < mesh->maxtriangles)
3673 mesh->numtriangles++;
3675 element[1] = element[2];
3679 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
3680 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
3682 int planenum, planenum2;
3685 mplane_t *plane, *plane2;
3687 double temppoints[2][256*3];
3688 // figure out how large a bounding box we need to properly compute this brush
3690 for (w = 0;w < numplanes;w++)
3691 maxdist = max(maxdist, planes[w].dist);
3692 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
3693 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
3694 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
3698 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
3699 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
3701 if (planenum2 == planenum)
3703 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);
3706 if (tempnumpoints < 3)
3708 // generate elements forming a triangle fan for this polygon
3709 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
3713 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)
3715 texturelayer_t *layer;
3716 layer = t->currentlayers + t->currentnumlayers++;
3718 layer->depthmask = depthmask;
3719 layer->blendfunc1 = blendfunc1;
3720 layer->blendfunc2 = blendfunc2;
3721 layer->texture = texture;
3722 layer->texmatrix = *matrix;
3723 layer->color[0] = r * r_view.colorscale;
3724 layer->color[1] = g * r_view.colorscale;
3725 layer->color[2] = b * r_view.colorscale;
3726 layer->color[3] = a;
3729 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
3732 index = parms[2] + r_refdef.time * parms[3];
3733 index -= floor(index);
3737 case Q3WAVEFUNC_NONE:
3738 case Q3WAVEFUNC_NOISE:
3739 case Q3WAVEFUNC_COUNT:
3742 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
3743 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
3744 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
3745 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
3746 case Q3WAVEFUNC_TRIANGLE:
3748 f = index - floor(index);
3759 return (float)(parms[0] + parms[1] * f);
3762 void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
3765 model_t *model = ent->model;
3768 q3shaderinfo_layer_tcmod_t *tcmod;
3770 // switch to an alternate material if this is a q1bsp animated material
3772 texture_t *texture = t;
3773 int s = ent->skinnum;
3774 if ((unsigned int)s >= (unsigned int)model->numskins)
3776 if (model->skinscenes)
3778 if (model->skinscenes[s].framecount > 1)
3779 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
3781 s = model->skinscenes[s].firstframe;
3784 t = t + s * model->num_surfaces;
3787 // use an alternate animation if the entity's frame is not 0,
3788 // and only if the texture has an alternate animation
3789 if (ent->frame2 != 0 && t->anim_total[1])
3790 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.time * 5.0f) % t->anim_total[1]) : 0];
3792 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.time * 5.0f) % t->anim_total[0]) : 0];
3794 texture->currentframe = t;
3797 // update currentskinframe to be a qw skin or animation frame
3798 if ((i = ent->entitynumber - 1) >= 0 && i < cl.maxclients)
3800 if (strcmp(r_qwskincache[i], cl.scores[i].qw_skin))
3802 strlcpy(r_qwskincache[i], cl.scores[i].qw_skin, sizeof(r_qwskincache[i]));
3803 Con_DPrintf("loading skins/%s\n", r_qwskincache[i]);
3804 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);
3806 t->currentskinframe = r_qwskincache_skinframe[i];
3807 if (t->currentskinframe == NULL)
3808 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->frame2time)) % t->numskinframes];
3810 else if (t->numskinframes >= 2)
3811 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->frame2time)) % t->numskinframes];
3812 if (t->backgroundnumskinframes >= 2)
3813 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - ent->frame2time)) % t->backgroundnumskinframes];
3815 t->currentmaterialflags = t->basematerialflags;
3816 t->currentalpha = ent->alpha;
3817 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
3819 t->currentalpha *= r_wateralpha.value;
3821 * FIXME what is this supposed to do?
3822 // if rendering refraction/reflection, disable transparency
3823 if (r_waterstate.enabled && (t->currentalpha < 1 || (t->currentmaterialflags & MATERIALFLAG_ALPHA)))
3824 t->currentmaterialflags |= MATERIALFLAG_WATERSHADER;
3827 if(!r_waterstate.enabled)
3829 t->currentmaterialflags &= ~MATERIALFLAG_WATERSHADER;
3830 t->currentmaterialflags &= ~MATERIALFLAG_REFLECTION;
3832 if (!(ent->flags & RENDER_LIGHT))
3833 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
3834 if (ent->effects & EF_ADDITIVE)
3835 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
3836 else if (t->currentalpha < 1)
3837 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
3838 if (ent->effects & EF_DOUBLESIDED)
3839 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
3840 if (ent->effects & EF_NODEPTHTEST)
3841 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
3842 if (ent->flags & RENDER_VIEWMODEL)
3843 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
3844 if (t->backgroundnumskinframes && !(t->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED))
3845 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
3846 if (t->currentmaterialflags & MATERIALFLAG_WATERSHADER)
3847 t->currentmaterialflags &= ~(MATERIALFLAG_ADD | MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_CUSTOMBLEND);
3849 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && (tcmod->tcmod || i < 1);i++, tcmod++)
3852 switch(tcmod->tcmod)
3856 if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
3857 matrix = r_waterscrollmatrix;
3859 matrix = identitymatrix;
3861 case Q3TCMOD_ENTITYTRANSLATE:
3862 // this is used in Q3 to allow the gamecode to control texcoord
3863 // scrolling on the entity, which is not supported in darkplaces yet.
3864 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
3866 case Q3TCMOD_ROTATE:
3867 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
3868 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.time, 0, 0, 1);
3869 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
3872 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
3874 case Q3TCMOD_SCROLL:
3875 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.time, tcmod->parms[1] * r_refdef.time, 0);
3877 case Q3TCMOD_STRETCH:
3878 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
3879 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
3881 case Q3TCMOD_TRANSFORM:
3882 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
3883 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
3884 VectorSet(tcmat + 6, 0 , 0 , 1);
3885 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
3886 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
3888 case Q3TCMOD_TURBULENT:
3889 // this is handled in the RSurf_PrepareVertices function
3890 matrix = identitymatrix;
3893 // either replace or concatenate the transformation
3895 t->currenttexmatrix = matrix;
3898 matrix4x4_t temp = t->currenttexmatrix;
3899 Matrix4x4_Concat(&t->currenttexmatrix, &matrix, &temp);
3903 t->colormapping = VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f);
3904 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
3905 t->glosstexture = r_texture_black;
3906 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
3907 t->backgroundglosstexture = r_texture_black;
3908 t->specularpower = r_shadow_glossexponent.value;
3909 // TODO: store reference values for these in the texture?
3910 t->specularscale = 0;
3911 if (r_shadow_gloss.integer > 0)
3913 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
3915 if (r_shadow_glossintensity.value > 0)
3917 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
3918 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
3919 t->specularscale = r_shadow_glossintensity.value;
3922 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
3924 t->glosstexture = r_texture_white;
3925 t->backgroundglosstexture = r_texture_white;
3926 t->specularscale = r_shadow_gloss2intensity.value;
3930 // lightmaps mode looks bad with dlights using actual texturing, so turn
3931 // off the colormap and glossmap, but leave the normalmap on as it still
3932 // accurately represents the shading involved
3933 if (gl_lightmaps.integer && !(t->currentmaterialflags & MATERIALFLAG_BLENDED))
3935 t->basetexture = r_texture_white;
3936 t->specularscale = 0;
3939 t->currentpolygonfactor = r_refdef.polygonfactor + t->basepolygonfactor;
3940 t->currentpolygonoffset = r_refdef.polygonoffset + t->basepolygonoffset;
3941 // submodels are biased to avoid z-fighting with world surfaces that they
3942 // may be exactly overlapping (avoids z-fighting artifacts on certain
3943 // doors and things in Quake maps)
3944 if (ent->model->brush.submodel)
3946 t->currentpolygonfactor += r_polygonoffset_submodel_factor.value;
3947 t->currentpolygonoffset += r_polygonoffset_submodel_offset.value;
3950 VectorClear(t->dlightcolor);
3951 t->currentnumlayers = 0;
3952 if (!(t->currentmaterialflags & MATERIALFLAG_NODRAW))
3954 if (!(t->currentmaterialflags & MATERIALFLAG_SKY))
3956 int blendfunc1, blendfunc2, depthmask;
3957 if (t->currentmaterialflags & MATERIALFLAG_ADD)
3959 blendfunc1 = GL_SRC_ALPHA;
3960 blendfunc2 = GL_ONE;
3962 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
3964 blendfunc1 = GL_SRC_ALPHA;
3965 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
3967 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
3969 blendfunc1 = t->customblendfunc[0];
3970 blendfunc2 = t->customblendfunc[1];
3974 blendfunc1 = GL_ONE;
3975 blendfunc2 = GL_ZERO;
3977 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
3978 if (t->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL))
3980 rtexture_t *currentbasetexture;
3982 if (r_refdef.fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED))
3983 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
3984 currentbasetexture = (VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) < (1.0f / 1048576.0f) && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
3985 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
3987 // fullbright is not affected by r_refdef.lightmapintensity
3988 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
3989 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
3990 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);
3991 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
3992 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);
3997 // set the color tint used for lights affecting this surface
3998 VectorSet(t->dlightcolor, ent->colormod[0] * t->currentalpha, ent->colormod[1] * t->currentalpha, ent->colormod[2] * t->currentalpha);
4000 // q3bsp has no lightmap updates, so the lightstylevalue that
4001 // would normally be baked into the lightmap must be
4002 // applied to the color
4003 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
4004 if (ent->model->type == mod_brushq3)
4005 colorscale *= r_refdef.lightstylevalue[0] * (1.0f / 256.0f);
4006 colorscale *= r_refdef.lightmapintensity;
4007 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);
4008 if (r_ambient.value >= (1.0f/64.0f))
4009 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);
4010 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
4012 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);
4013 if (r_ambient.value >= (1.0f/64.0f))
4014 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);
4016 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
4018 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);
4019 if (r_ambient.value >= (1.0f/64.0f))
4020 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);
4023 if (t->currentskinframe->glow != NULL)
4024 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);
4025 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
4027 // if this is opaque use alpha blend which will darken the earlier
4030 // if this is an alpha blended material, all the earlier passes
4031 // were darkened by fog already, so we only need to add the fog
4032 // color ontop through the fog mask texture
4034 // if this is an additive blended material, all the earlier passes
4035 // were darkened by fog already, and we should not add fog color
4036 // (because the background was not darkened, there is no fog color
4037 // that was lost behind it).
4038 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);
4045 void R_UpdateAllTextureInfo(entity_render_t *ent)
4049 for (i = 0;i < ent->model->num_texturesperskin;i++)
4050 R_UpdateTextureInfo(ent, ent->model->data_textures + i);
4053 rsurfacestate_t rsurface;
4055 void R_Mesh_ResizeArrays(int newvertices)
4058 if (rsurface.array_size >= newvertices)
4060 if (rsurface.array_modelvertex3f)
4061 Mem_Free(rsurface.array_modelvertex3f);
4062 rsurface.array_size = (newvertices + 1023) & ~1023;
4063 base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
4064 rsurface.array_modelvertex3f = base + rsurface.array_size * 0;
4065 rsurface.array_modelsvector3f = base + rsurface.array_size * 3;
4066 rsurface.array_modeltvector3f = base + rsurface.array_size * 6;
4067 rsurface.array_modelnormal3f = base + rsurface.array_size * 9;
4068 rsurface.array_deformedvertex3f = base + rsurface.array_size * 12;
4069 rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
4070 rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
4071 rsurface.array_deformednormal3f = base + rsurface.array_size * 21;
4072 rsurface.array_texcoord3f = base + rsurface.array_size * 24;
4073 rsurface.array_color4f = base + rsurface.array_size * 27;
4074 rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
4077 void RSurf_CleanUp(void)
4080 if (rsurface.mode == RSURFMODE_GLSL)
4082 qglUseProgramObjectARB(0);CHECKGLERROR
4084 GL_AlphaTest(false);
4085 rsurface.mode = RSURFMODE_NONE;
4086 rsurface.uselightmaptexture = false;
4087 rsurface.texture = NULL;
4090 void RSurf_ActiveWorldEntity(void)
4092 model_t *model = r_refdef.worldmodel;
4094 if (rsurface.array_size < model->surfmesh.num_vertices)
4095 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
4096 rsurface.matrix = identitymatrix;
4097 rsurface.inversematrix = identitymatrix;
4098 R_Mesh_Matrix(&identitymatrix);
4099 VectorCopy(r_view.origin, rsurface.modelorg);
4100 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
4101 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
4102 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
4103 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
4104 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
4105 rsurface.frameblend[0].frame = 0;
4106 rsurface.frameblend[0].lerp = 1;
4107 rsurface.frameblend[1].frame = 0;
4108 rsurface.frameblend[1].lerp = 0;
4109 rsurface.frameblend[2].frame = 0;
4110 rsurface.frameblend[2].lerp = 0;
4111 rsurface.frameblend[3].frame = 0;
4112 rsurface.frameblend[3].lerp = 0;
4113 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
4114 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
4115 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
4116 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
4117 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
4118 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
4119 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
4120 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
4121 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
4122 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
4123 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
4124 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
4125 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
4126 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
4127 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
4128 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
4129 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
4130 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
4131 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
4132 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
4133 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
4134 rsurface.modelelement3i = model->surfmesh.data_element3i;
4135 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo;
4136 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
4137 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
4138 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
4139 rsurface.modelsurfaces = model->data_surfaces;
4140 rsurface.generatedvertex = false;
4141 rsurface.vertex3f = rsurface.modelvertex3f;
4142 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
4143 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
4144 rsurface.svector3f = rsurface.modelsvector3f;
4145 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
4146 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
4147 rsurface.tvector3f = rsurface.modeltvector3f;
4148 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
4149 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
4150 rsurface.normal3f = rsurface.modelnormal3f;
4151 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
4152 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
4153 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
4156 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4158 model_t *model = ent->model;
4160 if (rsurface.array_size < model->surfmesh.num_vertices)
4161 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
4162 rsurface.matrix = ent->matrix;
4163 rsurface.inversematrix = ent->inversematrix;
4164 R_Mesh_Matrix(&rsurface.matrix);
4165 Matrix4x4_Transform(&rsurface.inversematrix, r_view.origin, rsurface.modelorg);
4166 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
4167 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
4168 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
4169 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
4170 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
4171 rsurface.frameblend[0] = ent->frameblend[0];
4172 rsurface.frameblend[1] = ent->frameblend[1];
4173 rsurface.frameblend[2] = ent->frameblend[2];
4174 rsurface.frameblend[3] = ent->frameblend[3];
4175 if (model->surfmesh.isanimated && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].frame != 0))
4179 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
4180 rsurface.modelsvector3f = rsurface.array_modelsvector3f;
4181 rsurface.modeltvector3f = rsurface.array_modeltvector3f;
4182 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
4183 Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
4185 else if (wantnormals)
4187 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
4188 rsurface.modelsvector3f = NULL;
4189 rsurface.modeltvector3f = NULL;
4190 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
4191 Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
4195 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
4196 rsurface.modelsvector3f = NULL;
4197 rsurface.modeltvector3f = NULL;
4198 rsurface.modelnormal3f = NULL;
4199 Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, NULL, NULL, NULL);
4201 rsurface.modelvertex3f_bufferobject = 0;
4202 rsurface.modelvertex3f_bufferoffset = 0;
4203 rsurface.modelsvector3f_bufferobject = 0;
4204 rsurface.modelsvector3f_bufferoffset = 0;
4205 rsurface.modeltvector3f_bufferobject = 0;
4206 rsurface.modeltvector3f_bufferoffset = 0;
4207 rsurface.modelnormal3f_bufferobject = 0;
4208 rsurface.modelnormal3f_bufferoffset = 0;
4209 rsurface.generatedvertex = true;
4213 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
4214 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
4215 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
4216 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
4217 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
4218 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
4219 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
4220 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
4221 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
4222 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
4223 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
4224 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
4225 rsurface.generatedvertex = false;
4227 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
4228 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
4229 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
4230 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
4231 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
4232 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
4233 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
4234 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
4235 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
4236 rsurface.modelelement3i = model->surfmesh.data_element3i;
4237 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo;
4238 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
4239 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
4240 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
4241 rsurface.modelsurfaces = model->data_surfaces;
4242 rsurface.vertex3f = rsurface.modelvertex3f;
4243 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
4244 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
4245 rsurface.svector3f = rsurface.modelsvector3f;
4246 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
4247 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
4248 rsurface.tvector3f = rsurface.modeltvector3f;
4249 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
4250 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
4251 rsurface.normal3f = rsurface.modelnormal3f;
4252 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
4253 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
4254 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
4257 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
4258 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, msurface_t **texturesurfacelist)
4261 int texturesurfaceindex;
4266 const float *v1, *in_tc;
4268 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
4270 q3shaderinfo_deform_t *deform;
4271 // 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
4272 if (rsurface.generatedvertex)
4274 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
4275 generatenormals = true;
4276 for (i = 0;i < Q3MAXDEFORMS;i++)
4278 if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
4280 generatetangents = true;
4281 generatenormals = true;
4283 if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
4284 generatenormals = true;
4286 if (generatenormals && !rsurface.modelnormal3f)
4288 rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
4289 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
4290 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
4291 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer);
4293 if (generatetangents && !rsurface.modelsvector3f)
4295 rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
4296 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
4297 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
4298 rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
4299 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
4300 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
4301 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);
4304 rsurface.vertex3f = rsurface.modelvertex3f;
4305 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
4306 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
4307 rsurface.svector3f = rsurface.modelsvector3f;
4308 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
4309 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
4310 rsurface.tvector3f = rsurface.modeltvector3f;
4311 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
4312 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
4313 rsurface.normal3f = rsurface.modelnormal3f;
4314 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
4315 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
4316 // if vertices are deformed (sprite flares and things in maps, possibly
4317 // water waves, bulges and other deformations), generate them into
4318 // rsurface.deform* arrays from whatever the rsurface.* arrays point to
4319 // (may be static model data or generated data for an animated model, or
4320 // the previous deform pass)
4321 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
4323 switch (deform->deform)
4326 case Q3DEFORM_PROJECTIONSHADOW:
4327 case Q3DEFORM_TEXT0:
4328 case Q3DEFORM_TEXT1:
4329 case Q3DEFORM_TEXT2:
4330 case Q3DEFORM_TEXT3:
4331 case Q3DEFORM_TEXT4:
4332 case Q3DEFORM_TEXT5:
4333 case Q3DEFORM_TEXT6:
4334 case Q3DEFORM_TEXT7:
4337 case Q3DEFORM_AUTOSPRITE:
4338 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.forward, newforward);
4339 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.right, newright);
4340 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.up, newup);
4341 VectorNormalize(newforward);
4342 VectorNormalize(newright);
4343 VectorNormalize(newup);
4344 // make deformed versions of only the model vertices used by the specified surfaces
4345 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4347 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4348 // a single autosprite surface can contain multiple sprites...
4349 for (j = 0;j < surface->num_vertices - 3;j += 4)
4351 VectorClear(center);
4352 for (i = 0;i < 4;i++)
4353 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
4354 VectorScale(center, 0.25f, center);
4355 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, forward);
4356 VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
4357 VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
4358 for (i = 0;i < 4;i++)
4360 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
4361 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
4364 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);
4365 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);
4367 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4368 rsurface.vertex3f_bufferobject = 0;
4369 rsurface.vertex3f_bufferoffset = 0;
4370 rsurface.svector3f = rsurface.array_deformedsvector3f;
4371 rsurface.svector3f_bufferobject = 0;
4372 rsurface.svector3f_bufferoffset = 0;
4373 rsurface.tvector3f = rsurface.array_deformedtvector3f;
4374 rsurface.tvector3f_bufferobject = 0;
4375 rsurface.tvector3f_bufferoffset = 0;
4376 rsurface.normal3f = rsurface.array_deformednormal3f;
4377 rsurface.normal3f_bufferobject = 0;
4378 rsurface.normal3f_bufferoffset = 0;
4380 case Q3DEFORM_AUTOSPRITE2:
4381 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.forward, newforward);
4382 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.right, newright);
4383 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.up, newup);
4384 VectorNormalize(newforward);
4385 VectorNormalize(newright);
4386 VectorNormalize(newup);
4387 // make deformed versions of only the model vertices used by the specified surfaces
4388 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4390 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4391 const float *v1, *v2;
4401 memset(shortest, 0, sizeof(shortest));
4402 // a single autosprite surface can contain multiple sprites...
4403 for (j = 0;j < surface->num_vertices - 3;j += 4)
4405 VectorClear(center);
4406 for (i = 0;i < 4;i++)
4407 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
4408 VectorScale(center, 0.25f, center);
4409 // find the two shortest edges, then use them to define the
4410 // axis vectors for rotating around the central axis
4411 for (i = 0;i < 6;i++)
4413 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
4414 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
4416 Debug_PolygonBegin(NULL, 0, false, 0);
4417 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
4418 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);
4419 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
4422 l = VectorDistance2(v1, v2);
4423 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
4425 l += (1.0f / 1024.0f);
4426 if (shortest[0].length2 > l || i == 0)
4428 shortest[1] = shortest[0];
4429 shortest[0].length2 = l;
4430 shortest[0].v1 = v1;
4431 shortest[0].v2 = v2;
4433 else if (shortest[1].length2 > l || i == 1)
4435 shortest[1].length2 = l;
4436 shortest[1].v1 = v1;
4437 shortest[1].v2 = v2;
4440 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
4441 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
4443 Debug_PolygonBegin(NULL, 0, false, 0);
4444 Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
4445 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);
4446 Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
4449 // this calculates the right vector from the shortest edge
4450 // and the up vector from the edge midpoints
4451 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
4452 VectorNormalize(right);
4453 VectorSubtract(end, start, up);
4454 VectorNormalize(up);
4455 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
4456 //VectorSubtract(rsurface.modelorg, center, forward);
4457 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.forward, forward);
4458 VectorNegate(forward, forward);
4459 VectorReflect(forward, 0, up, forward);
4460 VectorNormalize(forward);
4461 CrossProduct(up, forward, newright);
4462 VectorNormalize(newright);
4464 Debug_PolygonBegin(NULL, 0, false, 0);
4465 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);
4466 Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
4467 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
4471 Debug_PolygonBegin(NULL, 0, false, 0);
4472 Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
4473 Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
4474 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
4477 // rotate the quad around the up axis vector, this is made
4478 // especially easy by the fact we know the quad is flat,
4479 // so we only have to subtract the center position and
4480 // measure distance along the right vector, and then
4481 // multiply that by the newright vector and add back the
4483 // we also need to subtract the old position to undo the
4484 // displacement from the center, which we do with a
4485 // DotProduct, the subtraction/addition of center is also
4486 // optimized into DotProducts here
4487 l = DotProduct(right, center);
4488 for (i = 0;i < 4;i++)
4490 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
4491 f = DotProduct(right, v1) - l;
4492 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
4495 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);
4496 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);
4498 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4499 rsurface.vertex3f_bufferobject = 0;
4500 rsurface.vertex3f_bufferoffset = 0;
4501 rsurface.svector3f = rsurface.array_deformedsvector3f;
4502 rsurface.svector3f_bufferobject = 0;
4503 rsurface.svector3f_bufferoffset = 0;
4504 rsurface.tvector3f = rsurface.array_deformedtvector3f;
4505 rsurface.tvector3f_bufferobject = 0;
4506 rsurface.tvector3f_bufferoffset = 0;
4507 rsurface.normal3f = rsurface.array_deformednormal3f;
4508 rsurface.normal3f_bufferobject = 0;
4509 rsurface.normal3f_bufferoffset = 0;
4511 case Q3DEFORM_NORMAL:
4512 // deform the normals to make reflections wavey
4513 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4515 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4516 for (j = 0;j < surface->num_vertices;j++)
4519 float *normal = (rsurface.array_deformednormal3f + 3 * surface->num_firstvertex) + j*3;
4520 VectorScale((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
4521 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, normal);
4522 normal[0] += deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.time * deform->parms[1]);
4523 normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.time * deform->parms[1]);
4524 normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.time * deform->parms[1]);
4525 VectorNormalize(normal);
4527 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);
4529 rsurface.svector3f = rsurface.array_deformedsvector3f;
4530 rsurface.svector3f_bufferobject = 0;
4531 rsurface.svector3f_bufferoffset = 0;
4532 rsurface.tvector3f = rsurface.array_deformedtvector3f;
4533 rsurface.tvector3f_bufferobject = 0;
4534 rsurface.tvector3f_bufferoffset = 0;
4535 rsurface.normal3f = rsurface.array_deformednormal3f;
4536 rsurface.normal3f_bufferobject = 0;
4537 rsurface.normal3f_bufferoffset = 0;
4540 // deform vertex array to make wavey water and flags and such
4541 waveparms[0] = deform->waveparms[0];
4542 waveparms[1] = deform->waveparms[1];
4543 waveparms[2] = deform->waveparms[2];
4544 waveparms[3] = deform->waveparms[3];
4545 // this is how a divisor of vertex influence on deformation
4546 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
4547 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
4548 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4550 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4551 for (j = 0;j < surface->num_vertices;j++)
4553 float *vertex = (rsurface.array_deformedvertex3f + 3 * surface->num_firstvertex) + j*3;
4554 VectorCopy((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, vertex);
4555 // if the wavefunc depends on time, evaluate it per-vertex
4558 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
4559 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
4561 VectorMA(vertex, scale, (rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, vertex);
4564 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4565 rsurface.vertex3f_bufferobject = 0;
4566 rsurface.vertex3f_bufferoffset = 0;
4568 case Q3DEFORM_BULGE:
4569 // deform vertex array to make the surface have moving bulges
4570 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4572 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4573 for (j = 0;j < surface->num_vertices;j++)
4575 scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.time * deform->parms[2])) * deform->parms[1];
4576 VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
4579 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4580 rsurface.vertex3f_bufferobject = 0;
4581 rsurface.vertex3f_bufferoffset = 0;
4584 // deform vertex array
4585 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
4586 VectorScale(deform->parms, scale, waveparms);
4587 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4589 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4590 for (j = 0;j < surface->num_vertices;j++)
4591 VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
4593 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4594 rsurface.vertex3f_bufferobject = 0;
4595 rsurface.vertex3f_bufferoffset = 0;
4599 // generate texcoords based on the chosen texcoord source
4600 switch(rsurface.texture->tcgen.tcgen)
4603 case Q3TCGEN_TEXTURE:
4604 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
4605 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordtexture2f_bufferobject;
4606 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
4608 case Q3TCGEN_LIGHTMAP:
4609 rsurface.texcoordtexture2f = rsurface.modeltexcoordlightmap2f;
4610 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
4611 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
4613 case Q3TCGEN_VECTOR:
4614 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4616 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4617 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)
4619 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
4620 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
4623 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
4624 rsurface.texcoordtexture2f_bufferobject = 0;
4625 rsurface.texcoordtexture2f_bufferoffset = 0;
4627 case Q3TCGEN_ENVIRONMENT:
4628 // make environment reflections using a spheremap
4629 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4631 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4632 const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
4633 const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
4634 float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
4635 for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
4637 float l, d, eyedir[3];
4638 VectorSubtract(rsurface.modelorg, vertex, eyedir);
4639 l = 0.5f / VectorLength(eyedir);
4640 d = DotProduct(normal, eyedir)*2;
4641 out_tc[0] = 0.5f + (normal[1]*d - eyedir[1])*l;
4642 out_tc[1] = 0.5f - (normal[2]*d - eyedir[2])*l;
4645 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
4646 rsurface.texcoordtexture2f_bufferobject = 0;
4647 rsurface.texcoordtexture2f_bufferoffset = 0;
4650 // the only tcmod that needs software vertex processing is turbulent, so
4651 // check for it here and apply the changes if needed
4652 // and we only support that as the first one
4653 // (handling a mixture of turbulent and other tcmods would be problematic
4654 // without punting it entirely to a software path)
4655 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
4657 amplitude = rsurface.texture->tcmods[0].parms[1];
4658 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.time * rsurface.texture->tcmods[0].parms[3];
4659 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4661 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4662 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)
4664 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
4665 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
4668 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
4669 rsurface.texcoordtexture2f_bufferobject = 0;
4670 rsurface.texcoordtexture2f_bufferoffset = 0;
4672 rsurface.texcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
4673 rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
4674 rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
4675 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
4678 void RSurf_DrawBatch_Simple(int texturenumsurfaces, msurface_t **texturesurfacelist)
4681 const msurface_t *surface = texturesurfacelist[0];
4682 const msurface_t *surface2;
4687 // TODO: lock all array ranges before render, rather than on each surface
4688 if (texturenumsurfaces == 1)
4690 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
4691 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));
4693 else if (r_batchmode.integer == 2)
4695 #define MAXBATCHTRIANGLES 4096
4696 int batchtriangles = 0;
4697 int batchelements[MAXBATCHTRIANGLES*3];
4698 for (i = 0;i < texturenumsurfaces;i = j)
4700 surface = texturesurfacelist[i];
4702 if (surface->num_triangles > MAXBATCHTRIANGLES)
4704 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));
4707 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
4708 batchtriangles = surface->num_triangles;
4709 firstvertex = surface->num_firstvertex;
4710 endvertex = surface->num_firstvertex + surface->num_vertices;
4711 for (;j < texturenumsurfaces;j++)
4713 surface2 = texturesurfacelist[j];
4714 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
4716 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
4717 batchtriangles += surface2->num_triangles;
4718 firstvertex = min(firstvertex, surface2->num_firstvertex);
4719 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
4721 surface2 = texturesurfacelist[j-1];
4722 numvertices = endvertex - firstvertex;
4723 R_Mesh_Draw(firstvertex, numvertices, batchtriangles, batchelements, 0, 0);
4726 else if (r_batchmode.integer == 1)
4728 for (i = 0;i < texturenumsurfaces;i = j)
4730 surface = texturesurfacelist[i];
4731 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
4732 if (texturesurfacelist[j] != surface2)
4734 surface2 = texturesurfacelist[j-1];
4735 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
4736 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
4737 GL_LockArrays(surface->num_firstvertex, numvertices);
4738 R_Mesh_Draw(surface->num_firstvertex, numvertices, numtriangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
4743 for (i = 0;i < texturenumsurfaces;i++)
4745 surface = texturesurfacelist[i];
4746 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
4747 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));
4752 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit, int refractiontexunit, int reflectiontexunit)
4754 int i, planeindex, vertexindex;
4758 r_waterstate_waterplane_t *p, *bestp;
4759 msurface_t *surface;
4760 if (r_waterstate.renderingscene)
4762 for (i = 0;i < texturenumsurfaces;i++)
4764 surface = texturesurfacelist[i];
4765 if (lightmaptexunit >= 0)
4766 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
4767 if (deluxemaptexunit >= 0)
4768 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
4769 // pick the closest matching water plane
4772 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
4775 for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
4777 Matrix4x4_Transform(&rsurface.matrix, v, vert);
4778 d += fabs(PlaneDiff(vert, &p->plane));
4780 if (bestd > d || !bestp)
4788 if (refractiontexunit >= 0)
4789 R_Mesh_TexBind(refractiontexunit, R_GetTexture(bestp->texture_refraction));
4790 if (reflectiontexunit >= 0)
4791 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(bestp->texture_reflection));
4795 if (refractiontexunit >= 0)
4796 R_Mesh_TexBind(refractiontexunit, R_GetTexture(r_texture_black));
4797 if (reflectiontexunit >= 0)
4798 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(r_texture_black));
4800 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
4801 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));
4805 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit)
4809 const msurface_t *surface = texturesurfacelist[0];
4810 const msurface_t *surface2;
4815 // TODO: lock all array ranges before render, rather than on each surface
4816 if (texturenumsurfaces == 1)
4818 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
4819 if (deluxemaptexunit >= 0)
4820 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
4821 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
4822 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));
4824 else if (r_batchmode.integer == 2)
4826 #define MAXBATCHTRIANGLES 4096
4827 int batchtriangles = 0;
4828 int batchelements[MAXBATCHTRIANGLES*3];
4829 for (i = 0;i < texturenumsurfaces;i = j)
4831 surface = texturesurfacelist[i];
4832 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
4833 if (deluxemaptexunit >= 0)
4834 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
4836 if (surface->num_triangles > MAXBATCHTRIANGLES)
4838 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));
4841 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
4842 batchtriangles = surface->num_triangles;
4843 firstvertex = surface->num_firstvertex;
4844 endvertex = surface->num_firstvertex + surface->num_vertices;
4845 for (;j < texturenumsurfaces;j++)
4847 surface2 = texturesurfacelist[j];
4848 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
4850 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
4851 batchtriangles += surface2->num_triangles;
4852 firstvertex = min(firstvertex, surface2->num_firstvertex);
4853 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
4855 surface2 = texturesurfacelist[j-1];
4856 numvertices = endvertex - firstvertex;
4857 R_Mesh_Draw(firstvertex, numvertices, batchtriangles, batchelements, 0, 0);
4860 else if (r_batchmode.integer == 1)
4863 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
4864 for (i = 0;i < texturenumsurfaces;i = j)
4866 surface = texturesurfacelist[i];
4867 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
4868 if (texturesurfacelist[j] != surface2)
4870 Con_Printf(" %i", j - i);
4873 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
4875 for (i = 0;i < texturenumsurfaces;i = j)
4877 surface = texturesurfacelist[i];
4878 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
4879 if (deluxemaptexunit >= 0)
4880 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
4881 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
4882 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
4885 Con_Printf(" %i", j - i);
4887 surface2 = texturesurfacelist[j-1];
4888 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
4889 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
4890 GL_LockArrays(surface->num_firstvertex, numvertices);
4891 R_Mesh_Draw(surface->num_firstvertex, numvertices, numtriangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
4899 for (i = 0;i < texturenumsurfaces;i++)
4901 surface = texturesurfacelist[i];
4902 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
4903 if (deluxemaptexunit >= 0)
4904 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
4905 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
4906 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));
4911 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
4914 int texturesurfaceindex;
4915 if (r_showsurfaces.integer == 2)
4917 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4919 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4920 for (j = 0;j < surface->num_triangles;j++)
4922 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_view.colorscale;
4923 GL_Color(f, f, f, 1);
4924 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)));
4930 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4932 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4933 int k = (int)(((size_t)surface) / sizeof(msurface_t));
4934 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);
4935 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
4936 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));
4941 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, msurface_t **texturesurfacelist)
4943 int texturesurfaceindex;
4947 if (rsurface.lightmapcolor4f)
4949 // generate color arrays for the surfaces in this list
4950 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4952 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4953 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)
4955 f = FogPoint_Model(v);
4965 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4967 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4968 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)
4970 f = FogPoint_Model(v);
4978 rsurface.lightmapcolor4f = rsurface.array_color4f;
4979 rsurface.lightmapcolor4f_bufferobject = 0;
4980 rsurface.lightmapcolor4f_bufferoffset = 0;
4983 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a)
4985 int texturesurfaceindex;
4988 if (!rsurface.lightmapcolor4f)
4990 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4992 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4993 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)
5001 rsurface.lightmapcolor4f = rsurface.array_color4f;
5002 rsurface.lightmapcolor4f_bufferobject = 0;
5003 rsurface.lightmapcolor4f_bufferoffset = 0;
5006 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5009 rsurface.lightmapcolor4f = NULL;
5010 rsurface.lightmapcolor4f_bufferobject = 0;
5011 rsurface.lightmapcolor4f_bufferoffset = 0;
5012 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5013 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5014 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5015 GL_Color(r, g, b, a);
5016 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 0, -1);
5019 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5021 // TODO: optimize applyfog && applycolor case
5022 // just apply fog if necessary, and tint the fog color array if necessary
5023 rsurface.lightmapcolor4f = NULL;
5024 rsurface.lightmapcolor4f_bufferobject = 0;
5025 rsurface.lightmapcolor4f_bufferoffset = 0;
5026 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5027 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5028 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5029 GL_Color(r, g, b, a);
5030 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5033 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5035 int texturesurfaceindex;
5039 if (texturesurfacelist[0]->lightmapinfo && texturesurfacelist[0]->lightmapinfo->stainsamples)
5041 // generate color arrays for the surfaces in this list
5042 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5044 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5045 for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
5047 if (surface->lightmapinfo->samples)
5049 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
5050 float scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
5051 VectorScale(lm, scale, c);
5052 if (surface->lightmapinfo->styles[1] != 255)
5054 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
5056 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
5057 VectorMA(c, scale, lm, c);
5058 if (surface->lightmapinfo->styles[2] != 255)
5061 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
5062 VectorMA(c, scale, lm, c);
5063 if (surface->lightmapinfo->styles[3] != 255)
5066 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
5067 VectorMA(c, scale, lm, c);
5077 rsurface.lightmapcolor4f = rsurface.array_color4f;
5078 rsurface.lightmapcolor4f_bufferobject = 0;
5079 rsurface.lightmapcolor4f_bufferoffset = 0;
5083 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
5084 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
5085 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
5087 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5088 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5089 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5090 GL_Color(r, g, b, a);
5091 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5094 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5096 int texturesurfaceindex;
5100 vec3_t ambientcolor;
5101 vec3_t diffusecolor;
5105 VectorCopy(rsurface.modellight_lightdir, lightdir);
5106 ambientcolor[0] = rsurface.modellight_ambient[0] * r * 0.5f;
5107 ambientcolor[1] = rsurface.modellight_ambient[1] * g * 0.5f;
5108 ambientcolor[2] = rsurface.modellight_ambient[2] * b * 0.5f;
5109 diffusecolor[0] = rsurface.modellight_diffuse[0] * r * 0.5f;
5110 diffusecolor[1] = rsurface.modellight_diffuse[1] * g * 0.5f;
5111 diffusecolor[2] = rsurface.modellight_diffuse[2] * b * 0.5f;
5112 if (VectorLength2(diffusecolor) > 0)
5114 // generate color arrays for the surfaces in this list
5115 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5117 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5118 int numverts = surface->num_vertices;
5119 v = rsurface.vertex3f + 3 * surface->num_firstvertex;
5120 c2 = rsurface.normal3f + 3 * surface->num_firstvertex;
5121 c = rsurface.array_color4f + 4 * surface->num_firstvertex;
5122 // q3-style directional shading
5123 for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
5125 if ((f = DotProduct(c2, lightdir)) > 0)
5126 VectorMA(ambientcolor, f, diffusecolor, c);
5128 VectorCopy(ambientcolor, c);
5137 rsurface.lightmapcolor4f = rsurface.array_color4f;
5138 rsurface.lightmapcolor4f_bufferobject = 0;
5139 rsurface.lightmapcolor4f_bufferoffset = 0;
5143 r = ambientcolor[0];
5144 g = ambientcolor[1];
5145 b = ambientcolor[2];
5146 rsurface.lightmapcolor4f = NULL;
5147 rsurface.lightmapcolor4f_bufferobject = 0;
5148 rsurface.lightmapcolor4f_bufferoffset = 0;
5150 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5151 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5152 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5153 GL_Color(r, g, b, a);
5154 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5157 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
5159 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5160 GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset);
5161 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
5162 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_view.cullface_back);
5163 if (rsurface.mode != RSURFMODE_SHOWSURFACES)
5165 rsurface.mode = RSURFMODE_SHOWSURFACES;
5167 GL_BlendFunc(GL_ONE, GL_ZERO);
5168 R_Mesh_ColorPointer(NULL, 0, 0);
5169 R_Mesh_ResetTextureState();
5171 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
5172 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
5175 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, msurface_t **texturesurfacelist)
5177 // transparent sky would be ridiculous
5178 if ((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED))
5180 if (rsurface.mode != RSURFMODE_SKY)
5182 if (rsurface.mode == RSURFMODE_GLSL)
5184 qglUseProgramObjectARB(0);CHECKGLERROR
5186 rsurface.mode = RSURFMODE_SKY;
5190 skyrendernow = false;
5192 // restore entity matrix
5193 R_Mesh_Matrix(&rsurface.matrix);
5195 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5196 GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset);
5197 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
5198 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_view.cullface_back);
5200 // LordHavoc: HalfLife maps have freaky skypolys so don't use
5201 // skymasking on them, and Quake3 never did sky masking (unlike
5202 // software Quake and software Quake2), so disable the sky masking
5203 // in Quake3 maps as it causes problems with q3map2 sky tricks,
5204 // and skymasking also looks very bad when noclipping outside the
5205 // level, so don't use it then either.
5206 if (r_refdef.worldmodel && r_refdef.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_viewcache.world_novis)
5208 GL_Color(r_refdef.fogcolor[0] * r_view.colorscale, r_refdef.fogcolor[1] * r_view.colorscale, r_refdef.fogcolor[2] * r_view.colorscale, 1);
5209 R_Mesh_ColorPointer(NULL, 0, 0);
5210 R_Mesh_ResetTextureState();
5211 if (skyrendermasked)
5213 // depth-only (masking)
5214 GL_ColorMask(0,0,0,0);
5215 // just to make sure that braindead drivers don't draw
5216 // anything despite that colormask...
5217 GL_BlendFunc(GL_ZERO, GL_ONE);
5222 GL_BlendFunc(GL_ONE, GL_ZERO);
5224 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
5225 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5226 if (skyrendermasked)
5227 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
5231 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, msurface_t **texturesurfacelist)
5233 if (rsurface.mode != RSURFMODE_GLSL)
5235 rsurface.mode = RSURFMODE_GLSL;
5236 R_Mesh_ResetTextureState();
5239 R_SetupSurfaceShader(vec3_origin, rsurface.lightmode == 2, 1, 1, rsurface.texture->specularscale);
5240 if (!r_glsl_permutation)
5243 if (rsurface.lightmode == 2)
5244 RSurf_PrepareVerticesForBatch(true, r_glsl_permutation->loc_Texture_Normal >= 0, texturenumsurfaces, texturesurfacelist);
5246 RSurf_PrepareVerticesForBatch(r_glsl_permutation->loc_Texture_Normal >= 0, r_glsl_permutation->loc_Texture_Normal >= 0, texturenumsurfaces, texturesurfacelist);
5247 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
5248 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
5249 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
5250 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
5251 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
5253 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]);
5254 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
5256 R_Mesh_TexBind(7, R_GetTexture(r_texture_grey128));
5257 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
5258 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
5259 R_Mesh_ColorPointer(NULL, 0, 0);
5261 else if (rsurface.uselightmaptexture)
5263 R_Mesh_TexBind(7, R_GetTexture(texturesurfacelist[0]->lightmaptexture));
5264 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
5265 R_Mesh_TexBind(8, R_GetTexture(texturesurfacelist[0]->deluxemaptexture));
5266 R_Mesh_ColorPointer(NULL, 0, 0);
5270 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
5271 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
5272 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
5273 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
5276 if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
5278 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
5279 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist, 7, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? 8 : -1, 11, 12);
5280 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5281 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist, 7, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? 8 : -1, -1, 12);
5283 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 7, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? 8 : -1);
5287 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
5288 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist, -1, -1, 11, 12);
5289 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5290 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist, -1, -1, -1, 12);
5292 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5294 if (rsurface.texture->backgroundnumskinframes && !(rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED))
5299 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, msurface_t **texturesurfacelist)
5301 // OpenGL 1.3 path - anything not completely ancient
5302 int texturesurfaceindex;
5303 qboolean applycolor;
5307 const texturelayer_t *layer;
5308 if (rsurface.mode != RSURFMODE_MULTIPASS)
5309 rsurface.mode = RSURFMODE_MULTIPASS;
5310 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
5311 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
5314 int layertexrgbscale;
5315 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5317 if (layerindex == 0)
5321 GL_AlphaTest(false);
5322 qglDepthFunc(GL_EQUAL);CHECKGLERROR
5325 GL_DepthMask(layer->depthmask);
5326 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
5327 if ((layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2) && (gl_combine.integer || layer->depthmask))
5329 layertexrgbscale = 4;
5330 VectorScale(layer->color, 0.25f, layercolor);
5332 else if ((layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1) && (gl_combine.integer || layer->depthmask))
5334 layertexrgbscale = 2;
5335 VectorScale(layer->color, 0.5f, layercolor);
5339 layertexrgbscale = 1;
5340 VectorScale(layer->color, 1.0f, layercolor);
5342 layercolor[3] = layer->color[3];
5343 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
5344 R_Mesh_ColorPointer(NULL, 0, 0);
5345 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
5346 switch (layer->type)
5348 case TEXTURELAYERTYPE_LITTEXTURE:
5349 memset(&m, 0, sizeof(m));
5350 m.tex[0] = R_GetTexture(r_texture_white);
5351 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
5352 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
5353 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
5354 m.tex[1] = R_GetTexture(layer->texture);
5355 m.texmatrix[1] = layer->texmatrix;
5356 m.texrgbscale[1] = layertexrgbscale;
5357 m.pointer_texcoord[1] = rsurface.texcoordtexture2f;
5358 m.pointer_texcoord_bufferobject[1] = rsurface.texcoordtexture2f_bufferobject;
5359 m.pointer_texcoord_bufferoffset[1] = rsurface.texcoordtexture2f_bufferoffset;
5360 R_Mesh_TextureState(&m);
5361 if (rsurface.lightmode == 2)
5362 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
5363 else if (rsurface.uselightmaptexture)
5364 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
5366 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
5368 case TEXTURELAYERTYPE_TEXTURE:
5369 memset(&m, 0, sizeof(m));
5370 m.tex[0] = R_GetTexture(layer->texture);
5371 m.texmatrix[0] = layer->texmatrix;
5372 m.texrgbscale[0] = layertexrgbscale;
5373 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5374 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5375 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5376 R_Mesh_TextureState(&m);
5377 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
5379 case TEXTURELAYERTYPE_FOG:
5380 memset(&m, 0, sizeof(m));
5381 m.texrgbscale[0] = layertexrgbscale;
5384 m.tex[0] = R_GetTexture(layer->texture);
5385 m.texmatrix[0] = layer->texmatrix;
5386 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5387 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5388 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5390 R_Mesh_TextureState(&m);
5391 // generate a color array for the fog pass
5392 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
5393 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5397 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5398 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)
5400 f = 1 - FogPoint_Model(v);
5401 c[0] = layercolor[0];
5402 c[1] = layercolor[1];
5403 c[2] = layercolor[2];
5404 c[3] = f * layercolor[3];
5407 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5410 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
5412 GL_LockArrays(0, 0);
5415 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5417 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
5418 GL_AlphaTest(false);
5422 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, msurface_t **texturesurfacelist)
5424 // OpenGL 1.1 - crusty old voodoo path
5425 int texturesurfaceindex;
5429 const texturelayer_t *layer;
5430 if (rsurface.mode != RSURFMODE_MULTIPASS)
5431 rsurface.mode = RSURFMODE_MULTIPASS;
5432 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
5433 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
5435 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5437 if (layerindex == 0)
5441 GL_AlphaTest(false);
5442 qglDepthFunc(GL_EQUAL);CHECKGLERROR
5445 GL_DepthMask(layer->depthmask);
5446 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
5447 R_Mesh_ColorPointer(NULL, 0, 0);
5448 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
5449 switch (layer->type)
5451 case TEXTURELAYERTYPE_LITTEXTURE:
5452 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
5454 // two-pass lit texture with 2x rgbscale
5455 // first the lightmap pass
5456 memset(&m, 0, sizeof(m));
5457 m.tex[0] = R_GetTexture(r_texture_white);
5458 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
5459 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
5460 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
5461 R_Mesh_TextureState(&m);
5462 if (rsurface.lightmode == 2)
5463 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5464 else if (rsurface.uselightmaptexture)
5465 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5467 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5468 GL_LockArrays(0, 0);
5469 // then apply the texture to it
5470 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
5471 memset(&m, 0, sizeof(m));
5472 m.tex[0] = R_GetTexture(layer->texture);
5473 m.texmatrix[0] = layer->texmatrix;
5474 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5475 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5476 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5477 R_Mesh_TextureState(&m);
5478 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);
5482 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
5483 memset(&m, 0, sizeof(m));
5484 m.tex[0] = R_GetTexture(layer->texture);
5485 m.texmatrix[0] = layer->texmatrix;
5486 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5487 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5488 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5489 R_Mesh_TextureState(&m);
5490 if (rsurface.lightmode == 2)
5491 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);
5493 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);
5496 case TEXTURELAYERTYPE_TEXTURE:
5497 // singletexture unlit texture with transparency support
5498 memset(&m, 0, sizeof(m));
5499 m.tex[0] = R_GetTexture(layer->texture);
5500 m.texmatrix[0] = layer->texmatrix;
5501 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5502 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5503 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5504 R_Mesh_TextureState(&m);
5505 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);
5507 case TEXTURELAYERTYPE_FOG:
5508 // singletexture fogging
5509 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
5512 memset(&m, 0, sizeof(m));
5513 m.tex[0] = R_GetTexture(layer->texture);
5514 m.texmatrix[0] = layer->texmatrix;
5515 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5516 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5517 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5518 R_Mesh_TextureState(&m);
5521 R_Mesh_ResetTextureState();
5522 // generate a color array for the fog pass
5523 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5527 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5528 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)
5530 f = 1 - FogPoint_Model(v);
5531 c[0] = layer->color[0];
5532 c[1] = layer->color[1];
5533 c[2] = layer->color[2];
5534 c[3] = f * layer->color[3];
5537 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5540 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
5542 GL_LockArrays(0, 0);
5545 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5547 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
5548 GL_AlphaTest(false);
5552 static void R_DrawTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly)
5554 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW)
5556 rsurface.rtlight = NULL;
5560 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
5562 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
5564 if (rsurface.mode != RSURFMODE_MULTIPASS)
5565 rsurface.mode = RSURFMODE_MULTIPASS;
5566 if (r_depthfirst.integer == 3)
5568 int i = (int)(texturesurfacelist[0] - rsurface.modelsurfaces);
5569 if (!r_view.showdebug)
5570 GL_Color(0, 0, 0, 1);
5572 GL_Color(((i >> 6) & 7) / 7.0f, ((i >> 3) & 7) / 7.0f, (i & 7) / 7.0f,1);
5576 GL_ColorMask(0,0,0,0);
5579 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5580 GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset);
5581 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_view.cullface_back);
5583 GL_BlendFunc(GL_ONE, GL_ZERO);
5585 GL_AlphaTest(false);
5586 R_Mesh_ColorPointer(NULL, 0, 0);
5587 R_Mesh_ResetTextureState();
5588 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
5589 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5590 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
5591 r_refdef.stats.entities_surfaces += texturenumsurfaces;
5593 else if (r_depthfirst.integer == 3)
5595 else if (!r_view.showdebug && (r_showsurfaces.integer || gl_lightmaps.integer))
5597 GL_Color(0, 0, 0, 1);
5598 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5600 else if (r_showsurfaces.integer)
5602 if (rsurface.mode != RSURFMODE_MULTIPASS)
5603 rsurface.mode = RSURFMODE_MULTIPASS;
5604 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5605 GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset);
5607 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_view.cullface_back);
5608 GL_BlendFunc(GL_ONE, GL_ZERO);
5609 GL_DepthMask(writedepth);
5611 GL_AlphaTest(false);
5612 R_Mesh_ColorPointer(NULL, 0, 0);
5613 R_Mesh_ResetTextureState();
5614 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
5615 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
5616 r_refdef.stats.entities_surfaces += texturenumsurfaces;
5618 else if (gl_lightmaps.integer)
5621 if (rsurface.mode != RSURFMODE_MULTIPASS)
5622 rsurface.mode = RSURFMODE_MULTIPASS;
5623 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5625 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_view.cullface_back);
5626 GL_BlendFunc(GL_ONE, GL_ZERO);
5627 GL_DepthMask(writedepth);
5629 GL_AlphaTest(false);
5630 // use lightmode 0 (fullbright or lightmap) or 2 (model lighting)
5631 rsurface.lightmode = ((rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT) || rsurface.modeltexcoordlightmap2f != NULL) ? 0 : 2;
5632 R_Mesh_ColorPointer(NULL, 0, 0);
5633 memset(&m, 0, sizeof(m));
5634 m.tex[0] = R_GetTexture(r_texture_white);
5635 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
5636 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
5637 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
5638 R_Mesh_TextureState(&m);
5639 RSurf_PrepareVerticesForBatch(rsurface.lightmode == 2, false, texturenumsurfaces, texturesurfacelist);
5640 if (rsurface.lightmode == 2)
5641 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5642 else if (rsurface.uselightmaptexture)
5643 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5645 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5646 r_refdef.stats.entities_surfaces += texturenumsurfaces;
5648 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
5650 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
5651 r_refdef.stats.entities_surfaces += texturenumsurfaces;
5653 else if (rsurface.texture->currentnumlayers)
5655 // write depth for anything we skipped on the depth-only pass earlier
5656 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5658 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5659 GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset);
5660 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
5661 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_view.cullface_back);
5662 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5663 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
5664 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5665 // use lightmode 0 (fullbright or lightmap) or 2 (model lighting)
5666 rsurface.lightmode = ((rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT) || rsurface.modeltexcoordlightmap2f != NULL) ? 0 : 2;
5667 if (r_glsl.integer && gl_support_fragment_shader)
5668 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist);
5669 else if (gl_combine.integer && r_textureunits.integer >= 2)
5670 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist);
5672 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist);
5673 r_refdef.stats.entities_surfaces += texturenumsurfaces;
5676 GL_LockArrays(0, 0);
5679 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
5682 int texturenumsurfaces, endsurface;
5684 msurface_t *surface;
5685 msurface_t *texturesurfacelist[1024];
5687 // if the model is static it doesn't matter what value we give for
5688 // wantnormals and wanttangents, so this logic uses only rules applicable
5689 // to a model, knowing that they are meaningless otherwise
5690 if (ent == r_refdef.worldentity)
5691 RSurf_ActiveWorldEntity();
5692 else if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
5693 RSurf_ActiveModelEntity(ent, false, false);
5695 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
5697 for (i = 0;i < numsurfaces;i = j)
5700 surface = rsurface.modelsurfaces + surfacelist[i];
5701 texture = surface->texture;
5702 R_UpdateTextureInfo(ent, texture);
5703 rsurface.texture = texture->currentframe;
5704 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
5705 // scan ahead until we find a different texture
5706 endsurface = min(i + 1024, numsurfaces);
5707 texturenumsurfaces = 0;
5708 texturesurfacelist[texturenumsurfaces++] = surface;
5709 for (;j < endsurface;j++)
5711 surface = rsurface.modelsurfaces + surfacelist[j];
5712 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
5714 texturesurfacelist[texturenumsurfaces++] = surface;
5716 // render the range of surfaces
5717 R_DrawTextureSurfaceList(texturenumsurfaces, texturesurfacelist, true, false);
5723 void R_QueueSurfaceList(entity_render_t *ent, int numsurfaces, msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes)
5726 vec3_t tempcenter, center;
5728 // if we're rendering water textures (extra scene renders), use a separate loop to avoid burdening the main one
5731 for (i = 0;i < numsurfaces;i++)
5732 if (surfacelist[i]->texture->currentframe->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5733 R_Water_AddWaterPlane(surfacelist[i]);
5736 // break the surface list down into batches by texture and use of lightmapping
5737 for (i = 0;i < numsurfaces;i = j)
5740 // texture is the base texture pointer, rsurface.texture is the
5741 // current frame/skin the texture is directing us to use (for example
5742 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
5743 // use skin 1 instead)
5744 texture = surfacelist[i]->texture;
5745 rsurface.texture = texture->currentframe;
5746 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
5747 if (!(rsurface.texture->currentmaterialflags & flagsmask))
5749 // if this texture is not the kind we want, skip ahead to the next one
5750 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
5754 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
5756 // transparent surfaces get pushed off into the transparent queue
5757 const msurface_t *surface = surfacelist[i];
5760 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
5761 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
5762 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
5763 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
5764 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_view.origin : center, R_DrawSurface_TransparentCallback, ent, surface - rsurface.modelsurfaces, rsurface.rtlight);
5768 // simply scan ahead until we find a different texture or lightmap state
5769 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
5771 // render the range of surfaces
5772 R_DrawTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly);
5777 float locboxvertex3f[6*4*3] =
5779 1,0,1, 1,0,0, 1,1,0, 1,1,1,
5780 0,1,1, 0,1,0, 0,0,0, 0,0,1,
5781 1,1,1, 1,1,0, 0,1,0, 0,1,1,
5782 0,0,1, 0,0,0, 1,0,0, 1,0,1,
5783 0,0,1, 1,0,1, 1,1,1, 0,1,1,
5784 1,0,0, 0,0,0, 0,1,0, 1,1,0
5787 int locboxelement3i[6*2*3] =
5797 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
5800 cl_locnode_t *loc = (cl_locnode_t *)ent;
5802 float vertex3f[6*4*3];
5804 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5805 GL_DepthMask(false);
5806 GL_DepthRange(0, 1);
5807 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5809 GL_CullFace(GL_NONE);
5810 R_Mesh_Matrix(&identitymatrix);
5812 R_Mesh_VertexPointer(vertex3f, 0, 0);
5813 R_Mesh_ColorPointer(NULL, 0, 0);
5814 R_Mesh_ResetTextureState();
5817 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_view.colorscale,
5818 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_view.colorscale,
5819 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_view.colorscale,
5820 surfacelist[0] < 0 ? 0.5f : 0.125f);
5822 if (VectorCompare(loc->mins, loc->maxs))
5824 VectorSet(size, 2, 2, 2);
5825 VectorMA(loc->mins, -0.5f, size, mins);
5829 VectorCopy(loc->mins, mins);
5830 VectorSubtract(loc->maxs, loc->mins, size);
5833 for (i = 0;i < 6*4*3;)
5834 for (j = 0;j < 3;j++, i++)
5835 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
5837 R_Mesh_Draw(0, 6*4, 6*2, locboxelement3i, 0, 0);
5840 void R_DrawLocs(void)
5843 cl_locnode_t *loc, *nearestloc;
5845 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
5846 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
5848 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
5849 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
5853 void R_DrawDebugModel(entity_render_t *ent)
5855 int i, j, k, l, flagsmask;
5856 const int *elements;
5858 msurface_t *surface;
5859 model_t *model = ent->model;
5862 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WATER | MATERIALFLAG_WALL;
5864 R_Mesh_ColorPointer(NULL, 0, 0);
5865 R_Mesh_ResetTextureState();
5866 GL_DepthRange(0, 1);
5867 GL_DepthTest(!r_showdisabledepthtest.integer);
5868 GL_DepthMask(false);
5869 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5871 if (r_showcollisionbrushes.value > 0 && model->brush.num_brushes)
5873 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
5874 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
5876 if (brush->colbrushf && brush->colbrushf->numtriangles)
5878 R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
5879 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);
5880 R_Mesh_Draw(0, brush->colbrushf->numpoints, brush->colbrushf->numtriangles, brush->colbrushf->elements, 0, 0);
5883 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
5885 if (surface->num_collisiontriangles)
5887 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
5888 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);
5889 R_Mesh_Draw(0, surface->num_collisionvertices, surface->num_collisiontriangles, surface->data_collisionelement3i, 0, 0);
5894 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5896 if (r_showtris.integer || r_shownormals.integer)
5898 if (r_showdisabledepthtest.integer)
5900 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5901 GL_DepthMask(false);
5905 GL_BlendFunc(GL_ONE, GL_ZERO);
5908 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
5910 if (ent == r_refdef.worldentity && !r_viewcache.world_surfacevisible[j])
5912 rsurface.texture = surface->texture->currentframe;
5913 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
5915 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
5916 if (r_showtris.value > 0)
5918 if (!rsurface.texture->currentlayers->depthmask)
5919 GL_Color(r_view.colorscale, 0, 0, r_showtris.value);
5920 else if (ent == r_refdef.worldentity)
5921 GL_Color(r_view.colorscale, r_view.colorscale, r_view.colorscale, r_showtris.value);
5923 GL_Color(0, r_view.colorscale, 0, r_showtris.value);
5924 elements = (ent->model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
5927 for (k = 0;k < surface->num_triangles;k++, elements += 3)
5929 #define GLVERTEXELEMENT(n) qglVertex3f(rsurface.vertex3f[elements[n]*3+0], rsurface.vertex3f[elements[n]*3+1], rsurface.vertex3f[elements[n]*3+2])
5930 GLVERTEXELEMENT(0);GLVERTEXELEMENT(1);
5931 GLVERTEXELEMENT(1);GLVERTEXELEMENT(2);
5932 GLVERTEXELEMENT(2);GLVERTEXELEMENT(0);
5937 if (r_shownormals.value > 0)
5939 GL_Color(r_view.colorscale, 0, 0, r_shownormals.value);
5941 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
5943 VectorCopy(rsurface.vertex3f + l * 3, v);
5944 qglVertex3f(v[0], v[1], v[2]);
5945 VectorMA(v, 8, rsurface.svector3f + l * 3, v);
5946 qglVertex3f(v[0], v[1], v[2]);
5950 GL_Color(0, 0, r_view.colorscale, r_shownormals.value);
5952 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
5954 VectorCopy(rsurface.vertex3f + l * 3, v);
5955 qglVertex3f(v[0], v[1], v[2]);
5956 VectorMA(v, 8, rsurface.tvector3f + l * 3, v);
5957 qglVertex3f(v[0], v[1], v[2]);
5961 GL_Color(0, r_view.colorscale, 0, r_shownormals.value);
5963 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
5965 VectorCopy(rsurface.vertex3f + l * 3, v);
5966 qglVertex3f(v[0], v[1], v[2]);
5967 VectorMA(v, 8, rsurface.normal3f + l * 3, v);
5968 qglVertex3f(v[0], v[1], v[2]);
5975 rsurface.texture = NULL;
5979 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
5980 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes, qboolean debug)
5982 int i, j, endj, f, flagsmask;
5983 int counttriangles = 0;
5984 msurface_t *surface, **surfacechain;
5986 model_t *model = r_refdef.worldmodel;
5987 const int maxsurfacelist = 1024;
5988 int numsurfacelist = 0;
5989 msurface_t *surfacelist[1024];
5993 RSurf_ActiveWorldEntity();
5995 // update light styles
5996 if (!skysurfaces && !depthonly && !addwaterplanes && model->brushq1.light_styleupdatechains)
5998 for (i = 0;i < model->brushq1.light_styles;i++)
6000 if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
6002 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
6003 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
6004 for (;(surface = *surfacechain);surfacechain++)
6005 surface->cached_dlight = true;
6010 R_UpdateAllTextureInfo(r_refdef.worldentity);
6011 flagsmask = addwaterplanes ? (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION) : (skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL));
6015 R_DrawDebugModel(r_refdef.worldentity);
6021 rsurface.uselightmaptexture = false;
6022 rsurface.texture = NULL;
6024 j = model->firstmodelsurface;
6025 endj = j + model->nummodelsurfaces;
6028 // quickly skip over non-visible surfaces
6029 for (;j < endj && !r_viewcache.world_surfacevisible[j];j++)
6031 // quickly iterate over visible surfaces
6032 for (;j < endj && r_viewcache.world_surfacevisible[j];j++)
6034 // process this surface
6035 surface = model->data_surfaces + j;
6036 // if this surface fits the criteria, add it to the list
6037 if (surface->num_triangles)
6039 // if lightmap parameters changed, rebuild lightmap texture
6040 if (surface->cached_dlight)
6041 R_BuildLightMap(r_refdef.worldentity, surface);
6042 // add face to draw list
6043 surfacelist[numsurfacelist++] = surface;
6044 counttriangles += surface->num_triangles;
6045 if (numsurfacelist >= maxsurfacelist)
6047 R_QueueSurfaceList(r_refdef.worldentity, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
6054 R_QueueSurfaceList(r_refdef.worldentity, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
6055 r_refdef.stats.entities_triangles += counttriangles;
6059 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes, qboolean debug)
6061 int i, f, flagsmask;
6062 int counttriangles = 0;
6063 msurface_t *surface, *endsurface, **surfacechain;
6065 model_t *model = ent->model;
6066 const int maxsurfacelist = 1024;
6067 int numsurfacelist = 0;
6068 msurface_t *surfacelist[1024];
6072 // if the model is static it doesn't matter what value we give for
6073 // wantnormals and wanttangents, so this logic uses only rules applicable
6074 // to a model, knowing that they are meaningless otherwise
6075 if (ent == r_refdef.worldentity)
6076 RSurf_ActiveWorldEntity();
6077 else if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
6078 RSurf_ActiveModelEntity(ent, false, false);
6080 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader && !depthonly);
6082 // update light styles
6083 if (!skysurfaces && !depthonly && !addwaterplanes && model->brushq1.light_styleupdatechains)
6085 for (i = 0;i < model->brushq1.light_styles;i++)
6087 if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
6089 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
6090 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
6091 for (;(surface = *surfacechain);surfacechain++)
6092 surface->cached_dlight = true;
6097 R_UpdateAllTextureInfo(ent);
6098 flagsmask = addwaterplanes ? (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION) : (skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL));
6102 R_DrawDebugModel(ent);
6108 rsurface.uselightmaptexture = false;
6109 rsurface.texture = NULL;
6111 surface = model->data_surfaces + model->firstmodelsurface;
6112 endsurface = surface + model->nummodelsurfaces;
6113 for (;surface < endsurface;surface++)
6115 // if this surface fits the criteria, add it to the list
6116 if (surface->num_triangles)
6118 // if lightmap parameters changed, rebuild lightmap texture
6119 if (surface->cached_dlight)
6120 R_BuildLightMap(ent, surface);
6121 // add face to draw list
6122 surfacelist[numsurfacelist++] = surface;
6123 counttriangles += surface->num_triangles;
6124 if (numsurfacelist >= maxsurfacelist)
6126 R_QueueSurfaceList(ent, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
6132 R_QueueSurfaceList(ent, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
6133 r_refdef.stats.entities_triangles += counttriangles;