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"
575 "uniform myhalf ReflectOffset;\n"
577 "//# ifdef USEREFLECTION\n"
578 "//uniform vec4 DistortScaleRefractReflect;\n"
579 "//uniform vec4 ScreenScaleRefractReflect;\n"
580 "//uniform vec4 ScreenCenterRefractReflect;\n"
581 "//uniform myhvec3 ReflectColor;\n"
585 "uniform myhalf GlowScale;\n"
586 "uniform myhalf SceneBrightness;\n"
587 "#ifdef USECONTRASTBOOST\n"
588 "uniform myhalf ContrastBoostCoeff;\n"
591 "uniform float OffsetMapping_Scale;\n"
592 "uniform float OffsetMapping_Bias;\n"
593 "uniform float FogRangeRecip;\n"
595 "uniform myhalf AmbientScale;\n"
596 "uniform myhalf DiffuseScale;\n"
597 "uniform myhalf SpecularScale;\n"
598 "uniform myhalf SpecularPower;\n"
600 "#ifdef USEOFFSETMAPPING\n"
601 "vec2 OffsetMapping(vec2 TexCoord)\n"
603 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
604 " // 14 sample relief mapping: linear search and then binary search\n"
605 " // this basically steps forward a small amount repeatedly until it finds\n"
606 " // itself inside solid, then jitters forward and back using decreasing\n"
607 " // amounts to find the impact\n"
608 " //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
609 " //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
610 " vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
611 " vec3 RT = vec3(TexCoord, 1);\n"
612 " OffsetVector *= 0.1;\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);\n"
622 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) - 0.5);\n"
623 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5 - 0.25);\n"
624 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25 - 0.125);\n"
625 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125 - 0.0625);\n"
626 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
629 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
630 " // this basically moves forward the full distance, and then backs up based\n"
631 " // on height of samples\n"
632 " //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
633 " //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
634 " vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
635 " TexCoord += OffsetVector;\n"
636 " OffsetVector *= 0.333;\n"
637 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
638 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
639 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
640 " return TexCoord;\n"
647 "#ifdef USEOFFSETMAPPING\n"
648 " // apply offsetmapping\n"
649 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
650 "#define TexCoord TexCoordOffset\n"
653 " // combine the diffuse textures (base, pants, shirt)\n"
654 " myhvec4 color = myhvec4(texture2D(Texture_Color, TexCoord));\n"
655 "#ifdef USECOLORMAPPING\n"
656 " color.rgb += myhvec3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhvec3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
662 "#ifdef MODE_LIGHTSOURCE\n"
665 " // calculate surface normal, light normal, and specular normal\n"
666 " // compute color intensity for the two textures (colormap and glossmap)\n"
667 " // scale by light color and attenuation as efficiently as possible\n"
668 " // (do as much scalar math as possible rather than vector math)\n"
669 "# ifdef USESPECULAR\n"
670 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
671 " myhvec3 diffusenormal = myhvec3(normalize(LightVector));\n"
672 " myhvec3 specularnormal = normalize(diffusenormal + myhvec3(normalize(EyeVector)));\n"
674 " // calculate directional shading\n"
675 " 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"
677 "# ifdef USEDIFFUSE\n"
678 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
679 " myhvec3 diffusenormal = myhvec3(normalize(LightVector));\n"
681 " // calculate directional shading\n"
682 " 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"
684 " // calculate directionless shading\n"
685 " color.rgb = color.rgb * LightColor * myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
689 "# ifdef USECUBEFILTER\n"
690 " // apply light cubemap filter\n"
691 " //color.rgb *= normalize(CubeVector) * 0.5 + 0.5;//vec3(textureCube(Texture_Cube, CubeVector));\n"
692 " color.rgb *= myhvec3(textureCube(Texture_Cube, CubeVector));\n"
694 " color *= myhvec4(gl_Color);\n"
695 "#endif // MODE_LIGHTSOURCE\n"
700 "#ifdef MODE_LIGHTDIRECTION\n"
701 " // directional model lighting\n"
703 " // get the surface normal and light normal\n"
704 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
705 " myhvec3 diffusenormal = myhvec3(LightVector);\n"
707 " // calculate directional shading\n"
708 " color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
709 "# ifdef USESPECULAR\n"
710 " myhvec3 specularnormal = normalize(diffusenormal + myhvec3(normalize(EyeVector)));\n"
711 " color.rgb += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
713 " color *= myhvec4(gl_Color);\n"
714 "#endif // MODE_LIGHTDIRECTION\n"
719 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
720 " // deluxemap lightmapping using light vectors in modelspace (evil q3map2)\n"
722 " // get the surface normal and light normal\n"
723 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
725 " myhvec3 diffusenormal_modelspace = myhvec3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - myhvec3(0.5);\n"
726 " myhvec3 diffusenormal = normalize(myhvec3(dot(diffusenormal_modelspace, myhvec3(VectorS)), dot(diffusenormal_modelspace, myhvec3(VectorT)), dot(diffusenormal_modelspace, myhvec3(VectorR))));\n"
727 " // calculate directional shading\n"
728 " myhvec3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0)));\n"
729 "# ifdef USESPECULAR\n"
730 " myhvec3 specularnormal = myhvec3(normalize(diffusenormal + myhvec3(normalize(EyeVector))));\n"
731 " tempcolor += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
734 " // apply lightmap color\n"
735 " color.rgb = myhvec4(tempcolor,1) * myhvec4(texture2D(Texture_Lightmap, TexCoordLightmap)) * myhvec4(gl_Color) + myhvec4(color.rgb * AmbientScale, 0);\n"
736 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
741 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
742 " // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
744 " // get the surface normal and light normal\n"
745 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
747 " myhvec3 diffusenormal = normalize(myhvec3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - myhvec3(0.5));\n"
748 " // calculate directional shading\n"
749 " myhvec3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0)));\n"
750 "# ifdef USESPECULAR\n"
751 " myhvec3 specularnormal = myhvec3(normalize(diffusenormal + myhvec3(normalize(EyeVector))));\n"
752 " tempcolor += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
755 " // apply lightmap color\n"
756 " color = myhvec4(tempcolor, 1) * myhvec4(texture2D(Texture_Lightmap, TexCoordLightmap)) * myhvec4(gl_Color) + myhvec4(color.rgb * AmbientScale, 0);\n"
757 "#endif // MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
762 "#ifdef MODE_LIGHTMAP\n"
763 " // apply lightmap color\n"
764 " color *= myhvec4(texture2D(Texture_Lightmap, TexCoordLightmap)) * myhvec4(gl_Color) * myhvec4(myhvec3(DiffuseScale), 1) + myhvec4(myhvec3(AmbientScale), 0);\n"
765 "#endif // MODE_LIGHTMAP\n"
774 "#ifdef MODE_LIGHTSOURCE\n"
776 " color.rgb *= color.a;\n"
780 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
781 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
782 " vec4 ScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect + vec3(normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5))).xyxy * DistortScaleRefractReflect;\n"
783 " myhalf Fresnel = myhalf(pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0)) * ReflectFactor + ReflectOffset;\n"
784 " color.rgb = mix(mix(myhvec3(texture2D(Texture_Refraction, ScreenTexCoord.xy)) * RefractColor, myhvec3(texture2D(Texture_Reflection, ScreenTexCoord.zw)) * ReflectColor, Fresnel), color.rgb, color.a);\n"
786 "# ifdef USEREFLECTION\n"
787 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
788 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
789 " vec4 ScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect + vec3(normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5))).xyxy * DistortScaleRefractReflect;\n"
790 " color.rgb += myhvec3(texture2D(Texture_Reflection, ScreenTexCoord.zw)) * ReflectColor;\n"
796 " color.rgb += myhvec3(texture2D(Texture_Glow, TexCoord)) * GlowScale;\n"
801 " color.rgb = mix(FogColor, color.rgb, myhalf(texture2D(Texture_FogMask, myhvec2(length(EyeVectorModelSpace)*FogRangeRecip, 0.0))));\n"
804 "#ifdef USECONTRASTBOOST\n"
805 " color.rgb = color.rgb * SceneBrightness / (ContrastBoostCoeff * color.rgb + myhvec3(1, 1, 1));\n"
807 " color.rgb *= SceneBrightness;\n"
810 " gl_FragColor = vec4(color);\n"
813 "#endif // FRAGMENT_SHADER\n"
816 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
817 const char *permutationinfo[][2] =
819 {"#define MODE_LIGHTMAP\n", " lightmap"},
820 {"#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
821 {"#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
822 {"#define MODE_LIGHTDIRECTION\n", " lightdirection"},
823 {"#define MODE_LIGHTSOURCE\n", " lightsource"},
824 {"#define USEWATER\n", " water"},
825 {"#define USEREFLECTION\n", " reflection"},
826 {"#define USEGLOW\n", " glow"},
827 {"#define USEFOG\n", " fog"},
828 {"#define USECOLORMAPPING\n", " colormapping"},
829 {"#define USEDIFFUSE\n", " diffuse"},
830 {"#define USECONTRASTBOOST\n", " contrastboost"},
831 {"#define USESPECULAR\n", " specular"},
832 {"#define USECUBEFILTER\n", " cubefilter"},
833 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
834 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
838 void R_GLSL_CompilePermutation(const char *filename, int permutation)
841 qboolean shaderfound;
842 r_glsl_permutation_t *p = r_glsl_permutations + (permutation & SHADERPERMUTATION_MASK);
843 int vertstrings_count;
844 int geomstrings_count;
845 int fragstrings_count;
847 const char *vertstrings_list[32+1];
848 const char *geomstrings_list[32+1];
849 const char *fragstrings_list[32+1];
850 char permutationname[256];
855 vertstrings_list[0] = "#define VERTEX_SHADER\n";
856 geomstrings_list[0] = "#define GEOMETRY_SHADER\n";
857 fragstrings_list[0] = "#define FRAGMENT_SHADER\n";
858 vertstrings_count = 1;
859 geomstrings_count = 1;
860 fragstrings_count = 1;
861 permutationname[0] = 0;
862 for (i = 0;permutationinfo[i][0];i++)
864 if (permutation & (1<<i))
866 vertstrings_list[vertstrings_count++] = permutationinfo[i][0];
867 geomstrings_list[geomstrings_count++] = permutationinfo[i][0];
868 fragstrings_list[fragstrings_count++] = permutationinfo[i][0];
869 strlcat(permutationname, permutationinfo[i][1], sizeof(permutationname));
873 // keep line numbers correct
874 vertstrings_list[vertstrings_count++] = "\n";
875 geomstrings_list[geomstrings_count++] = "\n";
876 fragstrings_list[fragstrings_count++] = "\n";
879 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
883 Con_DPrintf("GLSL shader text for \"%s\" loaded from disk\n", filename);
884 vertstrings_list[vertstrings_count++] = shaderstring;
885 geomstrings_list[geomstrings_count++] = shaderstring;
886 fragstrings_list[fragstrings_count++] = shaderstring;
889 else if (!strcmp(filename, "glsl/default.glsl"))
891 Con_DPrintf("GLSL shader text for \"%s\" loaded from engine\n", filename);
892 vertstrings_list[vertstrings_count++] = builtinshaderstring;
893 geomstrings_list[geomstrings_count++] = builtinshaderstring;
894 fragstrings_list[fragstrings_count++] = builtinshaderstring;
897 // clear any lists that are not needed by this shader
898 if (!(permutation & SHADERPERMUTATION_USES_VERTEXSHADER))
899 vertstrings_count = 0;
900 if (!(permutation & SHADERPERMUTATION_USES_GEOMETRYSHADER))
901 geomstrings_count = 0;
902 if (!(permutation & SHADERPERMUTATION_USES_FRAGMENTSHADER))
903 fragstrings_count = 0;
904 // compile the shader program
905 if (shaderfound && vertstrings_count + geomstrings_count + fragstrings_count)
906 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
910 qglUseProgramObjectARB(p->program);CHECKGLERROR
911 // look up all the uniform variable names we care about, so we don't
912 // have to look them up every time we set them
913 p->loc_Texture_Normal = qglGetUniformLocationARB(p->program, "Texture_Normal");
914 p->loc_Texture_Color = qglGetUniformLocationARB(p->program, "Texture_Color");
915 p->loc_Texture_Gloss = qglGetUniformLocationARB(p->program, "Texture_Gloss");
916 p->loc_Texture_Cube = qglGetUniformLocationARB(p->program, "Texture_Cube");
917 p->loc_Texture_Attenuation = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
918 p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
919 p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
920 p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
921 p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
922 p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
923 p->loc_Texture_Glow = qglGetUniformLocationARB(p->program, "Texture_Glow");
924 p->loc_Texture_Refraction = qglGetUniformLocationARB(p->program, "Texture_Refraction");
925 p->loc_Texture_Reflection = qglGetUniformLocationARB(p->program, "Texture_Reflection");
926 p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
927 p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
928 p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
929 p->loc_LightColor = qglGetUniformLocationARB(p->program, "LightColor");
930 p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants");
931 p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt");
932 p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip");
933 p->loc_AmbientScale = qglGetUniformLocationARB(p->program, "AmbientScale");
934 p->loc_DiffuseScale = qglGetUniformLocationARB(p->program, "DiffuseScale");
935 p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
936 p->loc_SpecularScale = qglGetUniformLocationARB(p->program, "SpecularScale");
937 p->loc_GlowScale = qglGetUniformLocationARB(p->program, "GlowScale");
938 p->loc_SceneBrightness = qglGetUniformLocationARB(p->program, "SceneBrightness");
939 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
940 p->loc_AmbientColor = qglGetUniformLocationARB(p->program, "AmbientColor");
941 p->loc_DiffuseColor = qglGetUniformLocationARB(p->program, "DiffuseColor");
942 p->loc_SpecularColor = qglGetUniformLocationARB(p->program, "SpecularColor");
943 p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
944 p->loc_ContrastBoostCoeff = qglGetUniformLocationARB(p->program, "ContrastBoostCoeff");
945 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
946 p->loc_ScreenScaleRefractReflect = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
947 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
948 p->loc_RefractColor = qglGetUniformLocationARB(p->program, "RefractColor");
949 p->loc_ReflectColor = qglGetUniformLocationARB(p->program, "ReflectColor");
950 p->loc_ReflectFactor = qglGetUniformLocationARB(p->program, "ReflectFactor");
951 p->loc_ReflectOffset = qglGetUniformLocationARB(p->program, "ReflectOffset");
952 // initialize the samplers to refer to the texture units we use
953 if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal, 0);
954 if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color, 1);
955 if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss, 2);
956 if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube, 3);
957 if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask, 4);
958 if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants, 5);
959 if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt, 6);
960 if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap, 7);
961 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap, 8);
962 if (p->loc_Texture_Glow >= 0) qglUniform1iARB(p->loc_Texture_Glow, 9);
963 if (p->loc_Texture_Attenuation >= 0) qglUniform1iARB(p->loc_Texture_Attenuation, 10);
964 if (p->loc_Texture_Refraction >= 0) qglUniform1iARB(p->loc_Texture_Refraction, 11);
965 if (p->loc_Texture_Reflection >= 0) qglUniform1iARB(p->loc_Texture_Reflection, 12);
967 qglUseProgramObjectARB(0);CHECKGLERROR
970 Con_Printf("permutation%s failed for shader %s, some features may not work properly!\n", permutationname, filename);
972 Mem_Free(shaderstring);
975 void R_GLSL_Restart_f(void)
978 for (i = 0;i < SHADERPERMUTATION_MAX;i++)
979 if (r_glsl_permutations[i].program)
980 GL_Backend_FreeProgram(r_glsl_permutations[i].program);
981 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
984 void R_GLSL_DumpShader_f(void)
988 qfile_t *file = FS_Open("glsl/default.glsl", "w", false, false);
991 Con_Printf("failed to write to glsl/default.glsl\n");
995 FS_Print(file, "// The engine may define the following macros:\n");
996 FS_Print(file, "// #define VERTEX_SHADER\n// #define GEOMETRY_SHADER\n// #define FRAGMENT_SHADER\n");
997 for (i = 0;permutationinfo[i][0];i++)
998 FS_Printf(file, "// %s", permutationinfo[i][0]);
999 FS_Print(file, "\n");
1000 FS_Print(file, builtinshaderstring);
1003 Con_Printf("glsl/default.glsl written\n");
1006 extern rtexture_t *r_shadow_attenuationgradienttexture;
1007 extern rtexture_t *r_shadow_attenuation2dtexture;
1008 extern rtexture_t *r_shadow_attenuation3dtexture;
1009 int R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale)
1011 // select a permutation of the lighting shader appropriate to this
1012 // combination of texture, entity, light source, and fogging, only use the
1013 // minimum features necessary to avoid wasting rendering time in the
1014 // fragment shader on features that are not being used
1015 const char *shaderfilename = NULL;
1016 unsigned int permutation = 0;
1018 r_glsl_permutation = NULL;
1019 // TODO: implement geometry-shader based shadow volumes someday
1020 if (rsurface.rtlight)
1023 shaderfilename = "glsl/default.glsl";
1024 permutation = SHADERPERMUTATION_MODE_LIGHTSOURCE | SHADERPERMUTATION_USES_VERTEXSHADER | SHADERPERMUTATION_USES_FRAGMENTSHADER;
1025 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
1026 permutation |= SHADERPERMUTATION_CUBEFILTER;
1027 if (diffusescale > 0)
1028 permutation |= SHADERPERMUTATION_DIFFUSE;
1029 if (specularscale > 0)
1030 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
1031 if (r_refdef.fogenabled)
1032 permutation |= SHADERPERMUTATION_FOG;
1033 if (rsurface.texture->colormapping)
1034 permutation |= SHADERPERMUTATION_COLORMAPPING;
1035 if (r_glsl_offsetmapping.integer)
1037 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
1038 if (r_glsl_offsetmapping_reliefmapping.integer)
1039 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
1041 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1042 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1043 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
1044 permutation |= SHADERPERMUTATION_WATER;
1045 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1046 permutation |= SHADERPERMUTATION_REFLECTION;
1048 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
1050 // bright unshaded geometry
1051 shaderfilename = "glsl/default.glsl";
1052 permutation = SHADERPERMUTATION_USES_VERTEXSHADER | SHADERPERMUTATION_USES_FRAGMENTSHADER;
1053 permutation |= SHADERPERMUTATION_MODE_LIGHTMAP;
1054 if (rsurface.texture->currentskinframe->glow)
1055 permutation |= SHADERPERMUTATION_GLOW;
1056 if (r_refdef.fogenabled)
1057 permutation |= SHADERPERMUTATION_FOG;
1058 if (rsurface.texture->colormapping)
1059 permutation |= SHADERPERMUTATION_COLORMAPPING;
1060 if (r_glsl_offsetmapping.integer)
1062 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
1063 if (r_glsl_offsetmapping_reliefmapping.integer)
1064 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
1066 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1067 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1068 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
1069 permutation |= SHADERPERMUTATION_WATER;
1070 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1071 permutation |= SHADERPERMUTATION_REFLECTION;
1073 else if (modellighting)
1075 // directional model lighting
1076 shaderfilename = "glsl/default.glsl";
1077 permutation = SHADERPERMUTATION_USES_VERTEXSHADER | SHADERPERMUTATION_USES_FRAGMENTSHADER;
1078 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTION;
1079 if (rsurface.texture->currentskinframe->glow)
1080 permutation |= SHADERPERMUTATION_GLOW;
1081 if (specularscale > 0)
1082 permutation |= SHADERPERMUTATION_SPECULAR;
1083 if (r_refdef.fogenabled)
1084 permutation |= SHADERPERMUTATION_FOG;
1085 if (rsurface.texture->colormapping)
1086 permutation |= SHADERPERMUTATION_COLORMAPPING;
1087 if (r_glsl_offsetmapping.integer)
1089 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
1090 if (r_glsl_offsetmapping_reliefmapping.integer)
1091 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
1093 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1094 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1095 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
1096 permutation |= SHADERPERMUTATION_WATER;
1097 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1098 permutation |= SHADERPERMUTATION_REFLECTION;
1103 shaderfilename = "glsl/default.glsl";
1104 permutation = SHADERPERMUTATION_USES_VERTEXSHADER | SHADERPERMUTATION_USES_FRAGMENTSHADER;
1105 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.worldmodel && r_refdef.worldmodel->brushq3.deluxemapping)
1107 // deluxemapping (light direction texture)
1108 if (rsurface.uselightmaptexture && r_refdef.worldmodel && r_refdef.worldmodel->brushq3.deluxemapping && r_refdef.worldmodel->brushq3.deluxemapping_modelspace)
1109 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_MODELSPACE;
1111 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
1112 if (specularscale > 0)
1113 permutation |= SHADERPERMUTATION_SPECULAR;
1115 else if (r_glsl_deluxemapping.integer >= 2)
1117 // fake deluxemapping (uniform light direction in tangentspace)
1118 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
1119 if (specularscale > 0)
1120 permutation |= SHADERPERMUTATION_SPECULAR;
1124 // ordinary lightmapping
1125 permutation |= SHADERPERMUTATION_MODE_LIGHTMAP;
1127 if (rsurface.texture->currentskinframe->glow)
1128 permutation |= SHADERPERMUTATION_GLOW;
1129 if (r_refdef.fogenabled)
1130 permutation |= SHADERPERMUTATION_FOG;
1131 if (rsurface.texture->colormapping)
1132 permutation |= SHADERPERMUTATION_COLORMAPPING;
1133 if (r_glsl_offsetmapping.integer)
1135 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
1136 if (r_glsl_offsetmapping_reliefmapping.integer)
1137 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
1139 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1140 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1141 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
1142 permutation |= SHADERPERMUTATION_WATER;
1143 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1144 permutation |= SHADERPERMUTATION_REFLECTION;
1146 if (!r_glsl_permutations[permutation & SHADERPERMUTATION_MASK].program)
1148 if (!r_glsl_permutations[permutation & SHADERPERMUTATION_MASK].compiled)
1149 R_GLSL_CompilePermutation(shaderfilename, permutation);
1150 if (!r_glsl_permutations[permutation & SHADERPERMUTATION_MASK].program)
1152 // remove features until we find a valid permutation
1154 for (i = (SHADERPERMUTATION_MAX >> 1);;i>>=1)
1158 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");
1159 Cvar_SetValueQuick(&r_glsl, 0);
1160 return 0; // no bit left to clear
1162 // reduce i more quickly whenever it would not remove any bits
1163 if (!(permutation & i))
1166 if (!r_glsl_permutations[permutation & SHADERPERMUTATION_MASK].compiled)
1167 R_GLSL_CompilePermutation(shaderfilename, permutation);
1168 if (r_glsl_permutations[permutation & SHADERPERMUTATION_MASK].program)
1173 r_glsl_permutation = r_glsl_permutations + (permutation & SHADERPERMUTATION_MASK);
1175 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
1176 R_Mesh_TexMatrix(0, &rsurface.texture->currenttexmatrix);
1177 if (permutation & SHADERPERMUTATION_MODE_LIGHTSOURCE)
1179 if (r_glsl_permutation->loc_Texture_Cube >= 0 && rsurface.rtlight) R_Mesh_TexBindCubeMap(3, R_GetTexture(rsurface.rtlight->currentcubemap));
1180 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
1181 if (permutation & SHADERPERMUTATION_DIFFUSE)
1183 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
1184 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, ambientscale);
1185 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, diffusescale);
1186 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, specularscale);
1190 // ambient only is simpler
1191 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0] * ambientscale, lightcolorbase[1] * ambientscale, lightcolorbase[2] * ambientscale);
1192 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, 1);
1193 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, 0);
1194 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, 0);
1197 else if (permutation & SHADERPERMUTATION_MODE_LIGHTDIRECTION)
1199 if (r_glsl_permutation->loc_AmbientColor >= 0)
1200 qglUniform3fARB(r_glsl_permutation->loc_AmbientColor, rsurface.modellight_ambient[0] * ambientscale, rsurface.modellight_ambient[1] * ambientscale, rsurface.modellight_ambient[2] * ambientscale);
1201 if (r_glsl_permutation->loc_DiffuseColor >= 0)
1202 qglUniform3fARB(r_glsl_permutation->loc_DiffuseColor, rsurface.modellight_diffuse[0] * diffusescale, rsurface.modellight_diffuse[1] * diffusescale, rsurface.modellight_diffuse[2] * diffusescale);
1203 if (r_glsl_permutation->loc_SpecularColor >= 0)
1204 qglUniform3fARB(r_glsl_permutation->loc_SpecularColor, rsurface.modellight_diffuse[0] * specularscale, rsurface.modellight_diffuse[1] * specularscale, rsurface.modellight_diffuse[2] * specularscale);
1205 if (r_glsl_permutation->loc_LightDir >= 0)
1206 qglUniform3fARB(r_glsl_permutation->loc_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
1210 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_ambient.value * 2.0f / 128.0f);
1211 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_refdef.lightmapintensity * 2.0f);
1212 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, r_refdef.lightmapintensity * specularscale * 2.0f);
1214 nmap = rsurface.texture->currentskinframe->nmap;
1215 if (gl_lightmaps.integer)
1216 nmap = r_texture_blanknormalmap;
1217 if (r_glsl_permutation->loc_Texture_Normal >= 0) R_Mesh_TexBind(0, R_GetTexture(nmap));
1218 if (r_glsl_permutation->loc_Texture_Color >= 0) R_Mesh_TexBind(1, R_GetTexture(rsurface.texture->basetexture));
1219 if (r_glsl_permutation->loc_Texture_Gloss >= 0) R_Mesh_TexBind(2, R_GetTexture(rsurface.texture->glosstexture));
1220 //if (r_glsl_permutation->loc_Texture_Cube >= 0 && permutation & SHADERPERMUTATION_MODE_LIGHTSOURCE) R_Mesh_TexBindCubeMap(3, R_GetTexture(rsurface.rtlight->currentcubemap));
1221 if (r_glsl_permutation->loc_Texture_Attenuation >= 0) R_Mesh_TexBind(10, R_GetTexture(r_shadow_attenuationgradienttexture));
1222 if (r_glsl_permutation->loc_Texture_FogMask >= 0) R_Mesh_TexBind(4, R_GetTexture(r_texture_fogattenuation));
1223 if (r_glsl_permutation->loc_Texture_Pants >= 0) R_Mesh_TexBind(5, R_GetTexture(rsurface.texture->currentskinframe->pants));
1224 if (r_glsl_permutation->loc_Texture_Shirt >= 0) R_Mesh_TexBind(6, R_GetTexture(rsurface.texture->currentskinframe->shirt));
1225 //if (r_glsl_permutation->loc_Texture_Lightmap >= 0) R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
1226 //if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
1227 if (r_glsl_permutation->loc_Texture_Glow >= 0) R_Mesh_TexBind(9, R_GetTexture(rsurface.texture->currentskinframe->glow));
1228 if (r_glsl_permutation->loc_Texture_Refraction >= 0) R_Mesh_TexBind(11, R_GetTexture(r_texture_white)); // changed per surface
1229 if (r_glsl_permutation->loc_Texture_Reflection >= 0) R_Mesh_TexBind(12, R_GetTexture(r_texture_white)); // changed per surface
1230 if (r_glsl_permutation->loc_GlowScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_GlowScale, r_hdr_glowintensity.value);
1231 if (r_glsl_permutation->loc_ContrastBoostCoeff >= 0)
1233 // The formula used is actually:
1234 // color.rgb *= SceneBrightness;
1235 // color.rgb *= ContrastBoost / ((ContrastBoost - 1) * color.rgb + 1);
1236 // I simplify that to
1237 // color.rgb *= [[SceneBrightness * ContrastBoost]];
1238 // color.rgb /= [[(ContrastBoost - 1) / ContrastBoost]] * color.rgb + 1;
1240 // color.rgb = [[SceneBrightness * ContrastBoost]] / ([[(ContrastBoost - 1) * SceneBrightness]] + 1 / color.rgb);
1241 // and do [[calculations]] here in the engine
1242 qglUniform1fARB(r_glsl_permutation->loc_ContrastBoostCoeff, (r_glsl_contrastboost.value - 1) * r_view.colorscale);
1243 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_view.colorscale * r_glsl_contrastboost.value);
1246 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_view.colorscale);
1247 if (r_glsl_permutation->loc_FogColor >= 0)
1249 // additive passes are only darkened by fog, not tinted
1250 if (rsurface.rtlight || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD))
1251 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
1253 qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
1255 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.modelorg[0], rsurface.modelorg[1], rsurface.modelorg[2]);
1256 if (r_glsl_permutation->loc_Color_Pants >= 0)
1258 if (rsurface.texture->currentskinframe->pants)
1259 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
1261 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
1263 if (r_glsl_permutation->loc_Color_Shirt >= 0)
1265 if (rsurface.texture->currentskinframe->shirt)
1266 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
1268 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
1270 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, r_refdef.fograngerecip);
1271 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower);
1272 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
1273 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);
1274 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]);
1275 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]);
1276 if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform3fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor);
1277 if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform3fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor);
1278 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->refractmax - rsurface.texture->refractmin);
1279 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, 1 - rsurface.texture->refractmax);
1284 void R_SwitchSurfaceShader(int permutation)
1286 if (r_glsl_permutation != r_glsl_permutations + (permutation & SHADERPERMUTATION_MASK))
1288 r_glsl_permutation = r_glsl_permutations + (permutation & SHADERPERMUTATION_MASK);
1290 qglUseProgramObjectARB(r_glsl_permutation->program);
1295 #define SKINFRAME_HASH 1024
1299 int loadsequence; // incremented each level change
1300 memexpandablearray_t array;
1301 skinframe_t *hash[SKINFRAME_HASH];
1305 void R_SkinFrame_PrepareForPurge(void)
1307 r_skinframe.loadsequence++;
1308 // wrap it without hitting zero
1309 if (r_skinframe.loadsequence >= 200)
1310 r_skinframe.loadsequence = 1;
1313 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
1317 // mark the skinframe as used for the purging code
1318 skinframe->loadsequence = r_skinframe.loadsequence;
1321 void R_SkinFrame_Purge(void)
1325 for (i = 0;i < SKINFRAME_HASH;i++)
1327 for (s = r_skinframe.hash[i];s;s = s->next)
1329 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
1331 if (s->base == r_texture_notexture) s->base = NULL;
1332 if (s->nmap == r_texture_blanknormalmap)s->nmap = NULL;
1333 if (s->merged == s->base) s->merged = NULL;
1334 if (s->stain ) R_FreeTexture(s->stain );s->stain = NULL;
1335 if (s->merged) R_FreeTexture(s->merged);s->merged = NULL;
1336 if (s->base ) R_FreeTexture(s->base );s->base = NULL;
1337 if (s->pants ) R_FreeTexture(s->pants );s->pants = NULL;
1338 if (s->shirt ) R_FreeTexture(s->shirt );s->shirt = NULL;
1339 if (s->nmap ) R_FreeTexture(s->nmap );s->nmap = NULL;
1340 if (s->gloss ) R_FreeTexture(s->gloss );s->gloss = NULL;
1341 if (s->glow ) R_FreeTexture(s->glow );s->glow = NULL;
1342 if (s->fog ) R_FreeTexture(s->fog );s->fog = NULL;
1343 s->loadsequence = 0;
1349 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
1353 char basename[MAX_QPATH];
1355 Image_StripImageExtension(name, basename, sizeof(basename));
1357 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
1358 for (item = r_skinframe.hash[hashindex];item;item = item->next)
1359 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
1365 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
1366 memset(item, 0, sizeof(*item));
1367 strlcpy(item->basename, basename, sizeof(item->basename));
1368 item->textureflags = textureflags;
1369 item->comparewidth = comparewidth;
1370 item->compareheight = compareheight;
1371 item->comparecrc = comparecrc;
1372 item->next = r_skinframe.hash[hashindex];
1373 r_skinframe.hash[hashindex] = item;
1375 R_SkinFrame_MarkUsed(item);
1379 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
1381 // FIXME: it should be possible to disable loading various layers using
1382 // cvars, to prevent wasted loading time and memory usage if the user does
1384 qboolean loadnormalmap = true;
1385 qboolean loadgloss = true;
1386 qboolean loadpantsandshirt = true;
1387 qboolean loadglow = true;
1389 unsigned char *pixels;
1390 unsigned char *bumppixels;
1391 unsigned char *basepixels = NULL;
1392 int basepixels_width;
1393 int basepixels_height;
1394 skinframe_t *skinframe;
1396 if (cls.state == ca_dedicated)
1399 // return an existing skinframe if already loaded
1400 // if loading of the first image fails, don't make a new skinframe as it
1401 // would cause all future lookups of this to be missing
1402 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
1403 if (skinframe && skinframe->base)
1406 basepixels = loadimagepixels(name, complain, 0, 0);
1407 if (basepixels == NULL)
1410 // we've got some pixels to store, so really allocate this new texture now
1412 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
1413 skinframe->stain = NULL;
1414 skinframe->merged = NULL;
1415 skinframe->base = r_texture_notexture;
1416 skinframe->pants = NULL;
1417 skinframe->shirt = NULL;
1418 skinframe->nmap = r_texture_blanknormalmap;
1419 skinframe->gloss = NULL;
1420 skinframe->glow = NULL;
1421 skinframe->fog = NULL;
1423 basepixels_width = image_width;
1424 basepixels_height = image_height;
1425 skinframe->base = R_LoadTexture2D (r_main_texturepool, skinframe->basename, basepixels_width, basepixels_height, basepixels, TEXTYPE_RGBA, skinframe->textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), NULL);
1427 if (textureflags & TEXF_ALPHA)
1429 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
1430 if (basepixels[j] < 255)
1432 if (j < basepixels_width * basepixels_height * 4)
1434 // has transparent pixels
1435 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
1436 for (j = 0;j < image_width * image_height * 4;j += 4)
1441 pixels[j+3] = basepixels[j+3];
1443 skinframe->fog = R_LoadTexture2D (r_main_texturepool, va("%s_mask", skinframe->basename), image_width, image_height, pixels, TEXTYPE_RGBA, skinframe->textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), NULL);
1448 // _norm is the name used by tenebrae and has been adopted as standard
1451 if ((pixels = loadimagepixels(va("%s_norm", skinframe->basename), false, 0, 0)) != NULL)
1453 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_RGBA, skinframe->textureflags & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), NULL);
1457 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixels(va("%s_bump", skinframe->basename), false, 0, 0)) != NULL)
1459 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
1460 Image_HeightmapToNormalmap(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
1461 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_RGBA, skinframe->textureflags & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), NULL);
1463 Mem_Free(bumppixels);
1465 else if (r_shadow_bumpscale_basetexture.value > 0)
1467 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
1468 Image_HeightmapToNormalmap(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
1469 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), basepixels_width, basepixels_height, pixels, TEXTYPE_RGBA, skinframe->textureflags & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), NULL);
1473 // _luma is supported for tenebrae compatibility
1474 // (I think it's a very stupid name, but oh well)
1475 // _glow is the preferred name
1476 if (loadglow && ((pixels = loadimagepixels(va("%s_glow", skinframe->basename), false, 0, 0)) != NULL || (pixels = loadimagepixels(va("%s_luma", skinframe->basename), false, 0, 0)) != NULL)) {skinframe->glow = R_LoadTexture2D (r_main_texturepool, va("%s_glow", skinframe->basename), image_width, image_height, pixels, TEXTYPE_RGBA, skinframe->textureflags & (gl_texturecompression_glow.integer ? ~0 : ~TEXF_COMPRESS), NULL);Mem_Free(pixels);pixels = NULL;}
1477 if (loadgloss && (pixels = loadimagepixels(va("%s_gloss", skinframe->basename), false, 0, 0)) != NULL) {skinframe->gloss = R_LoadTexture2D (r_main_texturepool, va("%s_gloss", skinframe->basename), image_width, image_height, pixels, TEXTYPE_RGBA, skinframe->textureflags & (gl_texturecompression_gloss.integer ? ~0 : ~TEXF_COMPRESS), NULL);Mem_Free(pixels);pixels = NULL;}
1478 if (loadpantsandshirt && (pixels = loadimagepixels(va("%s_pants", skinframe->basename), false, 0, 0)) != NULL) {skinframe->pants = R_LoadTexture2D (r_main_texturepool, va("%s_pants", skinframe->basename), image_width, image_height, pixels, TEXTYPE_RGBA, skinframe->textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), NULL);Mem_Free(pixels);pixels = NULL;}
1479 if (loadpantsandshirt && (pixels = loadimagepixels(va("%s_shirt", skinframe->basename), false, 0, 0)) != NULL) {skinframe->shirt = R_LoadTexture2D (r_main_texturepool, va("%s_shirt", skinframe->basename), image_width, image_height, pixels, TEXTYPE_RGBA, skinframe->textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), NULL);Mem_Free(pixels);pixels = NULL;}
1482 Mem_Free(basepixels);
1487 static rtexture_t *R_SkinFrame_TextureForSkinLayer(const unsigned char *in, int width, int height, const char *name, const unsigned int *palette, int textureflags, qboolean force)
1492 for (i = 0;i < width*height;i++)
1493 if (((unsigned char *)&palette[in[i]])[3] > 0)
1495 if (i == width*height)
1498 return R_LoadTexture2D (r_main_texturepool, name, width, height, in, TEXTYPE_PALETTE, textureflags, palette);
1501 skinframe_t *R_SkinFrame_LoadInternal(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height, int bitsperpixel, const unsigned int *palette, const unsigned int *alphapalette)
1504 unsigned char *temp1, *temp2;
1505 skinframe_t *skinframe;
1507 if (cls.state == ca_dedicated)
1510 // if already loaded just return it, otherwise make a new skinframe
1511 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*bitsperpixel/8) : 0, true);
1512 if (skinframe && skinframe->base)
1515 skinframe->stain = NULL;
1516 skinframe->merged = NULL;
1517 skinframe->base = r_texture_notexture;
1518 skinframe->pants = NULL;
1519 skinframe->shirt = NULL;
1520 skinframe->nmap = r_texture_blanknormalmap;
1521 skinframe->gloss = NULL;
1522 skinframe->glow = NULL;
1523 skinframe->fog = NULL;
1525 // if no data was provided, then clearly the caller wanted to get a blank skinframe
1529 if (bitsperpixel == 32)
1531 if (r_shadow_bumpscale_basetexture.value > 0)
1533 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
1534 temp2 = temp1 + width * height * 4;
1535 Image_HeightmapToNormalmap(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
1536 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_RGBA, skinframe->textureflags | TEXF_ALPHA, NULL);
1539 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_RGBA, skinframe->textureflags, NULL);
1540 if (textureflags & TEXF_ALPHA)
1542 for (i = 3;i < width * height * 4;i += 4)
1543 if (skindata[i] < 255)
1545 if (i < width * height * 4)
1547 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
1548 memcpy(fogpixels, skindata, width * height * 4);
1549 for (i = 0;i < width * height * 4;i += 4)
1550 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
1551 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_RGBA, skinframe->textureflags, NULL);
1552 Mem_Free(fogpixels);
1556 else if (bitsperpixel == 8)
1558 if (r_shadow_bumpscale_basetexture.value > 0)
1560 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
1561 temp2 = temp1 + width * height * 4;
1562 if (bitsperpixel == 32)
1563 Image_HeightmapToNormalmap(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
1566 // use either a custom palette or the quake palette
1567 Image_Copy8bitRGBA(skindata, temp1, width * height, palette ? palette : palette_complete);
1568 Image_HeightmapToNormalmap(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
1570 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_RGBA, skinframe->textureflags | TEXF_ALPHA, NULL);
1573 // use either a custom palette, or the quake palette
1574 skinframe->base = skinframe->merged = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_merged", skinframe->basename), palette ? palette : (loadglowtexture ? palette_nofullbrights : ((skinframe->textureflags & TEXF_ALPHA) ? palette_transparent : palette_complete)), skinframe->textureflags, true); // all
1575 if (!palette && loadglowtexture)
1576 skinframe->glow = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_glow", skinframe->basename), palette_onlyfullbrights, skinframe->textureflags, false); // glow
1577 if (!palette && loadpantsandshirt)
1579 skinframe->pants = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_pants", skinframe->basename), palette_pantsaswhite, skinframe->textureflags, false); // pants
1580 skinframe->shirt = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_shirt", skinframe->basename), palette_shirtaswhite, skinframe->textureflags, false); // shirt
1582 if (skinframe->pants || skinframe->shirt)
1583 skinframe->base = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_nospecial", skinframe->basename),loadglowtexture ? palette_nocolormapnofullbrights : palette_nocolormap, skinframe->textureflags, false); // no special colors
1584 if (textureflags & TEXF_ALPHA)
1586 // if not using a custom alphapalette, use the quake one
1588 alphapalette = palette_alpha;
1589 for (i = 0;i < width * height;i++)
1590 if (((unsigned char *)alphapalette)[skindata[i]*4+3] < 255)
1592 if (i < width * height)
1593 skinframe->fog = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_fog", skinframe->basename), alphapalette, skinframe->textureflags, true); // fog mask
1600 skinframe_t *R_SkinFrame_LoadMissing(void)
1602 skinframe_t *skinframe;
1604 if (cls.state == ca_dedicated)
1607 skinframe = R_SkinFrame_Find("missing", TEXF_PRECACHE, 0, 0, 0, true);
1608 skinframe->stain = NULL;
1609 skinframe->merged = NULL;
1610 skinframe->base = r_texture_notexture;
1611 skinframe->pants = NULL;
1612 skinframe->shirt = NULL;
1613 skinframe->nmap = r_texture_blanknormalmap;
1614 skinframe->gloss = NULL;
1615 skinframe->glow = NULL;
1616 skinframe->fog = NULL;
1621 void gl_main_start(void)
1626 r = (-1.0/256.0) * (FOGMASKTABLEWIDTH * FOGMASKTABLEWIDTH);
1627 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
1629 alpha = 1 - exp(r / ((double)x*(double)x));
1630 if (x == FOGMASKTABLEWIDTH - 1)
1632 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
1635 memset(r_qwskincache, 0, sizeof(r_qwskincache));
1636 memset(r_qwskincache_skinframe, 0, sizeof(r_qwskincache_skinframe));
1638 // set up r_skinframe loading system for textures
1639 memset(&r_skinframe, 0, sizeof(r_skinframe));
1640 r_skinframe.loadsequence = 1;
1641 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
1643 r_main_texturepool = R_AllocTexturePool();
1644 R_BuildBlankTextures();
1646 if (gl_texturecubemap)
1649 R_BuildNormalizationCube();
1651 R_BuildFogTexture();
1652 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
1653 memset(&r_waterstate, 0, sizeof(r_waterstate));
1654 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
1655 memset(&r_svbsp, 0, sizeof (r_svbsp));
1658 void gl_main_shutdown(void)
1660 memset(r_qwskincache, 0, sizeof(r_qwskincache));
1661 memset(r_qwskincache_skinframe, 0, sizeof(r_qwskincache_skinframe));
1663 // clear out the r_skinframe state
1664 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
1665 memset(&r_skinframe, 0, sizeof(r_skinframe));
1668 Mem_Free(r_svbsp.nodes);
1669 memset(&r_svbsp, 0, sizeof (r_svbsp));
1670 R_FreeTexturePool(&r_main_texturepool);
1671 r_texture_blanknormalmap = NULL;
1672 r_texture_white = NULL;
1673 r_texture_grey128 = NULL;
1674 r_texture_black = NULL;
1675 r_texture_whitecube = NULL;
1676 r_texture_normalizationcube = NULL;
1677 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
1678 memset(&r_waterstate, 0, sizeof(r_waterstate));
1682 extern void CL_ParseEntityLump(char *entitystring);
1683 void gl_main_newmap(void)
1685 // FIXME: move this code to client
1687 char *entities, entname[MAX_QPATH];
1690 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
1691 l = (int)strlen(entname) - 4;
1692 if (l >= 0 && !strcmp(entname + l, ".bsp"))
1694 memcpy(entname + l, ".ent", 5);
1695 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
1697 CL_ParseEntityLump(entities);
1702 if (cl.worldmodel->brush.entities)
1703 CL_ParseEntityLump(cl.worldmodel->brush.entities);
1707 void GL_Main_Init(void)
1709 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
1711 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
1712 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
1713 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
1714 if (gamemode == GAME_NEHAHRA)
1716 Cvar_RegisterVariable (&gl_fogenable);
1717 Cvar_RegisterVariable (&gl_fogdensity);
1718 Cvar_RegisterVariable (&gl_fogred);
1719 Cvar_RegisterVariable (&gl_foggreen);
1720 Cvar_RegisterVariable (&gl_fogblue);
1721 Cvar_RegisterVariable (&gl_fogstart);
1722 Cvar_RegisterVariable (&gl_fogend);
1724 Cvar_RegisterVariable(&r_depthfirst);
1725 Cvar_RegisterVariable(&r_nearclip);
1726 Cvar_RegisterVariable(&r_showbboxes);
1727 Cvar_RegisterVariable(&r_showsurfaces);
1728 Cvar_RegisterVariable(&r_showtris);
1729 Cvar_RegisterVariable(&r_shownormals);
1730 Cvar_RegisterVariable(&r_showlighting);
1731 Cvar_RegisterVariable(&r_showshadowvolumes);
1732 Cvar_RegisterVariable(&r_showcollisionbrushes);
1733 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
1734 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
1735 Cvar_RegisterVariable(&r_showdisabledepthtest);
1736 Cvar_RegisterVariable(&r_drawportals);
1737 Cvar_RegisterVariable(&r_drawentities);
1738 Cvar_RegisterVariable(&r_cullentities_trace);
1739 Cvar_RegisterVariable(&r_cullentities_trace_samples);
1740 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
1741 Cvar_RegisterVariable(&r_cullentities_trace_delay);
1742 Cvar_RegisterVariable(&r_drawviewmodel);
1743 Cvar_RegisterVariable(&r_speeds);
1744 Cvar_RegisterVariable(&r_fullbrights);
1745 Cvar_RegisterVariable(&r_wateralpha);
1746 Cvar_RegisterVariable(&r_dynamic);
1747 Cvar_RegisterVariable(&r_fullbright);
1748 Cvar_RegisterVariable(&r_shadows);
1749 Cvar_RegisterVariable(&r_shadows_throwdistance);
1750 Cvar_RegisterVariable(&r_q1bsp_skymasking);
1751 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
1752 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
1753 Cvar_RegisterVariable(&r_textureunits);
1754 Cvar_RegisterVariable(&r_glsl);
1755 Cvar_RegisterVariable(&r_glsl_offsetmapping);
1756 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
1757 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
1758 Cvar_RegisterVariable(&r_glsl_water);
1759 Cvar_RegisterVariable(&r_glsl_water_resolutionmultiplier);
1760 Cvar_RegisterVariable(&r_glsl_water_clippingplanebias);
1761 Cvar_RegisterVariable(&r_glsl_water_refractdistort);
1762 Cvar_RegisterVariable(&r_glsl_water_reflectdistort);
1763 Cvar_RegisterVariable(&r_glsl_deluxemapping);
1764 Cvar_RegisterVariable(&r_lerpsprites);
1765 Cvar_RegisterVariable(&r_lerpmodels);
1766 Cvar_RegisterVariable(&r_waterscroll);
1767 Cvar_RegisterVariable(&r_bloom);
1768 Cvar_RegisterVariable(&r_bloom_colorscale);
1769 Cvar_RegisterVariable(&r_bloom_brighten);
1770 Cvar_RegisterVariable(&r_bloom_blur);
1771 Cvar_RegisterVariable(&r_bloom_resolution);
1772 Cvar_RegisterVariable(&r_bloom_colorexponent);
1773 Cvar_RegisterVariable(&r_bloom_colorsubtract);
1774 Cvar_RegisterVariable(&r_hdr);
1775 Cvar_RegisterVariable(&r_hdr_scenebrightness);
1776 Cvar_RegisterVariable(&r_glsl_contrastboost);
1777 Cvar_RegisterVariable(&r_hdr_glowintensity);
1778 Cvar_RegisterVariable(&r_hdr_range);
1779 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
1780 Cvar_RegisterVariable(&developer_texturelogging);
1781 Cvar_RegisterVariable(&gl_lightmaps);
1782 Cvar_RegisterVariable(&r_test);
1783 Cvar_RegisterVariable(&r_batchmode);
1784 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
1785 Cvar_SetValue("r_fullbrights", 0);
1786 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
1789 extern void R_Textures_Init(void);
1790 extern void GL_Draw_Init(void);
1791 extern void GL_Main_Init(void);
1792 extern void R_Shadow_Init(void);
1793 extern void R_Sky_Init(void);
1794 extern void GL_Surf_Init(void);
1795 extern void R_Light_Init(void);
1796 extern void R_Particles_Init(void);
1797 extern void R_Explosion_Init(void);
1798 extern void gl_backend_init(void);
1799 extern void Sbar_Init(void);
1800 extern void R_LightningBeams_Init(void);
1801 extern void Mod_RenderInit(void);
1803 void Render_Init(void)
1816 R_LightningBeams_Init();
1825 extern char *ENGINE_EXTENSIONS;
1828 VID_CheckExtensions();
1830 // LordHavoc: report supported extensions
1831 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
1833 // clear to black (loading plaque will be seen over this)
1835 qglClearColor(0,0,0,1);CHECKGLERROR
1836 qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
1839 int R_CullBox(const vec3_t mins, const vec3_t maxs)
1843 for (i = 0;i < r_view.numfrustumplanes;i++)
1845 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
1848 p = r_view.frustum + i;
1853 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1857 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1861 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1865 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1869 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1873 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1877 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1881 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1889 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
1893 for (i = 0;i < numplanes;i++)
1900 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1904 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1908 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1912 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1916 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1920 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1924 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1928 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1936 //==================================================================================
1938 static void R_UpdateEntityLighting(entity_render_t *ent)
1940 vec3_t tempdiffusenormal;
1942 // fetch the lighting from the worldmodel data
1943 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));
1944 VectorClear(ent->modellight_diffuse);
1945 VectorClear(tempdiffusenormal);
1946 if ((ent->flags & RENDER_LIGHT) && r_refdef.worldmodel && r_refdef.worldmodel->brush.LightPoint)
1949 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
1950 r_refdef.worldmodel->brush.LightPoint(r_refdef.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
1953 VectorSet(ent->modellight_ambient, 1, 1, 1);
1955 // move the light direction into modelspace coordinates for lighting code
1956 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
1957 if(VectorLength2(ent->modellight_lightdir) > 0)
1959 VectorNormalize(ent->modellight_lightdir);
1963 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
1966 // scale ambient and directional light contributions according to rendering variables
1967 ent->modellight_ambient[0] *= ent->colormod[0] * r_refdef.lightmapintensity;
1968 ent->modellight_ambient[1] *= ent->colormod[1] * r_refdef.lightmapintensity;
1969 ent->modellight_ambient[2] *= ent->colormod[2] * r_refdef.lightmapintensity;
1970 ent->modellight_diffuse[0] *= ent->colormod[0] * r_refdef.lightmapintensity;
1971 ent->modellight_diffuse[1] *= ent->colormod[1] * r_refdef.lightmapintensity;
1972 ent->modellight_diffuse[2] *= ent->colormod[2] * r_refdef.lightmapintensity;
1975 static void R_View_UpdateEntityVisible (void)
1978 entity_render_t *ent;
1980 if (!r_drawentities.integer)
1983 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : ((chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL : RENDER_EXTERIORMODEL);
1984 if (r_refdef.worldmodel && r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs)
1986 // worldmodel can check visibility
1987 for (i = 0;i < r_refdef.numentities;i++)
1989 ent = r_refdef.entities[i];
1990 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));
1992 if(r_cullentities_trace.integer)
1994 for (i = 0;i < r_refdef.numentities;i++)
1996 ent = r_refdef.entities[i];
1997 if(r_viewcache.entityvisible[i] && !(ent->effects & EF_NODEPTHTEST) && !(ent->flags & RENDER_VIEWMODEL) && !(ent->model && (ent->model->name[0] == '*')))
1999 if(Mod_CanSeeBox_Trace(r_cullentities_trace_samples.integer, r_cullentities_trace_enlarge.value, r_refdef.worldmodel, r_view.origin, ent->mins, ent->maxs))
2000 ent->last_trace_visibility = realtime;
2001 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
2002 r_viewcache.entityvisible[i] = 0;
2009 // no worldmodel or it can't check visibility
2010 for (i = 0;i < r_refdef.numentities;i++)
2012 ent = r_refdef.entities[i];
2013 r_viewcache.entityvisible[i] = !(ent->flags & renderimask) && !R_CullBox(ent->mins, ent->maxs);
2017 // update entity lighting (even on hidden entities for r_shadows)
2018 for (i = 0;i < r_refdef.numentities;i++)
2019 R_UpdateEntityLighting(r_refdef.entities[i]);
2022 // only used if skyrendermasked, and normally returns false
2023 int R_DrawBrushModelsSky (void)
2026 entity_render_t *ent;
2028 if (!r_drawentities.integer)
2032 for (i = 0;i < r_refdef.numentities;i++)
2034 if (!r_viewcache.entityvisible[i])
2036 ent = r_refdef.entities[i];
2037 if (!ent->model || !ent->model->DrawSky)
2039 ent->model->DrawSky(ent);
2045 static void R_DrawNoModel(entity_render_t *ent);
2046 static void R_DrawModels(void)
2049 entity_render_t *ent;
2051 if (!r_drawentities.integer)
2054 for (i = 0;i < r_refdef.numentities;i++)
2056 if (!r_viewcache.entityvisible[i])
2058 ent = r_refdef.entities[i];
2059 r_refdef.stats.entities++;
2060 if (ent->model && ent->model->Draw != NULL)
2061 ent->model->Draw(ent);
2067 static void R_DrawModelsDepth(void)
2070 entity_render_t *ent;
2072 if (!r_drawentities.integer)
2075 for (i = 0;i < r_refdef.numentities;i++)
2077 if (!r_viewcache.entityvisible[i])
2079 ent = r_refdef.entities[i];
2080 r_refdef.stats.entities++;
2081 if (ent->model && ent->model->DrawDepth != NULL)
2082 ent->model->DrawDepth(ent);
2086 static void R_DrawModelsDebug(void)
2089 entity_render_t *ent;
2091 if (!r_drawentities.integer)
2094 for (i = 0;i < r_refdef.numentities;i++)
2096 if (!r_viewcache.entityvisible[i])
2098 ent = r_refdef.entities[i];
2099 r_refdef.stats.entities++;
2100 if (ent->model && ent->model->DrawDebug != NULL)
2101 ent->model->DrawDebug(ent);
2105 static void R_DrawModelsAddWaterPlanes(void)
2108 entity_render_t *ent;
2110 if (!r_drawentities.integer)
2113 for (i = 0;i < r_refdef.numentities;i++)
2115 if (!r_viewcache.entityvisible[i])
2117 ent = r_refdef.entities[i];
2118 r_refdef.stats.entities++;
2119 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
2120 ent->model->DrawAddWaterPlanes(ent);
2124 static void R_View_SetFrustum(void)
2127 double slopex, slopey;
2129 // break apart the view matrix into vectors for various purposes
2130 Matrix4x4_ToVectors(&r_view.matrix, r_view.forward, r_view.left, r_view.up, r_view.origin);
2131 VectorNegate(r_view.left, r_view.right);
2134 r_view.frustum[0].normal[0] = 0 - 1.0 / r_view.frustum_x;
2135 r_view.frustum[0].normal[1] = 0 - 0;
2136 r_view.frustum[0].normal[2] = -1 - 0;
2137 r_view.frustum[1].normal[0] = 0 + 1.0 / r_view.frustum_x;
2138 r_view.frustum[1].normal[1] = 0 + 0;
2139 r_view.frustum[1].normal[2] = -1 + 0;
2140 r_view.frustum[2].normal[0] = 0 - 0;
2141 r_view.frustum[2].normal[1] = 0 - 1.0 / r_view.frustum_y;
2142 r_view.frustum[2].normal[2] = -1 - 0;
2143 r_view.frustum[3].normal[0] = 0 + 0;
2144 r_view.frustum[3].normal[1] = 0 + 1.0 / r_view.frustum_y;
2145 r_view.frustum[3].normal[2] = -1 + 0;
2149 zNear = r_refdef.nearclip;
2150 nudge = 1.0 - 1.0 / (1<<23);
2151 r_view.frustum[4].normal[0] = 0 - 0;
2152 r_view.frustum[4].normal[1] = 0 - 0;
2153 r_view.frustum[4].normal[2] = -1 - -nudge;
2154 r_view.frustum[4].dist = 0 - -2 * zNear * nudge;
2155 r_view.frustum[5].normal[0] = 0 + 0;
2156 r_view.frustum[5].normal[1] = 0 + 0;
2157 r_view.frustum[5].normal[2] = -1 + -nudge;
2158 r_view.frustum[5].dist = 0 + -2 * zNear * nudge;
2164 r_view.frustum[0].normal[0] = m[3] - m[0];
2165 r_view.frustum[0].normal[1] = m[7] - m[4];
2166 r_view.frustum[0].normal[2] = m[11] - m[8];
2167 r_view.frustum[0].dist = m[15] - m[12];
2169 r_view.frustum[1].normal[0] = m[3] + m[0];
2170 r_view.frustum[1].normal[1] = m[7] + m[4];
2171 r_view.frustum[1].normal[2] = m[11] + m[8];
2172 r_view.frustum[1].dist = m[15] + m[12];
2174 r_view.frustum[2].normal[0] = m[3] - m[1];
2175 r_view.frustum[2].normal[1] = m[7] - m[5];
2176 r_view.frustum[2].normal[2] = m[11] - m[9];
2177 r_view.frustum[2].dist = m[15] - m[13];
2179 r_view.frustum[3].normal[0] = m[3] + m[1];
2180 r_view.frustum[3].normal[1] = m[7] + m[5];
2181 r_view.frustum[3].normal[2] = m[11] + m[9];
2182 r_view.frustum[3].dist = m[15] + m[13];
2184 r_view.frustum[4].normal[0] = m[3] - m[2];
2185 r_view.frustum[4].normal[1] = m[7] - m[6];
2186 r_view.frustum[4].normal[2] = m[11] - m[10];
2187 r_view.frustum[4].dist = m[15] - m[14];
2189 r_view.frustum[5].normal[0] = m[3] + m[2];
2190 r_view.frustum[5].normal[1] = m[7] + m[6];
2191 r_view.frustum[5].normal[2] = m[11] + m[10];
2192 r_view.frustum[5].dist = m[15] + m[14];
2197 if (r_view.useperspective)
2199 slopex = 1.0 / r_view.frustum_x;
2200 slopey = 1.0 / r_view.frustum_y;
2201 VectorMA(r_view.forward, -slopex, r_view.left, r_view.frustum[0].normal);
2202 VectorMA(r_view.forward, slopex, r_view.left, r_view.frustum[1].normal);
2203 VectorMA(r_view.forward, -slopey, r_view.up , r_view.frustum[2].normal);
2204 VectorMA(r_view.forward, slopey, r_view.up , r_view.frustum[3].normal);
2205 VectorCopy(r_view.forward, r_view.frustum[4].normal);
2207 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
2208 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, -1024 * slopex, r_view.left, -1024 * slopey, r_view.up, r_view.frustumcorner[0]);
2209 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, 1024 * slopex, r_view.left, -1024 * slopey, r_view.up, r_view.frustumcorner[1]);
2210 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, -1024 * slopex, r_view.left, 1024 * slopey, r_view.up, r_view.frustumcorner[2]);
2211 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, 1024 * slopex, r_view.left, 1024 * slopey, r_view.up, r_view.frustumcorner[3]);
2213 r_view.frustum[0].dist = DotProduct (r_view.origin, r_view.frustum[0].normal);
2214 r_view.frustum[1].dist = DotProduct (r_view.origin, r_view.frustum[1].normal);
2215 r_view.frustum[2].dist = DotProduct (r_view.origin, r_view.frustum[2].normal);
2216 r_view.frustum[3].dist = DotProduct (r_view.origin, r_view.frustum[3].normal);
2217 r_view.frustum[4].dist = DotProduct (r_view.origin, r_view.frustum[4].normal) + r_refdef.nearclip;
2221 VectorScale(r_view.left, -r_view.ortho_x, r_view.frustum[0].normal);
2222 VectorScale(r_view.left, r_view.ortho_x, r_view.frustum[1].normal);
2223 VectorScale(r_view.up, -r_view.ortho_y, r_view.frustum[2].normal);
2224 VectorScale(r_view.up, r_view.ortho_y, r_view.frustum[3].normal);
2225 VectorCopy(r_view.forward, r_view.frustum[4].normal);
2226 r_view.frustum[0].dist = DotProduct (r_view.origin, r_view.frustum[0].normal) + r_view.ortho_x;
2227 r_view.frustum[1].dist = DotProduct (r_view.origin, r_view.frustum[1].normal) + r_view.ortho_x;
2228 r_view.frustum[2].dist = DotProduct (r_view.origin, r_view.frustum[2].normal) + r_view.ortho_y;
2229 r_view.frustum[3].dist = DotProduct (r_view.origin, r_view.frustum[3].normal) + r_view.ortho_y;
2230 r_view.frustum[4].dist = DotProduct (r_view.origin, r_view.frustum[4].normal) + r_refdef.nearclip;
2232 r_view.numfrustumplanes = 5;
2234 if (r_view.useclipplane)
2236 r_view.numfrustumplanes = 6;
2237 r_view.frustum[5] = r_view.clipplane;
2240 for (i = 0;i < r_view.numfrustumplanes;i++)
2241 PlaneClassify(r_view.frustum + i);
2243 // LordHavoc: note to all quake engine coders, Quake had a special case
2244 // for 90 degrees which assumed a square view (wrong), so I removed it,
2245 // Quake2 has it disabled as well.
2247 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
2248 //RotatePointAroundVector( r_view.frustum[0].normal, r_view.up, r_view.forward, -(90 - r_refdef.fov_x / 2));
2249 //r_view.frustum[0].dist = DotProduct (r_view.origin, frustum[0].normal);
2250 //PlaneClassify(&frustum[0]);
2252 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
2253 //RotatePointAroundVector( r_view.frustum[1].normal, r_view.up, r_view.forward, (90 - r_refdef.fov_x / 2));
2254 //r_view.frustum[1].dist = DotProduct (r_view.origin, frustum[1].normal);
2255 //PlaneClassify(&frustum[1]);
2257 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
2258 //RotatePointAroundVector( r_view.frustum[2].normal, r_view.left, r_view.forward, -(90 - r_refdef.fov_y / 2));
2259 //r_view.frustum[2].dist = DotProduct (r_view.origin, frustum[2].normal);
2260 //PlaneClassify(&frustum[2]);
2262 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
2263 //RotatePointAroundVector( r_view.frustum[3].normal, r_view.left, r_view.forward, (90 - r_refdef.fov_y / 2));
2264 //r_view.frustum[3].dist = DotProduct (r_view.origin, frustum[3].normal);
2265 //PlaneClassify(&frustum[3]);
2268 //VectorCopy(r_view.forward, r_view.frustum[4].normal);
2269 //r_view.frustum[4].dist = DotProduct (r_view.origin, frustum[4].normal) + r_nearclip.value;
2270 //PlaneClassify(&frustum[4]);
2273 void R_View_Update(void)
2275 R_View_SetFrustum();
2276 R_View_WorldVisibility(r_view.useclipplane);
2277 R_View_UpdateEntityVisible();
2280 void R_SetupView(void)
2282 if (!r_view.useperspective)
2283 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);
2284 else if (r_refdef.rtworldshadows || r_refdef.rtdlightshadows)
2285 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_view.frustum_x, r_view.frustum_y, r_refdef.nearclip);
2287 GL_SetupView_Mode_Perspective(r_view.frustum_x, r_view.frustum_y, r_refdef.nearclip, r_refdef.farclip);
2289 GL_SetupView_Orientation_FromEntity(&r_view.matrix);
2291 if (r_view.useclipplane)
2293 // LordHavoc: couldn't figure out how to make this approach the
2294 vec_t dist = r_view.clipplane.dist - r_glsl_water_clippingplanebias.value;
2295 vec_t viewdist = DotProduct(r_view.origin, r_view.clipplane.normal);
2296 if (viewdist < r_view.clipplane.dist + r_glsl_water_clippingplanebias.value)
2297 dist = r_view.clipplane.dist;
2298 GL_SetupView_ApplyCustomNearClipPlane(r_view.clipplane.normal[0], r_view.clipplane.normal[1], r_view.clipplane.normal[2], dist);
2302 void R_ResetViewRendering2D(void)
2304 if (gl_support_fragment_shader)
2306 qglUseProgramObjectARB(0);CHECKGLERROR
2311 // GL is weird because it's bottom to top, r_view.y is top to bottom
2312 qglViewport(r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
2313 GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
2314 GL_Scissor(r_view.x, r_view.y, r_view.width, r_view.height);
2315 GL_Color(1, 1, 1, 1);
2316 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
2317 GL_BlendFunc(GL_ONE, GL_ZERO);
2318 GL_AlphaTest(false);
2319 GL_ScissorTest(false);
2320 GL_DepthMask(false);
2321 GL_DepthRange(0, 1);
2322 GL_DepthTest(false);
2323 R_Mesh_Matrix(&identitymatrix);
2324 R_Mesh_ResetTextureState();
2325 GL_PolygonOffset(0, 0);
2326 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
2327 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
2328 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
2329 qglStencilMask(~0);CHECKGLERROR
2330 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
2331 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
2332 GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
2335 void R_ResetViewRendering3D(void)
2337 if (gl_support_fragment_shader)
2339 qglUseProgramObjectARB(0);CHECKGLERROR
2344 // GL is weird because it's bottom to top, r_view.y is top to bottom
2345 qglViewport(r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
2347 GL_Scissor(r_view.x, r_view.y, r_view.width, r_view.height);
2348 GL_Color(1, 1, 1, 1);
2349 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
2350 GL_BlendFunc(GL_ONE, GL_ZERO);
2351 GL_AlphaTest(false);
2352 GL_ScissorTest(true);
2354 GL_DepthRange(0, 1);
2356 R_Mesh_Matrix(&identitymatrix);
2357 R_Mesh_ResetTextureState();
2358 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
2359 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
2360 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
2361 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
2362 qglStencilMask(~0);CHECKGLERROR
2363 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
2364 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
2365 GL_CullFace(r_view.cullface_back);
2369 R_Bloom_SetupShader(
2371 "// written by Forest 'LordHavoc' Hale\n"
2373 "// common definitions between vertex shader and fragment shader:\n"
2375 "#ifdef __GLSL_CG_DATA_TYPES\n"
2376 "#define myhalf half\n"
2377 "#define myhvec2 hvec2\n"
2378 "#define myhvec3 hvec3\n"
2379 "#define myhvec4 hvec4\n"
2381 "#define myhalf float\n"
2382 "#define myhvec2 vec2\n"
2383 "#define myhvec3 vec3\n"
2384 "#define myhvec4 vec4\n"
2387 "varying vec2 ScreenTexCoord;\n"
2388 "varying vec2 BloomTexCoord;\n"
2393 "// vertex shader specific:\n"
2394 "#ifdef VERTEX_SHADER\n"
2398 " ScreenTexCoord = vec2(gl_MultiTexCoord0);\n"
2399 " BloomTexCoord = vec2(gl_MultiTexCoord1);\n"
2400 " // transform vertex to camera space, using ftransform to match non-VS\n"
2402 " gl_Position = ftransform();\n"
2405 "#endif // VERTEX_SHADER\n"
2410 "// fragment shader specific:\n"
2411 "#ifdef FRAGMENT_SHADER\n"
2416 " myhvec3 color = myhvec3(texture2D(Texture_Screen, ScreenTexCoord));\n"
2417 " for (x = -BLUR_X;x <= BLUR_X;x++)
2418 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2419 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2420 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2421 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2423 " gl_FragColor = vec4(color);\n"
2426 "#endif // FRAGMENT_SHADER\n"
2429 void R_RenderScene(qboolean addwaterplanes);
2431 static void R_Water_StartFrame(void)
2434 int waterwidth, waterheight, texturewidth, textureheight;
2435 r_waterstate_waterplane_t *p;
2437 // set waterwidth and waterheight to the water resolution that will be
2438 // used (often less than the screen resolution for faster rendering)
2439 waterwidth = (int)bound(1, r_view.width * r_glsl_water_resolutionmultiplier.value, r_view.width);
2440 waterheight = (int)bound(1, r_view.height * r_glsl_water_resolutionmultiplier.value, r_view.height);
2442 // calculate desired texture sizes
2443 // can't use water if the card does not support the texture size
2444 if (!r_glsl_water.integer || waterwidth > gl_max_texture_size || waterheight > gl_max_texture_size)
2445 texturewidth = textureheight = waterwidth = waterheight = 0;
2446 else if (gl_support_arb_texture_non_power_of_two)
2448 texturewidth = waterwidth;
2449 textureheight = waterheight;
2453 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
2454 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
2457 // allocate textures as needed
2458 if (r_waterstate.waterwidth != waterwidth || r_waterstate.waterheight != waterheight || r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight)
2460 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
2461 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
2463 if (p->texture_refraction)
2464 R_FreeTexture(p->texture_refraction);
2465 p->texture_refraction = NULL;
2466 if (p->texture_reflection)
2467 R_FreeTexture(p->texture_reflection);
2468 p->texture_reflection = NULL;
2470 memset(&r_waterstate, 0, sizeof(r_waterstate));
2471 r_waterstate.waterwidth = waterwidth;
2472 r_waterstate.waterheight = waterheight;
2473 r_waterstate.texturewidth = texturewidth;
2474 r_waterstate.textureheight = textureheight;
2477 if (r_waterstate.waterwidth)
2479 r_waterstate.enabled = true;
2481 // set up variables that will be used in shader setup
2482 r_waterstate.screenscale[0] = 0.5f * (float)waterwidth / (float)texturewidth;
2483 r_waterstate.screenscale[1] = 0.5f * (float)waterheight / (float)textureheight;
2484 r_waterstate.screencenter[0] = 0.5f * (float)waterwidth / (float)texturewidth;
2485 r_waterstate.screencenter[1] = 0.5f * (float)waterheight / (float)textureheight;
2488 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
2489 r_waterstate.numwaterplanes = 0;
2492 static void R_Water_AddWaterPlane(msurface_t *surface)
2494 int triangleindex, planeindex;
2500 r_waterstate_waterplane_t *p;
2501 // just use the first triangle with a valid normal for any decisions
2502 VectorClear(normal);
2503 Vectorclear(center);
2504 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
2506 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
2507 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
2508 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
2509 TriangleNormal(vert[0], vert[1], vert[2], normal);
2510 if (VectorLength2(normal) >= 0.001)
2513 // now find the center of this surface
2514 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles*3;triangleindex++, e++)
2516 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
2517 VectorAdd(center, vert[0], center);
2519 f = 1.0 / surface->num_triangles*3;
2520 VectorScale(center, f, center);
2522 // find a matching plane if there is one
2523 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
2524 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
2526 if (planeindex >= r_waterstate.maxwaterplanes)
2527 return; // nothing we can do, out of planes
2529 // if this triangle does not fit any known plane rendered this frame, add one
2530 if (planeindex >= r_waterstate.numwaterplanes)
2532 // store the new plane
2533 r_waterstate.numwaterplanes++;
2534 VectorCopy(normal, p->plane.normal);
2535 VectorNormalize(p->plane.normal);
2536 p->plane.dist = DotProduct(vert[0], p->plane.normal);
2537 PlaneClassify(&p->plane);
2538 // flip the plane if it does not face the viewer
2539 if (PlaneDiff(r_view.origin, &p->plane) < 0)
2541 VectorNegate(p->plane.normal, p->plane.normal);
2542 p->plane.dist *= -1;
2543 PlaneClassify(&p->plane);
2545 // clear materialflags and pvs
2546 p->materialflags = 0;
2547 p->pvsvalid = false;
2549 // merge this surface's materialflags into the waterplane
2550 p->materialflags |= surface->texture->currentframe->currentmaterialflags;
2551 // merge this surface's PVS into the waterplane
2552 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION) && r_refdef.worldmodel && r_refdef.worldmodel->brush.FatPVS)
2554 r_refdef.worldmodel->brush.FatPVS(r_refdef.worldmodel, r_view.origin, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
2559 static void R_Water_ProcessPlanes(void)
2561 r_view_t originalview;
2563 r_waterstate_waterplane_t *p;
2565 originalview = r_view;
2567 // make sure enough textures are allocated
2568 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
2570 if (p->materialflags & MATERIALFLAG_WATERSHADER)
2572 if (!p->texture_refraction)
2573 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);
2574 if (!p->texture_refraction)
2578 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
2580 if (!p->texture_reflection)
2581 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);
2582 if (!p->texture_reflection)
2588 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
2590 r_view.showdebug = false;
2591 r_view.width = r_waterstate.waterwidth;
2592 r_view.height = r_waterstate.waterheight;
2593 r_view.useclipplane = true;
2594 r_waterstate.renderingscene = true;
2596 // render the normal view scene and copy into texture
2597 // (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)
2598 if (p->materialflags & MATERIALFLAG_WATERSHADER)
2600 r_view.clipplane = p->plane;
2601 VectorNegate(r_view.clipplane.normal, r_view.clipplane.normal);
2602 r_view.clipplane.dist = -r_view.clipplane.dist;
2603 PlaneClassify(&r_view.clipplane);
2605 R_RenderScene(false);
2607 // copy view into the screen texture
2608 R_Mesh_TexBind(0, R_GetTexture(p->texture_refraction));
2609 GL_ActiveTexture(0);
2611 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
2614 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
2616 // render reflected scene and copy into texture
2617 Matrix4x4_Reflect(&r_view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
2618 r_view.clipplane = p->plane;
2619 // reverse the cullface settings for this render
2620 r_view.cullface_front = GL_FRONT;
2621 r_view.cullface_back = GL_BACK;
2622 if (r_refdef.worldmodel && r_refdef.worldmodel->brush.num_pvsclusterbytes)
2624 r_view.usecustompvs = true;
2626 memcpy(r_viewcache.world_pvsbits, p->pvsbits, r_refdef.worldmodel->brush.num_pvsclusterbytes);
2628 memset(r_viewcache.world_pvsbits, 0xFF, r_refdef.worldmodel->brush.num_pvsclusterbytes);
2631 R_ResetViewRendering3D();
2634 R_RenderScene(false);
2636 R_Mesh_TexBind(0, R_GetTexture(p->texture_reflection));
2637 GL_ActiveTexture(0);
2639 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
2641 R_ResetViewRendering3D();
2645 r_view = originalview;
2646 r_waterstate.renderingscene = false;
2650 r_view = originalview;
2651 r_waterstate.renderingscene = false;
2652 Cvar_SetValueQuick(&r_glsl_water, 0);
2653 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_glsl_water.\n");
2657 void R_Bloom_StartFrame(void)
2659 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
2661 // set bloomwidth and bloomheight to the bloom resolution that will be
2662 // used (often less than the screen resolution for faster rendering)
2663 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_view.width);
2664 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_view.height / r_view.width;
2665 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_view.height);
2667 // calculate desired texture sizes
2668 if (gl_support_arb_texture_non_power_of_two)
2670 screentexturewidth = r_view.width;
2671 screentextureheight = r_view.height;
2672 bloomtexturewidth = r_bloomstate.bloomwidth;
2673 bloomtextureheight = r_bloomstate.bloomheight;
2677 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
2678 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
2679 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
2680 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
2685 screentexturewidth = screentextureheight = 0;
2687 else if (r_bloom.integer)
2692 screentexturewidth = screentextureheight = 0;
2693 bloomtexturewidth = bloomtextureheight = 0;
2696 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)
2698 // can't use bloom if the parameters are too weird
2699 // can't use bloom if the card does not support the texture size
2700 if (r_bloomstate.texture_screen)
2701 R_FreeTexture(r_bloomstate.texture_screen);
2702 if (r_bloomstate.texture_bloom)
2703 R_FreeTexture(r_bloomstate.texture_bloom);
2704 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
2708 r_bloomstate.enabled = true;
2709 r_bloomstate.hdr = r_hdr.integer != 0;
2711 // allocate textures as needed
2712 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
2714 if (r_bloomstate.texture_screen)
2715 R_FreeTexture(r_bloomstate.texture_screen);
2716 r_bloomstate.texture_screen = NULL;
2717 r_bloomstate.screentexturewidth = screentexturewidth;
2718 r_bloomstate.screentextureheight = screentextureheight;
2719 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
2720 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);
2722 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
2724 if (r_bloomstate.texture_bloom)
2725 R_FreeTexture(r_bloomstate.texture_bloom);
2726 r_bloomstate.texture_bloom = NULL;
2727 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
2728 r_bloomstate.bloomtextureheight = bloomtextureheight;
2729 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
2730 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);
2733 // set up a texcoord array for the full resolution screen image
2734 // (we have to keep this around to copy back during final render)
2735 r_bloomstate.screentexcoord2f[0] = 0;
2736 r_bloomstate.screentexcoord2f[1] = (float)r_view.height / (float)r_bloomstate.screentextureheight;
2737 r_bloomstate.screentexcoord2f[2] = (float)r_view.width / (float)r_bloomstate.screentexturewidth;
2738 r_bloomstate.screentexcoord2f[3] = (float)r_view.height / (float)r_bloomstate.screentextureheight;
2739 r_bloomstate.screentexcoord2f[4] = (float)r_view.width / (float)r_bloomstate.screentexturewidth;
2740 r_bloomstate.screentexcoord2f[5] = 0;
2741 r_bloomstate.screentexcoord2f[6] = 0;
2742 r_bloomstate.screentexcoord2f[7] = 0;
2744 // set up a texcoord array for the reduced resolution bloom image
2745 // (which will be additive blended over the screen image)
2746 r_bloomstate.bloomtexcoord2f[0] = 0;
2747 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
2748 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
2749 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
2750 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
2751 r_bloomstate.bloomtexcoord2f[5] = 0;
2752 r_bloomstate.bloomtexcoord2f[6] = 0;
2753 r_bloomstate.bloomtexcoord2f[7] = 0;
2756 void R_Bloom_CopyScreenTexture(float colorscale)
2758 r_refdef.stats.bloom++;
2760 R_ResetViewRendering2D();
2761 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
2762 R_Mesh_ColorPointer(NULL, 0, 0);
2763 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
2764 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
2766 // copy view into the screen texture
2767 GL_ActiveTexture(0);
2769 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
2770 r_refdef.stats.bloom_copypixels += r_view.width * r_view.height;
2772 // now scale it down to the bloom texture size
2774 qglViewport(r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
2775 GL_BlendFunc(GL_ONE, GL_ZERO);
2776 GL_Color(colorscale, colorscale, colorscale, 1);
2777 // TODO: optimize with multitexture or GLSL
2778 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2779 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2781 // we now have a bloom image in the framebuffer
2782 // copy it into the bloom image texture for later processing
2783 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2784 GL_ActiveTexture(0);
2786 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
2787 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2790 void R_Bloom_CopyHDRTexture(void)
2792 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2793 GL_ActiveTexture(0);
2795 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
2796 r_refdef.stats.bloom_copypixels += r_view.width * r_view.height;
2799 void R_Bloom_MakeTexture(void)
2802 float xoffset, yoffset, r, brighten;
2804 r_refdef.stats.bloom++;
2806 R_ResetViewRendering2D();
2807 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
2808 R_Mesh_ColorPointer(NULL, 0, 0);
2810 // we have a bloom image in the framebuffer
2812 qglViewport(r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
2814 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
2817 r = bound(0, r_bloom_colorexponent.value / x, 1);
2818 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
2819 GL_Color(r, r, r, 1);
2820 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2821 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
2822 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2823 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2825 // copy the vertically blurred bloom view to a texture
2826 GL_ActiveTexture(0);
2828 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
2829 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2832 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
2833 brighten = r_bloom_brighten.value;
2835 brighten *= r_hdr_range.value;
2836 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2837 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
2839 for (dir = 0;dir < 2;dir++)
2841 // blend on at multiple vertical offsets to achieve a vertical blur
2842 // TODO: do offset blends using GLSL
2843 GL_BlendFunc(GL_ONE, GL_ZERO);
2844 for (x = -range;x <= range;x++)
2846 if (!dir){xoffset = 0;yoffset = x;}
2847 else {xoffset = x;yoffset = 0;}
2848 xoffset /= (float)r_bloomstate.bloomtexturewidth;
2849 yoffset /= (float)r_bloomstate.bloomtextureheight;
2850 // compute a texcoord array with the specified x and y offset
2851 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
2852 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
2853 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
2854 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
2855 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
2856 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
2857 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
2858 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
2859 // this r value looks like a 'dot' particle, fading sharply to
2860 // black at the edges
2861 // (probably not realistic but looks good enough)
2862 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
2863 //r = (dir ? 1.0f : brighten)/(range*2+1);
2864 r = (dir ? 1.0f : brighten)/(range*2+1)*(1 - x*x/(float)(range*range));
2865 GL_Color(r, r, r, 1);
2866 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2867 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2868 GL_BlendFunc(GL_ONE, GL_ONE);
2871 // copy the vertically blurred bloom view to a texture
2872 GL_ActiveTexture(0);
2874 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
2875 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2878 // apply subtract last
2879 // (just like it would be in a GLSL shader)
2880 if (r_bloom_colorsubtract.value > 0 && gl_support_ext_blend_subtract)
2882 GL_BlendFunc(GL_ONE, GL_ZERO);
2883 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2884 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
2885 GL_Color(1, 1, 1, 1);
2886 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2887 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2889 GL_BlendFunc(GL_ONE, GL_ONE);
2890 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
2891 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2892 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
2893 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
2894 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2895 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2896 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
2898 // copy the darkened bloom view to a texture
2899 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2900 GL_ActiveTexture(0);
2902 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
2903 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2907 void R_HDR_RenderBloomTexture(void)
2909 int oldwidth, oldheight;
2911 oldwidth = r_view.width;
2912 oldheight = r_view.height;
2913 r_view.width = r_bloomstate.bloomwidth;
2914 r_view.height = r_bloomstate.bloomheight;
2916 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
2917 // TODO: add exposure compensation features
2918 // TODO: add fp16 framebuffer support
2920 r_view.showdebug = false;
2921 r_view.colorscale = r_bloom_colorscale.value * r_hdr_scenebrightness.value;
2923 r_view.colorscale /= r_hdr_range.value;
2924 r_waterstate.numwaterplanes = 0;
2925 R_RenderScene(r_waterstate.enabled);
2926 r_view.showdebug = true;
2928 R_ResetViewRendering2D();
2930 R_Bloom_CopyHDRTexture();
2931 R_Bloom_MakeTexture();
2933 R_ResetViewRendering3D();
2936 if (r_timereport_active)
2937 R_TimeReport("clear");
2940 // restore the view settings
2941 r_view.width = oldwidth;
2942 r_view.height = oldheight;
2945 static void R_BlendView(void)
2947 if (r_bloomstate.enabled && r_bloomstate.hdr)
2949 // render high dynamic range bloom effect
2950 // the bloom texture was made earlier this render, so we just need to
2951 // blend it onto the screen...
2952 R_ResetViewRendering2D();
2953 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
2954 R_Mesh_ColorPointer(NULL, 0, 0);
2955 GL_Color(1, 1, 1, 1);
2956 GL_BlendFunc(GL_ONE, GL_ONE);
2957 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2958 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
2959 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2960 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
2962 else if (r_bloomstate.enabled)
2964 // render simple bloom effect
2965 // copy the screen and shrink it and darken it for the bloom process
2966 R_Bloom_CopyScreenTexture(r_bloom_colorscale.value);
2967 // make the bloom texture
2968 R_Bloom_MakeTexture();
2969 // put the original screen image back in place and blend the bloom
2971 R_ResetViewRendering2D();
2972 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
2973 R_Mesh_ColorPointer(NULL, 0, 0);
2974 GL_Color(1, 1, 1, 1);
2975 GL_BlendFunc(GL_ONE, GL_ZERO);
2976 // do both in one pass if possible
2977 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
2978 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
2979 if (r_textureunits.integer >= 2 && gl_combine.integer)
2981 R_Mesh_TexCombine(1, GL_ADD, GL_ADD, 1, 1);
2982 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_screen));
2983 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.screentexcoord2f, 0, 0);
2987 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2988 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
2989 // now blend on the bloom texture
2990 GL_BlendFunc(GL_ONE, GL_ONE);
2991 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
2992 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
2994 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2995 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
2997 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
2999 // apply a color tint to the whole view
3000 R_ResetViewRendering2D();
3001 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3002 R_Mesh_ColorPointer(NULL, 0, 0);
3003 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3004 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
3005 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3009 void R_RenderScene(qboolean addwaterplanes);
3011 matrix4x4_t r_waterscrollmatrix;
3013 void R_UpdateVariables(void)
3017 r_refdef.farclip = 4096;
3018 if (r_refdef.worldmodel)
3019 r_refdef.farclip += VectorDistance(r_refdef.worldmodel->normalmins, r_refdef.worldmodel->normalmaxs);
3020 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
3022 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
3023 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
3024 r_refdef.polygonfactor = 0;
3025 r_refdef.polygonoffset = 0;
3026 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
3027 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
3029 r_refdef.rtworld = r_shadow_realtime_world.integer;
3030 r_refdef.rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
3031 r_refdef.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
3032 r_refdef.rtdlightshadows = r_refdef.rtdlight && r_shadow_realtime_dlight_shadows.integer && gl_stencil;
3033 r_refdef.lightmapintensity = r_refdef.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
3034 if (r_showsurfaces.integer)
3036 r_refdef.rtworld = false;
3037 r_refdef.rtworldshadows = false;
3038 r_refdef.rtdlight = false;
3039 r_refdef.rtdlightshadows = false;
3040 r_refdef.lightmapintensity = 0;
3043 if (gamemode == GAME_NEHAHRA)
3045 if (gl_fogenable.integer)
3047 r_refdef.oldgl_fogenable = true;
3048 r_refdef.fog_density = gl_fogdensity.value;
3049 r_refdef.fog_red = gl_fogred.value;
3050 r_refdef.fog_green = gl_foggreen.value;
3051 r_refdef.fog_blue = gl_fogblue.value;
3053 else if (r_refdef.oldgl_fogenable)
3055 r_refdef.oldgl_fogenable = false;
3056 r_refdef.fog_density = 0;
3057 r_refdef.fog_red = 0;
3058 r_refdef.fog_green = 0;
3059 r_refdef.fog_blue = 0;
3062 if (r_refdef.fog_density)
3064 r_refdef.fogcolor[0] = bound(0.0f, r_refdef.fog_red , 1.0f);
3065 r_refdef.fogcolor[1] = bound(0.0f, r_refdef.fog_green, 1.0f);
3066 r_refdef.fogcolor[2] = bound(0.0f, r_refdef.fog_blue , 1.0f);
3068 if (r_refdef.fog_density)
3070 r_refdef.fogenabled = true;
3071 // this is the point where the fog reaches 0.9986 alpha, which we
3072 // consider a good enough cutoff point for the texture
3073 // (0.9986 * 256 == 255.6)
3074 r_refdef.fogrange = 400 / r_refdef.fog_density;
3075 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
3076 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
3077 // fog color was already set
3080 r_refdef.fogenabled = false;
3088 void R_RenderView(void)
3090 if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
3091 return; //Host_Error ("R_RenderView: NULL worldmodel");
3093 R_Shadow_UpdateWorldLightSelection();
3095 R_Bloom_StartFrame();
3096 R_Water_StartFrame();
3099 if (r_timereport_active)
3100 R_TimeReport("setup");
3102 R_ResetViewRendering3D();
3105 if (r_timereport_active)
3106 R_TimeReport("clear");
3108 r_view.showdebug = true;
3110 // this produces a bloom texture to be used in R_BlendView() later
3112 R_HDR_RenderBloomTexture();
3114 r_view.colorscale = r_hdr_scenebrightness.value;
3115 r_waterstate.numwaterplanes = 0;
3116 R_RenderScene(r_waterstate.enabled);
3119 if (r_timereport_active)
3120 R_TimeReport("blendview");
3122 GL_Scissor(0, 0, vid.width, vid.height);
3123 GL_ScissorTest(false);
3127 extern void R_DrawLightningBeams (void);
3128 extern void VM_CL_AddPolygonsToMeshQueue (void);
3129 extern void R_DrawPortals (void);
3130 extern cvar_t cl_locs_show;
3131 static void R_DrawLocs(void);
3132 static void R_DrawEntityBBoxes(void);
3133 void R_RenderScene(qboolean addwaterplanes)
3137 R_ResetViewRendering3D();
3140 if (r_timereport_active)
3141 R_TimeReport("watervisibility");
3143 if (cl.csqc_vidvars.drawworld && r_refdef.worldmodel && r_refdef.worldmodel->DrawAddWaterPlanes)
3145 r_refdef.worldmodel->DrawAddWaterPlanes(r_refdef.worldentity);
3146 if (r_timereport_active)
3147 R_TimeReport("waterworld");
3150 // don't let sound skip if going slow
3151 if (r_refdef.extraupdate)
3154 R_DrawModelsAddWaterPlanes();
3155 if (r_timereport_active)
3156 R_TimeReport("watermodels");
3158 R_Water_ProcessPlanes();
3159 if (r_timereport_active)
3160 R_TimeReport("waterscenes");
3163 R_ResetViewRendering3D();
3165 // don't let sound skip if going slow
3166 if (r_refdef.extraupdate)
3169 R_MeshQueue_BeginScene();
3174 if (r_timereport_active)
3175 R_TimeReport("visibility");
3177 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);
3179 if (cl.csqc_vidvars.drawworld)
3181 // don't let sound skip if going slow
3182 if (r_refdef.extraupdate)
3185 if (r_refdef.worldmodel && r_refdef.worldmodel->DrawSky)
3187 r_refdef.worldmodel->DrawSky(r_refdef.worldentity);
3188 if (r_timereport_active)
3189 R_TimeReport("worldsky");
3192 if (R_DrawBrushModelsSky() && r_timereport_active)
3193 R_TimeReport("bmodelsky");
3196 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.worldmodel && r_refdef.worldmodel->DrawDepth)
3198 r_refdef.worldmodel->DrawDepth(r_refdef.worldentity);
3199 if (r_timereport_active)
3200 R_TimeReport("worlddepth");
3202 if (r_depthfirst.integer >= 2)
3204 R_DrawModelsDepth();
3205 if (r_timereport_active)
3206 R_TimeReport("modeldepth");
3209 if (cl.csqc_vidvars.drawworld && r_refdef.worldmodel && r_refdef.worldmodel->Draw)
3211 r_refdef.worldmodel->Draw(r_refdef.worldentity);
3212 if (r_timereport_active)
3213 R_TimeReport("world");
3216 // don't let sound skip if going slow
3217 if (r_refdef.extraupdate)
3221 if (r_timereport_active)
3222 R_TimeReport("models");
3224 // don't let sound skip if going slow
3225 if (r_refdef.extraupdate)
3228 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
3230 R_DrawModelShadows();
3232 R_ResetViewRendering3D();
3234 // don't let sound skip if going slow
3235 if (r_refdef.extraupdate)
3239 R_ShadowVolumeLighting(false);
3240 if (r_timereport_active)
3241 R_TimeReport("rtlights");
3243 // don't let sound skip if going slow
3244 if (r_refdef.extraupdate)
3247 if (cl.csqc_vidvars.drawworld)
3249 R_DrawLightningBeams();
3250 if (r_timereport_active)
3251 R_TimeReport("lightning");
3254 if (r_timereport_active)
3255 R_TimeReport("particles");
3258 if (r_timereport_active)
3259 R_TimeReport("explosions");
3262 if (gl_support_fragment_shader)
3264 qglUseProgramObjectARB(0);CHECKGLERROR
3266 VM_CL_AddPolygonsToMeshQueue();
3268 if (r_view.showdebug)
3270 if (cl_locs_show.integer)
3273 if (r_timereport_active)
3274 R_TimeReport("showlocs");
3277 if (r_drawportals.integer)
3280 if (r_timereport_active)
3281 R_TimeReport("portals");
3284 if (r_showbboxes.value > 0)
3286 R_DrawEntityBBoxes();
3287 if (r_timereport_active)
3288 R_TimeReport("bboxes");
3292 if (gl_support_fragment_shader)
3294 qglUseProgramObjectARB(0);CHECKGLERROR
3296 R_MeshQueue_RenderTransparent();
3297 if (r_timereport_active)
3298 R_TimeReport("drawtrans");
3300 if (gl_support_fragment_shader)
3302 qglUseProgramObjectARB(0);CHECKGLERROR
3305 if (r_view.showdebug && r_refdef.worldmodel && r_refdef.worldmodel->DrawDebug && (r_showtris.value > 0 || r_shownormals.value > 0 || r_showcollisionbrushes.value > 0))
3307 r_refdef.worldmodel->DrawDebug(r_refdef.worldentity);
3308 if (r_timereport_active)
3309 R_TimeReport("worlddebug");
3310 R_DrawModelsDebug();
3311 if (r_timereport_active)
3312 R_TimeReport("modeldebug");
3315 if (gl_support_fragment_shader)
3317 qglUseProgramObjectARB(0);CHECKGLERROR
3320 if (cl.csqc_vidvars.drawworld)
3323 if (r_timereport_active)
3324 R_TimeReport("coronas");
3327 // don't let sound skip if going slow
3328 if (r_refdef.extraupdate)
3331 R_ResetViewRendering2D();
3334 static const int bboxelements[36] =
3344 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
3347 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
3348 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3349 GL_DepthMask(false);
3350 GL_DepthRange(0, 1);
3351 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3352 R_Mesh_Matrix(&identitymatrix);
3353 R_Mesh_ResetTextureState();
3355 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
3356 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
3357 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
3358 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
3359 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
3360 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
3361 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
3362 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
3363 R_FillColors(color4f, 8, cr, cg, cb, ca);
3364 if (r_refdef.fogenabled)
3366 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
3368 f1 = FogPoint_World(v);
3370 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
3371 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
3372 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
3375 R_Mesh_VertexPointer(vertex3f, 0, 0);
3376 R_Mesh_ColorPointer(color4f, 0, 0);
3377 R_Mesh_ResetTextureState();
3378 R_Mesh_Draw(0, 8, 12, bboxelements, 0, 0);
3381 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
3385 prvm_edict_t *edict;
3386 // this function draws bounding boxes of server entities
3390 for (i = 0;i < numsurfaces;i++)
3392 edict = PRVM_EDICT_NUM(surfacelist[i]);
3393 switch ((int)edict->fields.server->solid)
3395 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
3396 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
3397 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
3398 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
3399 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
3400 default: Vector4Set(color, 0, 0, 0, 0.50);break;
3402 color[3] *= r_showbboxes.value;
3403 color[3] = bound(0, color[3], 1);
3404 GL_DepthTest(!r_showdisabledepthtest.integer);
3405 GL_CullFace(r_view.cullface_front);
3406 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
3411 static void R_DrawEntityBBoxes(void)
3414 prvm_edict_t *edict;
3416 // this function draws bounding boxes of server entities
3420 for (i = 0;i < prog->num_edicts;i++)
3422 edict = PRVM_EDICT_NUM(i);
3423 if (edict->priv.server->free)
3425 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
3426 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
3431 int nomodelelements[24] =
3443 float nomodelvertex3f[6*3] =
3453 float nomodelcolor4f[6*4] =
3455 0.0f, 0.0f, 0.5f, 1.0f,
3456 0.0f, 0.0f, 0.5f, 1.0f,
3457 0.0f, 0.5f, 0.0f, 1.0f,
3458 0.0f, 0.5f, 0.0f, 1.0f,
3459 0.5f, 0.0f, 0.0f, 1.0f,
3460 0.5f, 0.0f, 0.0f, 1.0f
3463 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
3468 // this is only called once per entity so numsurfaces is always 1, and
3469 // surfacelist is always {0}, so this code does not handle batches
3470 R_Mesh_Matrix(&ent->matrix);
3472 if (ent->flags & EF_ADDITIVE)
3474 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
3475 GL_DepthMask(false);
3477 else if (ent->alpha < 1)
3479 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3480 GL_DepthMask(false);
3484 GL_BlendFunc(GL_ONE, GL_ZERO);
3487 GL_DepthRange(0, (ent->flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
3488 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3489 GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
3490 GL_CullFace((ent->effects & EF_DOUBLESIDED) ? GL_NONE : r_view.cullface_back);
3491 R_Mesh_VertexPointer(nomodelvertex3f, 0, 0);
3492 if (r_refdef.fogenabled)
3495 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
3496 R_Mesh_ColorPointer(color4f, 0, 0);
3497 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
3498 f1 = FogPoint_World(org);
3500 for (i = 0, c = color4f;i < 6;i++, c += 4)
3502 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
3503 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
3504 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
3508 else if (ent->alpha != 1)
3510 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
3511 R_Mesh_ColorPointer(color4f, 0, 0);
3512 for (i = 0, c = color4f;i < 6;i++, c += 4)
3516 R_Mesh_ColorPointer(nomodelcolor4f, 0, 0);
3517 R_Mesh_ResetTextureState();
3518 R_Mesh_Draw(0, 6, 8, nomodelelements, 0, 0);
3521 void R_DrawNoModel(entity_render_t *ent)
3524 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
3525 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
3526 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
3528 // R_DrawNoModelCallback(ent, 0);
3531 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
3533 vec3_t right1, right2, diff, normal;
3535 VectorSubtract (org2, org1, normal);
3537 // calculate 'right' vector for start
3538 VectorSubtract (r_view.origin, org1, diff);
3539 CrossProduct (normal, diff, right1);
3540 VectorNormalize (right1);
3542 // calculate 'right' vector for end
3543 VectorSubtract (r_view.origin, org2, diff);
3544 CrossProduct (normal, diff, right2);
3545 VectorNormalize (right2);
3547 vert[ 0] = org1[0] + width * right1[0];
3548 vert[ 1] = org1[1] + width * right1[1];
3549 vert[ 2] = org1[2] + width * right1[2];
3550 vert[ 3] = org1[0] - width * right1[0];
3551 vert[ 4] = org1[1] - width * right1[1];
3552 vert[ 5] = org1[2] - width * right1[2];
3553 vert[ 6] = org2[0] - width * right2[0];
3554 vert[ 7] = org2[1] - width * right2[1];
3555 vert[ 8] = org2[2] - width * right2[2];
3556 vert[ 9] = org2[0] + width * right2[0];
3557 vert[10] = org2[1] + width * right2[1];
3558 vert[11] = org2[2] + width * right2[2];
3561 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
3563 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)
3568 if (r_refdef.fogenabled)
3569 fog = FogPoint_World(origin);
3571 R_Mesh_Matrix(&identitymatrix);
3572 GL_BlendFunc(blendfunc1, blendfunc2);
3578 GL_CullFace(r_view.cullface_front);
3581 GL_CullFace(r_view.cullface_back);
3583 GL_DepthMask(false);
3584 GL_DepthRange(0, depthshort ? 0.0625 : 1);
3585 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3586 GL_DepthTest(!depthdisable);
3588 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
3589 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
3590 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
3591 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
3592 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
3593 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
3594 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
3595 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
3596 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
3597 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
3598 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
3599 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
3601 R_Mesh_VertexPointer(vertex3f, 0, 0);
3602 R_Mesh_ColorPointer(NULL, 0, 0);
3603 R_Mesh_ResetTextureState();
3604 R_Mesh_TexBind(0, R_GetTexture(texture));
3605 R_Mesh_TexCoordPointer(0, 2, spritetexcoord2f, 0, 0);
3606 // FIXME: fixed function path can't properly handle r_view.colorscale > 1
3607 GL_Color(cr * fog * r_view.colorscale, cg * fog * r_view.colorscale, cb * fog * r_view.colorscale, ca);
3608 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3610 if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
3612 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
3613 GL_BlendFunc(blendfunc1, GL_ONE);
3615 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);
3616 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3620 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
3625 VectorSet(v, x, y, z);
3626 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
3627 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
3629 if (i == mesh->numvertices)
3631 if (mesh->numvertices < mesh->maxvertices)
3633 VectorCopy(v, vertex3f);
3634 mesh->numvertices++;
3636 return mesh->numvertices;
3642 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
3646 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
3647 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
3648 e = mesh->element3i + mesh->numtriangles * 3;
3649 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
3651 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
3652 if (mesh->numtriangles < mesh->maxtriangles)
3657 mesh->numtriangles++;
3659 element[1] = element[2];
3663 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
3667 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
3668 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
3669 e = mesh->element3i + mesh->numtriangles * 3;
3670 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
3672 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
3673 if (mesh->numtriangles < mesh->maxtriangles)
3678 mesh->numtriangles++;
3680 element[1] = element[2];
3684 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
3685 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
3687 int planenum, planenum2;
3690 mplane_t *plane, *plane2;
3692 double temppoints[2][256*3];
3693 // figure out how large a bounding box we need to properly compute this brush
3695 for (w = 0;w < numplanes;w++)
3696 maxdist = max(maxdist, planes[w].dist);
3697 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
3698 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
3699 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
3703 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
3704 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
3706 if (planenum2 == planenum)
3708 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);
3711 if (tempnumpoints < 3)
3713 // generate elements forming a triangle fan for this polygon
3714 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
3718 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)
3720 texturelayer_t *layer;
3721 layer = t->currentlayers + t->currentnumlayers++;
3723 layer->depthmask = depthmask;
3724 layer->blendfunc1 = blendfunc1;
3725 layer->blendfunc2 = blendfunc2;
3726 layer->texture = texture;
3727 layer->texmatrix = *matrix;
3728 layer->color[0] = r * r_view.colorscale;
3729 layer->color[1] = g * r_view.colorscale;
3730 layer->color[2] = b * r_view.colorscale;
3731 layer->color[3] = a;
3734 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
3737 index = parms[2] + r_refdef.time * parms[3];
3738 index -= floor(index);
3742 case Q3WAVEFUNC_NONE:
3743 case Q3WAVEFUNC_NOISE:
3744 case Q3WAVEFUNC_COUNT:
3747 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
3748 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
3749 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
3750 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
3751 case Q3WAVEFUNC_TRIANGLE:
3753 f = index - floor(index);
3764 return (float)(parms[0] + parms[1] * f);
3767 void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
3770 model_t *model = ent->model;
3773 q3shaderinfo_layer_tcmod_t *tcmod;
3775 // switch to an alternate material if this is a q1bsp animated material
3777 texture_t *texture = t;
3778 int s = ent->skinnum;
3779 if ((unsigned int)s >= (unsigned int)model->numskins)
3781 if (model->skinscenes)
3783 if (model->skinscenes[s].framecount > 1)
3784 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
3786 s = model->skinscenes[s].firstframe;
3789 t = t + s * model->num_surfaces;
3792 // use an alternate animation if the entity's frame is not 0,
3793 // and only if the texture has an alternate animation
3794 if (ent->frame2 != 0 && t->anim_total[1])
3795 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.time * 5.0f) % t->anim_total[1]) : 0];
3797 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.time * 5.0f) % t->anim_total[0]) : 0];
3799 texture->currentframe = t;
3802 // update currentskinframe to be a qw skin or animation frame
3803 if ((i = ent->entitynumber - 1) >= 0 && i < cl.maxclients)
3805 if (strcmp(r_qwskincache[i], cl.scores[i].qw_skin))
3807 strlcpy(r_qwskincache[i], cl.scores[i].qw_skin, sizeof(r_qwskincache[i]));
3808 Con_DPrintf("loading skins/%s\n", r_qwskincache[i]);
3809 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);
3811 t->currentskinframe = r_qwskincache_skinframe[i];
3812 if (t->currentskinframe == NULL)
3813 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->frame2time)) % t->numskinframes];
3815 else if (t->numskinframes >= 2)
3816 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->frame2time)) % t->numskinframes];
3817 if (t->backgroundnumskinframes >= 2)
3818 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - ent->frame2time)) % t->backgroundnumskinframes];
3820 t->currentmaterialflags = t->basematerialflags;
3821 t->currentalpha = ent->alpha;
3822 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
3824 t->currentalpha *= r_wateralpha.value;
3826 * FIXME what is this supposed to do?
3827 // if rendering refraction/reflection, disable transparency
3828 if (r_waterstate.enabled && (t->currentalpha < 1 || (t->currentmaterialflags & MATERIALFLAG_ALPHA)))
3829 t->currentmaterialflags |= MATERIALFLAG_WATERSHADER;
3832 if(!r_waterstate.enabled)
3834 t->currentmaterialflags &= ~MATERIALFLAG_WATERSHADER;
3835 t->currentmaterialflags &= ~MATERIALFLAG_REFLECTION;
3837 if (!(ent->flags & RENDER_LIGHT))
3838 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
3839 if (ent->effects & EF_ADDITIVE)
3840 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
3841 else if (t->currentalpha < 1)
3842 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
3843 if (ent->effects & EF_DOUBLESIDED)
3844 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
3845 if (ent->effects & EF_NODEPTHTEST)
3846 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
3847 if (ent->flags & RENDER_VIEWMODEL)
3848 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
3849 if (t->backgroundnumskinframes && !(t->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED))
3850 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
3851 if (t->currentmaterialflags & MATERIALFLAG_WATERSHADER)
3852 t->currentmaterialflags &= ~(MATERIALFLAG_ADD | MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_CUSTOMBLEND);
3854 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && (tcmod->tcmod || i < 1);i++, tcmod++)
3857 switch(tcmod->tcmod)
3861 if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
3862 matrix = r_waterscrollmatrix;
3864 matrix = identitymatrix;
3866 case Q3TCMOD_ENTITYTRANSLATE:
3867 // this is used in Q3 to allow the gamecode to control texcoord
3868 // scrolling on the entity, which is not supported in darkplaces yet.
3869 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
3871 case Q3TCMOD_ROTATE:
3872 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
3873 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.time, 0, 0, 1);
3874 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
3877 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
3879 case Q3TCMOD_SCROLL:
3880 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.time, tcmod->parms[1] * r_refdef.time, 0);
3882 case Q3TCMOD_STRETCH:
3883 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
3884 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
3886 case Q3TCMOD_TRANSFORM:
3887 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
3888 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
3889 VectorSet(tcmat + 6, 0 , 0 , 1);
3890 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
3891 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
3893 case Q3TCMOD_TURBULENT:
3894 // this is handled in the RSurf_PrepareVertices function
3895 matrix = identitymatrix;
3898 // either replace or concatenate the transformation
3900 t->currenttexmatrix = matrix;
3903 matrix4x4_t temp = t->currenttexmatrix;
3904 Matrix4x4_Concat(&t->currenttexmatrix, &matrix, &temp);
3908 t->colormapping = VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f);
3909 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
3910 t->glosstexture = r_texture_black;
3911 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
3912 t->backgroundglosstexture = r_texture_black;
3913 t->specularpower = r_shadow_glossexponent.value;
3914 // TODO: store reference values for these in the texture?
3915 t->specularscale = 0;
3916 if (r_shadow_gloss.integer > 0)
3918 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
3920 if (r_shadow_glossintensity.value > 0)
3922 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
3923 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
3924 t->specularscale = r_shadow_glossintensity.value;
3927 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
3929 t->glosstexture = r_texture_white;
3930 t->backgroundglosstexture = r_texture_white;
3931 t->specularscale = r_shadow_gloss2intensity.value;
3935 // lightmaps mode looks bad with dlights using actual texturing, so turn
3936 // off the colormap and glossmap, but leave the normalmap on as it still
3937 // accurately represents the shading involved
3938 if (gl_lightmaps.integer && !(t->currentmaterialflags & MATERIALFLAG_BLENDED))
3940 t->basetexture = r_texture_white;
3941 t->specularscale = 0;
3944 t->currentpolygonfactor = r_refdef.polygonfactor + t->basepolygonfactor;
3945 t->currentpolygonoffset = r_refdef.polygonoffset + t->basepolygonoffset;
3946 // submodels are biased to avoid z-fighting with world surfaces that they
3947 // may be exactly overlapping (avoids z-fighting artifacts on certain
3948 // doors and things in Quake maps)
3949 if (ent->model->brush.submodel)
3951 t->currentpolygonfactor += r_polygonoffset_submodel_factor.value;
3952 t->currentpolygonoffset += r_polygonoffset_submodel_offset.value;
3955 VectorClear(t->dlightcolor);
3956 t->currentnumlayers = 0;
3957 if (!(t->currentmaterialflags & MATERIALFLAG_NODRAW))
3959 if (!(t->currentmaterialflags & MATERIALFLAG_SKY))
3961 int blendfunc1, blendfunc2, depthmask;
3962 if (t->currentmaterialflags & MATERIALFLAG_ADD)
3964 blendfunc1 = GL_SRC_ALPHA;
3965 blendfunc2 = GL_ONE;
3967 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
3969 blendfunc1 = GL_SRC_ALPHA;
3970 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
3972 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
3974 blendfunc1 = t->customblendfunc[0];
3975 blendfunc2 = t->customblendfunc[1];
3979 blendfunc1 = GL_ONE;
3980 blendfunc2 = GL_ZERO;
3982 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
3983 if (t->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL))
3985 rtexture_t *currentbasetexture;
3987 if (r_refdef.fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED))
3988 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
3989 currentbasetexture = (VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) < (1.0f / 1048576.0f) && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
3990 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
3992 // fullbright is not affected by r_refdef.lightmapintensity
3993 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
3994 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
3995 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);
3996 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
3997 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);
4002 // set the color tint used for lights affecting this surface
4003 VectorSet(t->dlightcolor, ent->colormod[0] * t->currentalpha, ent->colormod[1] * t->currentalpha, ent->colormod[2] * t->currentalpha);
4005 // q3bsp has no lightmap updates, so the lightstylevalue that
4006 // would normally be baked into the lightmap must be
4007 // applied to the color
4008 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
4009 if (ent->model->type == mod_brushq3)
4010 colorscale *= r_refdef.lightstylevalue[0] * (1.0f / 256.0f);
4011 colorscale *= r_refdef.lightmapintensity;
4012 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);
4013 if (r_ambient.value >= (1.0f/64.0f))
4014 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);
4015 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
4017 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);
4018 if (r_ambient.value >= (1.0f/64.0f))
4019 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);
4021 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
4023 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);
4024 if (r_ambient.value >= (1.0f/64.0f))
4025 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);
4028 if (t->currentskinframe->glow != NULL)
4029 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);
4030 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
4032 // if this is opaque use alpha blend which will darken the earlier
4035 // if this is an alpha blended material, all the earlier passes
4036 // were darkened by fog already, so we only need to add the fog
4037 // color ontop through the fog mask texture
4039 // if this is an additive blended material, all the earlier passes
4040 // were darkened by fog already, and we should not add fog color
4041 // (because the background was not darkened, there is no fog color
4042 // that was lost behind it).
4043 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);
4050 void R_UpdateAllTextureInfo(entity_render_t *ent)
4054 for (i = 0;i < ent->model->num_texturesperskin;i++)
4055 R_UpdateTextureInfo(ent, ent->model->data_textures + i);
4058 rsurfacestate_t rsurface;
4060 void R_Mesh_ResizeArrays(int newvertices)
4063 if (rsurface.array_size >= newvertices)
4065 if (rsurface.array_modelvertex3f)
4066 Mem_Free(rsurface.array_modelvertex3f);
4067 rsurface.array_size = (newvertices + 1023) & ~1023;
4068 base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
4069 rsurface.array_modelvertex3f = base + rsurface.array_size * 0;
4070 rsurface.array_modelsvector3f = base + rsurface.array_size * 3;
4071 rsurface.array_modeltvector3f = base + rsurface.array_size * 6;
4072 rsurface.array_modelnormal3f = base + rsurface.array_size * 9;
4073 rsurface.array_deformedvertex3f = base + rsurface.array_size * 12;
4074 rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
4075 rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
4076 rsurface.array_deformednormal3f = base + rsurface.array_size * 21;
4077 rsurface.array_texcoord3f = base + rsurface.array_size * 24;
4078 rsurface.array_color4f = base + rsurface.array_size * 27;
4079 rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
4082 void RSurf_CleanUp(void)
4085 if (rsurface.mode == RSURFMODE_GLSL)
4087 qglUseProgramObjectARB(0);CHECKGLERROR
4089 GL_AlphaTest(false);
4090 rsurface.mode = RSURFMODE_NONE;
4091 rsurface.uselightmaptexture = false;
4092 rsurface.texture = NULL;
4095 void RSurf_ActiveWorldEntity(void)
4097 model_t *model = r_refdef.worldmodel;
4099 if (rsurface.array_size < model->surfmesh.num_vertices)
4100 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
4101 rsurface.matrix = identitymatrix;
4102 rsurface.inversematrix = identitymatrix;
4103 R_Mesh_Matrix(&identitymatrix);
4104 VectorCopy(r_view.origin, rsurface.modelorg);
4105 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
4106 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
4107 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
4108 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
4109 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
4110 rsurface.frameblend[0].frame = 0;
4111 rsurface.frameblend[0].lerp = 1;
4112 rsurface.frameblend[1].frame = 0;
4113 rsurface.frameblend[1].lerp = 0;
4114 rsurface.frameblend[2].frame = 0;
4115 rsurface.frameblend[2].lerp = 0;
4116 rsurface.frameblend[3].frame = 0;
4117 rsurface.frameblend[3].lerp = 0;
4118 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
4119 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
4120 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
4121 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
4122 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
4123 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
4124 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
4125 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
4126 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
4127 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
4128 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
4129 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
4130 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
4131 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
4132 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
4133 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
4134 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
4135 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
4136 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
4137 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
4138 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
4139 rsurface.modelelement3i = model->surfmesh.data_element3i;
4140 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo;
4141 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
4142 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
4143 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
4144 rsurface.modelsurfaces = model->data_surfaces;
4145 rsurface.generatedvertex = false;
4146 rsurface.vertex3f = rsurface.modelvertex3f;
4147 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
4148 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
4149 rsurface.svector3f = rsurface.modelsvector3f;
4150 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
4151 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
4152 rsurface.tvector3f = rsurface.modeltvector3f;
4153 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
4154 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
4155 rsurface.normal3f = rsurface.modelnormal3f;
4156 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
4157 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
4158 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
4161 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4163 model_t *model = ent->model;
4165 if (rsurface.array_size < model->surfmesh.num_vertices)
4166 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
4167 rsurface.matrix = ent->matrix;
4168 rsurface.inversematrix = ent->inversematrix;
4169 R_Mesh_Matrix(&rsurface.matrix);
4170 Matrix4x4_Transform(&rsurface.inversematrix, r_view.origin, rsurface.modelorg);
4171 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
4172 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
4173 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
4174 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
4175 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
4176 rsurface.frameblend[0] = ent->frameblend[0];
4177 rsurface.frameblend[1] = ent->frameblend[1];
4178 rsurface.frameblend[2] = ent->frameblend[2];
4179 rsurface.frameblend[3] = ent->frameblend[3];
4180 if (model->surfmesh.isanimated && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].frame != 0))
4184 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
4185 rsurface.modelsvector3f = rsurface.array_modelsvector3f;
4186 rsurface.modeltvector3f = rsurface.array_modeltvector3f;
4187 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
4188 Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
4190 else if (wantnormals)
4192 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
4193 rsurface.modelsvector3f = NULL;
4194 rsurface.modeltvector3f = NULL;
4195 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
4196 Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
4200 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
4201 rsurface.modelsvector3f = NULL;
4202 rsurface.modeltvector3f = NULL;
4203 rsurface.modelnormal3f = NULL;
4204 Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, NULL, NULL, NULL);
4206 rsurface.modelvertex3f_bufferobject = 0;
4207 rsurface.modelvertex3f_bufferoffset = 0;
4208 rsurface.modelsvector3f_bufferobject = 0;
4209 rsurface.modelsvector3f_bufferoffset = 0;
4210 rsurface.modeltvector3f_bufferobject = 0;
4211 rsurface.modeltvector3f_bufferoffset = 0;
4212 rsurface.modelnormal3f_bufferobject = 0;
4213 rsurface.modelnormal3f_bufferoffset = 0;
4214 rsurface.generatedvertex = true;
4218 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
4219 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
4220 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
4221 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
4222 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
4223 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
4224 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
4225 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
4226 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
4227 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
4228 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
4229 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
4230 rsurface.generatedvertex = false;
4232 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
4233 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
4234 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
4235 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
4236 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
4237 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
4238 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
4239 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
4240 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
4241 rsurface.modelelement3i = model->surfmesh.data_element3i;
4242 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo;
4243 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
4244 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
4245 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
4246 rsurface.modelsurfaces = model->data_surfaces;
4247 rsurface.vertex3f = rsurface.modelvertex3f;
4248 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
4249 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
4250 rsurface.svector3f = rsurface.modelsvector3f;
4251 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
4252 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
4253 rsurface.tvector3f = rsurface.modeltvector3f;
4254 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
4255 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
4256 rsurface.normal3f = rsurface.modelnormal3f;
4257 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
4258 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
4259 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
4262 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
4263 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, msurface_t **texturesurfacelist)
4266 int texturesurfaceindex;
4271 const float *v1, *in_tc;
4273 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
4275 q3shaderinfo_deform_t *deform;
4276 // 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
4277 if (rsurface.generatedvertex)
4279 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
4280 generatenormals = true;
4281 for (i = 0;i < Q3MAXDEFORMS;i++)
4283 if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
4285 generatetangents = true;
4286 generatenormals = true;
4288 if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
4289 generatenormals = true;
4291 if (generatenormals && !rsurface.modelnormal3f)
4293 rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
4294 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
4295 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
4296 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer);
4298 if (generatetangents && !rsurface.modelsvector3f)
4300 rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
4301 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
4302 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
4303 rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
4304 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
4305 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
4306 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);
4309 rsurface.vertex3f = rsurface.modelvertex3f;
4310 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
4311 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
4312 rsurface.svector3f = rsurface.modelsvector3f;
4313 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
4314 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
4315 rsurface.tvector3f = rsurface.modeltvector3f;
4316 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
4317 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
4318 rsurface.normal3f = rsurface.modelnormal3f;
4319 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
4320 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
4321 // if vertices are deformed (sprite flares and things in maps, possibly
4322 // water waves, bulges and other deformations), generate them into
4323 // rsurface.deform* arrays from whatever the rsurface.* arrays point to
4324 // (may be static model data or generated data for an animated model, or
4325 // the previous deform pass)
4326 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
4328 switch (deform->deform)
4331 case Q3DEFORM_PROJECTIONSHADOW:
4332 case Q3DEFORM_TEXT0:
4333 case Q3DEFORM_TEXT1:
4334 case Q3DEFORM_TEXT2:
4335 case Q3DEFORM_TEXT3:
4336 case Q3DEFORM_TEXT4:
4337 case Q3DEFORM_TEXT5:
4338 case Q3DEFORM_TEXT6:
4339 case Q3DEFORM_TEXT7:
4342 case Q3DEFORM_AUTOSPRITE:
4343 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.forward, newforward);
4344 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.right, newright);
4345 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.up, newup);
4346 VectorNormalize(newforward);
4347 VectorNormalize(newright);
4348 VectorNormalize(newup);
4349 // make deformed versions of only the model vertices used by the specified surfaces
4350 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4352 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4353 // a single autosprite surface can contain multiple sprites...
4354 for (j = 0;j < surface->num_vertices - 3;j += 4)
4356 VectorClear(center);
4357 for (i = 0;i < 4;i++)
4358 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
4359 VectorScale(center, 0.25f, center);
4360 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, forward);
4361 VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
4362 VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
4363 for (i = 0;i < 4;i++)
4365 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
4366 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
4369 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);
4370 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);
4372 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4373 rsurface.vertex3f_bufferobject = 0;
4374 rsurface.vertex3f_bufferoffset = 0;
4375 rsurface.svector3f = rsurface.array_deformedsvector3f;
4376 rsurface.svector3f_bufferobject = 0;
4377 rsurface.svector3f_bufferoffset = 0;
4378 rsurface.tvector3f = rsurface.array_deformedtvector3f;
4379 rsurface.tvector3f_bufferobject = 0;
4380 rsurface.tvector3f_bufferoffset = 0;
4381 rsurface.normal3f = rsurface.array_deformednormal3f;
4382 rsurface.normal3f_bufferobject = 0;
4383 rsurface.normal3f_bufferoffset = 0;
4385 case Q3DEFORM_AUTOSPRITE2:
4386 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.forward, newforward);
4387 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.right, newright);
4388 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.up, newup);
4389 VectorNormalize(newforward);
4390 VectorNormalize(newright);
4391 VectorNormalize(newup);
4392 // make deformed versions of only the model vertices used by the specified surfaces
4393 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4395 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4396 const float *v1, *v2;
4406 memset(shortest, 0, sizeof(shortest));
4407 // a single autosprite surface can contain multiple sprites...
4408 for (j = 0;j < surface->num_vertices - 3;j += 4)
4410 VectorClear(center);
4411 for (i = 0;i < 4;i++)
4412 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
4413 VectorScale(center, 0.25f, center);
4414 // find the two shortest edges, then use them to define the
4415 // axis vectors for rotating around the central axis
4416 for (i = 0;i < 6;i++)
4418 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
4419 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
4421 Debug_PolygonBegin(NULL, 0, false, 0);
4422 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
4423 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);
4424 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
4427 l = VectorDistance2(v1, v2);
4428 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
4430 l += (1.0f / 1024.0f);
4431 if (shortest[0].length2 > l || i == 0)
4433 shortest[1] = shortest[0];
4434 shortest[0].length2 = l;
4435 shortest[0].v1 = v1;
4436 shortest[0].v2 = v2;
4438 else if (shortest[1].length2 > l || i == 1)
4440 shortest[1].length2 = l;
4441 shortest[1].v1 = v1;
4442 shortest[1].v2 = v2;
4445 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
4446 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
4448 Debug_PolygonBegin(NULL, 0, false, 0);
4449 Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
4450 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);
4451 Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
4454 // this calculates the right vector from the shortest edge
4455 // and the up vector from the edge midpoints
4456 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
4457 VectorNormalize(right);
4458 VectorSubtract(end, start, up);
4459 VectorNormalize(up);
4460 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
4461 //VectorSubtract(rsurface.modelorg, center, forward);
4462 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.forward, forward);
4463 VectorNegate(forward, forward);
4464 VectorReflect(forward, 0, up, forward);
4465 VectorNormalize(forward);
4466 CrossProduct(up, forward, newright);
4467 VectorNormalize(newright);
4469 Debug_PolygonBegin(NULL, 0, false, 0);
4470 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);
4471 Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
4472 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
4476 Debug_PolygonBegin(NULL, 0, false, 0);
4477 Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
4478 Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
4479 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
4482 // rotate the quad around the up axis vector, this is made
4483 // especially easy by the fact we know the quad is flat,
4484 // so we only have to subtract the center position and
4485 // measure distance along the right vector, and then
4486 // multiply that by the newright vector and add back the
4488 // we also need to subtract the old position to undo the
4489 // displacement from the center, which we do with a
4490 // DotProduct, the subtraction/addition of center is also
4491 // optimized into DotProducts here
4492 l = DotProduct(right, center);
4493 for (i = 0;i < 4;i++)
4495 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
4496 f = DotProduct(right, v1) - l;
4497 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
4500 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);
4501 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);
4503 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4504 rsurface.vertex3f_bufferobject = 0;
4505 rsurface.vertex3f_bufferoffset = 0;
4506 rsurface.svector3f = rsurface.array_deformedsvector3f;
4507 rsurface.svector3f_bufferobject = 0;
4508 rsurface.svector3f_bufferoffset = 0;
4509 rsurface.tvector3f = rsurface.array_deformedtvector3f;
4510 rsurface.tvector3f_bufferobject = 0;
4511 rsurface.tvector3f_bufferoffset = 0;
4512 rsurface.normal3f = rsurface.array_deformednormal3f;
4513 rsurface.normal3f_bufferobject = 0;
4514 rsurface.normal3f_bufferoffset = 0;
4516 case Q3DEFORM_NORMAL:
4517 // deform the normals to make reflections wavey
4518 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4520 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4521 for (j = 0;j < surface->num_vertices;j++)
4524 float *normal = (rsurface.array_deformednormal3f + 3 * surface->num_firstvertex) + j*3;
4525 VectorScale((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
4526 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, normal);
4527 normal[0] += deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.time * deform->parms[1]);
4528 normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.time * deform->parms[1]);
4529 normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.time * deform->parms[1]);
4530 VectorNormalize(normal);
4532 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);
4534 rsurface.svector3f = rsurface.array_deformedsvector3f;
4535 rsurface.svector3f_bufferobject = 0;
4536 rsurface.svector3f_bufferoffset = 0;
4537 rsurface.tvector3f = rsurface.array_deformedtvector3f;
4538 rsurface.tvector3f_bufferobject = 0;
4539 rsurface.tvector3f_bufferoffset = 0;
4540 rsurface.normal3f = rsurface.array_deformednormal3f;
4541 rsurface.normal3f_bufferobject = 0;
4542 rsurface.normal3f_bufferoffset = 0;
4545 // deform vertex array to make wavey water and flags and such
4546 waveparms[0] = deform->waveparms[0];
4547 waveparms[1] = deform->waveparms[1];
4548 waveparms[2] = deform->waveparms[2];
4549 waveparms[3] = deform->waveparms[3];
4550 // this is how a divisor of vertex influence on deformation
4551 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
4552 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
4553 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4555 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4556 for (j = 0;j < surface->num_vertices;j++)
4558 float *vertex = (rsurface.array_deformedvertex3f + 3 * surface->num_firstvertex) + j*3;
4559 VectorCopy((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, vertex);
4560 // if the wavefunc depends on time, evaluate it per-vertex
4563 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
4564 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
4566 VectorMA(vertex, scale, (rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, vertex);
4569 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4570 rsurface.vertex3f_bufferobject = 0;
4571 rsurface.vertex3f_bufferoffset = 0;
4573 case Q3DEFORM_BULGE:
4574 // deform vertex array to make the surface have moving bulges
4575 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4577 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4578 for (j = 0;j < surface->num_vertices;j++)
4580 scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.time * deform->parms[2])) * deform->parms[1];
4581 VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
4584 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4585 rsurface.vertex3f_bufferobject = 0;
4586 rsurface.vertex3f_bufferoffset = 0;
4589 // deform vertex array
4590 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
4591 VectorScale(deform->parms, scale, waveparms);
4592 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4594 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4595 for (j = 0;j < surface->num_vertices;j++)
4596 VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
4598 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4599 rsurface.vertex3f_bufferobject = 0;
4600 rsurface.vertex3f_bufferoffset = 0;
4604 // generate texcoords based on the chosen texcoord source
4605 switch(rsurface.texture->tcgen.tcgen)
4608 case Q3TCGEN_TEXTURE:
4609 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
4610 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordtexture2f_bufferobject;
4611 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
4613 case Q3TCGEN_LIGHTMAP:
4614 rsurface.texcoordtexture2f = rsurface.modeltexcoordlightmap2f;
4615 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
4616 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
4618 case Q3TCGEN_VECTOR:
4619 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4621 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4622 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)
4624 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
4625 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
4628 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
4629 rsurface.texcoordtexture2f_bufferobject = 0;
4630 rsurface.texcoordtexture2f_bufferoffset = 0;
4632 case Q3TCGEN_ENVIRONMENT:
4633 // make environment reflections using a spheremap
4634 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4636 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4637 const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
4638 const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
4639 float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
4640 for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
4642 float l, d, eyedir[3];
4643 VectorSubtract(rsurface.modelorg, vertex, eyedir);
4644 l = 0.5f / VectorLength(eyedir);
4645 d = DotProduct(normal, eyedir)*2;
4646 out_tc[0] = 0.5f + (normal[1]*d - eyedir[1])*l;
4647 out_tc[1] = 0.5f - (normal[2]*d - eyedir[2])*l;
4650 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
4651 rsurface.texcoordtexture2f_bufferobject = 0;
4652 rsurface.texcoordtexture2f_bufferoffset = 0;
4655 // the only tcmod that needs software vertex processing is turbulent, so
4656 // check for it here and apply the changes if needed
4657 // and we only support that as the first one
4658 // (handling a mixture of turbulent and other tcmods would be problematic
4659 // without punting it entirely to a software path)
4660 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
4662 amplitude = rsurface.texture->tcmods[0].parms[1];
4663 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.time * rsurface.texture->tcmods[0].parms[3];
4664 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4666 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4667 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)
4669 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
4670 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
4673 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
4674 rsurface.texcoordtexture2f_bufferobject = 0;
4675 rsurface.texcoordtexture2f_bufferoffset = 0;
4677 rsurface.texcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
4678 rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
4679 rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
4680 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
4683 void RSurf_DrawBatch_Simple(int texturenumsurfaces, msurface_t **texturesurfacelist)
4686 const msurface_t *surface = texturesurfacelist[0];
4687 const msurface_t *surface2;
4692 // TODO: lock all array ranges before render, rather than on each surface
4693 if (texturenumsurfaces == 1)
4695 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
4696 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));
4698 else if (r_batchmode.integer == 2)
4700 #define MAXBATCHTRIANGLES 4096
4701 int batchtriangles = 0;
4702 int batchelements[MAXBATCHTRIANGLES*3];
4703 for (i = 0;i < texturenumsurfaces;i = j)
4705 surface = texturesurfacelist[i];
4707 if (surface->num_triangles > MAXBATCHTRIANGLES)
4709 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));
4712 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
4713 batchtriangles = surface->num_triangles;
4714 firstvertex = surface->num_firstvertex;
4715 endvertex = surface->num_firstvertex + surface->num_vertices;
4716 for (;j < texturenumsurfaces;j++)
4718 surface2 = texturesurfacelist[j];
4719 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
4721 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
4722 batchtriangles += surface2->num_triangles;
4723 firstvertex = min(firstvertex, surface2->num_firstvertex);
4724 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
4726 surface2 = texturesurfacelist[j-1];
4727 numvertices = endvertex - firstvertex;
4728 R_Mesh_Draw(firstvertex, numvertices, batchtriangles, batchelements, 0, 0);
4731 else if (r_batchmode.integer == 1)
4733 for (i = 0;i < texturenumsurfaces;i = j)
4735 surface = texturesurfacelist[i];
4736 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
4737 if (texturesurfacelist[j] != surface2)
4739 surface2 = texturesurfacelist[j-1];
4740 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
4741 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
4742 GL_LockArrays(surface->num_firstvertex, numvertices);
4743 R_Mesh_Draw(surface->num_firstvertex, numvertices, numtriangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
4748 for (i = 0;i < texturenumsurfaces;i++)
4750 surface = texturesurfacelist[i];
4751 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
4752 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));
4757 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit, int refractiontexunit, int reflectiontexunit)
4759 int i, planeindex, vertexindex;
4763 r_waterstate_waterplane_t *p, *bestp;
4764 msurface_t *surface;
4765 if (r_waterstate.renderingscene)
4767 for (i = 0;i < texturenumsurfaces;i++)
4769 surface = texturesurfacelist[i];
4770 if (lightmaptexunit >= 0)
4771 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
4772 if (deluxemaptexunit >= 0)
4773 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
4774 // pick the closest matching water plane
4777 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
4780 for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
4782 Matrix4x4_Transform(&rsurface.matrix, v, vert);
4783 d += fabs(PlaneDiff(vert, &p->plane));
4785 if (bestd > d || !bestp)
4793 if (refractiontexunit >= 0)
4794 R_Mesh_TexBind(refractiontexunit, R_GetTexture(bestp->texture_refraction));
4795 if (reflectiontexunit >= 0)
4796 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(bestp->texture_reflection));
4800 if (refractiontexunit >= 0)
4801 R_Mesh_TexBind(refractiontexunit, R_GetTexture(r_texture_black));
4802 if (reflectiontexunit >= 0)
4803 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(r_texture_black));
4805 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
4806 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));
4810 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit)
4814 const msurface_t *surface = texturesurfacelist[0];
4815 const msurface_t *surface2;
4820 // TODO: lock all array ranges before render, rather than on each surface
4821 if (texturenumsurfaces == 1)
4823 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
4824 if (deluxemaptexunit >= 0)
4825 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
4826 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
4827 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));
4829 else if (r_batchmode.integer == 2)
4831 #define MAXBATCHTRIANGLES 4096
4832 int batchtriangles = 0;
4833 int batchelements[MAXBATCHTRIANGLES*3];
4834 for (i = 0;i < texturenumsurfaces;i = j)
4836 surface = texturesurfacelist[i];
4837 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
4838 if (deluxemaptexunit >= 0)
4839 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
4841 if (surface->num_triangles > MAXBATCHTRIANGLES)
4843 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));
4846 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
4847 batchtriangles = surface->num_triangles;
4848 firstvertex = surface->num_firstvertex;
4849 endvertex = surface->num_firstvertex + surface->num_vertices;
4850 for (;j < texturenumsurfaces;j++)
4852 surface2 = texturesurfacelist[j];
4853 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
4855 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
4856 batchtriangles += surface2->num_triangles;
4857 firstvertex = min(firstvertex, surface2->num_firstvertex);
4858 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
4860 surface2 = texturesurfacelist[j-1];
4861 numvertices = endvertex - firstvertex;
4862 R_Mesh_Draw(firstvertex, numvertices, batchtriangles, batchelements, 0, 0);
4865 else if (r_batchmode.integer == 1)
4868 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
4869 for (i = 0;i < texturenumsurfaces;i = j)
4871 surface = texturesurfacelist[i];
4872 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
4873 if (texturesurfacelist[j] != surface2)
4875 Con_Printf(" %i", j - i);
4878 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
4880 for (i = 0;i < texturenumsurfaces;i = j)
4882 surface = texturesurfacelist[i];
4883 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
4884 if (deluxemaptexunit >= 0)
4885 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
4886 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
4887 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
4890 Con_Printf(" %i", j - i);
4892 surface2 = texturesurfacelist[j-1];
4893 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
4894 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
4895 GL_LockArrays(surface->num_firstvertex, numvertices);
4896 R_Mesh_Draw(surface->num_firstvertex, numvertices, numtriangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
4904 for (i = 0;i < texturenumsurfaces;i++)
4906 surface = texturesurfacelist[i];
4907 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
4908 if (deluxemaptexunit >= 0)
4909 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
4910 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
4911 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));
4916 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
4919 int texturesurfaceindex;
4920 if (r_showsurfaces.integer == 2)
4922 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4924 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4925 for (j = 0;j < surface->num_triangles;j++)
4927 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_view.colorscale;
4928 GL_Color(f, f, f, 1);
4929 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)));
4935 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4937 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4938 int k = (int)(((size_t)surface) / sizeof(msurface_t));
4939 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);
4940 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
4941 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));
4946 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, msurface_t **texturesurfacelist)
4948 int texturesurfaceindex;
4952 if (rsurface.lightmapcolor4f)
4954 // generate color arrays for the surfaces in this list
4955 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4957 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4958 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)
4960 f = FogPoint_Model(v);
4970 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4972 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4973 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)
4975 f = FogPoint_Model(v);
4983 rsurface.lightmapcolor4f = rsurface.array_color4f;
4984 rsurface.lightmapcolor4f_bufferobject = 0;
4985 rsurface.lightmapcolor4f_bufferoffset = 0;
4988 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a)
4990 int texturesurfaceindex;
4993 if (!rsurface.lightmapcolor4f)
4995 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4997 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4998 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)
5006 rsurface.lightmapcolor4f = rsurface.array_color4f;
5007 rsurface.lightmapcolor4f_bufferobject = 0;
5008 rsurface.lightmapcolor4f_bufferoffset = 0;
5011 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5014 rsurface.lightmapcolor4f = NULL;
5015 rsurface.lightmapcolor4f_bufferobject = 0;
5016 rsurface.lightmapcolor4f_bufferoffset = 0;
5017 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5018 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5019 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5020 GL_Color(r, g, b, a);
5021 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 0, -1);
5024 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5026 // TODO: optimize applyfog && applycolor case
5027 // just apply fog if necessary, and tint the fog color array if necessary
5028 rsurface.lightmapcolor4f = NULL;
5029 rsurface.lightmapcolor4f_bufferobject = 0;
5030 rsurface.lightmapcolor4f_bufferoffset = 0;
5031 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5032 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5033 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5034 GL_Color(r, g, b, a);
5035 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5038 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5040 int texturesurfaceindex;
5044 if (texturesurfacelist[0]->lightmapinfo && texturesurfacelist[0]->lightmapinfo->stainsamples)
5046 // generate color arrays for the surfaces in this list
5047 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5049 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5050 for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
5052 if (surface->lightmapinfo->samples)
5054 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
5055 float scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
5056 VectorScale(lm, scale, c);
5057 if (surface->lightmapinfo->styles[1] != 255)
5059 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
5061 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
5062 VectorMA(c, scale, lm, c);
5063 if (surface->lightmapinfo->styles[2] != 255)
5066 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
5067 VectorMA(c, scale, lm, c);
5068 if (surface->lightmapinfo->styles[3] != 255)
5071 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
5072 VectorMA(c, scale, lm, c);
5082 rsurface.lightmapcolor4f = rsurface.array_color4f;
5083 rsurface.lightmapcolor4f_bufferobject = 0;
5084 rsurface.lightmapcolor4f_bufferoffset = 0;
5088 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
5089 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
5090 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
5092 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5093 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5094 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5095 GL_Color(r, g, b, a);
5096 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5099 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5101 int texturesurfaceindex;
5105 vec3_t ambientcolor;
5106 vec3_t diffusecolor;
5110 VectorCopy(rsurface.modellight_lightdir, lightdir);
5111 ambientcolor[0] = rsurface.modellight_ambient[0] * r * 0.5f;
5112 ambientcolor[1] = rsurface.modellight_ambient[1] * g * 0.5f;
5113 ambientcolor[2] = rsurface.modellight_ambient[2] * b * 0.5f;
5114 diffusecolor[0] = rsurface.modellight_diffuse[0] * r * 0.5f;
5115 diffusecolor[1] = rsurface.modellight_diffuse[1] * g * 0.5f;
5116 diffusecolor[2] = rsurface.modellight_diffuse[2] * b * 0.5f;
5117 if (VectorLength2(diffusecolor) > 0)
5119 // generate color arrays for the surfaces in this list
5120 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5122 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5123 int numverts = surface->num_vertices;
5124 v = rsurface.vertex3f + 3 * surface->num_firstvertex;
5125 c2 = rsurface.normal3f + 3 * surface->num_firstvertex;
5126 c = rsurface.array_color4f + 4 * surface->num_firstvertex;
5127 // q3-style directional shading
5128 for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
5130 if ((f = DotProduct(c2, lightdir)) > 0)
5131 VectorMA(ambientcolor, f, diffusecolor, c);
5133 VectorCopy(ambientcolor, c);
5142 rsurface.lightmapcolor4f = rsurface.array_color4f;
5143 rsurface.lightmapcolor4f_bufferobject = 0;
5144 rsurface.lightmapcolor4f_bufferoffset = 0;
5148 r = ambientcolor[0];
5149 g = ambientcolor[1];
5150 b = ambientcolor[2];
5151 rsurface.lightmapcolor4f = NULL;
5152 rsurface.lightmapcolor4f_bufferobject = 0;
5153 rsurface.lightmapcolor4f_bufferoffset = 0;
5155 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5156 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5157 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5158 GL_Color(r, g, b, a);
5159 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5162 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
5164 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5165 GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset);
5166 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
5167 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_view.cullface_back);
5168 if (rsurface.mode != RSURFMODE_SHOWSURFACES)
5170 rsurface.mode = RSURFMODE_SHOWSURFACES;
5172 GL_BlendFunc(GL_ONE, GL_ZERO);
5173 R_Mesh_ColorPointer(NULL, 0, 0);
5174 R_Mesh_ResetTextureState();
5176 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
5177 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
5180 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, msurface_t **texturesurfacelist)
5182 // transparent sky would be ridiculous
5183 if ((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED))
5185 if (rsurface.mode != RSURFMODE_SKY)
5187 if (rsurface.mode == RSURFMODE_GLSL)
5189 qglUseProgramObjectARB(0);CHECKGLERROR
5191 rsurface.mode = RSURFMODE_SKY;
5195 skyrendernow = false;
5197 // restore entity matrix
5198 R_Mesh_Matrix(&rsurface.matrix);
5200 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5201 GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset);
5202 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
5203 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_view.cullface_back);
5205 // LordHavoc: HalfLife maps have freaky skypolys so don't use
5206 // skymasking on them, and Quake3 never did sky masking (unlike
5207 // software Quake and software Quake2), so disable the sky masking
5208 // in Quake3 maps as it causes problems with q3map2 sky tricks,
5209 // and skymasking also looks very bad when noclipping outside the
5210 // level, so don't use it then either.
5211 if (r_refdef.worldmodel && r_refdef.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_viewcache.world_novis)
5213 GL_Color(r_refdef.fogcolor[0] * r_view.colorscale, r_refdef.fogcolor[1] * r_view.colorscale, r_refdef.fogcolor[2] * r_view.colorscale, 1);
5214 R_Mesh_ColorPointer(NULL, 0, 0);
5215 R_Mesh_ResetTextureState();
5216 if (skyrendermasked)
5218 // depth-only (masking)
5219 GL_ColorMask(0,0,0,0);
5220 // just to make sure that braindead drivers don't draw
5221 // anything despite that colormask...
5222 GL_BlendFunc(GL_ZERO, GL_ONE);
5227 GL_BlendFunc(GL_ONE, GL_ZERO);
5229 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
5230 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5231 if (skyrendermasked)
5232 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
5236 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, msurface_t **texturesurfacelist)
5238 if (rsurface.mode != RSURFMODE_GLSL)
5240 rsurface.mode = RSURFMODE_GLSL;
5241 R_Mesh_ResetTextureState();
5244 R_SetupSurfaceShader(vec3_origin, rsurface.lightmode == 2, 1, 1, rsurface.texture->specularscale);
5245 if (!r_glsl_permutation)
5248 if (rsurface.lightmode == 2)
5249 RSurf_PrepareVerticesForBatch(true, r_glsl_permutation->loc_Texture_Normal >= 0, texturenumsurfaces, texturesurfacelist);
5251 RSurf_PrepareVerticesForBatch(r_glsl_permutation->loc_Texture_Normal >= 0, r_glsl_permutation->loc_Texture_Normal >= 0, texturenumsurfaces, texturesurfacelist);
5252 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
5253 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
5254 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
5255 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
5256 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
5258 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]);
5259 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
5261 R_Mesh_TexBind(7, R_GetTexture(r_texture_grey128));
5262 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
5263 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
5264 R_Mesh_ColorPointer(NULL, 0, 0);
5266 else if (rsurface.uselightmaptexture)
5268 R_Mesh_TexBind(7, R_GetTexture(texturesurfacelist[0]->lightmaptexture));
5269 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
5270 R_Mesh_TexBind(8, R_GetTexture(texturesurfacelist[0]->deluxemaptexture));
5271 R_Mesh_ColorPointer(NULL, 0, 0);
5275 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
5276 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
5277 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
5278 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
5281 if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
5283 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
5284 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist, 7, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? 8 : -1, 11, 12);
5285 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5286 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist, 7, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? 8 : -1, -1, 12);
5288 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 7, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? 8 : -1);
5292 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
5293 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist, -1, -1, 11, 12);
5294 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5295 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist, -1, -1, -1, 12);
5297 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5299 if (rsurface.texture->backgroundnumskinframes && !(rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED))
5304 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, msurface_t **texturesurfacelist)
5306 // OpenGL 1.3 path - anything not completely ancient
5307 int texturesurfaceindex;
5308 qboolean applycolor;
5312 const texturelayer_t *layer;
5313 if (rsurface.mode != RSURFMODE_MULTIPASS)
5314 rsurface.mode = RSURFMODE_MULTIPASS;
5315 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
5316 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
5319 int layertexrgbscale;
5320 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5322 if (layerindex == 0)
5326 GL_AlphaTest(false);
5327 qglDepthFunc(GL_EQUAL);CHECKGLERROR
5330 GL_DepthMask(layer->depthmask);
5331 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
5332 if ((layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2) && (gl_combine.integer || layer->depthmask))
5334 layertexrgbscale = 4;
5335 VectorScale(layer->color, 0.25f, layercolor);
5337 else if ((layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1) && (gl_combine.integer || layer->depthmask))
5339 layertexrgbscale = 2;
5340 VectorScale(layer->color, 0.5f, layercolor);
5344 layertexrgbscale = 1;
5345 VectorScale(layer->color, 1.0f, layercolor);
5347 layercolor[3] = layer->color[3];
5348 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
5349 R_Mesh_ColorPointer(NULL, 0, 0);
5350 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
5351 switch (layer->type)
5353 case TEXTURELAYERTYPE_LITTEXTURE:
5354 memset(&m, 0, sizeof(m));
5355 m.tex[0] = R_GetTexture(r_texture_white);
5356 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
5357 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
5358 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
5359 m.tex[1] = R_GetTexture(layer->texture);
5360 m.texmatrix[1] = layer->texmatrix;
5361 m.texrgbscale[1] = layertexrgbscale;
5362 m.pointer_texcoord[1] = rsurface.texcoordtexture2f;
5363 m.pointer_texcoord_bufferobject[1] = rsurface.texcoordtexture2f_bufferobject;
5364 m.pointer_texcoord_bufferoffset[1] = rsurface.texcoordtexture2f_bufferoffset;
5365 R_Mesh_TextureState(&m);
5366 if (rsurface.lightmode == 2)
5367 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
5368 else if (rsurface.uselightmaptexture)
5369 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
5371 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
5373 case TEXTURELAYERTYPE_TEXTURE:
5374 memset(&m, 0, sizeof(m));
5375 m.tex[0] = R_GetTexture(layer->texture);
5376 m.texmatrix[0] = layer->texmatrix;
5377 m.texrgbscale[0] = layertexrgbscale;
5378 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5379 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5380 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5381 R_Mesh_TextureState(&m);
5382 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
5384 case TEXTURELAYERTYPE_FOG:
5385 memset(&m, 0, sizeof(m));
5386 m.texrgbscale[0] = layertexrgbscale;
5389 m.tex[0] = R_GetTexture(layer->texture);
5390 m.texmatrix[0] = layer->texmatrix;
5391 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5392 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5393 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5395 R_Mesh_TextureState(&m);
5396 // generate a color array for the fog pass
5397 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
5398 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5402 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5403 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)
5405 f = 1 - FogPoint_Model(v);
5406 c[0] = layercolor[0];
5407 c[1] = layercolor[1];
5408 c[2] = layercolor[2];
5409 c[3] = f * layercolor[3];
5412 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5415 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
5417 GL_LockArrays(0, 0);
5420 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5422 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
5423 GL_AlphaTest(false);
5427 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, msurface_t **texturesurfacelist)
5429 // OpenGL 1.1 - crusty old voodoo path
5430 int texturesurfaceindex;
5434 const texturelayer_t *layer;
5435 if (rsurface.mode != RSURFMODE_MULTIPASS)
5436 rsurface.mode = RSURFMODE_MULTIPASS;
5437 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
5438 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
5440 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5442 if (layerindex == 0)
5446 GL_AlphaTest(false);
5447 qglDepthFunc(GL_EQUAL);CHECKGLERROR
5450 GL_DepthMask(layer->depthmask);
5451 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
5452 R_Mesh_ColorPointer(NULL, 0, 0);
5453 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
5454 switch (layer->type)
5456 case TEXTURELAYERTYPE_LITTEXTURE:
5457 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
5459 // two-pass lit texture with 2x rgbscale
5460 // first the lightmap pass
5461 memset(&m, 0, sizeof(m));
5462 m.tex[0] = R_GetTexture(r_texture_white);
5463 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
5464 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
5465 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
5466 R_Mesh_TextureState(&m);
5467 if (rsurface.lightmode == 2)
5468 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5469 else if (rsurface.uselightmaptexture)
5470 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5472 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5473 GL_LockArrays(0, 0);
5474 // then apply the texture to it
5475 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
5476 memset(&m, 0, sizeof(m));
5477 m.tex[0] = R_GetTexture(layer->texture);
5478 m.texmatrix[0] = layer->texmatrix;
5479 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5480 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5481 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5482 R_Mesh_TextureState(&m);
5483 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);
5487 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
5488 memset(&m, 0, sizeof(m));
5489 m.tex[0] = R_GetTexture(layer->texture);
5490 m.texmatrix[0] = layer->texmatrix;
5491 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5492 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5493 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5494 R_Mesh_TextureState(&m);
5495 if (rsurface.lightmode == 2)
5496 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);
5498 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);
5501 case TEXTURELAYERTYPE_TEXTURE:
5502 // singletexture unlit texture with transparency support
5503 memset(&m, 0, sizeof(m));
5504 m.tex[0] = R_GetTexture(layer->texture);
5505 m.texmatrix[0] = layer->texmatrix;
5506 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5507 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5508 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5509 R_Mesh_TextureState(&m);
5510 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);
5512 case TEXTURELAYERTYPE_FOG:
5513 // singletexture fogging
5514 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
5517 memset(&m, 0, sizeof(m));
5518 m.tex[0] = R_GetTexture(layer->texture);
5519 m.texmatrix[0] = layer->texmatrix;
5520 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5521 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5522 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5523 R_Mesh_TextureState(&m);
5526 R_Mesh_ResetTextureState();
5527 // generate a color array for the fog pass
5528 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5532 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5533 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)
5535 f = 1 - FogPoint_Model(v);
5536 c[0] = layer->color[0];
5537 c[1] = layer->color[1];
5538 c[2] = layer->color[2];
5539 c[3] = f * layer->color[3];
5542 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5545 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
5547 GL_LockArrays(0, 0);
5550 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5552 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
5553 GL_AlphaTest(false);
5557 static void R_DrawTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly)
5559 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW)
5561 rsurface.rtlight = NULL;
5565 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
5567 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
5569 if (rsurface.mode != RSURFMODE_MULTIPASS)
5570 rsurface.mode = RSURFMODE_MULTIPASS;
5571 if (r_depthfirst.integer == 3)
5573 int i = (int)(texturesurfacelist[0] - rsurface.modelsurfaces);
5574 if (!r_view.showdebug)
5575 GL_Color(0, 0, 0, 1);
5577 GL_Color(((i >> 6) & 7) / 7.0f, ((i >> 3) & 7) / 7.0f, (i & 7) / 7.0f,1);
5581 GL_ColorMask(0,0,0,0);
5584 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5585 GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset);
5586 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_view.cullface_back);
5588 GL_BlendFunc(GL_ONE, GL_ZERO);
5590 GL_AlphaTest(false);
5591 R_Mesh_ColorPointer(NULL, 0, 0);
5592 R_Mesh_ResetTextureState();
5593 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
5594 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5595 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
5596 r_refdef.stats.entities_surfaces += texturenumsurfaces;
5598 else if (r_depthfirst.integer == 3)
5600 else if (!r_view.showdebug && (r_showsurfaces.integer || gl_lightmaps.integer))
5602 GL_Color(0, 0, 0, 1);
5603 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5605 else if (r_showsurfaces.integer)
5607 if (rsurface.mode != RSURFMODE_MULTIPASS)
5608 rsurface.mode = RSURFMODE_MULTIPASS;
5609 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5610 GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset);
5612 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_view.cullface_back);
5613 GL_BlendFunc(GL_ONE, GL_ZERO);
5614 GL_DepthMask(writedepth);
5616 GL_AlphaTest(false);
5617 R_Mesh_ColorPointer(NULL, 0, 0);
5618 R_Mesh_ResetTextureState();
5619 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
5620 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
5621 r_refdef.stats.entities_surfaces += texturenumsurfaces;
5623 else if (gl_lightmaps.integer)
5626 if (rsurface.mode != RSURFMODE_MULTIPASS)
5627 rsurface.mode = RSURFMODE_MULTIPASS;
5628 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5630 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_view.cullface_back);
5631 GL_BlendFunc(GL_ONE, GL_ZERO);
5632 GL_DepthMask(writedepth);
5634 GL_AlphaTest(false);
5635 // use lightmode 0 (fullbright or lightmap) or 2 (model lighting)
5636 rsurface.lightmode = ((rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT) || rsurface.modeltexcoordlightmap2f != NULL) ? 0 : 2;
5637 R_Mesh_ColorPointer(NULL, 0, 0);
5638 memset(&m, 0, sizeof(m));
5639 m.tex[0] = R_GetTexture(r_texture_white);
5640 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
5641 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
5642 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
5643 R_Mesh_TextureState(&m);
5644 RSurf_PrepareVerticesForBatch(rsurface.lightmode == 2, false, texturenumsurfaces, texturesurfacelist);
5645 if (rsurface.lightmode == 2)
5646 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5647 else if (rsurface.uselightmaptexture)
5648 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5650 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5651 r_refdef.stats.entities_surfaces += texturenumsurfaces;
5653 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
5655 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
5656 r_refdef.stats.entities_surfaces += texturenumsurfaces;
5658 else if (rsurface.texture->currentnumlayers)
5660 // write depth for anything we skipped on the depth-only pass earlier
5661 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5663 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5664 GL_PolygonOffset(rsurface.texture->currentpolygonfactor, rsurface.texture->currentpolygonoffset);
5665 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
5666 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_view.cullface_back);
5667 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5668 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
5669 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5670 // use lightmode 0 (fullbright or lightmap) or 2 (model lighting)
5671 rsurface.lightmode = ((rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT) || rsurface.modeltexcoordlightmap2f != NULL) ? 0 : 2;
5672 if (r_glsl.integer && gl_support_fragment_shader)
5673 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist);
5674 else if (gl_combine.integer && r_textureunits.integer >= 2)
5675 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist);
5677 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist);
5678 r_refdef.stats.entities_surfaces += texturenumsurfaces;
5681 GL_LockArrays(0, 0);
5684 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
5687 int texturenumsurfaces, endsurface;
5689 msurface_t *surface;
5690 msurface_t *texturesurfacelist[1024];
5692 // if the model is static it doesn't matter what value we give for
5693 // wantnormals and wanttangents, so this logic uses only rules applicable
5694 // to a model, knowing that they are meaningless otherwise
5695 if (ent == r_refdef.worldentity)
5696 RSurf_ActiveWorldEntity();
5697 else if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
5698 RSurf_ActiveModelEntity(ent, false, false);
5700 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
5702 for (i = 0;i < numsurfaces;i = j)
5705 surface = rsurface.modelsurfaces + surfacelist[i];
5706 texture = surface->texture;
5707 R_UpdateTextureInfo(ent, texture);
5708 rsurface.texture = texture->currentframe;
5709 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
5710 // scan ahead until we find a different texture
5711 endsurface = min(i + 1024, numsurfaces);
5712 texturenumsurfaces = 0;
5713 texturesurfacelist[texturenumsurfaces++] = surface;
5714 for (;j < endsurface;j++)
5716 surface = rsurface.modelsurfaces + surfacelist[j];
5717 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
5719 texturesurfacelist[texturenumsurfaces++] = surface;
5721 // render the range of surfaces
5722 R_DrawTextureSurfaceList(texturenumsurfaces, texturesurfacelist, true, false);
5728 void R_QueueSurfaceList(entity_render_t *ent, int numsurfaces, msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes)
5731 vec3_t tempcenter, center;
5733 // if we're rendering water textures (extra scene renders), use a separate loop to avoid burdening the main one
5736 for (i = 0;i < numsurfaces;i++)
5737 if (surfacelist[i]->texture->currentframe->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5738 R_Water_AddWaterPlane(surfacelist[i]);
5741 // break the surface list down into batches by texture and use of lightmapping
5742 for (i = 0;i < numsurfaces;i = j)
5745 // texture is the base texture pointer, rsurface.texture is the
5746 // current frame/skin the texture is directing us to use (for example
5747 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
5748 // use skin 1 instead)
5749 texture = surfacelist[i]->texture;
5750 rsurface.texture = texture->currentframe;
5751 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
5752 if (!(rsurface.texture->currentmaterialflags & flagsmask))
5754 // if this texture is not the kind we want, skip ahead to the next one
5755 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
5759 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
5761 // transparent surfaces get pushed off into the transparent queue
5762 const msurface_t *surface = surfacelist[i];
5765 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
5766 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
5767 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
5768 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
5769 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_view.origin : center, R_DrawSurface_TransparentCallback, ent, surface - rsurface.modelsurfaces, rsurface.rtlight);
5773 // simply scan ahead until we find a different texture or lightmap state
5774 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
5776 // render the range of surfaces
5777 R_DrawTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly);
5782 float locboxvertex3f[6*4*3] =
5784 1,0,1, 1,0,0, 1,1,0, 1,1,1,
5785 0,1,1, 0,1,0, 0,0,0, 0,0,1,
5786 1,1,1, 1,1,0, 0,1,0, 0,1,1,
5787 0,0,1, 0,0,0, 1,0,0, 1,0,1,
5788 0,0,1, 1,0,1, 1,1,1, 0,1,1,
5789 1,0,0, 0,0,0, 0,1,0, 1,1,0
5792 int locboxelement3i[6*2*3] =
5802 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
5805 cl_locnode_t *loc = (cl_locnode_t *)ent;
5807 float vertex3f[6*4*3];
5809 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5810 GL_DepthMask(false);
5811 GL_DepthRange(0, 1);
5812 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5814 GL_CullFace(GL_NONE);
5815 R_Mesh_Matrix(&identitymatrix);
5817 R_Mesh_VertexPointer(vertex3f, 0, 0);
5818 R_Mesh_ColorPointer(NULL, 0, 0);
5819 R_Mesh_ResetTextureState();
5822 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_view.colorscale,
5823 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_view.colorscale,
5824 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_view.colorscale,
5825 surfacelist[0] < 0 ? 0.5f : 0.125f);
5827 if (VectorCompare(loc->mins, loc->maxs))
5829 VectorSet(size, 2, 2, 2);
5830 VectorMA(loc->mins, -0.5f, size, mins);
5834 VectorCopy(loc->mins, mins);
5835 VectorSubtract(loc->maxs, loc->mins, size);
5838 for (i = 0;i < 6*4*3;)
5839 for (j = 0;j < 3;j++, i++)
5840 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
5842 R_Mesh_Draw(0, 6*4, 6*2, locboxelement3i, 0, 0);
5845 void R_DrawLocs(void)
5848 cl_locnode_t *loc, *nearestloc;
5850 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
5851 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
5853 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
5854 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
5858 void R_DrawDebugModel(entity_render_t *ent)
5860 int i, j, k, l, flagsmask;
5861 const int *elements;
5863 msurface_t *surface;
5864 model_t *model = ent->model;
5867 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WATER | MATERIALFLAG_WALL;
5869 R_Mesh_ColorPointer(NULL, 0, 0);
5870 R_Mesh_ResetTextureState();
5871 GL_DepthRange(0, 1);
5872 GL_DepthTest(!r_showdisabledepthtest.integer);
5873 GL_DepthMask(false);
5874 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5876 if (r_showcollisionbrushes.value > 0 && model->brush.num_brushes)
5878 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
5879 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
5881 if (brush->colbrushf && brush->colbrushf->numtriangles)
5883 R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
5884 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);
5885 R_Mesh_Draw(0, brush->colbrushf->numpoints, brush->colbrushf->numtriangles, brush->colbrushf->elements, 0, 0);
5888 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
5890 if (surface->num_collisiontriangles)
5892 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
5893 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);
5894 R_Mesh_Draw(0, surface->num_collisionvertices, surface->num_collisiontriangles, surface->data_collisionelement3i, 0, 0);
5899 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5901 if (r_showtris.integer || r_shownormals.integer)
5903 if (r_showdisabledepthtest.integer)
5905 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5906 GL_DepthMask(false);
5910 GL_BlendFunc(GL_ONE, GL_ZERO);
5913 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
5915 if (ent == r_refdef.worldentity && !r_viewcache.world_surfacevisible[j])
5917 rsurface.texture = surface->texture->currentframe;
5918 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
5920 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
5921 if (r_showtris.value > 0)
5923 if (!rsurface.texture->currentlayers->depthmask)
5924 GL_Color(r_view.colorscale, 0, 0, r_showtris.value);
5925 else if (ent == r_refdef.worldentity)
5926 GL_Color(r_view.colorscale, r_view.colorscale, r_view.colorscale, r_showtris.value);
5928 GL_Color(0, r_view.colorscale, 0, r_showtris.value);
5929 elements = (ent->model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
5932 for (k = 0;k < surface->num_triangles;k++, elements += 3)
5934 #define GLVERTEXELEMENT(n) qglVertex3f(rsurface.vertex3f[elements[n]*3+0], rsurface.vertex3f[elements[n]*3+1], rsurface.vertex3f[elements[n]*3+2])
5935 GLVERTEXELEMENT(0);GLVERTEXELEMENT(1);
5936 GLVERTEXELEMENT(1);GLVERTEXELEMENT(2);
5937 GLVERTEXELEMENT(2);GLVERTEXELEMENT(0);
5942 if (r_shownormals.value > 0)
5944 GL_Color(r_view.colorscale, 0, 0, r_shownormals.value);
5946 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
5948 VectorCopy(rsurface.vertex3f + l * 3, v);
5949 qglVertex3f(v[0], v[1], v[2]);
5950 VectorMA(v, 8, rsurface.svector3f + l * 3, v);
5951 qglVertex3f(v[0], v[1], v[2]);
5955 GL_Color(0, 0, r_view.colorscale, r_shownormals.value);
5957 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
5959 VectorCopy(rsurface.vertex3f + l * 3, v);
5960 qglVertex3f(v[0], v[1], v[2]);
5961 VectorMA(v, 8, rsurface.tvector3f + l * 3, v);
5962 qglVertex3f(v[0], v[1], v[2]);
5966 GL_Color(0, r_view.colorscale, 0, r_shownormals.value);
5968 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
5970 VectorCopy(rsurface.vertex3f + l * 3, v);
5971 qglVertex3f(v[0], v[1], v[2]);
5972 VectorMA(v, 8, rsurface.normal3f + l * 3, v);
5973 qglVertex3f(v[0], v[1], v[2]);
5980 rsurface.texture = NULL;
5984 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
5985 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes, qboolean debug)
5987 int i, j, endj, f, flagsmask;
5988 int counttriangles = 0;
5989 msurface_t *surface, **surfacechain;
5991 model_t *model = r_refdef.worldmodel;
5992 const int maxsurfacelist = 1024;
5993 int numsurfacelist = 0;
5994 msurface_t *surfacelist[1024];
5998 RSurf_ActiveWorldEntity();
6000 // update light styles
6001 if (!skysurfaces && !depthonly && !addwaterplanes && model->brushq1.light_styleupdatechains)
6003 for (i = 0;i < model->brushq1.light_styles;i++)
6005 if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
6007 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
6008 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
6009 for (;(surface = *surfacechain);surfacechain++)
6010 surface->cached_dlight = true;
6015 R_UpdateAllTextureInfo(r_refdef.worldentity);
6016 flagsmask = addwaterplanes ? (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION) : (skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL));
6020 R_DrawDebugModel(r_refdef.worldentity);
6026 rsurface.uselightmaptexture = false;
6027 rsurface.texture = NULL;
6029 j = model->firstmodelsurface;
6030 endj = j + model->nummodelsurfaces;
6033 // quickly skip over non-visible surfaces
6034 for (;j < endj && !r_viewcache.world_surfacevisible[j];j++)
6036 // quickly iterate over visible surfaces
6037 for (;j < endj && r_viewcache.world_surfacevisible[j];j++)
6039 // process this surface
6040 surface = model->data_surfaces + j;
6041 // if this surface fits the criteria, add it to the list
6042 if (surface->num_triangles)
6044 // if lightmap parameters changed, rebuild lightmap texture
6045 if (surface->cached_dlight)
6046 R_BuildLightMap(r_refdef.worldentity, surface);
6047 // add face to draw list
6048 surfacelist[numsurfacelist++] = surface;
6049 counttriangles += surface->num_triangles;
6050 if (numsurfacelist >= maxsurfacelist)
6052 R_QueueSurfaceList(r_refdef.worldentity, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
6059 R_QueueSurfaceList(r_refdef.worldentity, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
6060 r_refdef.stats.entities_triangles += counttriangles;
6064 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes, qboolean debug)
6066 int i, f, flagsmask;
6067 int counttriangles = 0;
6068 msurface_t *surface, *endsurface, **surfacechain;
6070 model_t *model = ent->model;
6071 const int maxsurfacelist = 1024;
6072 int numsurfacelist = 0;
6073 msurface_t *surfacelist[1024];
6077 // if the model is static it doesn't matter what value we give for
6078 // wantnormals and wanttangents, so this logic uses only rules applicable
6079 // to a model, knowing that they are meaningless otherwise
6080 if (ent == r_refdef.worldentity)
6081 RSurf_ActiveWorldEntity();
6082 else if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
6083 RSurf_ActiveModelEntity(ent, false, false);
6085 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader && !depthonly);
6087 // update light styles
6088 if (!skysurfaces && !depthonly && !addwaterplanes && model->brushq1.light_styleupdatechains)
6090 for (i = 0;i < model->brushq1.light_styles;i++)
6092 if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
6094 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
6095 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
6096 for (;(surface = *surfacechain);surfacechain++)
6097 surface->cached_dlight = true;
6102 R_UpdateAllTextureInfo(ent);
6103 flagsmask = addwaterplanes ? (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION) : (skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL));
6107 R_DrawDebugModel(ent);
6113 rsurface.uselightmaptexture = false;
6114 rsurface.texture = NULL;
6116 surface = model->data_surfaces + model->firstmodelsurface;
6117 endsurface = surface + model->nummodelsurfaces;
6118 for (;surface < endsurface;surface++)
6120 // if this surface fits the criteria, add it to the list
6121 if (surface->num_triangles)
6123 // if lightmap parameters changed, rebuild lightmap texture
6124 if (surface->cached_dlight)
6125 R_BuildLightMap(ent, surface);
6126 // add face to draw list
6127 surfacelist[numsurfacelist++] = surface;
6128 counttriangles += surface->num_triangles;
6129 if (numsurfacelist >= maxsurfacelist)
6131 R_QueueSurfaceList(ent, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
6137 R_QueueSurfaceList(ent, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
6138 r_refdef.stats.entities_triangles += counttriangles;