2 Copyright (C) 1996-1997 Id Software, Inc.
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 #include "cl_dyntexture.h"
28 mempool_t *r_main_mempool;
29 rtexturepool_t *r_main_texturepool;
36 r_viewcache_t r_viewcache;
38 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "1", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
39 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
40 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%, 10 = 100%)"};
41 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
42 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
43 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
44 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
45 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
46 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
47 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
48 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
49 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
50 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
51 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
52 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
53 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
54 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling"};
55 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
56 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
57 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
58 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
59 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
60 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
61 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
62 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this)"};
63 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
64 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
65 cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
66 cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "2", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
67 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
69 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
70 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
71 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
72 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
73 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
74 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
75 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
76 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
78 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)"};
80 cvar_t r_glsl = {CVAR_SAVE, "r_glsl", "1", "enables use of OpenGL 2.0 pixel shaders for lighting"};
81 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
82 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
83 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
84 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)"};
85 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)"};
87 cvar_t r_water = {CVAR_SAVE, "r_water", "0", "whether to use reflections and refraction on water surfaces (note: r_wateralpha must be set below 1)"};
88 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
89 cvar_t r_water_resolutionmultiplier = {CVAR_SAVE, "r_water_resolutionmultiplier", "0.5", "multiplier for screen resolution when rendering refracted/reflected scenes, 1 is full quality, lower values are faster"};
90 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
91 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
93 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1", "enables animation smoothing on sprites (requires r_lerpmodels 1)"};
94 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
95 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
96 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
98 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
99 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
100 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
101 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
102 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
103 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
104 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
106 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
107 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
108 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
109 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)"};
111 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"};
113 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"};
115 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
117 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
118 cvar_t r_batchmode = {0, "r_batchmode", "1", "selects method of rendering multiple surfaces with one driver call (values are 0, 1, 2, etc...)"};
119 cvar_t r_track_sprites = {CVAR_SAVE, "r_track_sprites", "1", "track SPR_LABEL* sprites by putting them as indicator at the screen border to rotate to"};
120 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accodringly, 2: Make it a continuous rotation"};
121 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
122 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
124 extern qboolean v_flipped_state;
126 typedef struct r_glsl_bloomshader_s
129 int loc_Texture_Bloom;
131 r_glsl_bloomshader_t;
133 static struct r_bloomstate_s
138 int bloomwidth, bloomheight;
140 int screentexturewidth, screentextureheight;
141 rtexture_t *texture_screen;
143 int bloomtexturewidth, bloomtextureheight;
144 rtexture_t *texture_bloom;
146 r_glsl_bloomshader_t *shader;
148 // arrays for rendering the screen passes
149 float screentexcoord2f[8];
150 float bloomtexcoord2f[8];
151 float offsettexcoord2f[8];
155 typedef struct r_waterstate_waterplane_s
157 rtexture_t *texture_refraction;
158 rtexture_t *texture_reflection;
160 int materialflags; // combined flags of all water surfaces on this plane
161 unsigned char pvsbits[(32768+7)>>3]; // FIXME: buffer overflow on huge maps
164 r_waterstate_waterplane_t;
166 #define MAX_WATERPLANES 16
168 static struct r_waterstate_s
172 qboolean renderingscene; // true while rendering a refraction or reflection texture, disables water surfaces
174 int waterwidth, waterheight;
175 int texturewidth, textureheight;
177 int maxwaterplanes; // same as MAX_WATERPLANES
179 r_waterstate_waterplane_t waterplanes[MAX_WATERPLANES];
181 float screenscale[2];
182 float screencenter[2];
186 // shadow volume bsp struct with automatically growing nodes buffer
189 rtexture_t *r_texture_blanknormalmap;
190 rtexture_t *r_texture_white;
191 rtexture_t *r_texture_grey128;
192 rtexture_t *r_texture_black;
193 rtexture_t *r_texture_notexture;
194 rtexture_t *r_texture_whitecube;
195 rtexture_t *r_texture_normalizationcube;
196 rtexture_t *r_texture_fogattenuation;
197 //rtexture_t *r_texture_fogintensity;
199 char r_qwskincache[MAX_SCOREBOARD][MAX_QPATH];
200 skinframe_t *r_qwskincache_skinframe[MAX_SCOREBOARD];
202 // vertex coordinates for a quad that covers the screen exactly
203 const static float r_screenvertex3f[12] =
211 extern void R_DrawModelShadows(void);
213 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
216 for (i = 0;i < verts;i++)
227 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
230 for (i = 0;i < verts;i++)
240 // FIXME: move this to client?
243 if (gamemode == GAME_NEHAHRA)
245 Cvar_Set("gl_fogenable", "0");
246 Cvar_Set("gl_fogdensity", "0.2");
247 Cvar_Set("gl_fogred", "0.3");
248 Cvar_Set("gl_foggreen", "0.3");
249 Cvar_Set("gl_fogblue", "0.3");
251 r_refdef.fog_density = 0;
252 r_refdef.fog_red = 0;
253 r_refdef.fog_green = 0;
254 r_refdef.fog_blue = 0;
255 r_refdef.fog_alpha = 1;
256 r_refdef.fog_start = 0;
257 r_refdef.fog_end = 0;
260 float FogForDistance(vec_t dist)
262 unsigned int fogmasktableindex = (unsigned int)(dist * r_refdef.fogmasktabledistmultiplier);
263 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
266 float FogPoint_World(const vec3_t p)
268 return FogForDistance(VectorDistance((p), r_view.origin));
271 float FogPoint_Model(const vec3_t p)
273 return FogForDistance(VectorDistance((p), rsurface.modelorg));
276 static void R_BuildBlankTextures(void)
278 unsigned char data[4];
279 data[2] = 128; // normal X
280 data[1] = 128; // normal Y
281 data[0] = 255; // normal Z
282 data[3] = 128; // height
283 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
288 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
293 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
298 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
301 static void R_BuildNoTexture(void)
304 unsigned char pix[16][16][4];
305 // this makes a light grey/dark grey checkerboard texture
306 for (y = 0;y < 16;y++)
308 for (x = 0;x < 16;x++)
310 if ((y < 8) ^ (x < 8))
326 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, NULL);
329 static void R_BuildWhiteCube(void)
331 unsigned char data[6*1*1*4];
332 memset(data, 255, sizeof(data));
333 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_CLAMP | TEXF_PERSISTENT, NULL);
336 static void R_BuildNormalizationCube(void)
340 vec_t s, t, intensity;
342 unsigned char data[6][NORMSIZE][NORMSIZE][4];
343 for (side = 0;side < 6;side++)
345 for (y = 0;y < NORMSIZE;y++)
347 for (x = 0;x < NORMSIZE;x++)
349 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
350 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
385 intensity = 127.0f / sqrt(DotProduct(v, v));
386 data[side][y][x][2] = (unsigned char)(128.0f + intensity * v[0]);
387 data[side][y][x][1] = (unsigned char)(128.0f + intensity * v[1]);
388 data[side][y][x][0] = (unsigned char)(128.0f + intensity * v[2]);
389 data[side][y][x][3] = 255;
393 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, &data[0][0][0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_CLAMP | TEXF_PERSISTENT, NULL);
396 static void R_BuildFogTexture(void)
400 unsigned char data1[FOGWIDTH][4];
401 //unsigned char data2[FOGWIDTH][4];
404 r_refdef.fogmasktable_start = r_refdef.fog_start;
405 r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
406 r_refdef.fogmasktable_range = r_refdef.fogrange;
407 r_refdef.fogmasktable_density = r_refdef.fog_density;
409 r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
410 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
412 d = (x * r - r_refdef.fogmasktable_start);
413 if(developer.integer >= 100)
414 Con_Printf("%f ", d);
416 if (r_fog_exp2.integer)
417 alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
419 alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
420 if(developer.integer >= 100)
421 Con_Printf(" : %f ", alpha);
422 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
423 if(developer.integer >= 100)
424 Con_Printf(" = %f\n", alpha);
425 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
428 for (x = 0;x < FOGWIDTH;x++)
430 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
435 //data2[x][0] = 255 - b;
436 //data2[x][1] = 255 - b;
437 //data2[x][2] = 255 - b;
440 if (r_texture_fogattenuation)
442 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, FOGWIDTH, 1);
443 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, FOGWIDTH, 1);
447 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, NULL);
448 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
452 static const char *builtinshaderstring =
453 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
454 "// written by Forest 'LordHavoc' Hale\n"
456 "// common definitions between vertex shader and fragment shader:\n"
458 "#ifdef __GLSL_CG_DATA_TYPES\n"
459 "# define myhalf half\n"
460 "# define myhvec2 hvec2\n"
461 "# define myhvec3 hvec3\n"
462 "# define myhvec4 hvec4\n"
464 "# define myhalf float\n"
465 "# define myhvec2 vec2\n"
466 "# define myhvec3 vec3\n"
467 "# define myhvec4 vec4\n"
470 "varying vec2 TexCoord;\n"
471 "varying vec2 TexCoordLightmap;\n"
473 "//#ifdef MODE_LIGHTSOURCE\n"
474 "varying vec3 CubeVector;\n"
477 "//#ifdef MODE_LIGHTSOURCE\n"
478 "varying vec3 LightVector;\n"
480 "//# ifdef MODE_LIGHTDIRECTION\n"
481 "//varying vec3 LightVector;\n"
485 "varying vec3 EyeVector;\n"
487 "varying vec3 EyeVectorModelSpace;\n"
490 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
491 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
492 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
494 "//#ifdef MODE_WATER\n"
495 "varying vec4 ModelViewProjectionPosition;\n"
497 "//# ifdef MODE_REFRACTION\n"
498 "//varying vec4 ModelViewProjectionPosition;\n"
500 "//# ifdef USEREFLECTION\n"
501 "//varying vec4 ModelViewProjectionPosition;\n"
510 "// vertex shader specific:\n"
511 "#ifdef VERTEX_SHADER\n"
513 "uniform vec3 LightPosition;\n"
514 "uniform vec3 EyePosition;\n"
515 "uniform vec3 LightDir;\n"
517 "// TODO: get rid of tangentt (texcoord2) and use a crossproduct to regenerate it from tangents (texcoord1) and normal (texcoord3)\n"
521 " gl_FrontColor = gl_Color;\n"
522 " // copy the surface texcoord\n"
523 " TexCoord = vec2(gl_TextureMatrix[0] * gl_MultiTexCoord0);\n"
524 "#ifndef MODE_LIGHTSOURCE\n"
525 "# ifndef MODE_LIGHTDIRECTION\n"
526 " TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
530 "#ifdef MODE_LIGHTSOURCE\n"
531 " // transform vertex position into light attenuation/cubemap space\n"
532 " // (-1 to +1 across the light box)\n"
533 " CubeVector = vec3(gl_TextureMatrix[3] * gl_Vertex);\n"
535 " // transform unnormalized light direction into tangent space\n"
536 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
537 " // normalize it per pixel)\n"
538 " vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
539 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
540 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
541 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
544 "#ifdef MODE_LIGHTDIRECTION\n"
545 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
546 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
547 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
550 " // transform unnormalized eye direction into tangent space\n"
552 " vec3 EyeVectorModelSpace;\n"
554 " EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
555 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
556 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
557 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
559 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
560 " VectorS = gl_MultiTexCoord1.xyz;\n"
561 " VectorT = gl_MultiTexCoord2.xyz;\n"
562 " VectorR = gl_MultiTexCoord3.xyz;\n"
565 "//#if defined(MODE_WATER) || defined(MODE_REFRACTION) || defined(USEREFLECTION)\n"
566 "// ModelViewProjectionPosition = gl_Vertex * gl_ModelViewProjectionMatrix;\n"
567 "// //ModelViewProjectionPosition_svector = (gl_Vertex + vec4(gl_MultiTexCoord1.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
568 "// //ModelViewProjectionPosition_tvector = (gl_Vertex + vec4(gl_MultiTexCoord2.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
571 "// transform vertex to camera space, using ftransform to match non-VS\n"
573 " gl_Position = ftransform();\n"
575 "#ifdef MODE_WATER\n"
576 " ModelViewProjectionPosition = gl_Position;\n"
578 "#ifdef MODE_REFRACTION\n"
579 " ModelViewProjectionPosition = gl_Position;\n"
581 "#ifdef USEREFLECTION\n"
582 " ModelViewProjectionPosition = gl_Position;\n"
586 "#endif // VERTEX_SHADER\n"
591 "// fragment shader specific:\n"
592 "#ifdef FRAGMENT_SHADER\n"
594 "// 13 textures, we can only use up to 16 on DX9-class hardware\n"
595 "uniform sampler2D Texture_Normal;\n"
596 "uniform sampler2D Texture_Color;\n"
597 "uniform sampler2D Texture_Gloss;\n"
598 "uniform samplerCube Texture_Cube;\n"
599 "uniform sampler2D Texture_Attenuation;\n"
600 "uniform sampler2D Texture_FogMask;\n"
601 "uniform sampler2D Texture_Pants;\n"
602 "uniform sampler2D Texture_Shirt;\n"
603 "uniform sampler2D Texture_Lightmap;\n"
604 "uniform sampler2D Texture_Deluxemap;\n"
605 "uniform sampler2D Texture_Glow;\n"
606 "uniform sampler2D Texture_Reflection;\n"
607 "uniform sampler2D Texture_Refraction;\n"
609 "uniform myhvec3 LightColor;\n"
610 "uniform myhvec3 AmbientColor;\n"
611 "uniform myhvec3 DiffuseColor;\n"
612 "uniform myhvec3 SpecularColor;\n"
613 "uniform myhvec3 Color_Pants;\n"
614 "uniform myhvec3 Color_Shirt;\n"
615 "uniform myhvec3 FogColor;\n"
617 "uniform myhvec4 TintColor;\n"
620 "//#ifdef MODE_WATER\n"
621 "uniform vec4 DistortScaleRefractReflect;\n"
622 "uniform vec4 ScreenScaleRefractReflect;\n"
623 "uniform vec4 ScreenCenterRefractReflect;\n"
624 "uniform myhvec4 RefractColor;\n"
625 "uniform myhvec4 ReflectColor;\n"
626 "uniform myhalf ReflectFactor;\n"
627 "uniform myhalf ReflectOffset;\n"
629 "//# ifdef MODE_REFRACTION\n"
630 "//uniform vec4 DistortScaleRefractReflect;\n"
631 "//uniform vec4 ScreenScaleRefractReflect;\n"
632 "//uniform vec4 ScreenCenterRefractReflect;\n"
633 "//uniform myhvec4 RefractColor;\n"
634 "//# ifdef USEREFLECTION\n"
635 "//uniform myhvec4 ReflectColor;\n"
638 "//# ifdef USEREFLECTION\n"
639 "//uniform vec4 DistortScaleRefractReflect;\n"
640 "//uniform vec4 ScreenScaleRefractReflect;\n"
641 "//uniform vec4 ScreenCenterRefractReflect;\n"
642 "//uniform myhvec4 ReflectColor;\n"
647 "uniform myhalf GlowScale;\n"
648 "uniform myhalf SceneBrightness;\n"
649 "#ifdef USECONTRASTBOOST\n"
650 "uniform myhalf ContrastBoostCoeff;\n"
653 "uniform float OffsetMapping_Scale;\n"
654 "uniform float OffsetMapping_Bias;\n"
655 "uniform float FogRangeRecip;\n"
657 "uniform myhalf AmbientScale;\n"
658 "uniform myhalf DiffuseScale;\n"
659 "uniform myhalf SpecularScale;\n"
660 "uniform myhalf SpecularPower;\n"
662 "#ifdef USEOFFSETMAPPING\n"
663 "vec2 OffsetMapping(vec2 TexCoord)\n"
665 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
666 " // 14 sample relief mapping: linear search and then binary search\n"
667 " // this basically steps forward a small amount repeatedly until it finds\n"
668 " // itself inside solid, then jitters forward and back using decreasing\n"
669 " // amounts to find the impact\n"
670 " //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
671 " //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
672 " vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
673 " vec3 RT = vec3(TexCoord, 1);\n"
674 " OffsetVector *= 0.1;\n"
675 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
676 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
677 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
678 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
679 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
680 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
681 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
682 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
683 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
684 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) - 0.5);\n"
685 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5 - 0.25);\n"
686 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25 - 0.125);\n"
687 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125 - 0.0625);\n"
688 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
691 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
692 " // this basically moves forward the full distance, and then backs up based\n"
693 " // on height of samples\n"
694 " //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
695 " //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
696 " vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
697 " TexCoord += OffsetVector;\n"
698 " OffsetVector *= 0.333;\n"
699 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
700 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
701 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
702 " return TexCoord;\n"
705 "#endif // USEOFFSETMAPPING\n"
707 "#ifdef MODE_WATER\n"
712 "#ifdef USEOFFSETMAPPING\n"
713 " // apply offsetmapping\n"
714 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
715 "#define TexCoord TexCoordOffset\n"
718 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
719 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
720 " vec4 ScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect + vec2(normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5))).xyxy * DistortScaleRefractReflect;\n"
721 " float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 5.0) * ReflectFactor + ReflectOffset;\n"
722 " gl_FragColor = mix(texture2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, texture2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
725 "#else // MODE_WATER\n"
726 "#ifdef MODE_REFRACTION\n"
728 "// refraction pass\n"
731 "#ifdef USEOFFSETMAPPING\n"
732 " // apply offsetmapping\n"
733 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
734 "#define TexCoord TexCoordOffset\n"
737 " vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
738 " //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
739 " vec2 ScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy + vec2(normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
740 " gl_FragColor = texture2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
743 "#else // MODE_REFRACTION\n"
746 "#ifdef USEOFFSETMAPPING\n"
747 " // apply offsetmapping\n"
748 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
749 "#define TexCoord TexCoordOffset\n"
752 " // combine the diffuse textures (base, pants, shirt)\n"
753 " myhvec4 color = myhvec4(texture2D(Texture_Color, TexCoord));\n"
754 "#ifdef USECOLORMAPPING\n"
755 " color.rgb += myhvec3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhvec3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
761 "#ifdef MODE_LIGHTSOURCE\n"
764 " // calculate surface normal, light normal, and specular normal\n"
765 " // compute color intensity for the two textures (colormap and glossmap)\n"
766 " // scale by light color and attenuation as efficiently as possible\n"
767 " // (do as much scalar math as possible rather than vector math)\n"
768 "# ifdef USESPECULAR\n"
769 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
770 " myhvec3 diffusenormal = myhvec3(normalize(LightVector));\n"
771 " myhvec3 specularnormal = normalize(diffusenormal + myhvec3(normalize(EyeVector)));\n"
773 " // calculate directional shading\n"
774 " 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"
776 "# ifdef USEDIFFUSE\n"
777 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
778 " myhvec3 diffusenormal = myhvec3(normalize(LightVector));\n"
780 " // calculate directional shading\n"
781 " 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"
783 " // calculate directionless shading\n"
784 " color.rgb = color.rgb * LightColor * myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
788 "# ifdef USECUBEFILTER\n"
789 " // apply light cubemap filter\n"
790 " //color.rgb *= normalize(CubeVector) * 0.5 + 0.5;//vec3(textureCube(Texture_Cube, CubeVector));\n"
791 " color.rgb *= myhvec3(textureCube(Texture_Cube, CubeVector));\n"
793 "#endif // MODE_LIGHTSOURCE\n"
798 "#ifdef MODE_LIGHTDIRECTION\n"
799 " // directional model lighting\n"
800 "# ifdef USESPECULAR\n"
801 " // get the surface normal and light normal\n"
802 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
803 " myhvec3 diffusenormal = myhvec3(LightVector);\n"
805 " // calculate directional shading\n"
806 " color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
807 " myhvec3 specularnormal = normalize(diffusenormal + myhvec3(normalize(EyeVector)));\n"
808 " color.rgb += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
810 "# ifdef USEDIFFUSE\n"
811 " // get the surface normal and light normal\n"
812 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
813 " myhvec3 diffusenormal = myhvec3(LightVector);\n"
815 " // calculate directional shading\n"
816 " color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
818 " color.rgb *= AmbientColor;\n"
822 " color.a *= TintColor.a;\n"
823 "#endif // MODE_LIGHTDIRECTION\n"
828 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
829 " // deluxemap lightmapping using light vectors in modelspace (evil q3map2)\n"
831 " // get the surface normal and light normal\n"
832 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
834 " myhvec3 diffusenormal_modelspace = myhvec3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - myhvec3(0.5);\n"
835 " myhvec3 diffusenormal = normalize(myhvec3(dot(diffusenormal_modelspace, myhvec3(VectorS)), dot(diffusenormal_modelspace, myhvec3(VectorT)), dot(diffusenormal_modelspace, myhvec3(VectorR))));\n"
836 " // calculate directional shading\n"
837 " myhvec3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0)));\n"
838 "# ifdef USESPECULAR\n"
839 " myhvec3 specularnormal = myhvec3(normalize(diffusenormal + myhvec3(normalize(EyeVector))));\n"
840 " tempcolor += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
843 " // apply lightmap color\n"
844 " color.rgb = color.rgb * AmbientScale + tempcolor * myhvec3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
846 " color *= TintColor;\n"
847 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
852 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
853 " // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
855 " // get the surface normal and light normal\n"
856 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
858 " myhvec3 diffusenormal = normalize(myhvec3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - myhvec3(0.5));\n"
859 " // calculate directional shading\n"
860 " myhvec3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0)));\n"
861 "# ifdef USESPECULAR\n"
862 " myhvec3 specularnormal = myhvec3(normalize(diffusenormal + myhvec3(normalize(EyeVector))));\n"
863 " tempcolor += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
866 " // apply lightmap color\n"
867 " color.rgb = color.rgb * AmbientScale + tempcolor * myhvec3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
869 " color *= TintColor;\n"
870 "#endif // MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
875 "#ifdef MODE_LIGHTMAP\n"
876 " // apply lightmap color\n"
877 " color.rgb = color.rgb * myhvec3(texture2D(Texture_Lightmap, TexCoordLightmap)) * DiffuseScale + color.rgb * AmbientScale;\n"
879 " color *= TintColor;\n"
880 "#endif // MODE_LIGHTMAP\n"
885 "#ifdef MODE_VERTEXCOLOR\n"
886 " // apply lightmap color\n"
887 " color.rgb = color.rgb * myhvec3(gl_Color.rgb) * DiffuseScale + color.rgb * AmbientScale;\n"
889 " color *= TintColor;\n"
890 "#endif // MODE_VERTEXCOLOR\n"
895 "#ifdef MODE_FLATCOLOR\n"
896 " color *= TintColor;\n"
897 "#endif // MODE_FLATCOLOR\n"
907 " color.rgb += myhvec3(texture2D(Texture_Glow, TexCoord)) * GlowScale;\n"
910 "#ifdef USECONTRASTBOOST\n"
911 " color.rgb = color.rgb / (ContrastBoostCoeff * color.rgb + myhvec3(1, 1, 1));\n"
914 " color.rgb *= SceneBrightness;\n"
916 " // apply fog after Contrastboost/SceneBrightness because its color is already modified appropriately\n"
918 " color.rgb = mix(FogColor, color.rgb, myhalf(texture2D(Texture_FogMask, myhvec2(length(EyeVectorModelSpace)*FogRangeRecip, 0.0))));\n"
921 " // reflection must come last because it already contains exactly the correct fog (the reflection render preserves camera distance from the plane, it only flips the side) and ContrastBoost/SceneBrightness\n"
922 "#ifdef USEREFLECTION\n"
923 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
924 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
925 " vec4 ScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect + vec3(normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5))).xyxy * DistortScaleRefractReflect;\n"
926 " color.rgb = mix(color.rgb, myhvec3(texture2D(Texture_Reflection, ScreenTexCoord.zw)) * ReflectColor.rgb, ReflectColor.a);\n"
929 " gl_FragColor = vec4(color);\n"
931 "#endif // MODE_REFRACTION\n"
932 "#endif // MODE_WATER\n"
934 "#endif // FRAGMENT_SHADER\n"
937 #define SHADERPERMUTATION_COLORMAPPING (1<<0) // indicates this is a colormapped skin
938 #define SHADERPERMUTATION_CONTRASTBOOST (1<<1) // r_glsl_contrastboost boosts the contrast at low color levels (similar to gamma)
939 #define SHADERPERMUTATION_FOG (1<<2) // tint the color by fog color or black if using additive blend mode
940 #define SHADERPERMUTATION_CUBEFILTER (1<<3) // (lightsource) use cubemap light filter
941 #define SHADERPERMUTATION_GLOW (1<<4) // (lightmap) blend in an additive glow texture
942 #define SHADERPERMUTATION_DIFFUSE (1<<5) // (lightsource) whether to use directional shading
943 #define SHADERPERMUTATION_SPECULAR (1<<6) // (lightsource or deluxemapping) render specular effects
944 #define SHADERPERMUTATION_REFLECTION (1<<7) // normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
945 #define SHADERPERMUTATION_OFFSETMAPPING (1<<8) // adjust texcoords to roughly simulate a displacement mapped surface
946 #define SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING (1<<9) // adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
947 #define SHADERPERMUTATION_MODEBASE (1<<10) // multiplier for the SHADERMODE_ values to get a valid index
949 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
950 const char *shaderpermutationinfo[][2] =
952 {"#define USECOLORMAPPING\n", " colormapping"},
953 {"#define USECONTRASTBOOST\n", " contrastboost"},
954 {"#define USEFOG\n", " fog"},
955 {"#define USECUBEFILTER\n", " cubefilter"},
956 {"#define USEGLOW\n", " glow"},
957 {"#define USEDIFFUSE\n", " diffuse"},
958 {"#define USESPECULAR\n", " specular"},
959 {"#define USEREFLECTION\n", " reflection"},
960 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
961 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
965 // this enum is multiplied by SHADERPERMUTATION_MODEBASE
966 typedef enum shadermode_e
968 SHADERMODE_FLATCOLOR, // (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
969 SHADERMODE_VERTEXCOLOR, // (lightmap) modulate texture by vertex colors (q3bsp)
970 SHADERMODE_LIGHTMAP, // (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
971 SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, // (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
972 SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, // (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
973 SHADERMODE_LIGHTDIRECTION, // (lightmap) use directional pixel shading from fixed light direction (q3bsp)
974 SHADERMODE_LIGHTSOURCE, // (lightsource) use directional pixel shading from light source (rtlight)
975 SHADERMODE_REFRACTION, // refract background (the material is rendered normally after this pass)
976 SHADERMODE_WATER, // refract background and reflection (the material is rendered normally after this pass)
981 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
982 const char *shadermodeinfo[][2] =
984 {"#define MODE_FLATCOLOR\n", " flatcolor"},
985 {"#define MODE_VERTEXCOLOR\n", " vertexcolor"},
986 {"#define MODE_LIGHTMAP\n", " lightmap"},
987 {"#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
988 {"#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
989 {"#define MODE_LIGHTDIRECTION\n", " lightdirection"},
990 {"#define MODE_LIGHTSOURCE\n", " lightsource"},
991 {"#define MODE_REFRACTION\n", " refraction"},
992 {"#define MODE_WATER\n", " water"},
996 #define SHADERPERMUTATION_INDICES (SHADERPERMUTATION_MODEBASE * SHADERMODE_COUNT)
998 typedef struct r_glsl_permutation_s
1000 // indicates if we have tried compiling this permutation already
1002 // 0 if compilation failed
1004 // locations of detected uniforms in program object, or -1 if not found
1005 int loc_Texture_Normal;
1006 int loc_Texture_Color;
1007 int loc_Texture_Gloss;
1008 int loc_Texture_Cube;
1009 int loc_Texture_Attenuation;
1010 int loc_Texture_FogMask;
1011 int loc_Texture_Pants;
1012 int loc_Texture_Shirt;
1013 int loc_Texture_Lightmap;
1014 int loc_Texture_Deluxemap;
1015 int loc_Texture_Glow;
1016 int loc_Texture_Refraction;
1017 int loc_Texture_Reflection;
1019 int loc_LightPosition;
1020 int loc_EyePosition;
1022 int loc_Color_Pants;
1023 int loc_Color_Shirt;
1024 int loc_FogRangeRecip;
1025 int loc_AmbientScale;
1026 int loc_DiffuseScale;
1027 int loc_SpecularScale;
1028 int loc_SpecularPower;
1030 int loc_SceneBrightness; // or: Scenebrightness * ContrastBoost
1031 int loc_OffsetMapping_Scale;
1033 int loc_AmbientColor;
1034 int loc_DiffuseColor;
1035 int loc_SpecularColor;
1037 int loc_ContrastBoostCoeff; // 1 - 1/ContrastBoost
1038 int loc_DistortScaleRefractReflect;
1039 int loc_ScreenScaleRefractReflect;
1040 int loc_ScreenCenterRefractReflect;
1041 int loc_RefractColor;
1042 int loc_ReflectColor;
1043 int loc_ReflectFactor;
1044 int loc_ReflectOffset;
1046 r_glsl_permutation_t;
1048 // information about each possible shader permutation
1049 r_glsl_permutation_t r_glsl_permutations[SHADERPERMUTATION_INDICES];
1050 // currently selected permutation
1051 r_glsl_permutation_t *r_glsl_permutation;
1053 // these are additional flags used only by R_GLSL_CompilePermutation
1054 #define SHADERTYPE_USES_VERTEXSHADER (1<<0)
1055 #define SHADERTYPE_USES_GEOMETRYSHADER (1<<1)
1056 #define SHADERTYPE_USES_FRAGMENTSHADER (1<<2)
1058 static void R_GLSL_CompilePermutation(const char *filename, int permutation, int shadertype)
1061 qboolean shaderfound;
1062 r_glsl_permutation_t *p = r_glsl_permutations + permutation;
1063 int vertstrings_count;
1064 int geomstrings_count;
1065 int fragstrings_count;
1067 const char *vertstrings_list[32+1];
1068 const char *geomstrings_list[32+1];
1069 const char *fragstrings_list[32+1];
1070 char permutationname[256];
1075 vertstrings_list[0] = "#define VERTEX_SHADER\n";
1076 geomstrings_list[0] = "#define GEOMETRY_SHADER\n";
1077 fragstrings_list[0] = "#define FRAGMENT_SHADER\n";
1078 vertstrings_count = 1;
1079 geomstrings_count = 1;
1080 fragstrings_count = 1;
1081 permutationname[0] = 0;
1082 i = permutation / SHADERPERMUTATION_MODEBASE;
1083 vertstrings_list[vertstrings_count++] = shadermodeinfo[i][0];
1084 geomstrings_list[geomstrings_count++] = shadermodeinfo[i][0];
1085 fragstrings_list[fragstrings_count++] = shadermodeinfo[i][0];
1086 strlcat(permutationname, shadermodeinfo[i][1], sizeof(permutationname));
1087 for (i = 0;shaderpermutationinfo[i][0];i++)
1089 if (permutation & (1<<i))
1091 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i][0];
1092 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i][0];
1093 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i][0];
1094 strlcat(permutationname, shaderpermutationinfo[i][1], sizeof(permutationname));
1098 // keep line numbers correct
1099 vertstrings_list[vertstrings_count++] = "\n";
1100 geomstrings_list[geomstrings_count++] = "\n";
1101 fragstrings_list[fragstrings_count++] = "\n";
1104 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1105 shaderfound = false;
1108 Con_DPrint("from disk... ");
1109 vertstrings_list[vertstrings_count++] = shaderstring;
1110 geomstrings_list[geomstrings_count++] = shaderstring;
1111 fragstrings_list[fragstrings_count++] = shaderstring;
1114 else if (!strcmp(filename, "glsl/default.glsl"))
1116 vertstrings_list[vertstrings_count++] = builtinshaderstring;
1117 geomstrings_list[geomstrings_count++] = builtinshaderstring;
1118 fragstrings_list[fragstrings_count++] = builtinshaderstring;
1121 // clear any lists that are not needed by this shader
1122 if (!(shadertype & SHADERTYPE_USES_VERTEXSHADER))
1123 vertstrings_count = 0;
1124 if (!(shadertype & SHADERTYPE_USES_GEOMETRYSHADER))
1125 geomstrings_count = 0;
1126 if (!(shadertype & SHADERTYPE_USES_FRAGMENTSHADER))
1127 fragstrings_count = 0;
1128 // compile the shader program
1129 if (shaderfound && vertstrings_count + geomstrings_count + fragstrings_count)
1130 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1134 qglUseProgramObjectARB(p->program);CHECKGLERROR
1135 // look up all the uniform variable names we care about, so we don't
1136 // have to look them up every time we set them
1137 p->loc_Texture_Normal = qglGetUniformLocationARB(p->program, "Texture_Normal");
1138 p->loc_Texture_Color = qglGetUniformLocationARB(p->program, "Texture_Color");
1139 p->loc_Texture_Gloss = qglGetUniformLocationARB(p->program, "Texture_Gloss");
1140 p->loc_Texture_Cube = qglGetUniformLocationARB(p->program, "Texture_Cube");
1141 p->loc_Texture_Attenuation = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
1142 p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
1143 p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
1144 p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
1145 p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
1146 p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
1147 p->loc_Texture_Glow = qglGetUniformLocationARB(p->program, "Texture_Glow");
1148 p->loc_Texture_Refraction = qglGetUniformLocationARB(p->program, "Texture_Refraction");
1149 p->loc_Texture_Reflection = qglGetUniformLocationARB(p->program, "Texture_Reflection");
1150 p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
1151 p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
1152 p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
1153 p->loc_LightColor = qglGetUniformLocationARB(p->program, "LightColor");
1154 p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants");
1155 p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt");
1156 p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip");
1157 p->loc_AmbientScale = qglGetUniformLocationARB(p->program, "AmbientScale");
1158 p->loc_DiffuseScale = qglGetUniformLocationARB(p->program, "DiffuseScale");
1159 p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
1160 p->loc_SpecularScale = qglGetUniformLocationARB(p->program, "SpecularScale");
1161 p->loc_GlowScale = qglGetUniformLocationARB(p->program, "GlowScale");
1162 p->loc_SceneBrightness = qglGetUniformLocationARB(p->program, "SceneBrightness");
1163 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
1164 p->loc_TintColor = qglGetUniformLocationARB(p->program, "TintColor");
1165 p->loc_AmbientColor = qglGetUniformLocationARB(p->program, "AmbientColor");
1166 p->loc_DiffuseColor = qglGetUniformLocationARB(p->program, "DiffuseColor");
1167 p->loc_SpecularColor = qglGetUniformLocationARB(p->program, "SpecularColor");
1168 p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
1169 p->loc_ContrastBoostCoeff = qglGetUniformLocationARB(p->program, "ContrastBoostCoeff");
1170 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
1171 p->loc_ScreenScaleRefractReflect = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
1172 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
1173 p->loc_RefractColor = qglGetUniformLocationARB(p->program, "RefractColor");
1174 p->loc_ReflectColor = qglGetUniformLocationARB(p->program, "ReflectColor");
1175 p->loc_ReflectFactor = qglGetUniformLocationARB(p->program, "ReflectFactor");
1176 p->loc_ReflectOffset = qglGetUniformLocationARB(p->program, "ReflectOffset");
1177 // initialize the samplers to refer to the texture units we use
1178 if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal, 0);
1179 if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color, 1);
1180 if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss, 2);
1181 if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube, 3);
1182 if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask, 4);
1183 if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants, 5);
1184 if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt, 6);
1185 if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap, 7);
1186 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap, 8);
1187 if (p->loc_Texture_Glow >= 0) qglUniform1iARB(p->loc_Texture_Glow, 9);
1188 if (p->loc_Texture_Attenuation >= 0) qglUniform1iARB(p->loc_Texture_Attenuation, 10);
1189 if (p->loc_Texture_Refraction >= 0) qglUniform1iARB(p->loc_Texture_Refraction, 11);
1190 if (p->loc_Texture_Reflection >= 0) qglUniform1iARB(p->loc_Texture_Reflection, 12);
1192 qglUseProgramObjectARB(0);CHECKGLERROR
1193 if (developer.integer)
1194 Con_Printf("GLSL shader %s :%s compiled.\n", filename, permutationname);
1198 if (developer.integer)
1199 Con_Printf("GLSL shader %s :%s failed! source code line offset for above errors is %i.\n", permutationname, filename, -(vertstrings_count - 1));
1201 Con_Printf("GLSL shader %s :%s failed! some features may not work properly.\n", permutationname, filename);
1204 Mem_Free(shaderstring);
1207 void R_GLSL_Restart_f(void)
1210 for (i = 0;i < SHADERPERMUTATION_INDICES;i++)
1211 if (r_glsl_permutations[i].program)
1212 GL_Backend_FreeProgram(r_glsl_permutations[i].program);
1213 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
1216 void R_GLSL_DumpShader_f(void)
1220 qfile_t *file = FS_Open("glsl/default.glsl", "w", false, false);
1223 Con_Printf("failed to write to glsl/default.glsl\n");
1227 FS_Print(file, "// The engine may define the following macros:\n");
1228 FS_Print(file, "// #define VERTEX_SHADER\n// #define GEOMETRY_SHADER\n// #define FRAGMENT_SHADER\n");
1229 for (i = 0;shadermodeinfo[i][0];i++)
1230 FS_Printf(file, "// %s", shadermodeinfo[i][0]);
1231 for (i = 0;shaderpermutationinfo[i][0];i++)
1232 FS_Printf(file, "// %s", shaderpermutationinfo[i][0]);
1233 FS_Print(file, "\n");
1234 FS_Print(file, builtinshaderstring);
1237 Con_Printf("glsl/default.glsl written\n");
1240 extern rtexture_t *r_shadow_attenuationgradienttexture;
1241 extern rtexture_t *r_shadow_attenuation2dtexture;
1242 extern rtexture_t *r_shadow_attenuation3dtexture;
1243 int R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass)
1245 // select a permutation of the lighting shader appropriate to this
1246 // combination of texture, entity, light source, and fogging, only use the
1247 // minimum features necessary to avoid wasting rendering time in the
1248 // fragment shader on features that are not being used
1249 const char *shaderfilename = NULL;
1250 unsigned int permutation = 0;
1251 unsigned int shadertype = 0;
1252 shadermode_t mode = 0;
1253 r_glsl_permutation = NULL;
1254 shaderfilename = "glsl/default.glsl";
1255 shadertype = SHADERTYPE_USES_VERTEXSHADER | SHADERTYPE_USES_FRAGMENTSHADER;
1256 // TODO: implement geometry-shader based shadow volumes someday
1257 if (r_glsl_offsetmapping.integer)
1259 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
1260 if (r_glsl_offsetmapping_reliefmapping.integer)
1261 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
1263 if (rsurfacepass == RSURFPASS_BACKGROUND)
1265 // distorted background
1266 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
1267 mode = SHADERMODE_WATER;
1269 mode = SHADERMODE_REFRACTION;
1271 else if (rsurfacepass == RSURFPASS_RTLIGHT)
1274 mode = SHADERMODE_LIGHTSOURCE;
1275 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
1276 permutation |= SHADERPERMUTATION_CUBEFILTER;
1277 if (diffusescale > 0)
1278 permutation |= SHADERPERMUTATION_DIFFUSE;
1279 if (specularscale > 0)
1280 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
1281 if (r_refdef.fogenabled)
1282 permutation |= SHADERPERMUTATION_FOG;
1283 if (rsurface.texture->colormapping)
1284 permutation |= SHADERPERMUTATION_COLORMAPPING;
1285 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1286 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1288 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
1290 // unshaded geometry (fullbright or ambient model lighting)
1291 mode = SHADERMODE_FLATCOLOR;
1292 if (rsurface.texture->currentskinframe->glow)
1293 permutation |= SHADERPERMUTATION_GLOW;
1294 if (r_refdef.fogenabled)
1295 permutation |= SHADERPERMUTATION_FOG;
1296 if (rsurface.texture->colormapping)
1297 permutation |= SHADERPERMUTATION_COLORMAPPING;
1298 if (r_glsl_offsetmapping.integer)
1300 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
1301 if (r_glsl_offsetmapping_reliefmapping.integer)
1302 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
1304 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1305 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1306 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1307 permutation |= SHADERPERMUTATION_REFLECTION;
1309 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
1311 // directional model lighting
1312 mode = SHADERMODE_LIGHTDIRECTION;
1313 if (rsurface.texture->currentskinframe->glow)
1314 permutation |= SHADERPERMUTATION_GLOW;
1315 permutation |= SHADERPERMUTATION_DIFFUSE;
1316 if (specularscale > 0)
1317 permutation |= SHADERPERMUTATION_SPECULAR;
1318 if (r_refdef.fogenabled)
1319 permutation |= SHADERPERMUTATION_FOG;
1320 if (rsurface.texture->colormapping)
1321 permutation |= SHADERPERMUTATION_COLORMAPPING;
1322 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1323 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1324 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1325 permutation |= SHADERPERMUTATION_REFLECTION;
1327 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
1329 // ambient model lighting
1330 mode = SHADERMODE_LIGHTDIRECTION;
1331 if (rsurface.texture->currentskinframe->glow)
1332 permutation |= SHADERPERMUTATION_GLOW;
1333 if (r_refdef.fogenabled)
1334 permutation |= SHADERPERMUTATION_FOG;
1335 if (rsurface.texture->colormapping)
1336 permutation |= SHADERPERMUTATION_COLORMAPPING;
1337 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1338 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1339 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1340 permutation |= SHADERPERMUTATION_REFLECTION;
1345 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.worldmodel && r_refdef.worldmodel->brushq3.deluxemapping)
1347 // deluxemapping (light direction texture)
1348 if (rsurface.uselightmaptexture && r_refdef.worldmodel && r_refdef.worldmodel->brushq3.deluxemapping && r_refdef.worldmodel->brushq3.deluxemapping_modelspace)
1349 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
1351 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
1352 if (specularscale > 0)
1353 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
1355 else if (r_glsl_deluxemapping.integer >= 2)
1357 // fake deluxemapping (uniform light direction in tangentspace)
1358 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
1359 if (specularscale > 0)
1360 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
1362 else if (rsurface.uselightmaptexture)
1364 // ordinary lightmapping (q1bsp, q3bsp)
1365 mode = SHADERMODE_LIGHTMAP;
1369 // ordinary vertex coloring (q3bsp)
1370 mode = SHADERMODE_VERTEXCOLOR;
1372 if (rsurface.texture->currentskinframe->glow)
1373 permutation |= SHADERPERMUTATION_GLOW;
1374 if (r_refdef.fogenabled)
1375 permutation |= SHADERPERMUTATION_FOG;
1376 if (rsurface.texture->colormapping)
1377 permutation |= SHADERPERMUTATION_COLORMAPPING;
1378 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1379 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1380 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1381 permutation |= SHADERPERMUTATION_REFLECTION;
1383 permutation |= mode * SHADERPERMUTATION_MODEBASE;
1384 if (!r_glsl_permutations[permutation].program)
1386 if (!r_glsl_permutations[permutation].compiled)
1387 R_GLSL_CompilePermutation(shaderfilename, permutation, shadertype);
1388 if (!r_glsl_permutations[permutation].program)
1390 // remove features until we find a valid permutation
1392 for (i = (SHADERPERMUTATION_MODEBASE >> 1);;i>>=1)
1396 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");
1397 Cvar_SetValueQuick(&r_glsl, 0);
1398 return 0; // no bit left to clear
1400 // reduce i more quickly whenever it would not remove any bits
1401 if (!(permutation & i))
1404 if (!r_glsl_permutations[permutation].compiled)
1405 R_GLSL_CompilePermutation(shaderfilename, permutation, shadertype);
1406 if (r_glsl_permutations[permutation].program)
1411 r_glsl_permutation = r_glsl_permutations + permutation;
1413 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
1414 if (mode == SHADERMODE_LIGHTSOURCE)
1416 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
1417 if (permutation & SHADERPERMUTATION_DIFFUSE)
1419 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
1420 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, ambientscale);
1421 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, diffusescale);
1422 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, specularscale);
1426 // ambient only is simpler
1427 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0] * ambientscale, lightcolorbase[1] * ambientscale, lightcolorbase[2] * ambientscale);
1428 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, 1);
1429 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, 0);
1430 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, 0);
1433 else if (mode == SHADERMODE_LIGHTDIRECTION)
1435 if (r_glsl_permutation->loc_AmbientColor >= 0)
1436 qglUniform3fARB(r_glsl_permutation->loc_AmbientColor , rsurface.modellight_ambient[0] * ambientscale * rsurface.texture->lightmapcolor[0] * 0.5f, rsurface.modellight_ambient[1] * ambientscale * rsurface.texture->lightmapcolor[1] * 0.5f, rsurface.modellight_ambient[2] * ambientscale * rsurface.texture->lightmapcolor[2] * 0.5f);
1437 if (r_glsl_permutation->loc_DiffuseColor >= 0)
1438 qglUniform3fARB(r_glsl_permutation->loc_DiffuseColor , rsurface.modellight_diffuse[0] * diffusescale * rsurface.texture->lightmapcolor[0] * 0.5f, rsurface.modellight_diffuse[1] * diffusescale * rsurface.texture->lightmapcolor[1] * 0.5f, rsurface.modellight_diffuse[2] * diffusescale * rsurface.texture->lightmapcolor[2] * 0.5f);
1439 if (r_glsl_permutation->loc_SpecularColor >= 0)
1440 qglUniform3fARB(r_glsl_permutation->loc_SpecularColor, rsurface.modellight_diffuse[0] * specularscale * rsurface.texture->lightmapcolor[0] * 0.5f, rsurface.modellight_diffuse[1] * specularscale * rsurface.texture->lightmapcolor[1] * 0.5f, rsurface.modellight_diffuse[2] * specularscale * rsurface.texture->lightmapcolor[2] * 0.5f);
1441 if (r_glsl_permutation->loc_LightDir >= 0)
1442 qglUniform3fARB(r_glsl_permutation->loc_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
1446 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_ambient.value * 1.0f / 128.0f);
1447 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_refdef.lightmapintensity);
1448 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, r_refdef.lightmapintensity * specularscale);
1450 if (r_glsl_permutation->loc_TintColor >= 0) qglUniform4fARB(r_glsl_permutation->loc_TintColor, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2], rsurface.texture->lightmapcolor[3]);
1451 if (r_glsl_permutation->loc_GlowScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_GlowScale, r_hdr_glowintensity.value);
1452 if (r_glsl_permutation->loc_ContrastBoostCoeff >= 0)
1454 // The formula used is actually:
1455 // color.rgb *= ContrastBoost / ((ContrastBoost - 1) * color.rgb + 1);
1456 // color.rgb *= SceneBrightness;
1458 // color.rgb = [[SceneBrightness * ContrastBoost]] * color.rgb / ([[ContrastBoost - 1]] * color.rgb + 1);
1459 // and do [[calculations]] here in the engine
1460 qglUniform1fARB(r_glsl_permutation->loc_ContrastBoostCoeff, r_glsl_contrastboost.value - 1);
1461 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_view.colorscale * r_glsl_contrastboost.value);
1464 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_view.colorscale);
1465 if (r_glsl_permutation->loc_FogColor >= 0)
1467 // additive passes are only darkened by fog, not tinted
1468 if (rsurface.rtlight || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD))
1469 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
1471 qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
1473 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.modelorg[0], rsurface.modelorg[1], rsurface.modelorg[2]);
1474 if (r_glsl_permutation->loc_Color_Pants >= 0)
1476 if (rsurface.texture->currentskinframe->pants)
1477 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
1479 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
1481 if (r_glsl_permutation->loc_Color_Shirt >= 0)
1483 if (rsurface.texture->currentskinframe->shirt)
1484 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
1486 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
1488 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, r_refdef.fograngerecip);
1489 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower);
1490 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
1491 if (r_glsl_permutation->loc_DistortScaleRefractReflect >= 0) qglUniform4fARB(r_glsl_permutation->loc_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);
1492 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]);
1493 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]);
1494 if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f);
1495 if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f);
1496 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
1497 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
1502 #define SKINFRAME_HASH 1024
1506 int loadsequence; // incremented each level change
1507 memexpandablearray_t array;
1508 skinframe_t *hash[SKINFRAME_HASH];
1512 void R_SkinFrame_PrepareForPurge(void)
1514 r_skinframe.loadsequence++;
1515 // wrap it without hitting zero
1516 if (r_skinframe.loadsequence >= 200)
1517 r_skinframe.loadsequence = 1;
1520 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
1524 // mark the skinframe as used for the purging code
1525 skinframe->loadsequence = r_skinframe.loadsequence;
1528 void R_SkinFrame_Purge(void)
1532 for (i = 0;i < SKINFRAME_HASH;i++)
1534 for (s = r_skinframe.hash[i];s;s = s->next)
1536 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
1538 if (s->merged == s->base)
1540 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
1541 R_PurgeTexture(s->stain );s->stain = NULL;
1542 R_PurgeTexture(s->merged);s->merged = NULL;
1543 R_PurgeTexture(s->base );s->base = NULL;
1544 R_PurgeTexture(s->pants );s->pants = NULL;
1545 R_PurgeTexture(s->shirt );s->shirt = NULL;
1546 R_PurgeTexture(s->nmap );s->nmap = NULL;
1547 R_PurgeTexture(s->gloss );s->gloss = NULL;
1548 R_PurgeTexture(s->glow );s->glow = NULL;
1549 R_PurgeTexture(s->fog );s->fog = NULL;
1550 s->loadsequence = 0;
1556 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
1558 char basename[MAX_QPATH];
1560 Image_StripImageExtension(name, basename, sizeof(basename));
1562 if( last == NULL ) {
1564 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
1565 item = r_skinframe.hash[hashindex];
1570 // linearly search through the hash bucket
1571 for( ; item ; item = item->next ) {
1572 if( !strcmp( item->basename, basename ) ) {
1579 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
1583 char basename[MAX_QPATH];
1585 Image_StripImageExtension(name, basename, sizeof(basename));
1587 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
1588 for (item = r_skinframe.hash[hashindex];item;item = item->next)
1589 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
1593 rtexture_t *dyntexture;
1594 // check whether its a dynamic texture
1595 dyntexture = CL_GetDynTexture( basename );
1596 if (!add && !dyntexture)
1598 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
1599 memset(item, 0, sizeof(*item));
1600 strlcpy(item->basename, basename, sizeof(item->basename));
1601 item->base = dyntexture; // either NULL or dyntexture handle
1602 item->textureflags = textureflags;
1603 item->comparewidth = comparewidth;
1604 item->compareheight = compareheight;
1605 item->comparecrc = comparecrc;
1606 item->next = r_skinframe.hash[hashindex];
1607 r_skinframe.hash[hashindex] = item;
1609 else if( item->base == NULL )
1611 rtexture_t *dyntexture;
1612 // check whether its a dynamic texture
1613 // this only needs to be done because Purge doesnt delete skinframes - only sets the texture pointers to NULL and we need to restore it before returing.. [11/29/2007 Black]
1614 dyntexture = CL_GetDynTexture( basename );
1615 item->base = dyntexture; // either NULL or dyntexture handle
1618 R_SkinFrame_MarkUsed(item);
1622 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
1624 // FIXME: it should be possible to disable loading various layers using
1625 // cvars, to prevent wasted loading time and memory usage if the user does
1627 qboolean loadnormalmap = true;
1628 qboolean loadgloss = true;
1629 qboolean loadpantsandshirt = true;
1630 qboolean loadglow = true;
1632 unsigned char *pixels;
1633 unsigned char *bumppixels;
1634 unsigned char *basepixels = NULL;
1635 int basepixels_width;
1636 int basepixels_height;
1637 skinframe_t *skinframe;
1639 if (cls.state == ca_dedicated)
1642 // return an existing skinframe if already loaded
1643 // if loading of the first image fails, don't make a new skinframe as it
1644 // would cause all future lookups of this to be missing
1645 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
1646 if (skinframe && skinframe->base)
1649 basepixels = loadimagepixelsbgra(name, complain, true);
1650 if (basepixels == NULL)
1653 // we've got some pixels to store, so really allocate this new texture now
1655 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
1656 skinframe->stain = NULL;
1657 skinframe->merged = NULL;
1658 skinframe->base = r_texture_notexture;
1659 skinframe->pants = NULL;
1660 skinframe->shirt = NULL;
1661 skinframe->nmap = r_texture_blanknormalmap;
1662 skinframe->gloss = NULL;
1663 skinframe->glow = NULL;
1664 skinframe->fog = NULL;
1666 basepixels_width = image_width;
1667 basepixels_height = image_height;
1668 skinframe->base = R_LoadTexture2D (r_main_texturepool, skinframe->basename, basepixels_width, basepixels_height, basepixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), NULL);
1670 if (textureflags & TEXF_ALPHA)
1672 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
1673 if (basepixels[j] < 255)
1675 if (j < basepixels_width * basepixels_height * 4)
1677 // has transparent pixels
1678 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
1679 for (j = 0;j < image_width * image_height * 4;j += 4)
1684 pixels[j+3] = basepixels[j+3];
1686 skinframe->fog = R_LoadTexture2D (r_main_texturepool, va("%s_mask", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), NULL);
1691 // _norm is the name used by tenebrae and has been adopted as standard
1694 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false)) != NULL)
1696 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), NULL);
1700 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false)) != NULL)
1702 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
1703 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
1704 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), NULL);
1706 Mem_Free(bumppixels);
1708 else if (r_shadow_bumpscale_basetexture.value > 0)
1710 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
1711 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
1712 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), basepixels_width, basepixels_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), NULL);
1716 // _luma is supported for tenebrae compatibility
1717 // (I think it's a very stupid name, but oh well)
1718 // _glow is the preferred name
1719 if (loadglow && ((pixels = loadimagepixelsbgra(va("%s_glow", skinframe->basename), false, false)) != NULL || (pixels = loadimagepixelsbgra(va("%s_luma", skinframe->basename), false, false)) != NULL)) {skinframe->glow = R_LoadTexture2D (r_main_texturepool, va("%s_glow", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_glow.integer ? ~0 : ~TEXF_COMPRESS), NULL);Mem_Free(pixels);pixels = NULL;}
1720 if (loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false)) != NULL) {skinframe->gloss = R_LoadTexture2D (r_main_texturepool, va("%s_gloss", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_gloss.integer ? ~0 : ~TEXF_COMPRESS), NULL);Mem_Free(pixels);pixels = NULL;}
1721 if (loadpantsandshirt && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false)) != NULL) {skinframe->pants = R_LoadTexture2D (r_main_texturepool, va("%s_pants", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), NULL);Mem_Free(pixels);pixels = NULL;}
1722 if (loadpantsandshirt && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false)) != NULL) {skinframe->shirt = R_LoadTexture2D (r_main_texturepool, va("%s_shirt", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), NULL);Mem_Free(pixels);pixels = NULL;}
1725 Mem_Free(basepixels);
1730 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)
1735 for (i = 0;i < width*height;i++)
1736 if (((unsigned char *)&palette[in[i]])[3] > 0)
1738 if (i == width*height)
1741 return R_LoadTexture2D (r_main_texturepool, name, width, height, in, TEXTYPE_PALETTE, textureflags, palette);
1744 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
1745 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
1748 unsigned char *temp1, *temp2;
1749 skinframe_t *skinframe;
1751 if (cls.state == ca_dedicated)
1754 // if already loaded just return it, otherwise make a new skinframe
1755 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
1756 if (skinframe && skinframe->base)
1759 skinframe->stain = NULL;
1760 skinframe->merged = NULL;
1761 skinframe->base = r_texture_notexture;
1762 skinframe->pants = NULL;
1763 skinframe->shirt = NULL;
1764 skinframe->nmap = r_texture_blanknormalmap;
1765 skinframe->gloss = NULL;
1766 skinframe->glow = NULL;
1767 skinframe->fog = NULL;
1769 // if no data was provided, then clearly the caller wanted to get a blank skinframe
1773 if (r_shadow_bumpscale_basetexture.value > 0)
1775 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
1776 temp2 = temp1 + width * height * 4;
1777 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
1778 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
1781 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, skinframe->textureflags, NULL);
1782 if (textureflags & TEXF_ALPHA)
1784 for (i = 3;i < width * height * 4;i += 4)
1785 if (skindata[i] < 255)
1787 if (i < width * height * 4)
1789 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
1790 memcpy(fogpixels, skindata, width * height * 4);
1791 for (i = 0;i < width * height * 4;i += 4)
1792 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
1793 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, skinframe->textureflags, NULL);
1794 Mem_Free(fogpixels);
1801 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
1804 unsigned char *temp1, *temp2;
1805 skinframe_t *skinframe;
1807 if (cls.state == ca_dedicated)
1810 // if already loaded just return it, otherwise make a new skinframe
1811 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
1812 if (skinframe && skinframe->base)
1815 skinframe->stain = NULL;
1816 skinframe->merged = NULL;
1817 skinframe->base = r_texture_notexture;
1818 skinframe->pants = NULL;
1819 skinframe->shirt = NULL;
1820 skinframe->nmap = r_texture_blanknormalmap;
1821 skinframe->gloss = NULL;
1822 skinframe->glow = NULL;
1823 skinframe->fog = NULL;
1825 // if no data was provided, then clearly the caller wanted to get a blank skinframe
1829 if (r_shadow_bumpscale_basetexture.value > 0)
1831 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
1832 temp2 = temp1 + width * height * 4;
1833 // use either a custom palette or the quake palette
1834 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
1835 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
1836 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
1839 // use either a custom palette, or the quake palette
1840 skinframe->base = skinframe->merged = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_merged", skinframe->basename), (loadglowtexture ? palette_bgra_nofullbrights : ((skinframe->textureflags & TEXF_ALPHA) ? palette_bgra_transparent : palette_bgra_complete)), skinframe->textureflags, true); // all
1841 if (loadglowtexture)
1842 skinframe->glow = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_glow", skinframe->basename), palette_bgra_onlyfullbrights, skinframe->textureflags, false); // glow
1843 if (loadpantsandshirt)
1845 skinframe->pants = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_pants", skinframe->basename), palette_bgra_pantsaswhite, skinframe->textureflags, false); // pants
1846 skinframe->shirt = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_shirt", skinframe->basename), palette_bgra_shirtaswhite, skinframe->textureflags, false); // shirt
1848 if (skinframe->pants || skinframe->shirt)
1849 skinframe->base = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_nospecial", skinframe->basename), loadglowtexture ? palette_bgra_nocolormapnofullbrights : palette_bgra_nocolormap, skinframe->textureflags, false); // no special colors
1850 if (textureflags & TEXF_ALPHA)
1852 for (i = 0;i < width * height;i++)
1853 if (((unsigned char *)palette_bgra_alpha)[skindata[i]*4+3] < 255)
1855 if (i < width * height)
1856 skinframe->fog = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_fog", skinframe->basename), palette_bgra_alpha, skinframe->textureflags, true); // fog mask
1862 skinframe_t *R_SkinFrame_LoadMissing(void)
1864 skinframe_t *skinframe;
1866 if (cls.state == ca_dedicated)
1869 skinframe = R_SkinFrame_Find("missing", TEXF_PRECACHE, 0, 0, 0, true);
1870 skinframe->stain = NULL;
1871 skinframe->merged = NULL;
1872 skinframe->base = r_texture_notexture;
1873 skinframe->pants = NULL;
1874 skinframe->shirt = NULL;
1875 skinframe->nmap = r_texture_blanknormalmap;
1876 skinframe->gloss = NULL;
1877 skinframe->glow = NULL;
1878 skinframe->fog = NULL;
1883 void gl_main_start(void)
1885 memset(r_qwskincache, 0, sizeof(r_qwskincache));
1886 memset(r_qwskincache_skinframe, 0, sizeof(r_qwskincache_skinframe));
1888 // set up r_skinframe loading system for textures
1889 memset(&r_skinframe, 0, sizeof(r_skinframe));
1890 r_skinframe.loadsequence = 1;
1891 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
1893 r_main_texturepool = R_AllocTexturePool();
1894 R_BuildBlankTextures();
1896 if (gl_texturecubemap)
1899 R_BuildNormalizationCube();
1901 r_texture_fogattenuation = NULL;
1902 //r_texture_fogintensity = NULL;
1903 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
1904 memset(&r_waterstate, 0, sizeof(r_waterstate));
1905 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
1906 memset(&r_svbsp, 0, sizeof (r_svbsp));
1908 r_refdef.fogmasktable_density = 0;
1911 void gl_main_shutdown(void)
1913 memset(r_qwskincache, 0, sizeof(r_qwskincache));
1914 memset(r_qwskincache_skinframe, 0, sizeof(r_qwskincache_skinframe));
1916 // clear out the r_skinframe state
1917 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
1918 memset(&r_skinframe, 0, sizeof(r_skinframe));
1921 Mem_Free(r_svbsp.nodes);
1922 memset(&r_svbsp, 0, sizeof (r_svbsp));
1923 R_FreeTexturePool(&r_main_texturepool);
1924 r_texture_blanknormalmap = NULL;
1925 r_texture_white = NULL;
1926 r_texture_grey128 = NULL;
1927 r_texture_black = NULL;
1928 r_texture_whitecube = NULL;
1929 r_texture_normalizationcube = NULL;
1930 r_texture_fogattenuation = NULL;
1931 //r_texture_fogintensity = NULL;
1932 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
1933 memset(&r_waterstate, 0, sizeof(r_waterstate));
1937 extern void CL_ParseEntityLump(char *entitystring);
1938 void gl_main_newmap(void)
1940 // FIXME: move this code to client
1942 char *entities, entname[MAX_QPATH];
1945 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
1946 l = (int)strlen(entname) - 4;
1947 if (l >= 0 && !strcmp(entname + l, ".bsp"))
1949 memcpy(entname + l, ".ent", 5);
1950 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
1952 CL_ParseEntityLump(entities);
1957 if (cl.worldmodel->brush.entities)
1958 CL_ParseEntityLump(cl.worldmodel->brush.entities);
1962 void GL_Main_Init(void)
1964 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
1966 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
1967 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
1968 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
1969 if (gamemode == GAME_NEHAHRA)
1971 Cvar_RegisterVariable (&gl_fogenable);
1972 Cvar_RegisterVariable (&gl_fogdensity);
1973 Cvar_RegisterVariable (&gl_fogred);
1974 Cvar_RegisterVariable (&gl_foggreen);
1975 Cvar_RegisterVariable (&gl_fogblue);
1976 Cvar_RegisterVariable (&gl_fogstart);
1977 Cvar_RegisterVariable (&gl_fogend);
1978 Cvar_RegisterVariable (&gl_skyclip);
1980 Cvar_RegisterVariable(&r_depthfirst);
1981 Cvar_RegisterVariable(&r_nearclip);
1982 Cvar_RegisterVariable(&r_showbboxes);
1983 Cvar_RegisterVariable(&r_showsurfaces);
1984 Cvar_RegisterVariable(&r_showtris);
1985 Cvar_RegisterVariable(&r_shownormals);
1986 Cvar_RegisterVariable(&r_showlighting);
1987 Cvar_RegisterVariable(&r_showshadowvolumes);
1988 Cvar_RegisterVariable(&r_showcollisionbrushes);
1989 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
1990 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
1991 Cvar_RegisterVariable(&r_showdisabledepthtest);
1992 Cvar_RegisterVariable(&r_drawportals);
1993 Cvar_RegisterVariable(&r_drawentities);
1994 Cvar_RegisterVariable(&r_cullentities_trace);
1995 Cvar_RegisterVariable(&r_cullentities_trace_samples);
1996 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
1997 Cvar_RegisterVariable(&r_cullentities_trace_delay);
1998 Cvar_RegisterVariable(&r_drawviewmodel);
1999 Cvar_RegisterVariable(&r_speeds);
2000 Cvar_RegisterVariable(&r_fullbrights);
2001 Cvar_RegisterVariable(&r_wateralpha);
2002 Cvar_RegisterVariable(&r_dynamic);
2003 Cvar_RegisterVariable(&r_fullbright);
2004 Cvar_RegisterVariable(&r_shadows);
2005 Cvar_RegisterVariable(&r_shadows_throwdistance);
2006 Cvar_RegisterVariable(&r_q1bsp_skymasking);
2007 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
2008 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
2009 Cvar_RegisterVariable(&r_fog_exp2);
2010 Cvar_RegisterVariable(&r_textureunits);
2011 Cvar_RegisterVariable(&r_glsl);
2012 Cvar_RegisterVariable(&r_glsl_offsetmapping);
2013 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
2014 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
2015 Cvar_RegisterVariable(&r_glsl_deluxemapping);
2016 Cvar_RegisterVariable(&r_water);
2017 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
2018 Cvar_RegisterVariable(&r_water_clippingplanebias);
2019 Cvar_RegisterVariable(&r_water_refractdistort);
2020 Cvar_RegisterVariable(&r_water_reflectdistort);
2021 Cvar_RegisterVariable(&r_lerpsprites);
2022 Cvar_RegisterVariable(&r_lerpmodels);
2023 Cvar_RegisterVariable(&r_lerplightstyles);
2024 Cvar_RegisterVariable(&r_waterscroll);
2025 Cvar_RegisterVariable(&r_bloom);
2026 Cvar_RegisterVariable(&r_bloom_colorscale);
2027 Cvar_RegisterVariable(&r_bloom_brighten);
2028 Cvar_RegisterVariable(&r_bloom_blur);
2029 Cvar_RegisterVariable(&r_bloom_resolution);
2030 Cvar_RegisterVariable(&r_bloom_colorexponent);
2031 Cvar_RegisterVariable(&r_bloom_colorsubtract);
2032 Cvar_RegisterVariable(&r_hdr);
2033 Cvar_RegisterVariable(&r_hdr_scenebrightness);
2034 Cvar_RegisterVariable(&r_glsl_contrastboost);
2035 Cvar_RegisterVariable(&r_hdr_glowintensity);
2036 Cvar_RegisterVariable(&r_hdr_range);
2037 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
2038 Cvar_RegisterVariable(&developer_texturelogging);
2039 Cvar_RegisterVariable(&gl_lightmaps);
2040 Cvar_RegisterVariable(&r_test);
2041 Cvar_RegisterVariable(&r_batchmode);
2042 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
2043 Cvar_SetValue("r_fullbrights", 0);
2044 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
2046 Cvar_RegisterVariable(&r_track_sprites);
2047 Cvar_RegisterVariable(&r_track_sprites_flags);
2048 Cvar_RegisterVariable(&r_track_sprites_scalew);
2049 Cvar_RegisterVariable(&r_track_sprites_scaleh);
2052 extern void R_Textures_Init(void);
2053 extern void GL_Draw_Init(void);
2054 extern void GL_Main_Init(void);
2055 extern void R_Shadow_Init(void);
2056 extern void R_Sky_Init(void);
2057 extern void GL_Surf_Init(void);
2058 extern void R_Particles_Init(void);
2059 extern void R_Explosion_Init(void);
2060 extern void gl_backend_init(void);
2061 extern void Sbar_Init(void);
2062 extern void R_LightningBeams_Init(void);
2063 extern void Mod_RenderInit(void);
2065 void Render_Init(void)
2077 R_LightningBeams_Init();
2086 extern char *ENGINE_EXTENSIONS;
2089 VID_CheckExtensions();
2091 // LordHavoc: report supported extensions
2092 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
2094 // clear to black (loading plaque will be seen over this)
2096 qglClearColor(0,0,0,1);CHECKGLERROR
2097 qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
2100 int R_CullBox(const vec3_t mins, const vec3_t maxs)
2104 for (i = 0;i < r_view.numfrustumplanes;i++)
2106 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
2109 p = r_view.frustum + i;
2114 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2118 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2122 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2126 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2130 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2134 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2138 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2142 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2150 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
2154 for (i = 0;i < numplanes;i++)
2161 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2165 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2169 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2173 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2177 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2181 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2185 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2189 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2197 //==================================================================================
2199 static void R_View_UpdateEntityVisible (void)
2202 entity_render_t *ent;
2204 if (!r_drawentities.integer)
2207 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : ((chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL : RENDER_EXTERIORMODEL);
2208 if (r_refdef.worldmodel && r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs)
2210 // worldmodel can check visibility
2211 for (i = 0;i < r_refdef.numentities;i++)
2213 ent = r_refdef.entities[i];
2214 r_viewcache.entityvisible[i] = !(ent->flags & renderimask) && ((ent->model && ent->model->type == mod_sprite && (ent->model->sprite.sprnum_type == SPR_LABEL || ent->model->sprite.sprnum_type == SPR_LABEL_SCALE)) || !R_CullBox(ent->mins, ent->maxs)) && ((ent->effects & EF_NODEPTHTEST) || (ent->flags & RENDER_VIEWMODEL) || r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs(r_refdef.worldmodel, r_viewcache.world_leafvisible, ent->mins, ent->maxs));
2217 if(r_cullentities_trace.integer)
2219 for (i = 0;i < r_refdef.numentities;i++)
2221 ent = r_refdef.entities[i];
2222 if(r_viewcache.entityvisible[i] && !(ent->effects & EF_NODEPTHTEST) && !(ent->flags & RENDER_VIEWMODEL) && !(ent->model && (ent->model->name[0] == '*')))
2224 if(Mod_CanSeeBox_Trace(r_cullentities_trace_samples.integer, r_cullentities_trace_enlarge.value, r_refdef.worldmodel, r_view.origin, ent->mins, ent->maxs))
2225 ent->last_trace_visibility = realtime;
2226 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
2227 r_viewcache.entityvisible[i] = 0;
2234 // no worldmodel or it can't check visibility
2235 for (i = 0;i < r_refdef.numentities;i++)
2237 ent = r_refdef.entities[i];
2238 r_viewcache.entityvisible[i] = !(ent->flags & renderimask) && ((ent->model && ent->model->type == mod_sprite && (ent->model->sprite.sprnum_type == SPR_LABEL || ent->model->sprite.sprnum_type == SPR_LABEL_SCALE)) || !R_CullBox(ent->mins, ent->maxs));
2243 // only used if skyrendermasked, and normally returns false
2244 int R_DrawBrushModelsSky (void)
2247 entity_render_t *ent;
2249 if (!r_drawentities.integer)
2253 for (i = 0;i < r_refdef.numentities;i++)
2255 if (!r_viewcache.entityvisible[i])
2257 ent = r_refdef.entities[i];
2258 if (!ent->model || !ent->model->DrawSky)
2260 ent->model->DrawSky(ent);
2266 static void R_DrawNoModel(entity_render_t *ent);
2267 static void R_DrawModels(void)
2270 entity_render_t *ent;
2272 if (!r_drawentities.integer)
2275 for (i = 0;i < r_refdef.numentities;i++)
2277 if (!r_viewcache.entityvisible[i])
2279 ent = r_refdef.entities[i];
2280 r_refdef.stats.entities++;
2281 if (ent->model && ent->model->Draw != NULL)
2282 ent->model->Draw(ent);
2288 static void R_DrawModelsDepth(void)
2291 entity_render_t *ent;
2293 if (!r_drawentities.integer)
2296 for (i = 0;i < r_refdef.numentities;i++)
2298 if (!r_viewcache.entityvisible[i])
2300 ent = r_refdef.entities[i];
2301 if (ent->model && ent->model->DrawDepth != NULL)
2302 ent->model->DrawDepth(ent);
2306 static void R_DrawModelsDebug(void)
2309 entity_render_t *ent;
2311 if (!r_drawentities.integer)
2314 for (i = 0;i < r_refdef.numentities;i++)
2316 if (!r_viewcache.entityvisible[i])
2318 ent = r_refdef.entities[i];
2319 if (ent->model && ent->model->DrawDebug != NULL)
2320 ent->model->DrawDebug(ent);
2324 static void R_DrawModelsAddWaterPlanes(void)
2327 entity_render_t *ent;
2329 if (!r_drawentities.integer)
2332 for (i = 0;i < r_refdef.numentities;i++)
2334 if (!r_viewcache.entityvisible[i])
2336 ent = r_refdef.entities[i];
2337 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
2338 ent->model->DrawAddWaterPlanes(ent);
2342 static void R_View_SetFrustum(void)
2345 double slopex, slopey;
2347 // break apart the view matrix into vectors for various purposes
2348 Matrix4x4_ToVectors(&r_view.matrix, r_view.forward, r_view.left, r_view.up, r_view.origin);
2349 VectorNegate(r_view.left, r_view.right);
2352 r_view.frustum[0].normal[0] = 0 - 1.0 / r_view.frustum_x;
2353 r_view.frustum[0].normal[1] = 0 - 0;
2354 r_view.frustum[0].normal[2] = -1 - 0;
2355 r_view.frustum[1].normal[0] = 0 + 1.0 / r_view.frustum_x;
2356 r_view.frustum[1].normal[1] = 0 + 0;
2357 r_view.frustum[1].normal[2] = -1 + 0;
2358 r_view.frustum[2].normal[0] = 0 - 0;
2359 r_view.frustum[2].normal[1] = 0 - 1.0 / r_view.frustum_y;
2360 r_view.frustum[2].normal[2] = -1 - 0;
2361 r_view.frustum[3].normal[0] = 0 + 0;
2362 r_view.frustum[3].normal[1] = 0 + 1.0 / r_view.frustum_y;
2363 r_view.frustum[3].normal[2] = -1 + 0;
2367 zNear = r_refdef.nearclip;
2368 nudge = 1.0 - 1.0 / (1<<23);
2369 r_view.frustum[4].normal[0] = 0 - 0;
2370 r_view.frustum[4].normal[1] = 0 - 0;
2371 r_view.frustum[4].normal[2] = -1 - -nudge;
2372 r_view.frustum[4].dist = 0 - -2 * zNear * nudge;
2373 r_view.frustum[5].normal[0] = 0 + 0;
2374 r_view.frustum[5].normal[1] = 0 + 0;
2375 r_view.frustum[5].normal[2] = -1 + -nudge;
2376 r_view.frustum[5].dist = 0 + -2 * zNear * nudge;
2382 r_view.frustum[0].normal[0] = m[3] - m[0];
2383 r_view.frustum[0].normal[1] = m[7] - m[4];
2384 r_view.frustum[0].normal[2] = m[11] - m[8];
2385 r_view.frustum[0].dist = m[15] - m[12];
2387 r_view.frustum[1].normal[0] = m[3] + m[0];
2388 r_view.frustum[1].normal[1] = m[7] + m[4];
2389 r_view.frustum[1].normal[2] = m[11] + m[8];
2390 r_view.frustum[1].dist = m[15] + m[12];
2392 r_view.frustum[2].normal[0] = m[3] - m[1];
2393 r_view.frustum[2].normal[1] = m[7] - m[5];
2394 r_view.frustum[2].normal[2] = m[11] - m[9];
2395 r_view.frustum[2].dist = m[15] - m[13];
2397 r_view.frustum[3].normal[0] = m[3] + m[1];
2398 r_view.frustum[3].normal[1] = m[7] + m[5];
2399 r_view.frustum[3].normal[2] = m[11] + m[9];
2400 r_view.frustum[3].dist = m[15] + m[13];
2402 r_view.frustum[4].normal[0] = m[3] - m[2];
2403 r_view.frustum[4].normal[1] = m[7] - m[6];
2404 r_view.frustum[4].normal[2] = m[11] - m[10];
2405 r_view.frustum[4].dist = m[15] - m[14];
2407 r_view.frustum[5].normal[0] = m[3] + m[2];
2408 r_view.frustum[5].normal[1] = m[7] + m[6];
2409 r_view.frustum[5].normal[2] = m[11] + m[10];
2410 r_view.frustum[5].dist = m[15] + m[14];
2413 if (r_view.useperspective)
2415 slopex = 1.0 / r_view.frustum_x;
2416 slopey = 1.0 / r_view.frustum_y;
2417 VectorMA(r_view.forward, -slopex, r_view.left, r_view.frustum[0].normal);
2418 VectorMA(r_view.forward, slopex, r_view.left, r_view.frustum[1].normal);
2419 VectorMA(r_view.forward, -slopey, r_view.up , r_view.frustum[2].normal);
2420 VectorMA(r_view.forward, slopey, r_view.up , r_view.frustum[3].normal);
2421 VectorCopy(r_view.forward, r_view.frustum[4].normal);
2423 // Leaving those out was a mistake, those were in the old code, and they
2424 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
2425 // I couldn't reproduce it after adding those normalizations. --blub
2426 VectorNormalize(r_view.frustum[0].normal);
2427 VectorNormalize(r_view.frustum[1].normal);
2428 VectorNormalize(r_view.frustum[2].normal);
2429 VectorNormalize(r_view.frustum[3].normal);
2431 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
2432 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, -1024 * slopex, r_view.left, -1024 * slopey, r_view.up, r_view.frustumcorner[0]);
2433 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, 1024 * slopex, r_view.left, -1024 * slopey, r_view.up, r_view.frustumcorner[1]);
2434 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, -1024 * slopex, r_view.left, 1024 * slopey, r_view.up, r_view.frustumcorner[2]);
2435 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, 1024 * slopex, r_view.left, 1024 * slopey, r_view.up, r_view.frustumcorner[3]);
2437 r_view.frustum[0].dist = DotProduct (r_view.origin, r_view.frustum[0].normal);
2438 r_view.frustum[1].dist = DotProduct (r_view.origin, r_view.frustum[1].normal);
2439 r_view.frustum[2].dist = DotProduct (r_view.origin, r_view.frustum[2].normal);
2440 r_view.frustum[3].dist = DotProduct (r_view.origin, r_view.frustum[3].normal);
2441 r_view.frustum[4].dist = DotProduct (r_view.origin, r_view.frustum[4].normal) + r_refdef.nearclip;
2445 VectorScale(r_view.left, -r_view.ortho_x, r_view.frustum[0].normal);
2446 VectorScale(r_view.left, r_view.ortho_x, r_view.frustum[1].normal);
2447 VectorScale(r_view.up, -r_view.ortho_y, r_view.frustum[2].normal);
2448 VectorScale(r_view.up, r_view.ortho_y, r_view.frustum[3].normal);
2449 VectorCopy(r_view.forward, r_view.frustum[4].normal);
2450 r_view.frustum[0].dist = DotProduct (r_view.origin, r_view.frustum[0].normal) + r_view.ortho_x;
2451 r_view.frustum[1].dist = DotProduct (r_view.origin, r_view.frustum[1].normal) + r_view.ortho_x;
2452 r_view.frustum[2].dist = DotProduct (r_view.origin, r_view.frustum[2].normal) + r_view.ortho_y;
2453 r_view.frustum[3].dist = DotProduct (r_view.origin, r_view.frustum[3].normal) + r_view.ortho_y;
2454 r_view.frustum[4].dist = DotProduct (r_view.origin, r_view.frustum[4].normal) + r_refdef.nearclip;
2456 r_view.numfrustumplanes = 5;
2458 if (r_view.useclipplane)
2460 r_view.numfrustumplanes = 6;
2461 r_view.frustum[5] = r_view.clipplane;
2464 for (i = 0;i < r_view.numfrustumplanes;i++)
2465 PlaneClassify(r_view.frustum + i);
2467 // LordHavoc: note to all quake engine coders, Quake had a special case
2468 // for 90 degrees which assumed a square view (wrong), so I removed it,
2469 // Quake2 has it disabled as well.
2471 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
2472 //RotatePointAroundVector( r_view.frustum[0].normal, r_view.up, r_view.forward, -(90 - r_refdef.fov_x / 2));
2473 //r_view.frustum[0].dist = DotProduct (r_view.origin, frustum[0].normal);
2474 //PlaneClassify(&frustum[0]);
2476 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
2477 //RotatePointAroundVector( r_view.frustum[1].normal, r_view.up, r_view.forward, (90 - r_refdef.fov_x / 2));
2478 //r_view.frustum[1].dist = DotProduct (r_view.origin, frustum[1].normal);
2479 //PlaneClassify(&frustum[1]);
2481 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
2482 //RotatePointAroundVector( r_view.frustum[2].normal, r_view.left, r_view.forward, -(90 - r_refdef.fov_y / 2));
2483 //r_view.frustum[2].dist = DotProduct (r_view.origin, frustum[2].normal);
2484 //PlaneClassify(&frustum[2]);
2486 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
2487 //RotatePointAroundVector( r_view.frustum[3].normal, r_view.left, r_view.forward, (90 - r_refdef.fov_y / 2));
2488 //r_view.frustum[3].dist = DotProduct (r_view.origin, frustum[3].normal);
2489 //PlaneClassify(&frustum[3]);
2492 //VectorCopy(r_view.forward, r_view.frustum[4].normal);
2493 //r_view.frustum[4].dist = DotProduct (r_view.origin, frustum[4].normal) + r_nearclip.value;
2494 //PlaneClassify(&frustum[4]);
2497 void R_View_Update(void)
2499 R_View_SetFrustum();
2500 R_View_WorldVisibility(r_view.useclipplane);
2501 R_View_UpdateEntityVisible();
2504 void R_SetupView(void)
2506 if (!r_view.useperspective)
2507 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);
2508 else if (r_refdef.rtworldshadows || r_refdef.rtdlightshadows)
2509 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_view.frustum_x, r_view.frustum_y, r_refdef.nearclip);
2511 GL_SetupView_Mode_Perspective(r_view.frustum_x, r_view.frustum_y, r_refdef.nearclip, r_refdef.farclip);
2513 GL_SetupView_Orientation_FromEntity(&r_view.matrix);
2515 if (r_view.useclipplane)
2517 // LordHavoc: couldn't figure out how to make this approach the
2518 vec_t dist = r_view.clipplane.dist - r_water_clippingplanebias.value;
2519 vec_t viewdist = DotProduct(r_view.origin, r_view.clipplane.normal);
2520 if (viewdist < r_view.clipplane.dist + r_water_clippingplanebias.value)
2521 dist = r_view.clipplane.dist;
2522 GL_SetupView_ApplyCustomNearClipPlane(r_view.clipplane.normal[0], r_view.clipplane.normal[1], r_view.clipplane.normal[2], dist);
2526 void R_ResetViewRendering2D(void)
2528 if (gl_support_fragment_shader)
2530 qglUseProgramObjectARB(0);CHECKGLERROR
2535 // GL is weird because it's bottom to top, r_view.y is top to bottom
2536 qglViewport(r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
2537 GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
2538 GL_Scissor(r_view.x, r_view.y, r_view.width, r_view.height);
2539 GL_Color(1, 1, 1, 1);
2540 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
2541 GL_BlendFunc(GL_ONE, GL_ZERO);
2542 GL_AlphaTest(false);
2543 GL_ScissorTest(false);
2544 GL_DepthMask(false);
2545 GL_DepthRange(0, 1);
2546 GL_DepthTest(false);
2547 R_Mesh_Matrix(&identitymatrix);
2548 R_Mesh_ResetTextureState();
2549 GL_PolygonOffset(0, 0);
2550 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
2551 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
2552 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
2553 qglStencilMask(~0);CHECKGLERROR
2554 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
2555 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
2556 GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
2559 void R_ResetViewRendering3D(void)
2561 if (gl_support_fragment_shader)
2563 qglUseProgramObjectARB(0);CHECKGLERROR
2568 // GL is weird because it's bottom to top, r_view.y is top to bottom
2569 qglViewport(r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
2571 GL_Scissor(r_view.x, r_view.y, r_view.width, r_view.height);
2572 GL_Color(1, 1, 1, 1);
2573 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
2574 GL_BlendFunc(GL_ONE, GL_ZERO);
2575 GL_AlphaTest(false);
2576 GL_ScissorTest(true);
2578 GL_DepthRange(0, 1);
2580 R_Mesh_Matrix(&identitymatrix);
2581 R_Mesh_ResetTextureState();
2582 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
2583 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
2584 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
2585 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
2586 qglStencilMask(~0);CHECKGLERROR
2587 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
2588 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
2589 GL_CullFace(r_view.cullface_back);
2593 R_Bloom_SetupShader(
2595 "// written by Forest 'LordHavoc' Hale\n"
2597 "// common definitions between vertex shader and fragment shader:\n"
2599 "#ifdef __GLSL_CG_DATA_TYPES\n"
2600 "#define myhalf half\n"
2601 "#define myhvec2 hvec2\n"
2602 "#define myhvec3 hvec3\n"
2603 "#define myhvec4 hvec4\n"
2605 "#define myhalf float\n"
2606 "#define myhvec2 vec2\n"
2607 "#define myhvec3 vec3\n"
2608 "#define myhvec4 vec4\n"
2611 "varying vec2 ScreenTexCoord;\n"
2612 "varying vec2 BloomTexCoord;\n"
2617 "// vertex shader specific:\n"
2618 "#ifdef VERTEX_SHADER\n"
2622 " ScreenTexCoord = vec2(gl_MultiTexCoord0);\n"
2623 " BloomTexCoord = vec2(gl_MultiTexCoord1);\n"
2624 " // transform vertex to camera space, using ftransform to match non-VS\n"
2626 " gl_Position = ftransform();\n"
2629 "#endif // VERTEX_SHADER\n"
2634 "// fragment shader specific:\n"
2635 "#ifdef FRAGMENT_SHADER\n"
2640 " myhvec3 color = myhvec3(texture2D(Texture_Screen, ScreenTexCoord));\n"
2641 " for (x = -BLUR_X;x <= BLUR_X;x++)
2642 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2643 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2644 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2645 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2647 " gl_FragColor = vec4(color);\n"
2650 "#endif // FRAGMENT_SHADER\n"
2653 void R_RenderScene(qboolean addwaterplanes);
2655 static void R_Water_StartFrame(void)
2658 int waterwidth, waterheight, texturewidth, textureheight;
2659 r_waterstate_waterplane_t *p;
2661 // set waterwidth and waterheight to the water resolution that will be
2662 // used (often less than the screen resolution for faster rendering)
2663 waterwidth = (int)bound(1, r_view.width * r_water_resolutionmultiplier.value, r_view.width);
2664 waterheight = (int)bound(1, r_view.height * r_water_resolutionmultiplier.value, r_view.height);
2666 // calculate desired texture sizes
2667 // can't use water if the card does not support the texture size
2668 if (!r_water.integer || !r_glsl.integer || !gl_support_fragment_shader || waterwidth > gl_max_texture_size || waterheight > gl_max_texture_size)
2669 texturewidth = textureheight = waterwidth = waterheight = 0;
2670 else if (gl_support_arb_texture_non_power_of_two)
2672 texturewidth = waterwidth;
2673 textureheight = waterheight;
2677 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
2678 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
2681 // allocate textures as needed
2682 if (r_waterstate.waterwidth != waterwidth || r_waterstate.waterheight != waterheight || r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight)
2684 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
2685 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
2687 if (p->texture_refraction)
2688 R_FreeTexture(p->texture_refraction);
2689 p->texture_refraction = NULL;
2690 if (p->texture_reflection)
2691 R_FreeTexture(p->texture_reflection);
2692 p->texture_reflection = NULL;
2694 memset(&r_waterstate, 0, sizeof(r_waterstate));
2695 r_waterstate.waterwidth = waterwidth;
2696 r_waterstate.waterheight = waterheight;
2697 r_waterstate.texturewidth = texturewidth;
2698 r_waterstate.textureheight = textureheight;
2701 if (r_waterstate.waterwidth)
2703 r_waterstate.enabled = true;
2705 // set up variables that will be used in shader setup
2706 r_waterstate.screenscale[0] = 0.5f * (float)waterwidth / (float)texturewidth;
2707 r_waterstate.screenscale[1] = 0.5f * (float)waterheight / (float)textureheight;
2708 r_waterstate.screencenter[0] = 0.5f * (float)waterwidth / (float)texturewidth;
2709 r_waterstate.screencenter[1] = 0.5f * (float)waterheight / (float)textureheight;
2712 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
2713 r_waterstate.numwaterplanes = 0;
2716 static void R_Water_AddWaterPlane(msurface_t *surface)
2718 int triangleindex, planeindex;
2723 r_waterstate_waterplane_t *p;
2724 // just use the first triangle with a valid normal for any decisions
2725 VectorClear(normal);
2726 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
2728 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
2729 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
2730 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
2731 TriangleNormal(vert[0], vert[1], vert[2], normal);
2732 if (VectorLength2(normal) >= 0.001)
2736 // find a matching plane if there is one
2737 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
2738 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
2740 if (planeindex >= r_waterstate.maxwaterplanes)
2741 return; // nothing we can do, out of planes
2743 // if this triangle does not fit any known plane rendered this frame, add one
2744 if (planeindex >= r_waterstate.numwaterplanes)
2746 // store the new plane
2747 r_waterstate.numwaterplanes++;
2748 VectorCopy(normal, p->plane.normal);
2749 VectorNormalize(p->plane.normal);
2750 p->plane.dist = DotProduct(vert[0], p->plane.normal);
2751 PlaneClassify(&p->plane);
2752 // flip the plane if it does not face the viewer
2753 if (PlaneDiff(r_view.origin, &p->plane) < 0)
2755 VectorNegate(p->plane.normal, p->plane.normal);
2756 p->plane.dist *= -1;
2757 PlaneClassify(&p->plane);
2759 // clear materialflags and pvs
2760 p->materialflags = 0;
2761 p->pvsvalid = false;
2763 // merge this surface's materialflags into the waterplane
2764 p->materialflags |= surface->texture->currentframe->currentmaterialflags;
2765 // merge this surface's PVS into the waterplane
2766 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
2767 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.worldmodel && r_refdef.worldmodel->brush.FatPVS
2768 && r_refdef.worldmodel->brush.PointInLeaf && r_refdef.worldmodel->brush.PointInLeaf(r_refdef.worldmodel, center)->clusterindex >= 0)
2770 r_refdef.worldmodel->brush.FatPVS(r_refdef.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
2775 static void R_Water_ProcessPlanes(void)
2777 r_view_t originalview;
2779 r_waterstate_waterplane_t *p;
2781 originalview = r_view;
2783 // make sure enough textures are allocated
2784 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
2786 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
2788 if (!p->texture_refraction)
2789 p->texture_refraction = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_refraction", planeindex), r_waterstate.texturewidth, r_waterstate.textureheight, NULL, TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
2790 if (!p->texture_refraction)
2794 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
2796 if (!p->texture_reflection)
2797 p->texture_reflection = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_reflection", planeindex), r_waterstate.texturewidth, r_waterstate.textureheight, NULL, TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
2798 if (!p->texture_reflection)
2804 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
2806 r_view.showdebug = false;
2807 r_view.width = r_waterstate.waterwidth;
2808 r_view.height = r_waterstate.waterheight;
2809 r_view.useclipplane = true;
2810 r_waterstate.renderingscene = true;
2812 // render the normal view scene and copy into texture
2813 // (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)
2814 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
2816 r_view.clipplane = p->plane;
2817 VectorNegate(r_view.clipplane.normal, r_view.clipplane.normal);
2818 r_view.clipplane.dist = -r_view.clipplane.dist;
2819 PlaneClassify(&r_view.clipplane);
2821 R_RenderScene(false);
2823 // copy view into the screen texture
2824 R_Mesh_TexBind(0, R_GetTexture(p->texture_refraction));
2825 GL_ActiveTexture(0);
2827 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
2830 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
2832 // render reflected scene and copy into texture
2833 Matrix4x4_Reflect(&r_view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
2834 r_view.clipplane = p->plane;
2835 // reverse the cullface settings for this render
2836 r_view.cullface_front = GL_FRONT;
2837 r_view.cullface_back = GL_BACK;
2838 if (r_refdef.worldmodel && r_refdef.worldmodel->brush.num_pvsclusterbytes)
2840 r_view.usecustompvs = true;
2842 memcpy(r_viewcache.world_pvsbits, p->pvsbits, r_refdef.worldmodel->brush.num_pvsclusterbytes);
2844 memset(r_viewcache.world_pvsbits, 0xFF, r_refdef.worldmodel->brush.num_pvsclusterbytes);
2847 R_ResetViewRendering3D();
2848 R_ClearScreen(r_refdef.fogenabled);
2849 if (r_timereport_active)
2850 R_TimeReport("viewclear");
2852 R_RenderScene(false);
2854 R_Mesh_TexBind(0, R_GetTexture(p->texture_reflection));
2855 GL_ActiveTexture(0);
2857 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
2859 R_ResetViewRendering3D();
2860 R_ClearScreen(r_refdef.fogenabled);
2861 if (r_timereport_active)
2862 R_TimeReport("viewclear");
2865 r_view = originalview;
2866 r_view.clear = true;
2867 r_waterstate.renderingscene = false;
2871 r_view = originalview;
2872 r_waterstate.renderingscene = false;
2873 Cvar_SetValueQuick(&r_water, 0);
2874 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
2878 void R_Bloom_StartFrame(void)
2880 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
2882 // set bloomwidth and bloomheight to the bloom resolution that will be
2883 // used (often less than the screen resolution for faster rendering)
2884 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_view.width);
2885 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_view.height / r_view.width;
2886 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_view.height);
2888 // calculate desired texture sizes
2889 if (gl_support_arb_texture_non_power_of_two)
2891 screentexturewidth = r_view.width;
2892 screentextureheight = r_view.height;
2893 bloomtexturewidth = r_bloomstate.bloomwidth;
2894 bloomtextureheight = r_bloomstate.bloomheight;
2898 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
2899 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
2900 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
2901 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
2906 screentexturewidth = screentextureheight = 0;
2908 else if (r_bloom.integer)
2913 screentexturewidth = screentextureheight = 0;
2914 bloomtexturewidth = bloomtextureheight = 0;
2917 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)
2919 // can't use bloom if the parameters are too weird
2920 // can't use bloom if the card does not support the texture size
2921 if (r_bloomstate.texture_screen)
2922 R_FreeTexture(r_bloomstate.texture_screen);
2923 if (r_bloomstate.texture_bloom)
2924 R_FreeTexture(r_bloomstate.texture_bloom);
2925 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
2929 r_bloomstate.enabled = true;
2930 r_bloomstate.hdr = r_hdr.integer != 0;
2932 // allocate textures as needed
2933 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
2935 if (r_bloomstate.texture_screen)
2936 R_FreeTexture(r_bloomstate.texture_screen);
2937 r_bloomstate.texture_screen = NULL;
2938 r_bloomstate.screentexturewidth = screentexturewidth;
2939 r_bloomstate.screentextureheight = screentextureheight;
2940 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
2941 r_bloomstate.texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, TEXTYPE_BGRA, TEXF_FORCENEAREST | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
2943 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
2945 if (r_bloomstate.texture_bloom)
2946 R_FreeTexture(r_bloomstate.texture_bloom);
2947 r_bloomstate.texture_bloom = NULL;
2948 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
2949 r_bloomstate.bloomtextureheight = bloomtextureheight;
2950 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
2951 r_bloomstate.texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", r_bloomstate.bloomtexturewidth, r_bloomstate.bloomtextureheight, NULL, TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
2954 // set up a texcoord array for the full resolution screen image
2955 // (we have to keep this around to copy back during final render)
2956 r_bloomstate.screentexcoord2f[0] = 0;
2957 r_bloomstate.screentexcoord2f[1] = (float)r_view.height / (float)r_bloomstate.screentextureheight;
2958 r_bloomstate.screentexcoord2f[2] = (float)r_view.width / (float)r_bloomstate.screentexturewidth;
2959 r_bloomstate.screentexcoord2f[3] = (float)r_view.height / (float)r_bloomstate.screentextureheight;
2960 r_bloomstate.screentexcoord2f[4] = (float)r_view.width / (float)r_bloomstate.screentexturewidth;
2961 r_bloomstate.screentexcoord2f[5] = 0;
2962 r_bloomstate.screentexcoord2f[6] = 0;
2963 r_bloomstate.screentexcoord2f[7] = 0;
2965 // set up a texcoord array for the reduced resolution bloom image
2966 // (which will be additive blended over the screen image)
2967 r_bloomstate.bloomtexcoord2f[0] = 0;
2968 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
2969 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
2970 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
2971 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
2972 r_bloomstate.bloomtexcoord2f[5] = 0;
2973 r_bloomstate.bloomtexcoord2f[6] = 0;
2974 r_bloomstate.bloomtexcoord2f[7] = 0;
2977 void R_Bloom_CopyScreenTexture(float colorscale)
2979 r_refdef.stats.bloom++;
2981 R_ResetViewRendering2D();
2982 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
2983 R_Mesh_ColorPointer(NULL, 0, 0);
2984 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
2985 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
2987 // copy view into the screen texture
2988 GL_ActiveTexture(0);
2990 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
2991 r_refdef.stats.bloom_copypixels += r_view.width * r_view.height;
2993 // now scale it down to the bloom texture size
2995 qglViewport(r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
2996 GL_BlendFunc(GL_ONE, GL_ZERO);
2997 GL_Color(colorscale, colorscale, colorscale, 1);
2998 // TODO: optimize with multitexture or GLSL
2999 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3000 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3002 // we now have a bloom image in the framebuffer
3003 // copy it into the bloom image texture for later processing
3004 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3005 GL_ActiveTexture(0);
3007 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
3008 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3011 void R_Bloom_CopyHDRTexture(void)
3013 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3014 GL_ActiveTexture(0);
3016 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
3017 r_refdef.stats.bloom_copypixels += r_view.width * r_view.height;
3020 void R_Bloom_MakeTexture(void)
3023 float xoffset, yoffset, r, brighten;
3025 r_refdef.stats.bloom++;
3027 R_ResetViewRendering2D();
3028 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3029 R_Mesh_ColorPointer(NULL, 0, 0);
3031 // we have a bloom image in the framebuffer
3033 qglViewport(r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
3035 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
3038 r = bound(0, r_bloom_colorexponent.value / x, 1);
3039 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
3040 GL_Color(r, r, r, 1);
3041 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3042 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3043 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3044 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3046 // copy the vertically blurred bloom view to a texture
3047 GL_ActiveTexture(0);
3049 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
3050 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3053 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
3054 brighten = r_bloom_brighten.value;
3056 brighten *= r_hdr_range.value;
3057 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3058 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
3060 for (dir = 0;dir < 2;dir++)
3062 // blend on at multiple vertical offsets to achieve a vertical blur
3063 // TODO: do offset blends using GLSL
3064 GL_BlendFunc(GL_ONE, GL_ZERO);
3065 for (x = -range;x <= range;x++)
3067 if (!dir){xoffset = 0;yoffset = x;}
3068 else {xoffset = x;yoffset = 0;}
3069 xoffset /= (float)r_bloomstate.bloomtexturewidth;
3070 yoffset /= (float)r_bloomstate.bloomtextureheight;
3071 // compute a texcoord array with the specified x and y offset
3072 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
3073 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3074 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3075 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3076 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3077 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
3078 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
3079 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
3080 // this r value looks like a 'dot' particle, fading sharply to
3081 // black at the edges
3082 // (probably not realistic but looks good enough)
3083 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
3084 //r = (dir ? 1.0f : brighten)/(range*2+1);
3085 r = (dir ? 1.0f : brighten)/(range*2+1)*(1 - x*x/(float)(range*range));
3086 GL_Color(r, r, r, 1);
3087 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3088 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3089 GL_BlendFunc(GL_ONE, GL_ONE);
3092 // copy the vertically blurred bloom view to a texture
3093 GL_ActiveTexture(0);
3095 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
3096 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3099 // apply subtract last
3100 // (just like it would be in a GLSL shader)
3101 if (r_bloom_colorsubtract.value > 0 && gl_support_ext_blend_subtract)
3103 GL_BlendFunc(GL_ONE, GL_ZERO);
3104 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3105 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3106 GL_Color(1, 1, 1, 1);
3107 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3108 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3110 GL_BlendFunc(GL_ONE, GL_ONE);
3111 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
3112 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
3113 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3114 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
3115 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3116 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3117 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
3119 // copy the darkened bloom view to a texture
3120 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3121 GL_ActiveTexture(0);
3123 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
3124 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3128 void R_HDR_RenderBloomTexture(void)
3130 int oldwidth, oldheight;
3131 float oldcolorscale;
3133 oldcolorscale = r_view.colorscale;
3134 oldwidth = r_view.width;
3135 oldheight = r_view.height;
3136 r_view.width = r_bloomstate.bloomwidth;
3137 r_view.height = r_bloomstate.bloomheight;
3139 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
3140 // TODO: add exposure compensation features
3141 // TODO: add fp16 framebuffer support
3143 r_view.showdebug = false;
3144 r_view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
3146 R_ClearScreen(r_refdef.fogenabled);
3147 if (r_timereport_active)
3148 R_TimeReport("HDRclear");
3150 r_waterstate.numwaterplanes = 0;
3151 R_RenderScene(r_waterstate.enabled);
3152 r_view.showdebug = true;
3154 R_ResetViewRendering2D();
3156 R_Bloom_CopyHDRTexture();
3157 R_Bloom_MakeTexture();
3159 // restore the view settings
3160 r_view.width = oldwidth;
3161 r_view.height = oldheight;
3162 r_view.colorscale = oldcolorscale;
3164 R_ResetViewRendering3D();
3166 R_ClearScreen(r_refdef.fogenabled);
3167 if (r_timereport_active)
3168 R_TimeReport("viewclear");
3171 static void R_BlendView(void)
3173 if (r_bloomstate.enabled && r_bloomstate.hdr)
3175 // render high dynamic range bloom effect
3176 // the bloom texture was made earlier this render, so we just need to
3177 // blend it onto the screen...
3178 R_ResetViewRendering2D();
3179 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3180 R_Mesh_ColorPointer(NULL, 0, 0);
3181 GL_Color(1, 1, 1, 1);
3182 GL_BlendFunc(GL_ONE, GL_ONE);
3183 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3184 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3185 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3186 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
3188 else if (r_bloomstate.enabled)
3190 // render simple bloom effect
3191 // copy the screen and shrink it and darken it for the bloom process
3192 R_Bloom_CopyScreenTexture(r_bloom_colorscale.value);
3193 // make the bloom texture
3194 R_Bloom_MakeTexture();
3195 // put the original screen image back in place and blend the bloom
3197 R_ResetViewRendering2D();
3198 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3199 R_Mesh_ColorPointer(NULL, 0, 0);
3200 GL_Color(1, 1, 1, 1);
3201 GL_BlendFunc(GL_ONE, GL_ZERO);
3202 // do both in one pass if possible
3203 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3204 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3205 if (r_textureunits.integer >= 2 && gl_combine.integer)
3207 R_Mesh_TexCombine(1, GL_ADD, GL_ADD, 1, 1);
3208 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_screen));
3209 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.screentexcoord2f, 0, 0);
3213 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3214 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
3215 // now blend on the bloom texture
3216 GL_BlendFunc(GL_ONE, GL_ONE);
3217 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
3218 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
3220 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3221 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
3223 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
3225 // apply a color tint to the whole view
3226 R_ResetViewRendering2D();
3227 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3228 R_Mesh_ColorPointer(NULL, 0, 0);
3229 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3230 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
3231 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3235 void R_RenderScene(qboolean addwaterplanes);
3237 matrix4x4_t r_waterscrollmatrix;
3239 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
3241 if (r_refdef.fog_density)
3243 r_refdef.fogcolor[0] = r_refdef.fog_red;
3244 r_refdef.fogcolor[1] = r_refdef.fog_green;
3245 r_refdef.fogcolor[2] = r_refdef.fog_blue;
3249 VectorCopy(r_refdef.fogcolor, fogvec);
3250 if(r_glsl.integer && (r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)) // need to support contrast boost
3252 // color.rgb /= ((ContrastBoost - 1) * color.rgb + 1);
3253 fogvec[0] *= r_glsl_contrastboost.value / ((r_glsl_contrastboost.value - 1) * fogvec[0] + 1);
3254 fogvec[1] *= r_glsl_contrastboost.value / ((r_glsl_contrastboost.value - 1) * fogvec[1] + 1);
3255 fogvec[2] *= r_glsl_contrastboost.value / ((r_glsl_contrastboost.value - 1) * fogvec[2] + 1);
3257 // color.rgb *= ContrastBoost * SceneBrightness;
3258 VectorScale(fogvec, r_view.colorscale, fogvec);
3259 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
3260 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
3261 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
3266 void R_UpdateVariables(void)
3270 r_refdef.farclip = 4096;
3271 if (r_refdef.worldmodel)
3272 r_refdef.farclip += VectorDistance(r_refdef.worldmodel->normalmins, r_refdef.worldmodel->normalmaxs);
3273 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
3275 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
3276 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
3277 r_refdef.polygonfactor = 0;
3278 r_refdef.polygonoffset = 0;
3279 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
3280 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
3282 r_refdef.rtworld = r_shadow_realtime_world.integer;
3283 r_refdef.rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
3284 r_refdef.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
3285 r_refdef.rtdlightshadows = r_refdef.rtdlight && r_shadow_realtime_dlight_shadows.integer && gl_stencil;
3286 r_refdef.lightmapintensity = r_refdef.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
3287 if (r_showsurfaces.integer)
3289 r_refdef.rtworld = false;
3290 r_refdef.rtworldshadows = false;
3291 r_refdef.rtdlight = false;
3292 r_refdef.rtdlightshadows = false;
3293 r_refdef.lightmapintensity = 0;
3296 if (gamemode == GAME_NEHAHRA)
3298 if (gl_fogenable.integer)
3300 r_refdef.oldgl_fogenable = true;
3301 r_refdef.fog_density = gl_fogdensity.value;
3302 r_refdef.fog_red = gl_fogred.value;
3303 r_refdef.fog_green = gl_foggreen.value;
3304 r_refdef.fog_blue = gl_fogblue.value;
3305 r_refdef.fog_alpha = 1;
3306 r_refdef.fog_start = 0;
3307 r_refdef.fog_end = gl_skyclip.value;
3309 else if (r_refdef.oldgl_fogenable)
3311 r_refdef.oldgl_fogenable = false;
3312 r_refdef.fog_density = 0;
3313 r_refdef.fog_red = 0;
3314 r_refdef.fog_green = 0;
3315 r_refdef.fog_blue = 0;
3316 r_refdef.fog_alpha = 0;
3317 r_refdef.fog_start = 0;
3318 r_refdef.fog_end = 0;
3322 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
3323 r_refdef.fog_start = max(0, r_refdef.fog_start);
3324 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
3326 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
3328 if (r_refdef.fog_density)
3330 r_refdef.fogenabled = true;
3331 // this is the point where the fog reaches 0.9986 alpha, which we
3332 // consider a good enough cutoff point for the texture
3333 // (0.9986 * 256 == 255.6)
3334 if (r_fog_exp2.integer)
3335 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
3337 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
3338 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
3339 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
3340 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
3341 // fog color was already set
3342 // update the fog texture
3343 if (r_refdef.fogmasktable_start != r_refdef.fog_start || r_refdef.fogmasktable_alpha != r_refdef.fog_alpha || r_refdef.fogmasktable_density != r_refdef.fog_density || r_refdef.fogmasktable_range != r_refdef.fogrange)
3344 R_BuildFogTexture();
3347 r_refdef.fogenabled = false;
3355 void R_RenderView(void)
3357 if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
3358 return; //Host_Error ("R_RenderView: NULL worldmodel");
3360 r_view.colorscale = r_hdr_scenebrightness.value;
3362 R_Shadow_UpdateWorldLightSelection();
3364 R_Bloom_StartFrame();
3365 R_Water_StartFrame();
3368 if (r_timereport_active)
3369 R_TimeReport("viewsetup");
3371 R_ResetViewRendering3D();
3373 if (r_view.clear || r_refdef.fogenabled)
3375 R_ClearScreen(r_refdef.fogenabled);
3376 if (r_timereport_active)
3377 R_TimeReport("viewclear");
3379 r_view.clear = true;
3381 r_view.showdebug = true;
3383 // this produces a bloom texture to be used in R_BlendView() later
3385 R_HDR_RenderBloomTexture();
3387 r_waterstate.numwaterplanes = 0;
3388 R_RenderScene(r_waterstate.enabled);
3391 if (r_timereport_active)
3392 R_TimeReport("blendview");
3394 GL_Scissor(0, 0, vid.width, vid.height);
3395 GL_ScissorTest(false);
3399 extern void R_DrawLightningBeams (void);
3400 extern void VM_CL_AddPolygonsToMeshQueue (void);
3401 extern void R_DrawPortals (void);
3402 extern cvar_t cl_locs_show;
3403 static void R_DrawLocs(void);
3404 static void R_DrawEntityBBoxes(void);
3405 void R_RenderScene(qboolean addwaterplanes)
3407 Matrix4x4_Invert_Simple(&r_view.inverse_matrix, &r_view.matrix);
3412 R_ResetViewRendering3D();
3415 if (r_timereport_active)
3416 R_TimeReport("watervis");
3418 if (cl.csqc_vidvars.drawworld && r_refdef.worldmodel && r_refdef.worldmodel->DrawAddWaterPlanes)
3420 r_refdef.worldmodel->DrawAddWaterPlanes(r_refdef.worldentity);
3421 if (r_timereport_active)
3422 R_TimeReport("waterworld");
3425 // don't let sound skip if going slow
3426 if (r_refdef.extraupdate)
3429 R_DrawModelsAddWaterPlanes();
3430 if (r_timereport_active)
3431 R_TimeReport("watermodels");
3433 R_Water_ProcessPlanes();
3434 if (r_timereport_active)
3435 R_TimeReport("waterscenes");
3438 R_ResetViewRendering3D();
3440 // don't let sound skip if going slow
3441 if (r_refdef.extraupdate)
3444 R_MeshQueue_BeginScene();
3449 if (r_timereport_active)
3450 R_TimeReport("visibility");
3452 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);
3454 if (cl.csqc_vidvars.drawworld)
3456 // don't let sound skip if going slow
3457 if (r_refdef.extraupdate)
3460 if (r_refdef.worldmodel && r_refdef.worldmodel->DrawSky)
3462 r_refdef.worldmodel->DrawSky(r_refdef.worldentity);
3463 if (r_timereport_active)
3464 R_TimeReport("worldsky");
3467 if (R_DrawBrushModelsSky() && r_timereport_active)
3468 R_TimeReport("bmodelsky");
3471 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.worldmodel && r_refdef.worldmodel->DrawDepth)
3473 r_refdef.worldmodel->DrawDepth(r_refdef.worldentity);
3474 if (r_timereport_active)
3475 R_TimeReport("worlddepth");
3477 if (r_depthfirst.integer >= 2)
3479 R_DrawModelsDepth();
3480 if (r_timereport_active)
3481 R_TimeReport("modeldepth");
3484 if (cl.csqc_vidvars.drawworld && r_refdef.worldmodel && r_refdef.worldmodel->Draw)
3486 r_refdef.worldmodel->Draw(r_refdef.worldentity);
3487 if (r_timereport_active)
3488 R_TimeReport("world");
3491 // don't let sound skip if going slow
3492 if (r_refdef.extraupdate)
3496 if (r_timereport_active)
3497 R_TimeReport("models");
3499 // don't let sound skip if going slow
3500 if (r_refdef.extraupdate)
3503 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
3505 R_DrawModelShadows();
3507 R_ResetViewRendering3D();
3509 // don't let sound skip if going slow
3510 if (r_refdef.extraupdate)
3514 R_ShadowVolumeLighting(false);
3515 if (r_timereport_active)
3516 R_TimeReport("rtlights");
3518 // don't let sound skip if going slow
3519 if (r_refdef.extraupdate)
3522 if (cl.csqc_vidvars.drawworld)
3524 R_DrawLightningBeams();
3525 if (r_timereport_active)
3526 R_TimeReport("lightning");
3529 if (r_timereport_active)
3530 R_TimeReport("decals");
3533 if (r_timereport_active)
3534 R_TimeReport("particles");
3537 if (r_timereport_active)
3538 R_TimeReport("explosions");
3541 if (gl_support_fragment_shader)
3543 qglUseProgramObjectARB(0);CHECKGLERROR
3545 VM_CL_AddPolygonsToMeshQueue();
3547 if (r_view.showdebug)
3549 if (cl_locs_show.integer)
3552 if (r_timereport_active)
3553 R_TimeReport("showlocs");
3556 if (r_drawportals.integer)
3559 if (r_timereport_active)
3560 R_TimeReport("portals");
3563 if (r_showbboxes.value > 0)
3565 R_DrawEntityBBoxes();
3566 if (r_timereport_active)
3567 R_TimeReport("bboxes");
3571 if (gl_support_fragment_shader)
3573 qglUseProgramObjectARB(0);CHECKGLERROR
3575 R_MeshQueue_RenderTransparent();
3576 if (r_timereport_active)
3577 R_TimeReport("drawtrans");
3579 if (gl_support_fragment_shader)
3581 qglUseProgramObjectARB(0);CHECKGLERROR
3584 if (r_view.showdebug && r_refdef.worldmodel && r_refdef.worldmodel->DrawDebug && (r_showtris.value > 0 || r_shownormals.value > 0 || r_showcollisionbrushes.value > 0))
3586 r_refdef.worldmodel->DrawDebug(r_refdef.worldentity);
3587 if (r_timereport_active)
3588 R_TimeReport("worlddebug");
3589 R_DrawModelsDebug();
3590 if (r_timereport_active)
3591 R_TimeReport("modeldebug");
3594 if (gl_support_fragment_shader)
3596 qglUseProgramObjectARB(0);CHECKGLERROR
3599 if (cl.csqc_vidvars.drawworld)
3602 if (r_timereport_active)
3603 R_TimeReport("coronas");
3606 // don't let sound skip if going slow
3607 if (r_refdef.extraupdate)
3610 R_ResetViewRendering2D();
3613 static const int bboxelements[36] =
3623 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
3626 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
3627 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3628 GL_DepthMask(false);
3629 GL_DepthRange(0, 1);
3630 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3631 R_Mesh_Matrix(&identitymatrix);
3632 R_Mesh_ResetTextureState();
3634 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
3635 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
3636 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
3637 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
3638 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
3639 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
3640 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
3641 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
3642 R_FillColors(color4f, 8, cr, cg, cb, ca);
3643 if (r_refdef.fogenabled)
3645 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
3647 f1 = FogPoint_World(v);
3649 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
3650 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
3651 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
3654 R_Mesh_VertexPointer(vertex3f, 0, 0);
3655 R_Mesh_ColorPointer(color4f, 0, 0);
3656 R_Mesh_ResetTextureState();
3657 R_Mesh_Draw(0, 8, 12, bboxelements, 0, 0);
3660 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
3664 prvm_edict_t *edict;
3665 // this function draws bounding boxes of server entities
3669 for (i = 0;i < numsurfaces;i++)
3671 edict = PRVM_EDICT_NUM(surfacelist[i]);
3672 switch ((int)edict->fields.server->solid)
3674 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
3675 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
3676 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
3677 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
3678 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
3679 default: Vector4Set(color, 0, 0, 0, 0.50);break;
3681 color[3] *= r_showbboxes.value;
3682 color[3] = bound(0, color[3], 1);
3683 GL_DepthTest(!r_showdisabledepthtest.integer);
3684 GL_CullFace(r_view.cullface_front);
3685 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
3690 static void R_DrawEntityBBoxes(void)
3693 prvm_edict_t *edict;
3695 // this function draws bounding boxes of server entities
3699 for (i = 0;i < prog->num_edicts;i++)
3701 edict = PRVM_EDICT_NUM(i);
3702 if (edict->priv.server->free)
3704 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
3705 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
3710 int nomodelelements[24] =
3722 float nomodelvertex3f[6*3] =
3732 float nomodelcolor4f[6*4] =
3734 0.0f, 0.0f, 0.5f, 1.0f,
3735 0.0f, 0.0f, 0.5f, 1.0f,
3736 0.0f, 0.5f, 0.0f, 1.0f,
3737 0.0f, 0.5f, 0.0f, 1.0f,
3738 0.5f, 0.0f, 0.0f, 1.0f,
3739 0.5f, 0.0f, 0.0f, 1.0f
3742 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
3747 // this is only called once per entity so numsurfaces is always 1, and
3748 // surfacelist is always {0}, so this code does not handle batches
3749 R_Mesh_Matrix(&ent->matrix);
3751 if (ent->flags & EF_ADDITIVE)
3753 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
3754 GL_DepthMask(false);
3756 else if (ent->alpha < 1)
3758 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3759 GL_DepthMask(false);
3763 GL_BlendFunc(GL_ONE, GL_ZERO);
3766 GL_DepthRange(0, (ent->flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
3767 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3768 GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
3769 GL_CullFace((ent->effects & EF_DOUBLESIDED) ? GL_NONE : r_view.cullface_back);
3770 R_Mesh_VertexPointer(nomodelvertex3f, 0, 0);
3771 if (r_refdef.fogenabled)
3774 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
3775 R_Mesh_ColorPointer(color4f, 0, 0);
3776 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
3777 f1 = FogPoint_World(org);
3779 for (i = 0, c = color4f;i < 6;i++, c += 4)
3781 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
3782 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
3783 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
3787 else if (ent->alpha != 1)
3789 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
3790 R_Mesh_ColorPointer(color4f, 0, 0);
3791 for (i = 0, c = color4f;i < 6;i++, c += 4)
3795 R_Mesh_ColorPointer(nomodelcolor4f, 0, 0);
3796 R_Mesh_ResetTextureState();
3797 R_Mesh_Draw(0, 6, 8, nomodelelements, 0, 0);
3800 void R_DrawNoModel(entity_render_t *ent)
3803 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
3804 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
3805 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
3807 // R_DrawNoModelCallback(ent, 0);
3810 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
3812 vec3_t right1, right2, diff, normal;
3814 VectorSubtract (org2, org1, normal);
3816 // calculate 'right' vector for start
3817 VectorSubtract (r_view.origin, org1, diff);
3818 CrossProduct (normal, diff, right1);
3819 VectorNormalize (right1);
3821 // calculate 'right' vector for end
3822 VectorSubtract (r_view.origin, org2, diff);
3823 CrossProduct (normal, diff, right2);
3824 VectorNormalize (right2);
3826 vert[ 0] = org1[0] + width * right1[0];
3827 vert[ 1] = org1[1] + width * right1[1];
3828 vert[ 2] = org1[2] + width * right1[2];
3829 vert[ 3] = org1[0] - width * right1[0];
3830 vert[ 4] = org1[1] - width * right1[1];
3831 vert[ 5] = org1[2] - width * right1[2];
3832 vert[ 6] = org2[0] - width * right2[0];
3833 vert[ 7] = org2[1] - width * right2[1];
3834 vert[ 8] = org2[2] - width * right2[2];
3835 vert[ 9] = org2[0] + width * right2[0];
3836 vert[10] = org2[1] + width * right2[1];
3837 vert[11] = org2[2] + width * right2[2];
3840 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
3842 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)
3847 if (r_refdef.fogenabled && !depthdisable) // TODO maybe make the unfog effect a separate flag?
3848 fog = FogPoint_World(origin);
3850 R_Mesh_Matrix(&identitymatrix);
3851 GL_BlendFunc(blendfunc1, blendfunc2);
3857 GL_CullFace(r_view.cullface_front);
3860 GL_CullFace(r_view.cullface_back);
3862 GL_DepthMask(false);
3863 GL_DepthRange(0, depthshort ? 0.0625 : 1);
3864 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3865 GL_DepthTest(!depthdisable);
3867 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
3868 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
3869 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
3870 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
3871 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
3872 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
3873 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
3874 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
3875 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
3876 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
3877 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
3878 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
3880 R_Mesh_VertexPointer(vertex3f, 0, 0);
3881 R_Mesh_ColorPointer(NULL, 0, 0);
3882 R_Mesh_ResetTextureState();
3883 R_Mesh_TexBind(0, R_GetTexture(texture));
3884 R_Mesh_TexCoordPointer(0, 2, spritetexcoord2f, 0, 0);
3885 // FIXME: fixed function path can't properly handle r_view.colorscale > 1
3886 GL_Color(cr * fog * r_view.colorscale, cg * fog * r_view.colorscale, cb * fog * r_view.colorscale, ca);
3887 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3889 if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
3891 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
3892 GL_BlendFunc(blendfunc1, GL_ONE);
3894 GL_Color(r_refdef.fogcolor[0] * fog, r_refdef.fogcolor[1] * fog, r_refdef.fogcolor[2] * fog, ca);
3895 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3899 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
3904 VectorSet(v, x, y, z);
3905 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
3906 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
3908 if (i == mesh->numvertices)
3910 if (mesh->numvertices < mesh->maxvertices)
3912 VectorCopy(v, vertex3f);
3913 mesh->numvertices++;
3915 return mesh->numvertices;
3921 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
3925 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
3926 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
3927 e = mesh->element3i + mesh->numtriangles * 3;
3928 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
3930 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
3931 if (mesh->numtriangles < mesh->maxtriangles)
3936 mesh->numtriangles++;
3938 element[1] = element[2];
3942 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
3946 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
3947 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
3948 e = mesh->element3i + mesh->numtriangles * 3;
3949 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
3951 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
3952 if (mesh->numtriangles < mesh->maxtriangles)
3957 mesh->numtriangles++;
3959 element[1] = element[2];
3963 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
3964 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
3966 int planenum, planenum2;
3969 mplane_t *plane, *plane2;
3971 double temppoints[2][256*3];
3972 // figure out how large a bounding box we need to properly compute this brush
3974 for (w = 0;w < numplanes;w++)
3975 maxdist = max(maxdist, planes[w].dist);
3976 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
3977 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
3978 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
3982 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
3983 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
3985 if (planenum2 == planenum)
3987 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);
3990 if (tempnumpoints < 3)
3992 // generate elements forming a triangle fan for this polygon
3993 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
3997 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)
3999 texturelayer_t *layer;
4000 layer = t->currentlayers + t->currentnumlayers++;
4002 layer->depthmask = depthmask;
4003 layer->blendfunc1 = blendfunc1;
4004 layer->blendfunc2 = blendfunc2;
4005 layer->texture = texture;
4006 layer->texmatrix = *matrix;
4007 layer->color[0] = r * r_view.colorscale;
4008 layer->color[1] = g * r_view.colorscale;
4009 layer->color[2] = b * r_view.colorscale;
4010 layer->color[3] = a;
4013 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
4016 index = parms[2] + r_refdef.time * parms[3];
4017 index -= floor(index);
4021 case Q3WAVEFUNC_NONE:
4022 case Q3WAVEFUNC_NOISE:
4023 case Q3WAVEFUNC_COUNT:
4026 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
4027 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
4028 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
4029 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
4030 case Q3WAVEFUNC_TRIANGLE:
4032 f = index - floor(index);
4043 return (float)(parms[0] + parms[1] * f);
4046 void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
4049 model_t *model = ent->model;
4052 q3shaderinfo_layer_tcmod_t *tcmod;
4054 // switch to an alternate material if this is a q1bsp animated material
4056 texture_t *texture = t;
4057 int s = ent->skinnum;
4058 if ((unsigned int)s >= (unsigned int)model->numskins)
4060 if (model->skinscenes)
4062 if (model->skinscenes[s].framecount > 1)
4063 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
4065 s = model->skinscenes[s].firstframe;
4068 t = t + s * model->num_surfaces;
4071 // use an alternate animation if the entity's frame is not 0,
4072 // and only if the texture has an alternate animation
4073 if (ent->frame2 != 0 && t->anim_total[1])
4074 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.time * 5.0f) % t->anim_total[1]) : 0];
4076 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.time * 5.0f) % t->anim_total[0]) : 0];
4078 texture->currentframe = t;
4081 // update currentskinframe to be a qw skin or animation frame
4082 if ((i = ent->entitynumber - 1) >= 0 && i < cl.maxclients)
4084 if (strcmp(r_qwskincache[i], cl.scores[i].qw_skin))
4086 strlcpy(r_qwskincache[i], cl.scores[i].qw_skin, sizeof(r_qwskincache[i]));
4087 Con_DPrintf("loading skins/%s\n", r_qwskincache[i]);
4088 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);
4090 t->currentskinframe = r_qwskincache_skinframe[i];
4091 if (t->currentskinframe == NULL)
4092 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->frame2time)) % t->numskinframes];
4094 else if (t->numskinframes >= 2)
4095 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->frame2time)) % t->numskinframes];
4096 if (t->backgroundnumskinframes >= 2)
4097 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - ent->frame2time)) % t->backgroundnumskinframes];
4099 t->currentmaterialflags = t->basematerialflags;
4100 t->currentalpha = ent->alpha;
4101 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
4103 t->currentalpha *= r_wateralpha.value;
4105 * FIXME what is this supposed to do?
4106 // if rendering refraction/reflection, disable transparency
4107 if (r_waterstate.enabled && (t->currentalpha < 1 || (t->currentmaterialflags & MATERIALFLAG_ALPHA)))
4108 t->currentmaterialflags |= MATERIALFLAG_WATERSHADER;
4111 if(!r_waterstate.enabled)
4112 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION);
4113 if (!(ent->flags & RENDER_LIGHT))
4114 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
4115 else if (rsurface.modeltexcoordlightmap2f == NULL)
4117 // pick a model lighting mode
4118 if (VectorLength2(ent->modellight_diffuse) >= (1.0f / 256.0f))
4119 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
4121 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
4123 if (ent->effects & EF_ADDITIVE)
4124 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
4125 else if (t->currentalpha < 1)
4126 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
4127 if (ent->effects & EF_DOUBLESIDED)
4128 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
4129 if (ent->effects & EF_NODEPTHTEST)
4130 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
4131 if (ent->flags & RENDER_VIEWMODEL)
4132 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
4133 if (t->backgroundnumskinframes && !(t->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED))
4134 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
4136 // make sure that the waterscroll matrix is used on water surfaces when
4137 // there is no tcmod
4138 if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
4139 t->currenttexmatrix = r_waterscrollmatrix;
4141 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
4144 switch(tcmod->tcmod)
4148 if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
4149 matrix = r_waterscrollmatrix;
4151 matrix = identitymatrix;
4153 case Q3TCMOD_ENTITYTRANSLATE:
4154 // this is used in Q3 to allow the gamecode to control texcoord
4155 // scrolling on the entity, which is not supported in darkplaces yet.
4156 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
4158 case Q3TCMOD_ROTATE:
4159 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
4160 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.time, 0, 0, 1);
4161 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
4164 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
4166 case Q3TCMOD_SCROLL:
4167 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.time, tcmod->parms[1] * r_refdef.time, 0);
4169 case Q3TCMOD_STRETCH:
4170 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
4171 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
4173 case Q3TCMOD_TRANSFORM:
4174 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
4175 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
4176 VectorSet(tcmat + 6, 0 , 0 , 1);
4177 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
4178 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
4180 case Q3TCMOD_TURBULENT:
4181 // this is handled in the RSurf_PrepareVertices function
4182 matrix = identitymatrix;
4185 // either replace or concatenate the transformation
4187 t->currenttexmatrix = matrix;
4190 matrix4x4_t temp = t->currenttexmatrix;
4191 Matrix4x4_Concat(&t->currenttexmatrix, &matrix, &temp);
4195 t->colormapping = VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f);
4196 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
4197 t->glosstexture = r_texture_black;
4198 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
4199 t->backgroundglosstexture = r_texture_black;
4200 t->specularpower = r_shadow_glossexponent.value;
4201 // TODO: store reference values for these in the texture?
4202 t->specularscale = 0;
4203 if (r_shadow_gloss.integer > 0)
4205 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
4207 if (r_shadow_glossintensity.value > 0)
4209 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
4210 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
4211 t->specularscale = r_shadow_glossintensity.value;
4214 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
4216 t->glosstexture = r_texture_white;
4217 t->backgroundglosstexture = r_texture_white;
4218 t->specularscale = r_shadow_gloss2intensity.value;
4222 // lightmaps mode looks bad with dlights using actual texturing, so turn
4223 // off the colormap and glossmap, but leave the normalmap on as it still
4224 // accurately represents the shading involved
4225 if (gl_lightmaps.integer && !(t->currentmaterialflags & MATERIALFLAG_BLENDED))
4227 t->basetexture = r_texture_white;
4228 t->specularscale = 0;
4231 Vector4Set(t->lightmapcolor, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
4232 VectorClear(t->dlightcolor);
4233 t->currentnumlayers = 0;
4234 if (!(t->currentmaterialflags & MATERIALFLAG_NODRAW))
4236 if (!(t->currentmaterialflags & MATERIALFLAG_SKY))
4238 int blendfunc1, blendfunc2, depthmask;
4239 if (t->currentmaterialflags & MATERIALFLAG_ADD)
4241 blendfunc1 = GL_SRC_ALPHA;
4242 blendfunc2 = GL_ONE;
4244 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
4246 blendfunc1 = GL_SRC_ALPHA;
4247 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
4249 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
4251 blendfunc1 = t->customblendfunc[0];
4252 blendfunc2 = t->customblendfunc[1];
4256 blendfunc1 = GL_ONE;
4257 blendfunc2 = GL_ZERO;
4259 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
4260 if (t->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL))
4262 rtexture_t *currentbasetexture;
4264 if (r_refdef.fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED))
4265 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
4266 currentbasetexture = (VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) < (1.0f / 1048576.0f) && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
4267 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
4269 // fullbright is not affected by r_refdef.lightmapintensity
4270 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, t->lightmapcolor[0], t->lightmapcolor[1], t->lightmapcolor[2], t->lightmapcolor[3]);
4271 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
4272 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->pants, &t->currenttexmatrix, ent->colormap_pantscolor[0] * t->lightmapcolor[0], ent->colormap_pantscolor[1] * t->lightmapcolor[1], ent->colormap_pantscolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
4273 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
4274 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->shirt, &t->currenttexmatrix, ent->colormap_shirtcolor[0] * t->lightmapcolor[0], ent->colormap_shirtcolor[1] * t->lightmapcolor[1], ent->colormap_shirtcolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
4278 vec3_t ambientcolor;
4280 // set the color tint used for lights affecting this surface
4281 VectorSet(t->dlightcolor, ent->colormod[0] * t->lightmapcolor[3], ent->colormod[1] * t->lightmapcolor[3], ent->colormod[2] * t->lightmapcolor[3]);
4283 // q3bsp has no lightmap updates, so the lightstylevalue that
4284 // would normally be baked into the lightmap must be
4285 // applied to the color
4286 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
4287 if (ent->model->type == mod_brushq3)
4288 colorscale *= r_refdef.rtlightstylevalue[0];
4289 colorscale *= r_refdef.lightmapintensity;
4290 VectorScale(t->lightmapcolor, r_ambient.value * (1.0f / 64.0f), ambientcolor);
4291 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
4292 // basic lit geometry
4293 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_LITTEXTURE, currentbasetexture, &t->currenttexmatrix, t->lightmapcolor[0], t->lightmapcolor[1], t->lightmapcolor[2], t->lightmapcolor[3]);
4294 // add pants/shirt if needed
4295 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
4296 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->currentskinframe->pants, &t->currenttexmatrix, ent->colormap_pantscolor[0] * t->lightmapcolor[0], ent->colormap_pantscolor[1] * t->lightmapcolor[1], ent->colormap_pantscolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
4297 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
4298 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->currentskinframe->shirt, &t->currenttexmatrix, ent->colormap_shirtcolor[0] * t->lightmapcolor[0], ent->colormap_shirtcolor[1] * t->lightmapcolor[1], ent->colormap_shirtcolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
4299 // now add ambient passes if needed
4300 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
4302 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ambientcolor[0], ambientcolor[1], ambientcolor[2], t->lightmapcolor[3]);
4303 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
4304 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->pants, &t->currenttexmatrix, ent->colormap_pantscolor[0] * ambientcolor[0], ent->colormap_pantscolor[1] * ambientcolor[1], ent->colormap_pantscolor[2] * ambientcolor[2], t->lightmapcolor[3]);
4305 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
4306 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->shirt, &t->currenttexmatrix, ent->colormap_shirtcolor[0] * ambientcolor[0], ent->colormap_shirtcolor[1] * ambientcolor[1], ent->colormap_shirtcolor[2] * ambientcolor[2], t->lightmapcolor[3]);
4309 if (t->currentskinframe->glow != NULL)
4310 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->lightmapcolor[3]);
4311 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
4313 // if this is opaque use alpha blend which will darken the earlier
4316 // if this is an alpha blended material, all the earlier passes
4317 // were darkened by fog already, so we only need to add the fog
4318 // color ontop through the fog mask texture
4320 // if this is an additive blended material, all the earlier passes
4321 // were darkened by fog already, and we should not add fog color
4322 // (because the background was not darkened, there is no fog color
4323 // that was lost behind it).
4324 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_view.colorscale, r_refdef.fogcolor[1] / r_view.colorscale, r_refdef.fogcolor[2] / r_view.colorscale, t->lightmapcolor[3]);
4331 void R_UpdateAllTextureInfo(entity_render_t *ent)
4335 for (i = 0;i < ent->model->num_texturesperskin;i++)
4336 R_UpdateTextureInfo(ent, ent->model->data_textures + i);
4339 rsurfacestate_t rsurface;
4341 void R_Mesh_ResizeArrays(int newvertices)
4344 if (rsurface.array_size >= newvertices)
4346 if (rsurface.array_modelvertex3f)
4347 Mem_Free(rsurface.array_modelvertex3f);
4348 rsurface.array_size = (newvertices + 1023) & ~1023;
4349 base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
4350 rsurface.array_modelvertex3f = base + rsurface.array_size * 0;
4351 rsurface.array_modelsvector3f = base + rsurface.array_size * 3;
4352 rsurface.array_modeltvector3f = base + rsurface.array_size * 6;
4353 rsurface.array_modelnormal3f = base + rsurface.array_size * 9;
4354 rsurface.array_deformedvertex3f = base + rsurface.array_size * 12;
4355 rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
4356 rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
4357 rsurface.array_deformednormal3f = base + rsurface.array_size * 21;
4358 rsurface.array_texcoord3f = base + rsurface.array_size * 24;
4359 rsurface.array_color4f = base + rsurface.array_size * 27;
4360 rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
4363 void RSurf_CleanUp(void)
4366 if (rsurface.mode == RSURFMODE_GLSL)
4368 qglUseProgramObjectARB(0);CHECKGLERROR
4370 GL_AlphaTest(false);
4371 rsurface.mode = RSURFMODE_NONE;
4372 rsurface.uselightmaptexture = false;
4373 rsurface.texture = NULL;
4376 void RSurf_ActiveWorldEntity(void)
4378 model_t *model = r_refdef.worldmodel;
4380 if (rsurface.array_size < model->surfmesh.num_vertices)
4381 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
4382 rsurface.matrix = identitymatrix;
4383 rsurface.inversematrix = identitymatrix;
4384 R_Mesh_Matrix(&identitymatrix);
4385 VectorCopy(r_view.origin, rsurface.modelorg);
4386 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
4387 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
4388 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
4389 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
4390 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
4391 rsurface.frameblend[0].frame = 0;
4392 rsurface.frameblend[0].lerp = 1;
4393 rsurface.frameblend[1].frame = 0;
4394 rsurface.frameblend[1].lerp = 0;
4395 rsurface.frameblend[2].frame = 0;
4396 rsurface.frameblend[2].lerp = 0;
4397 rsurface.frameblend[3].frame = 0;
4398 rsurface.frameblend[3].lerp = 0;
4399 rsurface.basepolygonfactor = r_refdef.polygonfactor;
4400 rsurface.basepolygonoffset = r_refdef.polygonoffset;
4401 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
4402 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
4403 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
4404 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
4405 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
4406 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
4407 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
4408 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
4409 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
4410 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
4411 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
4412 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
4413 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
4414 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
4415 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
4416 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
4417 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
4418 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
4419 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
4420 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
4421 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
4422 rsurface.modelelement3i = model->surfmesh.data_element3i;
4423 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo;
4424 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
4425 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
4426 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
4427 rsurface.modelsurfaces = model->data_surfaces;
4428 rsurface.generatedvertex = false;
4429 rsurface.vertex3f = rsurface.modelvertex3f;
4430 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
4431 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
4432 rsurface.svector3f = rsurface.modelsvector3f;
4433 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
4434 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
4435 rsurface.tvector3f = rsurface.modeltvector3f;
4436 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
4437 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
4438 rsurface.normal3f = rsurface.modelnormal3f;
4439 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
4440 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
4441 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
4444 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4446 model_t *model = ent->model;
4448 if (rsurface.array_size < model->surfmesh.num_vertices)
4449 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
4450 rsurface.matrix = ent->matrix;
4451 rsurface.inversematrix = ent->inversematrix;
4452 R_Mesh_Matrix(&rsurface.matrix);
4453 Matrix4x4_Transform(&rsurface.inversematrix, r_view.origin, rsurface.modelorg);
4454 rsurface.modellight_ambient[0] = ent->modellight_ambient[0] * ent->colormod[0];
4455 rsurface.modellight_ambient[1] = ent->modellight_ambient[1] * ent->colormod[1];
4456 rsurface.modellight_ambient[2] = ent->modellight_ambient[2] * ent->colormod[2];
4457 rsurface.modellight_diffuse[0] = ent->modellight_diffuse[0] * ent->colormod[0];
4458 rsurface.modellight_diffuse[1] = ent->modellight_diffuse[1] * ent->colormod[1];
4459 rsurface.modellight_diffuse[2] = ent->modellight_diffuse[2] * ent->colormod[2];
4460 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
4461 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
4462 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
4463 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
4464 rsurface.frameblend[0] = ent->frameblend[0];
4465 rsurface.frameblend[1] = ent->frameblend[1];
4466 rsurface.frameblend[2] = ent->frameblend[2];
4467 rsurface.frameblend[3] = ent->frameblend[3];
4468 rsurface.basepolygonfactor = r_refdef.polygonfactor;
4469 rsurface.basepolygonoffset = r_refdef.polygonoffset;
4470 if (ent->model->brush.submodel)
4472 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
4473 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
4475 if (model->surfmesh.isanimated && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].frame != 0))
4479 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
4480 rsurface.modelsvector3f = rsurface.array_modelsvector3f;
4481 rsurface.modeltvector3f = rsurface.array_modeltvector3f;
4482 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
4483 Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
4485 else if (wantnormals)
4487 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
4488 rsurface.modelsvector3f = NULL;
4489 rsurface.modeltvector3f = NULL;
4490 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
4491 Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
4495 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
4496 rsurface.modelsvector3f = NULL;
4497 rsurface.modeltvector3f = NULL;
4498 rsurface.modelnormal3f = NULL;
4499 Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, NULL, NULL, NULL);
4501 rsurface.modelvertex3f_bufferobject = 0;
4502 rsurface.modelvertex3f_bufferoffset = 0;
4503 rsurface.modelsvector3f_bufferobject = 0;
4504 rsurface.modelsvector3f_bufferoffset = 0;
4505 rsurface.modeltvector3f_bufferobject = 0;
4506 rsurface.modeltvector3f_bufferoffset = 0;
4507 rsurface.modelnormal3f_bufferobject = 0;
4508 rsurface.modelnormal3f_bufferoffset = 0;
4509 rsurface.generatedvertex = true;
4513 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
4514 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
4515 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
4516 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
4517 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
4518 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
4519 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
4520 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
4521 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
4522 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
4523 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
4524 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
4525 rsurface.generatedvertex = false;
4527 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
4528 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
4529 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
4530 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
4531 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
4532 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
4533 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
4534 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
4535 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
4536 rsurface.modelelement3i = model->surfmesh.data_element3i;
4537 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo;
4538 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
4539 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
4540 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
4541 rsurface.modelsurfaces = model->data_surfaces;
4542 rsurface.vertex3f = rsurface.modelvertex3f;
4543 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
4544 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
4545 rsurface.svector3f = rsurface.modelsvector3f;
4546 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
4547 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
4548 rsurface.tvector3f = rsurface.modeltvector3f;
4549 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
4550 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
4551 rsurface.normal3f = rsurface.modelnormal3f;
4552 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
4553 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
4554 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
4557 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
4558 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, msurface_t **texturesurfacelist)
4561 int texturesurfaceindex;
4566 const float *v1, *in_tc;
4568 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
4570 q3shaderinfo_deform_t *deform;
4571 // 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
4572 if (rsurface.generatedvertex)
4574 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
4575 generatenormals = true;
4576 for (i = 0;i < Q3MAXDEFORMS;i++)
4578 if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
4580 generatetangents = true;
4581 generatenormals = true;
4583 if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
4584 generatenormals = true;
4586 if (generatenormals && !rsurface.modelnormal3f)
4588 rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
4589 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
4590 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
4591 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer);
4593 if (generatetangents && !rsurface.modelsvector3f)
4595 rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
4596 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
4597 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
4598 rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
4599 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
4600 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
4601 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);
4604 rsurface.vertex3f = rsurface.modelvertex3f;
4605 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
4606 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
4607 rsurface.svector3f = rsurface.modelsvector3f;
4608 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
4609 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
4610 rsurface.tvector3f = rsurface.modeltvector3f;
4611 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
4612 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
4613 rsurface.normal3f = rsurface.modelnormal3f;
4614 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
4615 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
4616 // if vertices are deformed (sprite flares and things in maps, possibly
4617 // water waves, bulges and other deformations), generate them into
4618 // rsurface.deform* arrays from whatever the rsurface.* arrays point to
4619 // (may be static model data or generated data for an animated model, or
4620 // the previous deform pass)
4621 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
4623 switch (deform->deform)
4626 case Q3DEFORM_PROJECTIONSHADOW:
4627 case Q3DEFORM_TEXT0:
4628 case Q3DEFORM_TEXT1:
4629 case Q3DEFORM_TEXT2:
4630 case Q3DEFORM_TEXT3:
4631 case Q3DEFORM_TEXT4:
4632 case Q3DEFORM_TEXT5:
4633 case Q3DEFORM_TEXT6:
4634 case Q3DEFORM_TEXT7:
4637 case Q3DEFORM_AUTOSPRITE:
4638 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.forward, newforward);
4639 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.right, newright);
4640 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.up, newup);
4641 VectorNormalize(newforward);
4642 VectorNormalize(newright);
4643 VectorNormalize(newup);
4644 // make deformed versions of only the model vertices used by the specified surfaces
4645 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4647 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4648 // a single autosprite surface can contain multiple sprites...
4649 for (j = 0;j < surface->num_vertices - 3;j += 4)
4651 VectorClear(center);
4652 for (i = 0;i < 4;i++)
4653 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
4654 VectorScale(center, 0.25f, center);
4655 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, forward);
4656 VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
4657 VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
4658 for (i = 0;i < 4;i++)
4660 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
4661 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
4664 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);
4665 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);
4667 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4668 rsurface.vertex3f_bufferobject = 0;
4669 rsurface.vertex3f_bufferoffset = 0;
4670 rsurface.svector3f = rsurface.array_deformedsvector3f;
4671 rsurface.svector3f_bufferobject = 0;
4672 rsurface.svector3f_bufferoffset = 0;
4673 rsurface.tvector3f = rsurface.array_deformedtvector3f;
4674 rsurface.tvector3f_bufferobject = 0;
4675 rsurface.tvector3f_bufferoffset = 0;
4676 rsurface.normal3f = rsurface.array_deformednormal3f;
4677 rsurface.normal3f_bufferobject = 0;
4678 rsurface.normal3f_bufferoffset = 0;
4680 case Q3DEFORM_AUTOSPRITE2:
4681 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.forward, newforward);
4682 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.right, newright);
4683 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.up, newup);
4684 VectorNormalize(newforward);
4685 VectorNormalize(newright);
4686 VectorNormalize(newup);
4687 // make deformed versions of only the model vertices used by the specified surfaces
4688 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4690 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4691 const float *v1, *v2;
4701 memset(shortest, 0, sizeof(shortest));
4702 // a single autosprite surface can contain multiple sprites...
4703 for (j = 0;j < surface->num_vertices - 3;j += 4)
4705 VectorClear(center);
4706 for (i = 0;i < 4;i++)
4707 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
4708 VectorScale(center, 0.25f, center);
4709 // find the two shortest edges, then use them to define the
4710 // axis vectors for rotating around the central axis
4711 for (i = 0;i < 6;i++)
4713 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
4714 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
4716 Debug_PolygonBegin(NULL, 0, false, 0);
4717 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
4718 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);
4719 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
4722 l = VectorDistance2(v1, v2);
4723 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
4725 l += (1.0f / 1024.0f);
4726 if (shortest[0].length2 > l || i == 0)
4728 shortest[1] = shortest[0];
4729 shortest[0].length2 = l;
4730 shortest[0].v1 = v1;
4731 shortest[0].v2 = v2;
4733 else if (shortest[1].length2 > l || i == 1)
4735 shortest[1].length2 = l;
4736 shortest[1].v1 = v1;
4737 shortest[1].v2 = v2;
4740 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
4741 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
4743 Debug_PolygonBegin(NULL, 0, false, 0);
4744 Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
4745 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);
4746 Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
4749 // this calculates the right vector from the shortest edge
4750 // and the up vector from the edge midpoints
4751 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
4752 VectorNormalize(right);
4753 VectorSubtract(end, start, up);
4754 VectorNormalize(up);
4755 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
4756 //VectorSubtract(rsurface.modelorg, center, forward);
4757 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.forward, forward);
4758 VectorNegate(forward, forward);
4759 VectorReflect(forward, 0, up, forward);
4760 VectorNormalize(forward);
4761 CrossProduct(up, forward, newright);
4762 VectorNormalize(newright);
4764 Debug_PolygonBegin(NULL, 0, false, 0);
4765 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);
4766 Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
4767 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
4771 Debug_PolygonBegin(NULL, 0, false, 0);
4772 Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
4773 Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
4774 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
4777 // rotate the quad around the up axis vector, this is made
4778 // especially easy by the fact we know the quad is flat,
4779 // so we only have to subtract the center position and
4780 // measure distance along the right vector, and then
4781 // multiply that by the newright vector and add back the
4783 // we also need to subtract the old position to undo the
4784 // displacement from the center, which we do with a
4785 // DotProduct, the subtraction/addition of center is also
4786 // optimized into DotProducts here
4787 l = DotProduct(right, center);
4788 for (i = 0;i < 4;i++)
4790 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
4791 f = DotProduct(right, v1) - l;
4792 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
4795 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);
4796 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);
4798 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4799 rsurface.vertex3f_bufferobject = 0;
4800 rsurface.vertex3f_bufferoffset = 0;
4801 rsurface.svector3f = rsurface.array_deformedsvector3f;
4802 rsurface.svector3f_bufferobject = 0;
4803 rsurface.svector3f_bufferoffset = 0;
4804 rsurface.tvector3f = rsurface.array_deformedtvector3f;
4805 rsurface.tvector3f_bufferobject = 0;
4806 rsurface.tvector3f_bufferoffset = 0;
4807 rsurface.normal3f = rsurface.array_deformednormal3f;
4808 rsurface.normal3f_bufferobject = 0;
4809 rsurface.normal3f_bufferoffset = 0;
4811 case Q3DEFORM_NORMAL:
4812 // deform the normals to make reflections wavey
4813 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4815 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4816 for (j = 0;j < surface->num_vertices;j++)
4819 float *normal = (rsurface.array_deformednormal3f + 3 * surface->num_firstvertex) + j*3;
4820 VectorScale((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
4821 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, normal);
4822 normal[0] += deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.time * deform->parms[1]);
4823 normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.time * deform->parms[1]);
4824 normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.time * deform->parms[1]);
4825 VectorNormalize(normal);
4827 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);
4829 rsurface.svector3f = rsurface.array_deformedsvector3f;
4830 rsurface.svector3f_bufferobject = 0;
4831 rsurface.svector3f_bufferoffset = 0;
4832 rsurface.tvector3f = rsurface.array_deformedtvector3f;
4833 rsurface.tvector3f_bufferobject = 0;
4834 rsurface.tvector3f_bufferoffset = 0;
4835 rsurface.normal3f = rsurface.array_deformednormal3f;
4836 rsurface.normal3f_bufferobject = 0;
4837 rsurface.normal3f_bufferoffset = 0;
4840 // deform vertex array to make wavey water and flags and such
4841 waveparms[0] = deform->waveparms[0];
4842 waveparms[1] = deform->waveparms[1];
4843 waveparms[2] = deform->waveparms[2];
4844 waveparms[3] = deform->waveparms[3];
4845 // this is how a divisor of vertex influence on deformation
4846 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
4847 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
4848 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4850 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4851 for (j = 0;j < surface->num_vertices;j++)
4853 float *vertex = (rsurface.array_deformedvertex3f + 3 * surface->num_firstvertex) + j*3;
4854 VectorCopy((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, vertex);
4855 // if the wavefunc depends on time, evaluate it per-vertex
4858 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
4859 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
4861 VectorMA(vertex, scale, (rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, vertex);
4864 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4865 rsurface.vertex3f_bufferobject = 0;
4866 rsurface.vertex3f_bufferoffset = 0;
4868 case Q3DEFORM_BULGE:
4869 // deform vertex array to make the surface have moving bulges
4870 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4872 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4873 for (j = 0;j < surface->num_vertices;j++)
4875 scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.time * deform->parms[2])) * deform->parms[1];
4876 VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
4879 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4880 rsurface.vertex3f_bufferobject = 0;
4881 rsurface.vertex3f_bufferoffset = 0;
4884 // deform vertex array
4885 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
4886 VectorScale(deform->parms, scale, waveparms);
4887 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4889 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4890 for (j = 0;j < surface->num_vertices;j++)
4891 VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
4893 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4894 rsurface.vertex3f_bufferobject = 0;
4895 rsurface.vertex3f_bufferoffset = 0;
4899 // generate texcoords based on the chosen texcoord source
4900 switch(rsurface.texture->tcgen.tcgen)
4903 case Q3TCGEN_TEXTURE:
4904 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
4905 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordtexture2f_bufferobject;
4906 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
4908 case Q3TCGEN_LIGHTMAP:
4909 rsurface.texcoordtexture2f = rsurface.modeltexcoordlightmap2f;
4910 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
4911 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
4913 case Q3TCGEN_VECTOR:
4914 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4916 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4917 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)
4919 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
4920 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
4923 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
4924 rsurface.texcoordtexture2f_bufferobject = 0;
4925 rsurface.texcoordtexture2f_bufferoffset = 0;
4927 case Q3TCGEN_ENVIRONMENT:
4928 // make environment reflections using a spheremap
4929 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4931 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4932 const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
4933 const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
4934 float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
4935 for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
4937 float l, d, eyedir[3];
4938 VectorSubtract(rsurface.modelorg, vertex, eyedir);
4939 l = 0.5f / VectorLength(eyedir);
4940 d = DotProduct(normal, eyedir)*2;
4941 out_tc[0] = 0.5f + (normal[1]*d - eyedir[1])*l;
4942 out_tc[1] = 0.5f - (normal[2]*d - eyedir[2])*l;
4945 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
4946 rsurface.texcoordtexture2f_bufferobject = 0;
4947 rsurface.texcoordtexture2f_bufferoffset = 0;
4950 // the only tcmod that needs software vertex processing is turbulent, so
4951 // check for it here and apply the changes if needed
4952 // and we only support that as the first one
4953 // (handling a mixture of turbulent and other tcmods would be problematic
4954 // without punting it entirely to a software path)
4955 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
4957 amplitude = rsurface.texture->tcmods[0].parms[1];
4958 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.time * rsurface.texture->tcmods[0].parms[3];
4959 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4961 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4962 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)
4964 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
4965 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
4968 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
4969 rsurface.texcoordtexture2f_bufferobject = 0;
4970 rsurface.texcoordtexture2f_bufferoffset = 0;
4972 rsurface.texcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
4973 rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
4974 rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
4975 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
4978 void RSurf_DrawBatch_Simple(int texturenumsurfaces, msurface_t **texturesurfacelist)
4981 const msurface_t *surface = texturesurfacelist[0];
4982 const msurface_t *surface2;
4987 // TODO: lock all array ranges before render, rather than on each surface
4988 if (texturenumsurfaces == 1)
4990 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
4991 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));
4993 else if (r_batchmode.integer == 2)
4995 #define MAXBATCHTRIANGLES 4096
4996 int batchtriangles = 0;
4997 int batchelements[MAXBATCHTRIANGLES*3];
4998 for (i = 0;i < texturenumsurfaces;i = j)
5000 surface = texturesurfacelist[i];
5002 if (surface->num_triangles > MAXBATCHTRIANGLES)
5004 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));
5007 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
5008 batchtriangles = surface->num_triangles;
5009 firstvertex = surface->num_firstvertex;
5010 endvertex = surface->num_firstvertex + surface->num_vertices;
5011 for (;j < texturenumsurfaces;j++)
5013 surface2 = texturesurfacelist[j];
5014 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
5016 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
5017 batchtriangles += surface2->num_triangles;
5018 firstvertex = min(firstvertex, surface2->num_firstvertex);
5019 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
5021 surface2 = texturesurfacelist[j-1];
5022 numvertices = endvertex - firstvertex;
5023 R_Mesh_Draw(firstvertex, numvertices, batchtriangles, batchelements, 0, 0);
5026 else if (r_batchmode.integer == 1)
5028 for (i = 0;i < texturenumsurfaces;i = j)
5030 surface = texturesurfacelist[i];
5031 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
5032 if (texturesurfacelist[j] != surface2)
5034 surface2 = texturesurfacelist[j-1];
5035 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
5036 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
5037 GL_LockArrays(surface->num_firstvertex, numvertices);
5038 R_Mesh_Draw(surface->num_firstvertex, numvertices, numtriangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
5043 for (i = 0;i < texturenumsurfaces;i++)
5045 surface = texturesurfacelist[i];
5046 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5047 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));
5052 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit, int refractiontexunit, int reflectiontexunit)
5054 int i, planeindex, vertexindex;
5058 r_waterstate_waterplane_t *p, *bestp;
5059 msurface_t *surface;
5060 if (r_waterstate.renderingscene)
5062 for (i = 0;i < texturenumsurfaces;i++)
5064 surface = texturesurfacelist[i];
5065 if (lightmaptexunit >= 0)
5066 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5067 if (deluxemaptexunit >= 0)
5068 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5069 // pick the closest matching water plane
5072 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5075 for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
5077 Matrix4x4_Transform(&rsurface.matrix, v, vert);
5078 d += fabs(PlaneDiff(vert, &p->plane));
5080 if (bestd > d || !bestp)
5088 if (refractiontexunit >= 0)
5089 R_Mesh_TexBind(refractiontexunit, R_GetTexture(bestp->texture_refraction));
5090 if (reflectiontexunit >= 0)
5091 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(bestp->texture_reflection));
5095 if (refractiontexunit >= 0)
5096 R_Mesh_TexBind(refractiontexunit, R_GetTexture(r_texture_black));
5097 if (reflectiontexunit >= 0)
5098 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(r_texture_black));
5100 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5101 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));
5105 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit)
5109 const msurface_t *surface = texturesurfacelist[0];
5110 const msurface_t *surface2;
5115 // TODO: lock all array ranges before render, rather than on each surface
5116 if (texturenumsurfaces == 1)
5118 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5119 if (deluxemaptexunit >= 0)
5120 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5121 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5122 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));
5124 else if (r_batchmode.integer == 2)
5126 #define MAXBATCHTRIANGLES 4096
5127 int batchtriangles = 0;
5128 int batchelements[MAXBATCHTRIANGLES*3];
5129 for (i = 0;i < texturenumsurfaces;i = j)
5131 surface = texturesurfacelist[i];
5132 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5133 if (deluxemaptexunit >= 0)
5134 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5136 if (surface->num_triangles > MAXBATCHTRIANGLES)
5138 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));
5141 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
5142 batchtriangles = surface->num_triangles;
5143 firstvertex = surface->num_firstvertex;
5144 endvertex = surface->num_firstvertex + surface->num_vertices;
5145 for (;j < texturenumsurfaces;j++)
5147 surface2 = texturesurfacelist[j];
5148 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
5150 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
5151 batchtriangles += surface2->num_triangles;
5152 firstvertex = min(firstvertex, surface2->num_firstvertex);
5153 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
5155 surface2 = texturesurfacelist[j-1];
5156 numvertices = endvertex - firstvertex;
5157 R_Mesh_Draw(firstvertex, numvertices, batchtriangles, batchelements, 0, 0);
5160 else if (r_batchmode.integer == 1)
5163 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
5164 for (i = 0;i < texturenumsurfaces;i = j)
5166 surface = texturesurfacelist[i];
5167 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
5168 if (texturesurfacelist[j] != surface2)
5170 Con_Printf(" %i", j - i);
5173 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
5175 for (i = 0;i < texturenumsurfaces;i = j)
5177 surface = texturesurfacelist[i];
5178 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5179 if (deluxemaptexunit >= 0)
5180 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5181 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
5182 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
5185 Con_Printf(" %i", j - i);
5187 surface2 = texturesurfacelist[j-1];
5188 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
5189 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
5190 GL_LockArrays(surface->num_firstvertex, numvertices);
5191 R_Mesh_Draw(surface->num_firstvertex, numvertices, numtriangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
5199 for (i = 0;i < texturenumsurfaces;i++)
5201 surface = texturesurfacelist[i];
5202 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5203 if (deluxemaptexunit >= 0)
5204 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5205 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5206 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));
5211 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
5214 int texturesurfaceindex;
5215 if (r_showsurfaces.integer == 2)
5217 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5219 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5220 for (j = 0;j < surface->num_triangles;j++)
5222 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_view.colorscale;
5223 GL_Color(f, f, f, 1);
5224 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)));
5230 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5232 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5233 int k = (int)(((size_t)surface) / sizeof(msurface_t));
5234 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);
5235 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5236 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));
5241 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, msurface_t **texturesurfacelist)
5243 int texturesurfaceindex;
5247 if (rsurface.lightmapcolor4f)
5249 // generate color arrays for the surfaces in this list
5250 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5252 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5253 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)
5255 f = FogPoint_Model(v);
5265 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5267 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5268 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)
5270 f = FogPoint_Model(v);
5278 rsurface.lightmapcolor4f = rsurface.array_color4f;
5279 rsurface.lightmapcolor4f_bufferobject = 0;
5280 rsurface.lightmapcolor4f_bufferoffset = 0;
5283 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a)
5285 int texturesurfaceindex;
5288 if (!rsurface.lightmapcolor4f)
5290 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5292 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5293 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)
5301 rsurface.lightmapcolor4f = rsurface.array_color4f;
5302 rsurface.lightmapcolor4f_bufferobject = 0;
5303 rsurface.lightmapcolor4f_bufferoffset = 0;
5306 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5309 rsurface.lightmapcolor4f = NULL;
5310 rsurface.lightmapcolor4f_bufferobject = 0;
5311 rsurface.lightmapcolor4f_bufferoffset = 0;
5312 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5313 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5314 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5315 GL_Color(r, g, b, a);
5316 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 0, -1);
5319 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5321 // TODO: optimize applyfog && applycolor case
5322 // just apply fog if necessary, and tint the fog color array if necessary
5323 rsurface.lightmapcolor4f = NULL;
5324 rsurface.lightmapcolor4f_bufferobject = 0;
5325 rsurface.lightmapcolor4f_bufferoffset = 0;
5326 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5327 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5328 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5329 GL_Color(r, g, b, a);
5330 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5333 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5335 int texturesurfaceindex;
5339 if (texturesurfacelist[0]->lightmapinfo && texturesurfacelist[0]->lightmapinfo->stainsamples)
5341 // generate color arrays for the surfaces in this list
5342 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5344 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5345 for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
5347 if (surface->lightmapinfo->samples)
5349 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
5350 float scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
5351 VectorScale(lm, scale, c);
5352 if (surface->lightmapinfo->styles[1] != 255)
5354 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
5356 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
5357 VectorMA(c, scale, lm, c);
5358 if (surface->lightmapinfo->styles[2] != 255)
5361 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
5362 VectorMA(c, scale, lm, c);
5363 if (surface->lightmapinfo->styles[3] != 255)
5366 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
5367 VectorMA(c, scale, lm, c);
5377 rsurface.lightmapcolor4f = rsurface.array_color4f;
5378 rsurface.lightmapcolor4f_bufferobject = 0;
5379 rsurface.lightmapcolor4f_bufferoffset = 0;
5383 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
5384 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
5385 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
5387 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5388 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5389 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5390 GL_Color(r, g, b, a);
5391 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5394 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5396 int texturesurfaceindex;
5400 vec3_t ambientcolor;
5401 vec3_t diffusecolor;
5405 VectorCopy(rsurface.modellight_lightdir, lightdir);
5406 f = 0.5f * r_refdef.lightmapintensity;
5407 ambientcolor[0] = rsurface.modellight_ambient[0] * r * f;
5408 ambientcolor[1] = rsurface.modellight_ambient[1] * g * f;
5409 ambientcolor[2] = rsurface.modellight_ambient[2] * b * f;
5410 diffusecolor[0] = rsurface.modellight_diffuse[0] * r * f;
5411 diffusecolor[1] = rsurface.modellight_diffuse[1] * g * f;
5412 diffusecolor[2] = rsurface.modellight_diffuse[2] * b * f;
5413 if (VectorLength2(diffusecolor) > 0)
5415 // generate color arrays for the surfaces in this list
5416 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5418 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5419 int numverts = surface->num_vertices;
5420 v = rsurface.vertex3f + 3 * surface->num_firstvertex;
5421 c2 = rsurface.normal3f + 3 * surface->num_firstvertex;
5422 c = rsurface.array_color4f + 4 * surface->num_firstvertex;
5423 // q3-style directional shading
5424 for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
5426 if ((f = DotProduct(c2, lightdir)) > 0)
5427 VectorMA(ambientcolor, f, diffusecolor, c);
5429 VectorCopy(ambientcolor, c);
5438 rsurface.lightmapcolor4f = rsurface.array_color4f;
5439 rsurface.lightmapcolor4f_bufferobject = 0;
5440 rsurface.lightmapcolor4f_bufferoffset = 0;
5444 r = ambientcolor[0];
5445 g = ambientcolor[1];
5446 b = ambientcolor[2];
5447 rsurface.lightmapcolor4f = NULL;
5448 rsurface.lightmapcolor4f_bufferobject = 0;
5449 rsurface.lightmapcolor4f_bufferoffset = 0;
5451 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5452 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5453 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5454 GL_Color(r, g, b, a);
5455 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5458 void RSurf_SetupDepthAndCulling(void)
5460 // submodels are biased to avoid z-fighting with world surfaces that they
5461 // may be exactly overlapping (avoids z-fighting artifacts on certain
5462 // doors and things in Quake maps)
5463 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5464 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
5465 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
5466 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_view.cullface_back);
5469 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
5471 RSurf_SetupDepthAndCulling();
5472 if (rsurface.mode != RSURFMODE_SHOWSURFACES)
5474 rsurface.mode = RSURFMODE_SHOWSURFACES;
5476 GL_BlendFunc(GL_ONE, GL_ZERO);
5477 R_Mesh_ColorPointer(NULL, 0, 0);
5478 R_Mesh_ResetTextureState();
5480 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
5481 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
5484 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, msurface_t **texturesurfacelist)
5486 // transparent sky would be ridiculous
5487 if ((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED))
5489 if (rsurface.mode != RSURFMODE_SKY)
5491 if (rsurface.mode == RSURFMODE_GLSL)
5493 qglUseProgramObjectARB(0);CHECKGLERROR
5495 rsurface.mode = RSURFMODE_SKY;
5499 skyrendernow = false;
5501 // restore entity matrix
5502 R_Mesh_Matrix(&rsurface.matrix);
5504 RSurf_SetupDepthAndCulling();
5506 // LordHavoc: HalfLife maps have freaky skypolys so don't use
5507 // skymasking on them, and Quake3 never did sky masking (unlike
5508 // software Quake and software Quake2), so disable the sky masking
5509 // in Quake3 maps as it causes problems with q3map2 sky tricks,
5510 // and skymasking also looks very bad when noclipping outside the
5511 // level, so don't use it then either.
5512 if (r_refdef.worldmodel && r_refdef.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_viewcache.world_novis)
5514 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
5515 R_Mesh_ColorPointer(NULL, 0, 0);
5516 R_Mesh_ResetTextureState();
5517 if (skyrendermasked)
5519 // depth-only (masking)
5520 GL_ColorMask(0,0,0,0);
5521 // just to make sure that braindead drivers don't draw
5522 // anything despite that colormask...
5523 GL_BlendFunc(GL_ZERO, GL_ONE);
5528 GL_BlendFunc(GL_ONE, GL_ZERO);
5530 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
5531 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5532 if (skyrendermasked)
5533 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
5537 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, msurface_t **texturesurfacelist)
5539 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION)))
5542 if (rsurface.mode != RSURFMODE_GLSL)
5544 rsurface.mode = RSURFMODE_GLSL;
5545 R_Mesh_ResetTextureState();
5546 GL_Color(1, 1, 1, 1);
5549 R_Mesh_TexMatrix(0, &rsurface.texture->currenttexmatrix);
5550 R_Mesh_TexBind(0, R_GetTexture(rsurface.texture->currentskinframe->nmap));
5551 R_Mesh_TexBind(1, R_GetTexture(rsurface.texture->basetexture));
5552 R_Mesh_TexBind(2, R_GetTexture(rsurface.texture->glosstexture));
5553 R_Mesh_TexBind(4, R_GetTexture(r_texture_fogattenuation));
5554 R_Mesh_TexBind(5, R_GetTexture(rsurface.texture->currentskinframe->pants));
5555 R_Mesh_TexBind(6, R_GetTexture(rsurface.texture->currentskinframe->shirt));
5556 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
5558 R_Mesh_TexBind(7, R_GetTexture(r_texture_grey128));
5559 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
5560 R_Mesh_ColorPointer(NULL, 0, 0);
5562 else if (rsurface.uselightmaptexture)
5564 R_Mesh_TexBind(7, R_GetTexture(texturesurfacelist[0]->lightmaptexture));
5565 R_Mesh_TexBind(8, R_GetTexture(texturesurfacelist[0]->deluxemaptexture));
5566 R_Mesh_ColorPointer(NULL, 0, 0);
5570 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
5571 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
5572 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
5574 R_Mesh_TexBind(9, R_GetTexture(rsurface.texture->currentskinframe->glow));
5575 R_Mesh_TexBind(11, R_GetTexture(r_texture_white)); // changed per surface
5576 R_Mesh_TexBind(12, R_GetTexture(r_texture_white)); // changed per surface
5578 if (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5580 // render background
5581 GL_BlendFunc(GL_ONE, GL_ZERO);
5583 GL_AlphaTest(false);
5585 GL_Color(1, 1, 1, 1);
5586 R_Mesh_ColorPointer(NULL, 0, 0);
5588 R_SetupSurfaceShader(vec3_origin, rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
5589 if (r_glsl_permutation)
5591 RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
5592 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
5593 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
5594 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
5595 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
5596 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
5597 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist, -1, -1, r_glsl_permutation->loc_Texture_Refraction ? 11 : -1, r_glsl_permutation->loc_Texture_Reflection ? 12 : -1);
5600 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5601 GL_DepthMask(false);
5602 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5603 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
5605 R_Mesh_TexBind(7, R_GetTexture(r_texture_grey128));
5606 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
5607 R_Mesh_ColorPointer(NULL, 0, 0);
5609 else if (rsurface.uselightmaptexture)
5611 R_Mesh_TexBind(7, R_GetTexture(texturesurfacelist[0]->lightmaptexture));
5612 R_Mesh_TexBind(8, R_GetTexture(texturesurfacelist[0]->deluxemaptexture));
5613 R_Mesh_ColorPointer(NULL, 0, 0);
5617 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
5618 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
5619 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
5621 R_Mesh_TexBind(11, R_GetTexture(r_texture_white)); // changed per surface
5622 R_Mesh_TexBind(12, R_GetTexture(r_texture_white)); // changed per surface
5625 R_SetupSurfaceShader(vec3_origin, rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE);
5626 if (!r_glsl_permutation)
5629 RSurf_PrepareVerticesForBatch(r_glsl_permutation->loc_Texture_Normal >= 0 || r_glsl_permutation->loc_LightDir >= 0, r_glsl_permutation->loc_Texture_Normal >= 0, texturenumsurfaces, texturesurfacelist);
5630 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
5631 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
5632 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
5633 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
5634 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
5636 if (r_glsl_permutation->loc_Texture_Refraction >= 0)
5638 GL_BlendFunc(GL_ONE, GL_ZERO);
5640 GL_AlphaTest(false);
5643 if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
5645 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
5646 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist, 7, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? 8 : -1, r_glsl_permutation->loc_Texture_Refraction >= 0 ? 11 : -1, r_glsl_permutation->loc_Texture_Reflection >= 0 ? 12 : -1);
5648 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 7, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? 8 : -1);
5652 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
5653 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist, -1, -1, r_glsl_permutation->loc_Texture_Refraction >= 0 ? 11 : -1, r_glsl_permutation->loc_Texture_Reflection >= 0 ? 12 : -1);
5655 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5657 if (rsurface.texture->backgroundnumskinframes && !(rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED))
5662 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, msurface_t **texturesurfacelist)
5664 // OpenGL 1.3 path - anything not completely ancient
5665 int texturesurfaceindex;
5666 qboolean applycolor;
5670 const texturelayer_t *layer;
5671 if (rsurface.mode != RSURFMODE_MULTIPASS)
5672 rsurface.mode = RSURFMODE_MULTIPASS;
5673 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
5675 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
5678 int layertexrgbscale;
5679 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5681 if (layerindex == 0)
5685 GL_AlphaTest(false);
5686 qglDepthFunc(GL_EQUAL);CHECKGLERROR
5689 GL_DepthMask(layer->depthmask);
5690 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
5691 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
5693 layertexrgbscale = 4;
5694 VectorScale(layer->color, 0.25f, layercolor);
5696 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
5698 layertexrgbscale = 2;
5699 VectorScale(layer->color, 0.5f, layercolor);
5703 layertexrgbscale = 1;
5704 VectorScale(layer->color, 1.0f, layercolor);
5706 layercolor[3] = layer->color[3];
5707 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
5708 R_Mesh_ColorPointer(NULL, 0, 0);
5709 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
5710 switch (layer->type)
5712 case TEXTURELAYERTYPE_LITTEXTURE:
5713 memset(&m, 0, sizeof(m));
5714 m.tex[0] = R_GetTexture(r_texture_white);
5715 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
5716 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
5717 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
5718 m.tex[1] = R_GetTexture(layer->texture);
5719 m.texmatrix[1] = layer->texmatrix;
5720 m.texrgbscale[1] = layertexrgbscale;
5721 m.pointer_texcoord[1] = rsurface.texcoordtexture2f;
5722 m.pointer_texcoord_bufferobject[1] = rsurface.texcoordtexture2f_bufferobject;
5723 m.pointer_texcoord_bufferoffset[1] = rsurface.texcoordtexture2f_bufferoffset;
5724 R_Mesh_TextureState(&m);
5725 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
5726 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
5727 else if (rsurface.uselightmaptexture)
5728 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
5730 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
5732 case TEXTURELAYERTYPE_TEXTURE:
5733 memset(&m, 0, sizeof(m));
5734 m.tex[0] = R_GetTexture(layer->texture);
5735 m.texmatrix[0] = layer->texmatrix;
5736 m.texrgbscale[0] = layertexrgbscale;
5737 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5738 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5739 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5740 R_Mesh_TextureState(&m);
5741 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
5743 case TEXTURELAYERTYPE_FOG:
5744 memset(&m, 0, sizeof(m));
5745 m.texrgbscale[0] = layertexrgbscale;
5748 m.tex[0] = R_GetTexture(layer->texture);
5749 m.texmatrix[0] = layer->texmatrix;
5750 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5751 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5752 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5754 R_Mesh_TextureState(&m);
5755 // generate a color array for the fog pass
5756 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
5757 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5761 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5762 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)
5764 f = 1 - FogPoint_Model(v);
5765 c[0] = layercolor[0];
5766 c[1] = layercolor[1];
5767 c[2] = layercolor[2];
5768 c[3] = f * layercolor[3];
5771 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5774 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
5776 GL_LockArrays(0, 0);
5779 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5781 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
5782 GL_AlphaTest(false);
5786 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, msurface_t **texturesurfacelist)
5788 // OpenGL 1.1 - crusty old voodoo path
5789 int texturesurfaceindex;
5793 const texturelayer_t *layer;
5794 if (rsurface.mode != RSURFMODE_MULTIPASS)
5795 rsurface.mode = RSURFMODE_MULTIPASS;
5796 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
5798 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
5800 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5802 if (layerindex == 0)
5806 GL_AlphaTest(false);
5807 qglDepthFunc(GL_EQUAL);CHECKGLERROR
5810 GL_DepthMask(layer->depthmask);
5811 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
5812 R_Mesh_ColorPointer(NULL, 0, 0);
5813 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
5814 switch (layer->type)
5816 case TEXTURELAYERTYPE_LITTEXTURE:
5817 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
5819 // two-pass lit texture with 2x rgbscale
5820 // first the lightmap pass
5821 memset(&m, 0, sizeof(m));
5822 m.tex[0] = R_GetTexture(r_texture_white);
5823 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
5824 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
5825 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
5826 R_Mesh_TextureState(&m);
5827 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
5828 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5829 else if (rsurface.uselightmaptexture)
5830 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5832 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5833 GL_LockArrays(0, 0);
5834 // then apply the texture to it
5835 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
5836 memset(&m, 0, sizeof(m));
5837 m.tex[0] = R_GetTexture(layer->texture);
5838 m.texmatrix[0] = layer->texmatrix;
5839 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5840 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5841 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5842 R_Mesh_TextureState(&m);
5843 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);
5847 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
5848 memset(&m, 0, sizeof(m));
5849 m.tex[0] = R_GetTexture(layer->texture);
5850 m.texmatrix[0] = layer->texmatrix;
5851 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5852 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5853 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5854 R_Mesh_TextureState(&m);
5855 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
5856 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);
5858 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);
5861 case TEXTURELAYERTYPE_TEXTURE:
5862 // singletexture unlit texture with transparency support
5863 memset(&m, 0, sizeof(m));
5864 m.tex[0] = R_GetTexture(layer->texture);
5865 m.texmatrix[0] = layer->texmatrix;
5866 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5867 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5868 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5869 R_Mesh_TextureState(&m);
5870 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);
5872 case TEXTURELAYERTYPE_FOG:
5873 // singletexture fogging
5874 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
5877 memset(&m, 0, sizeof(m));
5878 m.tex[0] = R_GetTexture(layer->texture);
5879 m.texmatrix[0] = layer->texmatrix;
5880 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5881 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5882 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5883 R_Mesh_TextureState(&m);
5886 R_Mesh_ResetTextureState();
5887 // generate a color array for the fog pass
5888 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5892 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5893 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)
5895 f = 1 - FogPoint_Model(v);
5896 c[0] = layer->color[0];
5897 c[1] = layer->color[1];
5898 c[2] = layer->color[2];
5899 c[3] = f * layer->color[3];
5902 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5905 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
5907 GL_LockArrays(0, 0);
5910 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5912 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
5913 GL_AlphaTest(false);
5917 static void R_DrawTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly)
5919 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW)
5921 rsurface.rtlight = NULL;
5925 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
5927 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
5929 if (rsurface.mode != RSURFMODE_MULTIPASS)
5930 rsurface.mode = RSURFMODE_MULTIPASS;
5931 if (r_depthfirst.integer == 3)
5933 int i = (int)(texturesurfacelist[0] - rsurface.modelsurfaces);
5934 if (!r_view.showdebug)
5935 GL_Color(0, 0, 0, 1);
5937 GL_Color(((i >> 6) & 7) / 7.0f, ((i >> 3) & 7) / 7.0f, (i & 7) / 7.0f,1);
5941 GL_ColorMask(0,0,0,0);
5944 RSurf_SetupDepthAndCulling();
5946 GL_BlendFunc(GL_ONE, GL_ZERO);
5948 GL_AlphaTest(false);
5949 R_Mesh_ColorPointer(NULL, 0, 0);
5950 R_Mesh_ResetTextureState();
5951 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
5952 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5953 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
5955 else if (r_depthfirst.integer == 3)
5957 else if (!r_view.showdebug && (r_showsurfaces.integer || gl_lightmaps.integer))
5959 GL_Color(0, 0, 0, 1);
5960 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5962 else if (r_showsurfaces.integer)
5964 if (rsurface.mode != RSURFMODE_MULTIPASS)
5965 rsurface.mode = RSURFMODE_MULTIPASS;
5966 RSurf_SetupDepthAndCulling();
5968 GL_BlendFunc(GL_ONE, GL_ZERO);
5969 GL_DepthMask(writedepth);
5971 GL_AlphaTest(false);
5972 R_Mesh_ColorPointer(NULL, 0, 0);
5973 R_Mesh_ResetTextureState();
5974 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
5975 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
5977 else if (gl_lightmaps.integer)
5980 if (rsurface.mode != RSURFMODE_MULTIPASS)
5981 rsurface.mode = RSURFMODE_MULTIPASS;
5982 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5984 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_view.cullface_back);
5985 GL_BlendFunc(GL_ONE, GL_ZERO);
5986 GL_DepthMask(writedepth);
5988 GL_AlphaTest(false);
5989 R_Mesh_ColorPointer(NULL, 0, 0);
5990 memset(&m, 0, sizeof(m));
5991 m.tex[0] = R_GetTexture(r_texture_white);
5992 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
5993 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
5994 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
5995 R_Mesh_TextureState(&m);
5996 RSurf_PrepareVerticesForBatch(rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT, false, texturenumsurfaces, texturesurfacelist);
5997 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
5998 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5999 else if (rsurface.uselightmaptexture)
6000 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
6002 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
6004 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
6005 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
6006 else if (rsurface.texture->currentnumlayers)
6008 // write depth for anything we skipped on the depth-only pass earlier
6009 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
6011 RSurf_SetupDepthAndCulling();
6012 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
6013 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
6014 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
6015 if (r_glsl.integer && gl_support_fragment_shader)
6016 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist);
6017 else if (gl_combine.integer && r_textureunits.integer >= 2)
6018 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist);
6020 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist);
6023 GL_LockArrays(0, 0);
6026 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6029 int texturenumsurfaces, endsurface;
6031 msurface_t *surface;
6032 msurface_t *texturesurfacelist[1024];
6034 // if the model is static it doesn't matter what value we give for
6035 // wantnormals and wanttangents, so this logic uses only rules applicable
6036 // to a model, knowing that they are meaningless otherwise
6037 if (ent == r_refdef.worldentity)
6038 RSurf_ActiveWorldEntity();
6039 else if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
6040 RSurf_ActiveModelEntity(ent, false, false);
6042 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
6044 for (i = 0;i < numsurfaces;i = j)
6047 surface = rsurface.modelsurfaces + surfacelist[i];
6048 texture = surface->texture;
6049 R_UpdateTextureInfo(ent, texture);
6050 rsurface.texture = texture->currentframe;
6051 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
6052 // scan ahead until we find a different texture
6053 endsurface = min(i + 1024, numsurfaces);
6054 texturenumsurfaces = 0;
6055 texturesurfacelist[texturenumsurfaces++] = surface;
6056 for (;j < endsurface;j++)
6058 surface = rsurface.modelsurfaces + surfacelist[j];
6059 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
6061 texturesurfacelist[texturenumsurfaces++] = surface;
6063 // render the range of surfaces
6064 R_DrawTextureSurfaceList(texturenumsurfaces, texturesurfacelist, true, false);
6070 void R_QueueSurfaceList(entity_render_t *ent, int numsurfaces, msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes)
6073 vec3_t tempcenter, center;
6075 // if we're rendering water textures (extra scene renders), use a separate loop to avoid burdening the main one
6078 for (i = 0;i < numsurfaces;i++)
6079 if (surfacelist[i]->texture->currentframe->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION))
6080 R_Water_AddWaterPlane(surfacelist[i]);
6083 // break the surface list down into batches by texture and use of lightmapping
6084 for (i = 0;i < numsurfaces;i = j)
6087 // texture is the base texture pointer, rsurface.texture is the
6088 // current frame/skin the texture is directing us to use (for example
6089 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
6090 // use skin 1 instead)
6091 texture = surfacelist[i]->texture;
6092 rsurface.texture = texture->currentframe;
6093 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
6094 if (!(rsurface.texture->currentmaterialflags & flagsmask))
6096 // if this texture is not the kind we want, skip ahead to the next one
6097 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
6101 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
6103 // transparent surfaces get pushed off into the transparent queue
6104 const msurface_t *surface = surfacelist[i];
6107 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
6108 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
6109 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
6110 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
6111 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_view.origin : center, R_DrawSurface_TransparentCallback, ent, surface - rsurface.modelsurfaces, rsurface.rtlight);
6115 // simply scan ahead until we find a different texture or lightmap state
6116 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
6118 // render the range of surfaces
6119 R_DrawTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly);
6124 float locboxvertex3f[6*4*3] =
6126 1,0,1, 1,0,0, 1,1,0, 1,1,1,
6127 0,1,1, 0,1,0, 0,0,0, 0,0,1,
6128 1,1,1, 1,1,0, 0,1,0, 0,1,1,
6129 0,0,1, 0,0,0, 1,0,0, 1,0,1,
6130 0,0,1, 1,0,1, 1,1,1, 0,1,1,
6131 1,0,0, 0,0,0, 0,1,0, 1,1,0
6134 int locboxelement3i[6*2*3] =
6144 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6147 cl_locnode_t *loc = (cl_locnode_t *)ent;
6149 float vertex3f[6*4*3];
6151 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6152 GL_DepthMask(false);
6153 GL_DepthRange(0, 1);
6154 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6156 GL_CullFace(GL_NONE);
6157 R_Mesh_Matrix(&identitymatrix);
6159 R_Mesh_VertexPointer(vertex3f, 0, 0);
6160 R_Mesh_ColorPointer(NULL, 0, 0);
6161 R_Mesh_ResetTextureState();
6164 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_view.colorscale,
6165 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_view.colorscale,
6166 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_view.colorscale,
6167 surfacelist[0] < 0 ? 0.5f : 0.125f);
6169 if (VectorCompare(loc->mins, loc->maxs))
6171 VectorSet(size, 2, 2, 2);
6172 VectorMA(loc->mins, -0.5f, size, mins);
6176 VectorCopy(loc->mins, mins);
6177 VectorSubtract(loc->maxs, loc->mins, size);
6180 for (i = 0;i < 6*4*3;)
6181 for (j = 0;j < 3;j++, i++)
6182 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
6184 R_Mesh_Draw(0, 6*4, 6*2, locboxelement3i, 0, 0);
6187 void R_DrawLocs(void)
6190 cl_locnode_t *loc, *nearestloc;
6192 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
6193 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
6195 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
6196 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
6200 void R_DrawDebugModel(entity_render_t *ent)
6202 int i, j, k, l, flagsmask;
6203 const int *elements;
6205 msurface_t *surface;
6206 model_t *model = ent->model;
6209 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WATER | MATERIALFLAG_WALL;
6211 R_Mesh_ColorPointer(NULL, 0, 0);
6212 R_Mesh_ResetTextureState();
6213 GL_DepthRange(0, 1);
6214 GL_DepthTest(!r_showdisabledepthtest.integer);
6215 GL_DepthMask(false);
6216 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6218 if (r_showcollisionbrushes.value > 0 && model->brush.num_brushes)
6220 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
6221 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
6223 if (brush->colbrushf && brush->colbrushf->numtriangles)
6225 R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
6226 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);
6227 R_Mesh_Draw(0, brush->colbrushf->numpoints, brush->colbrushf->numtriangles, brush->colbrushf->elements, 0, 0);
6230 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
6232 if (surface->num_collisiontriangles)
6234 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
6235 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);
6236 R_Mesh_Draw(0, surface->num_collisionvertices, surface->num_collisiontriangles, surface->data_collisionelement3i, 0, 0);
6241 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6243 if (r_showtris.integer || r_shownormals.integer)
6245 if (r_showdisabledepthtest.integer)
6247 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6248 GL_DepthMask(false);
6252 GL_BlendFunc(GL_ONE, GL_ZERO);
6255 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
6257 if (ent == r_refdef.worldentity && !r_viewcache.world_surfacevisible[j])
6259 rsurface.texture = surface->texture->currentframe;
6260 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
6262 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
6263 if (r_showtris.value > 0)
6265 if (!rsurface.texture->currentlayers->depthmask)
6266 GL_Color(r_view.colorscale, 0, 0, r_showtris.value);
6267 else if (ent == r_refdef.worldentity)
6268 GL_Color(r_view.colorscale, r_view.colorscale, r_view.colorscale, r_showtris.value);
6270 GL_Color(0, r_view.colorscale, 0, r_showtris.value);
6271 elements = (ent->model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
6274 for (k = 0;k < surface->num_triangles;k++, elements += 3)
6276 #define GLVERTEXELEMENT(n) qglVertex3f(rsurface.vertex3f[elements[n]*3+0], rsurface.vertex3f[elements[n]*3+1], rsurface.vertex3f[elements[n]*3+2])
6277 GLVERTEXELEMENT(0);GLVERTEXELEMENT(1);
6278 GLVERTEXELEMENT(1);GLVERTEXELEMENT(2);
6279 GLVERTEXELEMENT(2);GLVERTEXELEMENT(0);
6284 if (r_shownormals.value > 0)
6287 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
6289 VectorCopy(rsurface.vertex3f + l * 3, v);
6290 GL_Color(r_view.colorscale, 0, 0, 1);
6291 qglVertex3f(v[0], v[1], v[2]);
6292 VectorMA(v, r_shownormals.value, rsurface.svector3f + l * 3, v);
6293 GL_Color(r_view.colorscale, 1, 1, 1);
6294 qglVertex3f(v[0], v[1], v[2]);
6299 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
6301 VectorCopy(rsurface.vertex3f + l * 3, v);
6302 GL_Color(0, r_view.colorscale, 0, 1);
6303 qglVertex3f(v[0], v[1], v[2]);
6304 VectorMA(v, r_shownormals.value, rsurface.tvector3f + l * 3, v);
6305 GL_Color(r_view.colorscale, 1, 1, 1);
6306 qglVertex3f(v[0], v[1], v[2]);
6311 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
6313 VectorCopy(rsurface.vertex3f + l * 3, v);
6314 GL_Color(0, 0, r_view.colorscale, 1);
6315 qglVertex3f(v[0], v[1], v[2]);
6316 VectorMA(v, r_shownormals.value, rsurface.normal3f + l * 3, v);
6317 GL_Color(r_view.colorscale, 1, 1, 1);
6318 qglVertex3f(v[0], v[1], v[2]);
6325 rsurface.texture = NULL;
6329 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
6330 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes, qboolean debug)
6332 int i, j, endj, f, flagsmask;
6333 msurface_t *surface;
6335 model_t *model = r_refdef.worldmodel;
6336 const int maxsurfacelist = 1024;
6337 int numsurfacelist = 0;
6338 msurface_t *surfacelist[1024];
6342 RSurf_ActiveWorldEntity();
6344 // update light styles on this submodel
6345 if (!skysurfaces && !depthonly && !addwaterplanes && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
6347 model_brush_lightstyleinfo_t *style;
6348 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
6350 if (style->value != r_refdef.lightstylevalue[style->style])
6352 msurface_t *surfaces = model->data_surfaces;
6353 int *list = style->surfacelist;
6354 style->value = r_refdef.lightstylevalue[style->style];
6355 for (j = 0;j < style->numsurfaces;j++)
6356 surfaces[list[j]].cached_dlight = true;
6361 R_UpdateAllTextureInfo(r_refdef.worldentity);
6362 flagsmask = addwaterplanes ? (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) : (skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL));
6366 R_DrawDebugModel(r_refdef.worldentity);
6372 rsurface.uselightmaptexture = false;
6373 rsurface.texture = NULL;
6375 j = model->firstmodelsurface;
6376 endj = j + model->nummodelsurfaces;
6379 // quickly skip over non-visible surfaces
6380 for (;j < endj && !r_viewcache.world_surfacevisible[j];j++)
6382 // quickly iterate over visible surfaces
6383 for (;j < endj && r_viewcache.world_surfacevisible[j];j++)
6385 // process this surface
6386 surface = model->data_surfaces + j;
6387 // if this surface fits the criteria, add it to the list
6388 if (surface->num_triangles)
6390 // if lightmap parameters changed, rebuild lightmap texture
6391 if (surface->cached_dlight)
6392 R_BuildLightMap(r_refdef.worldentity, surface);
6393 // add face to draw list
6394 surfacelist[numsurfacelist++] = surface;
6395 r_refdef.stats.world_triangles += surface->num_triangles;
6396 if (numsurfacelist >= maxsurfacelist)
6398 r_refdef.stats.world_surfaces += numsurfacelist;
6399 R_QueueSurfaceList(r_refdef.worldentity, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
6405 r_refdef.stats.world_surfaces += numsurfacelist;
6407 R_QueueSurfaceList(r_refdef.worldentity, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
6411 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes, qboolean debug)
6413 int i, j, f, flagsmask;
6414 msurface_t *surface, *endsurface;
6416 model_t *model = ent->model;
6417 const int maxsurfacelist = 1024;
6418 int numsurfacelist = 0;
6419 msurface_t *surfacelist[1024];
6423 // if the model is static it doesn't matter what value we give for
6424 // wantnormals and wanttangents, so this logic uses only rules applicable
6425 // to a model, knowing that they are meaningless otherwise
6426 if (ent == r_refdef.worldentity)
6427 RSurf_ActiveWorldEntity();
6428 else if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
6429 RSurf_ActiveModelEntity(ent, false, false);
6431 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader && !depthonly);
6433 // update light styles
6434 if (!skysurfaces && !depthonly && !addwaterplanes && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
6436 model_brush_lightstyleinfo_t *style;
6437 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
6439 if (style->value != r_refdef.lightstylevalue[style->style])
6441 msurface_t *surfaces = model->data_surfaces;
6442 int *list = style->surfacelist;
6443 style->value = r_refdef.lightstylevalue[style->style];
6444 for (j = 0;j < style->numsurfaces;j++)
6445 surfaces[list[j]].cached_dlight = true;
6450 R_UpdateAllTextureInfo(ent);
6451 flagsmask = addwaterplanes ? (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) : (skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL));
6455 R_DrawDebugModel(ent);
6461 rsurface.uselightmaptexture = false;
6462 rsurface.texture = NULL;
6464 surface = model->data_surfaces + model->firstmodelsurface;
6465 endsurface = surface + model->nummodelsurfaces;
6466 for (;surface < endsurface;surface++)
6468 // if this surface fits the criteria, add it to the list
6469 if (surface->num_triangles)
6471 // if lightmap parameters changed, rebuild lightmap texture
6472 if (surface->cached_dlight)
6473 R_BuildLightMap(ent, surface);
6474 // add face to draw list
6475 surfacelist[numsurfacelist++] = surface;
6476 r_refdef.stats.entities_triangles += surface->num_triangles;
6477 if (numsurfacelist >= maxsurfacelist)
6479 r_refdef.stats.entities_surfaces += numsurfacelist;
6480 R_QueueSurfaceList(ent, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
6485 r_refdef.stats.entities_surfaces += numsurfacelist;
6487 R_QueueSurfaceList(ent, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);