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 - 1) * fogvec[0] + 1);
3254 fogvec[1] /= ((r_glsl_contrastboost.value - 1) * fogvec[1] + 1);
3255 fogvec[2] /= ((r_glsl_contrastboost.value - 1) * fogvec[2] + 1);
3257 // color.rgb *= ContrastBoost * SceneBrightness;
3258 VectorScale(fogvec, r_glsl_contrastboost.value * 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)
3411 R_ResetViewRendering3D();
3414 if (r_timereport_active)
3415 R_TimeReport("watervis");
3417 if (cl.csqc_vidvars.drawworld && r_refdef.worldmodel && r_refdef.worldmodel->DrawAddWaterPlanes)
3419 r_refdef.worldmodel->DrawAddWaterPlanes(r_refdef.worldentity);
3420 if (r_timereport_active)
3421 R_TimeReport("waterworld");
3424 // don't let sound skip if going slow
3425 if (r_refdef.extraupdate)
3428 R_DrawModelsAddWaterPlanes();
3429 if (r_timereport_active)
3430 R_TimeReport("watermodels");
3432 R_Water_ProcessPlanes();
3433 if (r_timereport_active)
3434 R_TimeReport("waterscenes");
3437 R_ResetViewRendering3D();
3439 // don't let sound skip if going slow
3440 if (r_refdef.extraupdate)
3443 R_MeshQueue_BeginScene();
3448 if (r_timereport_active)
3449 R_TimeReport("visibility");
3451 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);
3453 if (cl.csqc_vidvars.drawworld)
3455 // don't let sound skip if going slow
3456 if (r_refdef.extraupdate)
3459 if (r_refdef.worldmodel && r_refdef.worldmodel->DrawSky)
3461 r_refdef.worldmodel->DrawSky(r_refdef.worldentity);
3462 if (r_timereport_active)
3463 R_TimeReport("worldsky");
3466 if (R_DrawBrushModelsSky() && r_timereport_active)
3467 R_TimeReport("bmodelsky");
3470 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.worldmodel && r_refdef.worldmodel->DrawDepth)
3472 r_refdef.worldmodel->DrawDepth(r_refdef.worldentity);
3473 if (r_timereport_active)
3474 R_TimeReport("worlddepth");
3476 if (r_depthfirst.integer >= 2)
3478 R_DrawModelsDepth();
3479 if (r_timereport_active)
3480 R_TimeReport("modeldepth");
3483 if (cl.csqc_vidvars.drawworld && r_refdef.worldmodel && r_refdef.worldmodel->Draw)
3485 r_refdef.worldmodel->Draw(r_refdef.worldentity);
3486 if (r_timereport_active)
3487 R_TimeReport("world");
3490 // don't let sound skip if going slow
3491 if (r_refdef.extraupdate)
3495 if (r_timereport_active)
3496 R_TimeReport("models");
3498 // don't let sound skip if going slow
3499 if (r_refdef.extraupdate)
3502 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
3504 R_DrawModelShadows();
3506 R_ResetViewRendering3D();
3508 // don't let sound skip if going slow
3509 if (r_refdef.extraupdate)
3513 R_ShadowVolumeLighting(false);
3514 if (r_timereport_active)
3515 R_TimeReport("rtlights");
3517 // don't let sound skip if going slow
3518 if (r_refdef.extraupdate)
3521 if (cl.csqc_vidvars.drawworld)
3523 R_DrawLightningBeams();
3524 if (r_timereport_active)
3525 R_TimeReport("lightning");
3528 if (r_timereport_active)
3529 R_TimeReport("decals");
3532 if (r_timereport_active)
3533 R_TimeReport("particles");
3536 if (r_timereport_active)
3537 R_TimeReport("explosions");
3540 if (gl_support_fragment_shader)
3542 qglUseProgramObjectARB(0);CHECKGLERROR
3544 VM_CL_AddPolygonsToMeshQueue();
3546 if (r_view.showdebug)
3548 if (cl_locs_show.integer)
3551 if (r_timereport_active)
3552 R_TimeReport("showlocs");
3555 if (r_drawportals.integer)
3558 if (r_timereport_active)
3559 R_TimeReport("portals");
3562 if (r_showbboxes.value > 0)
3564 R_DrawEntityBBoxes();
3565 if (r_timereport_active)
3566 R_TimeReport("bboxes");
3570 if (gl_support_fragment_shader)
3572 qglUseProgramObjectARB(0);CHECKGLERROR
3574 R_MeshQueue_RenderTransparent();
3575 if (r_timereport_active)
3576 R_TimeReport("drawtrans");
3578 if (gl_support_fragment_shader)
3580 qglUseProgramObjectARB(0);CHECKGLERROR
3583 if (r_view.showdebug && r_refdef.worldmodel && r_refdef.worldmodel->DrawDebug && (r_showtris.value > 0 || r_shownormals.value > 0 || r_showcollisionbrushes.value > 0))
3585 r_refdef.worldmodel->DrawDebug(r_refdef.worldentity);
3586 if (r_timereport_active)
3587 R_TimeReport("worlddebug");
3588 R_DrawModelsDebug();
3589 if (r_timereport_active)
3590 R_TimeReport("modeldebug");
3593 if (gl_support_fragment_shader)
3595 qglUseProgramObjectARB(0);CHECKGLERROR
3598 if (cl.csqc_vidvars.drawworld)
3601 if (r_timereport_active)
3602 R_TimeReport("coronas");
3605 // don't let sound skip if going slow
3606 if (r_refdef.extraupdate)
3609 R_ResetViewRendering2D();
3612 static const int bboxelements[36] =
3622 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
3625 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
3626 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3627 GL_DepthMask(false);
3628 GL_DepthRange(0, 1);
3629 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3630 R_Mesh_Matrix(&identitymatrix);
3631 R_Mesh_ResetTextureState();
3633 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
3634 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
3635 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
3636 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
3637 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
3638 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
3639 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
3640 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
3641 R_FillColors(color4f, 8, cr, cg, cb, ca);
3642 if (r_refdef.fogenabled)
3644 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
3646 f1 = FogPoint_World(v);
3648 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
3649 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
3650 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
3653 R_Mesh_VertexPointer(vertex3f, 0, 0);
3654 R_Mesh_ColorPointer(color4f, 0, 0);
3655 R_Mesh_ResetTextureState();
3656 R_Mesh_Draw(0, 8, 12, bboxelements, 0, 0);
3659 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
3663 prvm_edict_t *edict;
3664 // this function draws bounding boxes of server entities
3668 for (i = 0;i < numsurfaces;i++)
3670 edict = PRVM_EDICT_NUM(surfacelist[i]);
3671 switch ((int)edict->fields.server->solid)
3673 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
3674 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
3675 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
3676 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
3677 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
3678 default: Vector4Set(color, 0, 0, 0, 0.50);break;
3680 color[3] *= r_showbboxes.value;
3681 color[3] = bound(0, color[3], 1);
3682 GL_DepthTest(!r_showdisabledepthtest.integer);
3683 GL_CullFace(r_view.cullface_front);
3684 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
3689 static void R_DrawEntityBBoxes(void)
3692 prvm_edict_t *edict;
3694 // this function draws bounding boxes of server entities
3698 for (i = 0;i < prog->num_edicts;i++)
3700 edict = PRVM_EDICT_NUM(i);
3701 if (edict->priv.server->free)
3703 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
3704 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
3709 int nomodelelements[24] =
3721 float nomodelvertex3f[6*3] =
3731 float nomodelcolor4f[6*4] =
3733 0.0f, 0.0f, 0.5f, 1.0f,
3734 0.0f, 0.0f, 0.5f, 1.0f,
3735 0.0f, 0.5f, 0.0f, 1.0f,
3736 0.0f, 0.5f, 0.0f, 1.0f,
3737 0.5f, 0.0f, 0.0f, 1.0f,
3738 0.5f, 0.0f, 0.0f, 1.0f
3741 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
3746 // this is only called once per entity so numsurfaces is always 1, and
3747 // surfacelist is always {0}, so this code does not handle batches
3748 R_Mesh_Matrix(&ent->matrix);
3750 if (ent->flags & EF_ADDITIVE)
3752 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
3753 GL_DepthMask(false);
3755 else if (ent->alpha < 1)
3757 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3758 GL_DepthMask(false);
3762 GL_BlendFunc(GL_ONE, GL_ZERO);
3765 GL_DepthRange(0, (ent->flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
3766 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3767 GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
3768 GL_CullFace((ent->effects & EF_DOUBLESIDED) ? GL_NONE : r_view.cullface_back);
3769 R_Mesh_VertexPointer(nomodelvertex3f, 0, 0);
3770 if (r_refdef.fogenabled)
3773 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
3774 R_Mesh_ColorPointer(color4f, 0, 0);
3775 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
3776 f1 = FogPoint_World(org);
3778 for (i = 0, c = color4f;i < 6;i++, c += 4)
3780 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
3781 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
3782 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
3786 else if (ent->alpha != 1)
3788 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
3789 R_Mesh_ColorPointer(color4f, 0, 0);
3790 for (i = 0, c = color4f;i < 6;i++, c += 4)
3794 R_Mesh_ColorPointer(nomodelcolor4f, 0, 0);
3795 R_Mesh_ResetTextureState();
3796 R_Mesh_Draw(0, 6, 8, nomodelelements, 0, 0);
3799 void R_DrawNoModel(entity_render_t *ent)
3802 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
3803 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
3804 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
3806 // R_DrawNoModelCallback(ent, 0);
3809 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
3811 vec3_t right1, right2, diff, normal;
3813 VectorSubtract (org2, org1, normal);
3815 // calculate 'right' vector for start
3816 VectorSubtract (r_view.origin, org1, diff);
3817 CrossProduct (normal, diff, right1);
3818 VectorNormalize (right1);
3820 // calculate 'right' vector for end
3821 VectorSubtract (r_view.origin, org2, diff);
3822 CrossProduct (normal, diff, right2);
3823 VectorNormalize (right2);
3825 vert[ 0] = org1[0] + width * right1[0];
3826 vert[ 1] = org1[1] + width * right1[1];
3827 vert[ 2] = org1[2] + width * right1[2];
3828 vert[ 3] = org1[0] - width * right1[0];
3829 vert[ 4] = org1[1] - width * right1[1];
3830 vert[ 5] = org1[2] - width * right1[2];
3831 vert[ 6] = org2[0] - width * right2[0];
3832 vert[ 7] = org2[1] - width * right2[1];
3833 vert[ 8] = org2[2] - width * right2[2];
3834 vert[ 9] = org2[0] + width * right2[0];
3835 vert[10] = org2[1] + width * right2[1];
3836 vert[11] = org2[2] + width * right2[2];
3839 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
3841 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)
3846 if (r_refdef.fogenabled)
3847 fog = FogPoint_World(origin);
3849 R_Mesh_Matrix(&identitymatrix);
3850 GL_BlendFunc(blendfunc1, blendfunc2);
3856 GL_CullFace(r_view.cullface_front);
3859 GL_CullFace(r_view.cullface_back);
3861 GL_DepthMask(false);
3862 GL_DepthRange(0, depthshort ? 0.0625 : 1);
3863 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3864 GL_DepthTest(!depthdisable);
3866 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
3867 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
3868 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
3869 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
3870 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
3871 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
3872 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
3873 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
3874 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
3875 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
3876 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
3877 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
3879 R_Mesh_VertexPointer(vertex3f, 0, 0);
3880 R_Mesh_ColorPointer(NULL, 0, 0);
3881 R_Mesh_ResetTextureState();
3882 R_Mesh_TexBind(0, R_GetTexture(texture));
3883 R_Mesh_TexCoordPointer(0, 2, spritetexcoord2f, 0, 0);
3884 // FIXME: fixed function path can't properly handle r_view.colorscale > 1
3885 GL_Color(cr * fog * r_view.colorscale, cg * fog * r_view.colorscale, cb * fog * r_view.colorscale, ca);
3886 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3888 if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
3890 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
3891 GL_BlendFunc(blendfunc1, GL_ONE);
3893 GL_Color(r_refdef.fogcolor[0] * fog, r_refdef.fogcolor[1] * fog, r_refdef.fogcolor[2] * fog, ca);
3894 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3898 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
3903 VectorSet(v, x, y, z);
3904 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
3905 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
3907 if (i == mesh->numvertices)
3909 if (mesh->numvertices < mesh->maxvertices)
3911 VectorCopy(v, vertex3f);
3912 mesh->numvertices++;
3914 return mesh->numvertices;
3920 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
3924 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
3925 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
3926 e = mesh->element3i + mesh->numtriangles * 3;
3927 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
3929 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
3930 if (mesh->numtriangles < mesh->maxtriangles)
3935 mesh->numtriangles++;
3937 element[1] = element[2];
3941 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
3945 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
3946 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
3947 e = mesh->element3i + mesh->numtriangles * 3;
3948 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
3950 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
3951 if (mesh->numtriangles < mesh->maxtriangles)
3956 mesh->numtriangles++;
3958 element[1] = element[2];
3962 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
3963 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
3965 int planenum, planenum2;
3968 mplane_t *plane, *plane2;
3970 double temppoints[2][256*3];
3971 // figure out how large a bounding box we need to properly compute this brush
3973 for (w = 0;w < numplanes;w++)
3974 maxdist = max(maxdist, planes[w].dist);
3975 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
3976 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
3977 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
3981 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
3982 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
3984 if (planenum2 == planenum)
3986 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);
3989 if (tempnumpoints < 3)
3991 // generate elements forming a triangle fan for this polygon
3992 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
3996 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)
3998 texturelayer_t *layer;
3999 layer = t->currentlayers + t->currentnumlayers++;
4001 layer->depthmask = depthmask;
4002 layer->blendfunc1 = blendfunc1;
4003 layer->blendfunc2 = blendfunc2;
4004 layer->texture = texture;
4005 layer->texmatrix = *matrix;
4006 layer->color[0] = r * r_view.colorscale;
4007 layer->color[1] = g * r_view.colorscale;
4008 layer->color[2] = b * r_view.colorscale;
4009 layer->color[3] = a;
4012 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
4015 index = parms[2] + r_refdef.time * parms[3];
4016 index -= floor(index);
4020 case Q3WAVEFUNC_NONE:
4021 case Q3WAVEFUNC_NOISE:
4022 case Q3WAVEFUNC_COUNT:
4025 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
4026 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
4027 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
4028 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
4029 case Q3WAVEFUNC_TRIANGLE:
4031 f = index - floor(index);
4042 return (float)(parms[0] + parms[1] * f);
4045 void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
4048 model_t *model = ent->model;
4051 q3shaderinfo_layer_tcmod_t *tcmod;
4053 // switch to an alternate material if this is a q1bsp animated material
4055 texture_t *texture = t;
4056 int s = ent->skinnum;
4057 if ((unsigned int)s >= (unsigned int)model->numskins)
4059 if (model->skinscenes)
4061 if (model->skinscenes[s].framecount > 1)
4062 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
4064 s = model->skinscenes[s].firstframe;
4067 t = t + s * model->num_surfaces;
4070 // use an alternate animation if the entity's frame is not 0,
4071 // and only if the texture has an alternate animation
4072 if (ent->frame2 != 0 && t->anim_total[1])
4073 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.time * 5.0f) % t->anim_total[1]) : 0];
4075 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.time * 5.0f) % t->anim_total[0]) : 0];
4077 texture->currentframe = t;
4080 // update currentskinframe to be a qw skin or animation frame
4081 if ((i = ent->entitynumber - 1) >= 0 && i < cl.maxclients)
4083 if (strcmp(r_qwskincache[i], cl.scores[i].qw_skin))
4085 strlcpy(r_qwskincache[i], cl.scores[i].qw_skin, sizeof(r_qwskincache[i]));
4086 Con_DPrintf("loading skins/%s\n", r_qwskincache[i]);
4087 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);
4089 t->currentskinframe = r_qwskincache_skinframe[i];
4090 if (t->currentskinframe == NULL)
4091 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->frame2time)) % t->numskinframes];
4093 else if (t->numskinframes >= 2)
4094 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->frame2time)) % t->numskinframes];
4095 if (t->backgroundnumskinframes >= 2)
4096 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - ent->frame2time)) % t->backgroundnumskinframes];
4098 t->currentmaterialflags = t->basematerialflags;
4099 t->currentalpha = ent->alpha;
4100 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
4102 t->currentalpha *= r_wateralpha.value;
4104 * FIXME what is this supposed to do?
4105 // if rendering refraction/reflection, disable transparency
4106 if (r_waterstate.enabled && (t->currentalpha < 1 || (t->currentmaterialflags & MATERIALFLAG_ALPHA)))
4107 t->currentmaterialflags |= MATERIALFLAG_WATERSHADER;
4110 if(!r_waterstate.enabled)
4111 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION);
4112 if (!(ent->flags & RENDER_LIGHT))
4113 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
4114 else if (rsurface.modeltexcoordlightmap2f == NULL)
4116 // pick a model lighting mode
4117 if (VectorLength2(ent->modellight_diffuse) >= (1.0f / 256.0f))
4118 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
4120 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
4122 if (ent->effects & EF_ADDITIVE)
4123 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
4124 else if (t->currentalpha < 1)
4125 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
4126 if (ent->effects & EF_DOUBLESIDED)
4127 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
4128 if (ent->effects & EF_NODEPTHTEST)
4129 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
4130 if (ent->flags & RENDER_VIEWMODEL)
4131 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
4132 if (t->backgroundnumskinframes && !(t->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED))
4133 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
4135 // make sure that the waterscroll matrix is used on water surfaces when
4136 // there is no tcmod
4137 if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
4138 t->currenttexmatrix = r_waterscrollmatrix;
4140 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
4143 switch(tcmod->tcmod)
4147 if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
4148 matrix = r_waterscrollmatrix;
4150 matrix = identitymatrix;
4152 case Q3TCMOD_ENTITYTRANSLATE:
4153 // this is used in Q3 to allow the gamecode to control texcoord
4154 // scrolling on the entity, which is not supported in darkplaces yet.
4155 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
4157 case Q3TCMOD_ROTATE:
4158 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
4159 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.time, 0, 0, 1);
4160 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
4163 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
4165 case Q3TCMOD_SCROLL:
4166 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.time, tcmod->parms[1] * r_refdef.time, 0);
4168 case Q3TCMOD_STRETCH:
4169 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
4170 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
4172 case Q3TCMOD_TRANSFORM:
4173 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
4174 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
4175 VectorSet(tcmat + 6, 0 , 0 , 1);
4176 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
4177 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
4179 case Q3TCMOD_TURBULENT:
4180 // this is handled in the RSurf_PrepareVertices function
4181 matrix = identitymatrix;
4184 // either replace or concatenate the transformation
4186 t->currenttexmatrix = matrix;
4189 matrix4x4_t temp = t->currenttexmatrix;
4190 Matrix4x4_Concat(&t->currenttexmatrix, &matrix, &temp);
4194 t->colormapping = VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f);
4195 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
4196 t->glosstexture = r_texture_black;
4197 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
4198 t->backgroundglosstexture = r_texture_black;
4199 t->specularpower = r_shadow_glossexponent.value;
4200 // TODO: store reference values for these in the texture?
4201 t->specularscale = 0;
4202 if (r_shadow_gloss.integer > 0)
4204 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
4206 if (r_shadow_glossintensity.value > 0)
4208 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
4209 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
4210 t->specularscale = r_shadow_glossintensity.value;
4213 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
4215 t->glosstexture = r_texture_white;
4216 t->backgroundglosstexture = r_texture_white;
4217 t->specularscale = r_shadow_gloss2intensity.value;
4221 // lightmaps mode looks bad with dlights using actual texturing, so turn
4222 // off the colormap and glossmap, but leave the normalmap on as it still
4223 // accurately represents the shading involved
4224 if (gl_lightmaps.integer && !(t->currentmaterialflags & MATERIALFLAG_BLENDED))
4226 t->basetexture = r_texture_white;
4227 t->specularscale = 0;
4230 Vector4Set(t->lightmapcolor, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
4231 VectorClear(t->dlightcolor);
4232 t->currentnumlayers = 0;
4233 if (!(t->currentmaterialflags & MATERIALFLAG_NODRAW))
4235 if (!(t->currentmaterialflags & MATERIALFLAG_SKY))
4237 int blendfunc1, blendfunc2, depthmask;
4238 if (t->currentmaterialflags & MATERIALFLAG_ADD)
4240 blendfunc1 = GL_SRC_ALPHA;
4241 blendfunc2 = GL_ONE;
4243 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
4245 blendfunc1 = GL_SRC_ALPHA;
4246 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
4248 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
4250 blendfunc1 = t->customblendfunc[0];
4251 blendfunc2 = t->customblendfunc[1];
4255 blendfunc1 = GL_ONE;
4256 blendfunc2 = GL_ZERO;
4258 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
4259 if (t->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL))
4261 rtexture_t *currentbasetexture;
4263 if (r_refdef.fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED))
4264 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
4265 currentbasetexture = (VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) < (1.0f / 1048576.0f) && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
4266 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
4268 // fullbright is not affected by r_refdef.lightmapintensity
4269 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
4270 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
4271 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->pants, &t->currenttexmatrix, ent->colormap_pantscolor[0] * ent->colormod[0], ent->colormap_pantscolor[1] * ent->colormod[1], ent->colormap_pantscolor[2] * ent->colormod[2], t->currentalpha);
4272 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
4273 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->shirt, &t->currenttexmatrix, ent->colormap_shirtcolor[0] * ent->colormod[0], ent->colormap_shirtcolor[1] * ent->colormod[1], ent->colormap_shirtcolor[2] * ent->colormod[2], t->currentalpha);
4278 // set the color tint used for lights affecting this surface
4279 VectorSet(t->dlightcolor, ent->colormod[0] * t->currentalpha, ent->colormod[1] * t->currentalpha, ent->colormod[2] * t->currentalpha);
4281 // q3bsp has no lightmap updates, so the lightstylevalue that
4282 // would normally be baked into the lightmap must be
4283 // applied to the color
4284 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
4285 if (ent->model->type == mod_brushq3)
4286 colorscale *= r_refdef.rtlightstylevalue[0];
4287 colorscale *= r_refdef.lightmapintensity;
4288 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
4289 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_LITTEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0] * colorscale, ent->colormod[1] * colorscale, ent->colormod[2] * colorscale, t->currentalpha);
4290 if (r_ambient.value >= (1.0f/64.0f))
4291 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0] * r_ambient.value * (1.0f / 64.0f), ent->colormod[1] * r_ambient.value * (1.0f / 64.0f), ent->colormod[2] * r_ambient.value * (1.0f / 64.0f), t->currentalpha);
4292 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
4294 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->currentskinframe->pants, &t->currenttexmatrix, ent->colormap_pantscolor[0] * ent->colormod[0] * colorscale, ent->colormap_pantscolor[1] * ent->colormod[1] * colorscale, ent->colormap_pantscolor[2] * ent->colormod[2] * colorscale, t->currentalpha);
4295 if (r_ambient.value >= (1.0f/64.0f))
4296 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->pants, &t->currenttexmatrix, ent->colormap_pantscolor[0] * ent->colormod[0] * r_ambient.value * (1.0f / 64.0f), ent->colormap_pantscolor[1] * ent->colormod[1] * r_ambient.value * (1.0f / 64.0f), ent->colormap_pantscolor[2] * ent->colormod[2] * r_ambient.value * (1.0f / 64.0f), t->currentalpha);
4298 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
4300 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->currentskinframe->shirt, &t->currenttexmatrix, ent->colormap_shirtcolor[0] * ent->colormod[0] * colorscale, ent->colormap_shirtcolor[1] * ent->colormod[1] * colorscale, ent->colormap_shirtcolor[2] * ent->colormod[2] * colorscale, t->currentalpha);
4301 if (r_ambient.value >= (1.0f/64.0f))
4302 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->shirt, &t->currenttexmatrix, ent->colormap_shirtcolor[0] * ent->colormod[0] * r_ambient.value * (1.0f / 64.0f), ent->colormap_shirtcolor[1] * ent->colormod[1] * r_ambient.value * (1.0f / 64.0f), ent->colormap_shirtcolor[2] * ent->colormod[2] * r_ambient.value * (1.0f / 64.0f), t->currentalpha);
4305 if (t->currentskinframe->glow != NULL)
4306 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->glow, &t->currenttexmatrix, r_hdr_glowintensity.value, r_hdr_glowintensity.value, r_hdr_glowintensity.value, t->currentalpha);
4307 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
4309 // if this is opaque use alpha blend which will darken the earlier
4312 // if this is an alpha blended material, all the earlier passes
4313 // were darkened by fog already, so we only need to add the fog
4314 // color ontop through the fog mask texture
4316 // if this is an additive blended material, all the earlier passes
4317 // were darkened by fog already, and we should not add fog color
4318 // (because the background was not darkened, there is no fog color
4319 // that was lost behind it).
4320 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->currentalpha);
4327 void R_UpdateAllTextureInfo(entity_render_t *ent)
4331 for (i = 0;i < ent->model->num_texturesperskin;i++)
4332 R_UpdateTextureInfo(ent, ent->model->data_textures + i);
4335 rsurfacestate_t rsurface;
4337 void R_Mesh_ResizeArrays(int newvertices)
4340 if (rsurface.array_size >= newvertices)
4342 if (rsurface.array_modelvertex3f)
4343 Mem_Free(rsurface.array_modelvertex3f);
4344 rsurface.array_size = (newvertices + 1023) & ~1023;
4345 base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
4346 rsurface.array_modelvertex3f = base + rsurface.array_size * 0;
4347 rsurface.array_modelsvector3f = base + rsurface.array_size * 3;
4348 rsurface.array_modeltvector3f = base + rsurface.array_size * 6;
4349 rsurface.array_modelnormal3f = base + rsurface.array_size * 9;
4350 rsurface.array_deformedvertex3f = base + rsurface.array_size * 12;
4351 rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
4352 rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
4353 rsurface.array_deformednormal3f = base + rsurface.array_size * 21;
4354 rsurface.array_texcoord3f = base + rsurface.array_size * 24;
4355 rsurface.array_color4f = base + rsurface.array_size * 27;
4356 rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
4359 void RSurf_CleanUp(void)
4362 if (rsurface.mode == RSURFMODE_GLSL)
4364 qglUseProgramObjectARB(0);CHECKGLERROR
4366 GL_AlphaTest(false);
4367 rsurface.mode = RSURFMODE_NONE;
4368 rsurface.uselightmaptexture = false;
4369 rsurface.texture = NULL;
4372 void RSurf_ActiveWorldEntity(void)
4374 model_t *model = r_refdef.worldmodel;
4376 if (rsurface.array_size < model->surfmesh.num_vertices)
4377 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
4378 rsurface.matrix = identitymatrix;
4379 rsurface.inversematrix = identitymatrix;
4380 R_Mesh_Matrix(&identitymatrix);
4381 VectorCopy(r_view.origin, rsurface.modelorg);
4382 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
4383 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
4384 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
4385 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
4386 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
4387 rsurface.frameblend[0].frame = 0;
4388 rsurface.frameblend[0].lerp = 1;
4389 rsurface.frameblend[1].frame = 0;
4390 rsurface.frameblend[1].lerp = 0;
4391 rsurface.frameblend[2].frame = 0;
4392 rsurface.frameblend[2].lerp = 0;
4393 rsurface.frameblend[3].frame = 0;
4394 rsurface.frameblend[3].lerp = 0;
4395 rsurface.basepolygonfactor = r_refdef.polygonfactor;
4396 rsurface.basepolygonoffset = r_refdef.polygonoffset;
4397 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
4398 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
4399 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
4400 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
4401 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
4402 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
4403 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
4404 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
4405 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
4406 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
4407 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
4408 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
4409 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
4410 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
4411 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
4412 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
4413 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
4414 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
4415 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
4416 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
4417 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
4418 rsurface.modelelement3i = model->surfmesh.data_element3i;
4419 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo;
4420 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
4421 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
4422 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
4423 rsurface.modelsurfaces = model->data_surfaces;
4424 rsurface.generatedvertex = false;
4425 rsurface.vertex3f = rsurface.modelvertex3f;
4426 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
4427 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
4428 rsurface.svector3f = rsurface.modelsvector3f;
4429 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
4430 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
4431 rsurface.tvector3f = rsurface.modeltvector3f;
4432 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
4433 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
4434 rsurface.normal3f = rsurface.modelnormal3f;
4435 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
4436 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
4437 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
4440 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4442 model_t *model = ent->model;
4444 if (rsurface.array_size < model->surfmesh.num_vertices)
4445 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
4446 rsurface.matrix = ent->matrix;
4447 rsurface.inversematrix = ent->inversematrix;
4448 R_Mesh_Matrix(&rsurface.matrix);
4449 Matrix4x4_Transform(&rsurface.inversematrix, r_view.origin, rsurface.modelorg);
4450 rsurface.modellight_ambient[0] = ent->modellight_ambient[0] * ent->colormod[0];
4451 rsurface.modellight_ambient[1] = ent->modellight_ambient[1] * ent->colormod[1];
4452 rsurface.modellight_ambient[2] = ent->modellight_ambient[2] * ent->colormod[2];
4453 rsurface.modellight_diffuse[0] = ent->modellight_diffuse[0] * ent->colormod[0];
4454 rsurface.modellight_diffuse[1] = ent->modellight_diffuse[1] * ent->colormod[1];
4455 rsurface.modellight_diffuse[2] = ent->modellight_diffuse[2] * ent->colormod[2];
4456 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
4457 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
4458 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
4459 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
4460 rsurface.frameblend[0] = ent->frameblend[0];
4461 rsurface.frameblend[1] = ent->frameblend[1];
4462 rsurface.frameblend[2] = ent->frameblend[2];
4463 rsurface.frameblend[3] = ent->frameblend[3];
4464 rsurface.basepolygonfactor = r_refdef.polygonfactor;
4465 rsurface.basepolygonoffset = r_refdef.polygonoffset;
4466 if (ent->model->brush.submodel)
4468 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
4469 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
4471 if (model->surfmesh.isanimated && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].frame != 0))
4475 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
4476 rsurface.modelsvector3f = rsurface.array_modelsvector3f;
4477 rsurface.modeltvector3f = rsurface.array_modeltvector3f;
4478 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
4479 Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
4481 else if (wantnormals)
4483 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
4484 rsurface.modelsvector3f = NULL;
4485 rsurface.modeltvector3f = NULL;
4486 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
4487 Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
4491 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
4492 rsurface.modelsvector3f = NULL;
4493 rsurface.modeltvector3f = NULL;
4494 rsurface.modelnormal3f = NULL;
4495 Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, NULL, NULL, NULL);
4497 rsurface.modelvertex3f_bufferobject = 0;
4498 rsurface.modelvertex3f_bufferoffset = 0;
4499 rsurface.modelsvector3f_bufferobject = 0;
4500 rsurface.modelsvector3f_bufferoffset = 0;
4501 rsurface.modeltvector3f_bufferobject = 0;
4502 rsurface.modeltvector3f_bufferoffset = 0;
4503 rsurface.modelnormal3f_bufferobject = 0;
4504 rsurface.modelnormal3f_bufferoffset = 0;
4505 rsurface.generatedvertex = true;
4509 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
4510 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
4511 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
4512 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
4513 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
4514 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
4515 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
4516 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
4517 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
4518 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
4519 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
4520 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
4521 rsurface.generatedvertex = false;
4523 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
4524 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
4525 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
4526 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
4527 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
4528 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
4529 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
4530 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
4531 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
4532 rsurface.modelelement3i = model->surfmesh.data_element3i;
4533 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo;
4534 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
4535 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
4536 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
4537 rsurface.modelsurfaces = model->data_surfaces;
4538 rsurface.vertex3f = rsurface.modelvertex3f;
4539 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
4540 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
4541 rsurface.svector3f = rsurface.modelsvector3f;
4542 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
4543 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
4544 rsurface.tvector3f = rsurface.modeltvector3f;
4545 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
4546 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
4547 rsurface.normal3f = rsurface.modelnormal3f;
4548 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
4549 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
4550 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
4553 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
4554 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, msurface_t **texturesurfacelist)
4557 int texturesurfaceindex;
4562 const float *v1, *in_tc;
4564 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
4566 q3shaderinfo_deform_t *deform;
4567 // 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
4568 if (rsurface.generatedvertex)
4570 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
4571 generatenormals = true;
4572 for (i = 0;i < Q3MAXDEFORMS;i++)
4574 if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
4576 generatetangents = true;
4577 generatenormals = true;
4579 if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
4580 generatenormals = true;
4582 if (generatenormals && !rsurface.modelnormal3f)
4584 rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
4585 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
4586 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
4587 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer);
4589 if (generatetangents && !rsurface.modelsvector3f)
4591 rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
4592 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
4593 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
4594 rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
4595 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
4596 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
4597 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);
4600 rsurface.vertex3f = rsurface.modelvertex3f;
4601 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
4602 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
4603 rsurface.svector3f = rsurface.modelsvector3f;
4604 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
4605 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
4606 rsurface.tvector3f = rsurface.modeltvector3f;
4607 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
4608 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
4609 rsurface.normal3f = rsurface.modelnormal3f;
4610 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
4611 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
4612 // if vertices are deformed (sprite flares and things in maps, possibly
4613 // water waves, bulges and other deformations), generate them into
4614 // rsurface.deform* arrays from whatever the rsurface.* arrays point to
4615 // (may be static model data or generated data for an animated model, or
4616 // the previous deform pass)
4617 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
4619 switch (deform->deform)
4622 case Q3DEFORM_PROJECTIONSHADOW:
4623 case Q3DEFORM_TEXT0:
4624 case Q3DEFORM_TEXT1:
4625 case Q3DEFORM_TEXT2:
4626 case Q3DEFORM_TEXT3:
4627 case Q3DEFORM_TEXT4:
4628 case Q3DEFORM_TEXT5:
4629 case Q3DEFORM_TEXT6:
4630 case Q3DEFORM_TEXT7:
4633 case Q3DEFORM_AUTOSPRITE:
4634 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.forward, newforward);
4635 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.right, newright);
4636 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.up, newup);
4637 VectorNormalize(newforward);
4638 VectorNormalize(newright);
4639 VectorNormalize(newup);
4640 // make deformed versions of only the model vertices used by the specified surfaces
4641 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4643 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4644 // a single autosprite surface can contain multiple sprites...
4645 for (j = 0;j < surface->num_vertices - 3;j += 4)
4647 VectorClear(center);
4648 for (i = 0;i < 4;i++)
4649 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
4650 VectorScale(center, 0.25f, center);
4651 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, forward);
4652 VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
4653 VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
4654 for (i = 0;i < 4;i++)
4656 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
4657 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
4660 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);
4661 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);
4663 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4664 rsurface.vertex3f_bufferobject = 0;
4665 rsurface.vertex3f_bufferoffset = 0;
4666 rsurface.svector3f = rsurface.array_deformedsvector3f;
4667 rsurface.svector3f_bufferobject = 0;
4668 rsurface.svector3f_bufferoffset = 0;
4669 rsurface.tvector3f = rsurface.array_deformedtvector3f;
4670 rsurface.tvector3f_bufferobject = 0;
4671 rsurface.tvector3f_bufferoffset = 0;
4672 rsurface.normal3f = rsurface.array_deformednormal3f;
4673 rsurface.normal3f_bufferobject = 0;
4674 rsurface.normal3f_bufferoffset = 0;
4676 case Q3DEFORM_AUTOSPRITE2:
4677 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.forward, newforward);
4678 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.right, newright);
4679 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.up, newup);
4680 VectorNormalize(newforward);
4681 VectorNormalize(newright);
4682 VectorNormalize(newup);
4683 // make deformed versions of only the model vertices used by the specified surfaces
4684 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4686 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4687 const float *v1, *v2;
4697 memset(shortest, 0, sizeof(shortest));
4698 // a single autosprite surface can contain multiple sprites...
4699 for (j = 0;j < surface->num_vertices - 3;j += 4)
4701 VectorClear(center);
4702 for (i = 0;i < 4;i++)
4703 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
4704 VectorScale(center, 0.25f, center);
4705 // find the two shortest edges, then use them to define the
4706 // axis vectors for rotating around the central axis
4707 for (i = 0;i < 6;i++)
4709 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
4710 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
4712 Debug_PolygonBegin(NULL, 0, false, 0);
4713 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
4714 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);
4715 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
4718 l = VectorDistance2(v1, v2);
4719 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
4721 l += (1.0f / 1024.0f);
4722 if (shortest[0].length2 > l || i == 0)
4724 shortest[1] = shortest[0];
4725 shortest[0].length2 = l;
4726 shortest[0].v1 = v1;
4727 shortest[0].v2 = v2;
4729 else if (shortest[1].length2 > l || i == 1)
4731 shortest[1].length2 = l;
4732 shortest[1].v1 = v1;
4733 shortest[1].v2 = v2;
4736 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
4737 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
4739 Debug_PolygonBegin(NULL, 0, false, 0);
4740 Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
4741 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);
4742 Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
4745 // this calculates the right vector from the shortest edge
4746 // and the up vector from the edge midpoints
4747 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
4748 VectorNormalize(right);
4749 VectorSubtract(end, start, up);
4750 VectorNormalize(up);
4751 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
4752 //VectorSubtract(rsurface.modelorg, center, forward);
4753 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.forward, forward);
4754 VectorNegate(forward, forward);
4755 VectorReflect(forward, 0, up, forward);
4756 VectorNormalize(forward);
4757 CrossProduct(up, forward, newright);
4758 VectorNormalize(newright);
4760 Debug_PolygonBegin(NULL, 0, false, 0);
4761 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);
4762 Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
4763 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
4767 Debug_PolygonBegin(NULL, 0, false, 0);
4768 Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
4769 Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
4770 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
4773 // rotate the quad around the up axis vector, this is made
4774 // especially easy by the fact we know the quad is flat,
4775 // so we only have to subtract the center position and
4776 // measure distance along the right vector, and then
4777 // multiply that by the newright vector and add back the
4779 // we also need to subtract the old position to undo the
4780 // displacement from the center, which we do with a
4781 // DotProduct, the subtraction/addition of center is also
4782 // optimized into DotProducts here
4783 l = DotProduct(right, center);
4784 for (i = 0;i < 4;i++)
4786 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
4787 f = DotProduct(right, v1) - l;
4788 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
4791 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);
4792 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);
4794 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4795 rsurface.vertex3f_bufferobject = 0;
4796 rsurface.vertex3f_bufferoffset = 0;
4797 rsurface.svector3f = rsurface.array_deformedsvector3f;
4798 rsurface.svector3f_bufferobject = 0;
4799 rsurface.svector3f_bufferoffset = 0;
4800 rsurface.tvector3f = rsurface.array_deformedtvector3f;
4801 rsurface.tvector3f_bufferobject = 0;
4802 rsurface.tvector3f_bufferoffset = 0;
4803 rsurface.normal3f = rsurface.array_deformednormal3f;
4804 rsurface.normal3f_bufferobject = 0;
4805 rsurface.normal3f_bufferoffset = 0;
4807 case Q3DEFORM_NORMAL:
4808 // deform the normals to make reflections wavey
4809 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4811 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4812 for (j = 0;j < surface->num_vertices;j++)
4815 float *normal = (rsurface.array_deformednormal3f + 3 * surface->num_firstvertex) + j*3;
4816 VectorScale((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
4817 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, normal);
4818 normal[0] += deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.time * deform->parms[1]);
4819 normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.time * deform->parms[1]);
4820 normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.time * deform->parms[1]);
4821 VectorNormalize(normal);
4823 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);
4825 rsurface.svector3f = rsurface.array_deformedsvector3f;
4826 rsurface.svector3f_bufferobject = 0;
4827 rsurface.svector3f_bufferoffset = 0;
4828 rsurface.tvector3f = rsurface.array_deformedtvector3f;
4829 rsurface.tvector3f_bufferobject = 0;
4830 rsurface.tvector3f_bufferoffset = 0;
4831 rsurface.normal3f = rsurface.array_deformednormal3f;
4832 rsurface.normal3f_bufferobject = 0;
4833 rsurface.normal3f_bufferoffset = 0;
4836 // deform vertex array to make wavey water and flags and such
4837 waveparms[0] = deform->waveparms[0];
4838 waveparms[1] = deform->waveparms[1];
4839 waveparms[2] = deform->waveparms[2];
4840 waveparms[3] = deform->waveparms[3];
4841 // this is how a divisor of vertex influence on deformation
4842 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
4843 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
4844 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4846 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4847 for (j = 0;j < surface->num_vertices;j++)
4849 float *vertex = (rsurface.array_deformedvertex3f + 3 * surface->num_firstvertex) + j*3;
4850 VectorCopy((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, vertex);
4851 // if the wavefunc depends on time, evaluate it per-vertex
4854 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
4855 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
4857 VectorMA(vertex, scale, (rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, vertex);
4860 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4861 rsurface.vertex3f_bufferobject = 0;
4862 rsurface.vertex3f_bufferoffset = 0;
4864 case Q3DEFORM_BULGE:
4865 // deform vertex array to make the surface have moving bulges
4866 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4868 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4869 for (j = 0;j < surface->num_vertices;j++)
4871 scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.time * deform->parms[2])) * deform->parms[1];
4872 VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
4875 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4876 rsurface.vertex3f_bufferobject = 0;
4877 rsurface.vertex3f_bufferoffset = 0;
4880 // deform vertex array
4881 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
4882 VectorScale(deform->parms, scale, waveparms);
4883 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4885 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4886 for (j = 0;j < surface->num_vertices;j++)
4887 VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
4889 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4890 rsurface.vertex3f_bufferobject = 0;
4891 rsurface.vertex3f_bufferoffset = 0;
4895 // generate texcoords based on the chosen texcoord source
4896 switch(rsurface.texture->tcgen.tcgen)
4899 case Q3TCGEN_TEXTURE:
4900 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
4901 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordtexture2f_bufferobject;
4902 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
4904 case Q3TCGEN_LIGHTMAP:
4905 rsurface.texcoordtexture2f = rsurface.modeltexcoordlightmap2f;
4906 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
4907 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
4909 case Q3TCGEN_VECTOR:
4910 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4912 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4913 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)
4915 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
4916 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
4919 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
4920 rsurface.texcoordtexture2f_bufferobject = 0;
4921 rsurface.texcoordtexture2f_bufferoffset = 0;
4923 case Q3TCGEN_ENVIRONMENT:
4924 // make environment reflections using a spheremap
4925 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4927 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4928 const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
4929 const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
4930 float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
4931 for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
4933 float l, d, eyedir[3];
4934 VectorSubtract(rsurface.modelorg, vertex, eyedir);
4935 l = 0.5f / VectorLength(eyedir);
4936 d = DotProduct(normal, eyedir)*2;
4937 out_tc[0] = 0.5f + (normal[1]*d - eyedir[1])*l;
4938 out_tc[1] = 0.5f - (normal[2]*d - eyedir[2])*l;
4941 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
4942 rsurface.texcoordtexture2f_bufferobject = 0;
4943 rsurface.texcoordtexture2f_bufferoffset = 0;
4946 // the only tcmod that needs software vertex processing is turbulent, so
4947 // check for it here and apply the changes if needed
4948 // and we only support that as the first one
4949 // (handling a mixture of turbulent and other tcmods would be problematic
4950 // without punting it entirely to a software path)
4951 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
4953 amplitude = rsurface.texture->tcmods[0].parms[1];
4954 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.time * rsurface.texture->tcmods[0].parms[3];
4955 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4957 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4958 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)
4960 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
4961 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
4964 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
4965 rsurface.texcoordtexture2f_bufferobject = 0;
4966 rsurface.texcoordtexture2f_bufferoffset = 0;
4968 rsurface.texcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
4969 rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
4970 rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
4971 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
4974 void RSurf_DrawBatch_Simple(int texturenumsurfaces, msurface_t **texturesurfacelist)
4977 const msurface_t *surface = texturesurfacelist[0];
4978 const msurface_t *surface2;
4983 // TODO: lock all array ranges before render, rather than on each surface
4984 if (texturenumsurfaces == 1)
4986 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
4987 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));
4989 else if (r_batchmode.integer == 2)
4991 #define MAXBATCHTRIANGLES 4096
4992 int batchtriangles = 0;
4993 int batchelements[MAXBATCHTRIANGLES*3];
4994 for (i = 0;i < texturenumsurfaces;i = j)
4996 surface = texturesurfacelist[i];
4998 if (surface->num_triangles > MAXBATCHTRIANGLES)
5000 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));
5003 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
5004 batchtriangles = surface->num_triangles;
5005 firstvertex = surface->num_firstvertex;
5006 endvertex = surface->num_firstvertex + surface->num_vertices;
5007 for (;j < texturenumsurfaces;j++)
5009 surface2 = texturesurfacelist[j];
5010 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
5012 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
5013 batchtriangles += surface2->num_triangles;
5014 firstvertex = min(firstvertex, surface2->num_firstvertex);
5015 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
5017 surface2 = texturesurfacelist[j-1];
5018 numvertices = endvertex - firstvertex;
5019 R_Mesh_Draw(firstvertex, numvertices, batchtriangles, batchelements, 0, 0);
5022 else if (r_batchmode.integer == 1)
5024 for (i = 0;i < texturenumsurfaces;i = j)
5026 surface = texturesurfacelist[i];
5027 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
5028 if (texturesurfacelist[j] != surface2)
5030 surface2 = texturesurfacelist[j-1];
5031 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
5032 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
5033 GL_LockArrays(surface->num_firstvertex, numvertices);
5034 R_Mesh_Draw(surface->num_firstvertex, numvertices, numtriangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
5039 for (i = 0;i < texturenumsurfaces;i++)
5041 surface = texturesurfacelist[i];
5042 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5043 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));
5048 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit, int refractiontexunit, int reflectiontexunit)
5050 int i, planeindex, vertexindex;
5054 r_waterstate_waterplane_t *p, *bestp;
5055 msurface_t *surface;
5056 if (r_waterstate.renderingscene)
5058 for (i = 0;i < texturenumsurfaces;i++)
5060 surface = texturesurfacelist[i];
5061 if (lightmaptexunit >= 0)
5062 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5063 if (deluxemaptexunit >= 0)
5064 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5065 // pick the closest matching water plane
5068 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5071 for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
5073 Matrix4x4_Transform(&rsurface.matrix, v, vert);
5074 d += fabs(PlaneDiff(vert, &p->plane));
5076 if (bestd > d || !bestp)
5084 if (refractiontexunit >= 0)
5085 R_Mesh_TexBind(refractiontexunit, R_GetTexture(bestp->texture_refraction));
5086 if (reflectiontexunit >= 0)
5087 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(bestp->texture_reflection));
5091 if (refractiontexunit >= 0)
5092 R_Mesh_TexBind(refractiontexunit, R_GetTexture(r_texture_black));
5093 if (reflectiontexunit >= 0)
5094 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(r_texture_black));
5096 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5097 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));
5101 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit)
5105 const msurface_t *surface = texturesurfacelist[0];
5106 const msurface_t *surface2;
5111 // TODO: lock all array ranges before render, rather than on each surface
5112 if (texturenumsurfaces == 1)
5114 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5115 if (deluxemaptexunit >= 0)
5116 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5117 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5118 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));
5120 else if (r_batchmode.integer == 2)
5122 #define MAXBATCHTRIANGLES 4096
5123 int batchtriangles = 0;
5124 int batchelements[MAXBATCHTRIANGLES*3];
5125 for (i = 0;i < texturenumsurfaces;i = j)
5127 surface = texturesurfacelist[i];
5128 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5129 if (deluxemaptexunit >= 0)
5130 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5132 if (surface->num_triangles > MAXBATCHTRIANGLES)
5134 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));
5137 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
5138 batchtriangles = surface->num_triangles;
5139 firstvertex = surface->num_firstvertex;
5140 endvertex = surface->num_firstvertex + surface->num_vertices;
5141 for (;j < texturenumsurfaces;j++)
5143 surface2 = texturesurfacelist[j];
5144 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
5146 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
5147 batchtriangles += surface2->num_triangles;
5148 firstvertex = min(firstvertex, surface2->num_firstvertex);
5149 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
5151 surface2 = texturesurfacelist[j-1];
5152 numvertices = endvertex - firstvertex;
5153 R_Mesh_Draw(firstvertex, numvertices, batchtriangles, batchelements, 0, 0);
5156 else if (r_batchmode.integer == 1)
5159 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
5160 for (i = 0;i < texturenumsurfaces;i = j)
5162 surface = texturesurfacelist[i];
5163 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
5164 if (texturesurfacelist[j] != surface2)
5166 Con_Printf(" %i", j - i);
5169 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
5171 for (i = 0;i < texturenumsurfaces;i = j)
5173 surface = texturesurfacelist[i];
5174 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5175 if (deluxemaptexunit >= 0)
5176 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5177 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
5178 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
5181 Con_Printf(" %i", j - i);
5183 surface2 = texturesurfacelist[j-1];
5184 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
5185 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
5186 GL_LockArrays(surface->num_firstvertex, numvertices);
5187 R_Mesh_Draw(surface->num_firstvertex, numvertices, numtriangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
5195 for (i = 0;i < texturenumsurfaces;i++)
5197 surface = texturesurfacelist[i];
5198 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5199 if (deluxemaptexunit >= 0)
5200 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5201 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5202 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));
5207 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
5210 int texturesurfaceindex;
5211 if (r_showsurfaces.integer == 2)
5213 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5215 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5216 for (j = 0;j < surface->num_triangles;j++)
5218 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_view.colorscale;
5219 GL_Color(f, f, f, 1);
5220 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)));
5226 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5228 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5229 int k = (int)(((size_t)surface) / sizeof(msurface_t));
5230 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);
5231 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5232 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));
5237 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, msurface_t **texturesurfacelist)
5239 int texturesurfaceindex;
5243 if (rsurface.lightmapcolor4f)
5245 // generate color arrays for the surfaces in this list
5246 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5248 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5249 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)
5251 f = FogPoint_Model(v);
5261 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5263 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5264 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)
5266 f = FogPoint_Model(v);
5274 rsurface.lightmapcolor4f = rsurface.array_color4f;
5275 rsurface.lightmapcolor4f_bufferobject = 0;
5276 rsurface.lightmapcolor4f_bufferoffset = 0;
5279 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a)
5281 int texturesurfaceindex;
5284 if (!rsurface.lightmapcolor4f)
5286 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5288 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5289 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)
5297 rsurface.lightmapcolor4f = rsurface.array_color4f;
5298 rsurface.lightmapcolor4f_bufferobject = 0;
5299 rsurface.lightmapcolor4f_bufferoffset = 0;
5302 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5305 rsurface.lightmapcolor4f = NULL;
5306 rsurface.lightmapcolor4f_bufferobject = 0;
5307 rsurface.lightmapcolor4f_bufferoffset = 0;
5308 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5309 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5310 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5311 GL_Color(r, g, b, a);
5312 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 0, -1);
5315 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5317 // TODO: optimize applyfog && applycolor case
5318 // just apply fog if necessary, and tint the fog color array if necessary
5319 rsurface.lightmapcolor4f = NULL;
5320 rsurface.lightmapcolor4f_bufferobject = 0;
5321 rsurface.lightmapcolor4f_bufferoffset = 0;
5322 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5323 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5324 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5325 GL_Color(r, g, b, a);
5326 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5329 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5331 int texturesurfaceindex;
5335 if (texturesurfacelist[0]->lightmapinfo && texturesurfacelist[0]->lightmapinfo->stainsamples)
5337 // generate color arrays for the surfaces in this list
5338 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5340 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5341 for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
5343 if (surface->lightmapinfo->samples)
5345 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
5346 float scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
5347 VectorScale(lm, scale, c);
5348 if (surface->lightmapinfo->styles[1] != 255)
5350 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
5352 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
5353 VectorMA(c, scale, lm, c);
5354 if (surface->lightmapinfo->styles[2] != 255)
5357 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
5358 VectorMA(c, scale, lm, c);
5359 if (surface->lightmapinfo->styles[3] != 255)
5362 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
5363 VectorMA(c, scale, lm, c);
5373 rsurface.lightmapcolor4f = rsurface.array_color4f;
5374 rsurface.lightmapcolor4f_bufferobject = 0;
5375 rsurface.lightmapcolor4f_bufferoffset = 0;
5379 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
5380 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
5381 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
5383 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5384 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5385 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5386 GL_Color(r, g, b, a);
5387 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5390 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5392 int texturesurfaceindex;
5396 vec3_t ambientcolor;
5397 vec3_t diffusecolor;
5401 VectorCopy(rsurface.modellight_lightdir, lightdir);
5402 f = 0.5f * r_refdef.lightmapintensity;
5403 ambientcolor[0] = rsurface.modellight_ambient[0] * r * f;
5404 ambientcolor[1] = rsurface.modellight_ambient[1] * g * f;
5405 ambientcolor[2] = rsurface.modellight_ambient[2] * b * f;
5406 diffusecolor[0] = rsurface.modellight_diffuse[0] * r * f;
5407 diffusecolor[1] = rsurface.modellight_diffuse[1] * g * f;
5408 diffusecolor[2] = rsurface.modellight_diffuse[2] * b * f;
5409 if (VectorLength2(diffusecolor) > 0)
5411 // generate color arrays for the surfaces in this list
5412 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5414 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5415 int numverts = surface->num_vertices;
5416 v = rsurface.vertex3f + 3 * surface->num_firstvertex;
5417 c2 = rsurface.normal3f + 3 * surface->num_firstvertex;
5418 c = rsurface.array_color4f + 4 * surface->num_firstvertex;
5419 // q3-style directional shading
5420 for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
5422 if ((f = DotProduct(c2, lightdir)) > 0)
5423 VectorMA(ambientcolor, f, diffusecolor, c);
5425 VectorCopy(ambientcolor, c);
5434 rsurface.lightmapcolor4f = rsurface.array_color4f;
5435 rsurface.lightmapcolor4f_bufferobject = 0;
5436 rsurface.lightmapcolor4f_bufferoffset = 0;
5440 r = ambientcolor[0];
5441 g = ambientcolor[1];
5442 b = ambientcolor[2];
5443 rsurface.lightmapcolor4f = NULL;
5444 rsurface.lightmapcolor4f_bufferobject = 0;
5445 rsurface.lightmapcolor4f_bufferoffset = 0;
5447 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5448 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5449 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5450 GL_Color(r, g, b, a);
5451 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5454 void RSurf_SetupDepthAndCulling(void)
5456 // submodels are biased to avoid z-fighting with world surfaces that they
5457 // may be exactly overlapping (avoids z-fighting artifacts on certain
5458 // doors and things in Quake maps)
5459 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5460 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
5461 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
5462 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_view.cullface_back);
5465 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
5467 RSurf_SetupDepthAndCulling();
5468 if (rsurface.mode != RSURFMODE_SHOWSURFACES)
5470 rsurface.mode = RSURFMODE_SHOWSURFACES;
5472 GL_BlendFunc(GL_ONE, GL_ZERO);
5473 R_Mesh_ColorPointer(NULL, 0, 0);
5474 R_Mesh_ResetTextureState();
5476 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
5477 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
5480 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, msurface_t **texturesurfacelist)
5482 // transparent sky would be ridiculous
5483 if ((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED))
5485 if (rsurface.mode != RSURFMODE_SKY)
5487 if (rsurface.mode == RSURFMODE_GLSL)
5489 qglUseProgramObjectARB(0);CHECKGLERROR
5491 rsurface.mode = RSURFMODE_SKY;
5495 skyrendernow = false;
5497 // restore entity matrix
5498 R_Mesh_Matrix(&rsurface.matrix);
5500 RSurf_SetupDepthAndCulling();
5502 // LordHavoc: HalfLife maps have freaky skypolys so don't use
5503 // skymasking on them, and Quake3 never did sky masking (unlike
5504 // software Quake and software Quake2), so disable the sky masking
5505 // in Quake3 maps as it causes problems with q3map2 sky tricks,
5506 // and skymasking also looks very bad when noclipping outside the
5507 // level, so don't use it then either.
5508 if (r_refdef.worldmodel && r_refdef.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_viewcache.world_novis)
5510 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
5511 R_Mesh_ColorPointer(NULL, 0, 0);
5512 R_Mesh_ResetTextureState();
5513 if (skyrendermasked)
5515 // depth-only (masking)
5516 GL_ColorMask(0,0,0,0);
5517 // just to make sure that braindead drivers don't draw
5518 // anything despite that colormask...
5519 GL_BlendFunc(GL_ZERO, GL_ONE);
5524 GL_BlendFunc(GL_ONE, GL_ZERO);
5526 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
5527 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5528 if (skyrendermasked)
5529 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
5533 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, msurface_t **texturesurfacelist)
5535 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION)))
5538 if (rsurface.mode != RSURFMODE_GLSL)
5540 rsurface.mode = RSURFMODE_GLSL;
5541 R_Mesh_ResetTextureState();
5542 GL_Color(1, 1, 1, 1);
5545 R_Mesh_TexMatrix(0, &rsurface.texture->currenttexmatrix);
5546 R_Mesh_TexBind(0, R_GetTexture(rsurface.texture->currentskinframe->nmap));
5547 R_Mesh_TexBind(1, R_GetTexture(rsurface.texture->basetexture));
5548 R_Mesh_TexBind(2, R_GetTexture(rsurface.texture->glosstexture));
5549 R_Mesh_TexBind(4, R_GetTexture(r_texture_fogattenuation));
5550 R_Mesh_TexBind(5, R_GetTexture(rsurface.texture->currentskinframe->pants));
5551 R_Mesh_TexBind(6, R_GetTexture(rsurface.texture->currentskinframe->shirt));
5552 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
5554 R_Mesh_TexBind(7, R_GetTexture(r_texture_grey128));
5555 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
5556 R_Mesh_ColorPointer(NULL, 0, 0);
5558 else if (rsurface.uselightmaptexture)
5560 R_Mesh_TexBind(7, R_GetTexture(texturesurfacelist[0]->lightmaptexture));
5561 R_Mesh_TexBind(8, R_GetTexture(texturesurfacelist[0]->deluxemaptexture));
5562 R_Mesh_ColorPointer(NULL, 0, 0);
5566 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
5567 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
5568 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
5570 R_Mesh_TexBind(9, R_GetTexture(rsurface.texture->currentskinframe->glow));
5571 R_Mesh_TexBind(11, R_GetTexture(r_texture_white)); // changed per surface
5572 R_Mesh_TexBind(12, R_GetTexture(r_texture_white)); // changed per surface
5574 if (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5576 // render background
5577 GL_BlendFunc(GL_ONE, GL_ZERO);
5579 GL_AlphaTest(false);
5581 GL_Color(1, 1, 1, 1);
5582 R_Mesh_ColorPointer(NULL, 0, 0);
5584 R_SetupSurfaceShader(vec3_origin, rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
5585 if (r_glsl_permutation)
5587 RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
5588 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
5589 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
5590 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
5591 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
5592 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
5593 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist, -1, -1, r_glsl_permutation->loc_Texture_Refraction ? 11 : -1, r_glsl_permutation->loc_Texture_Reflection ? 12 : -1);
5596 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5597 GL_DepthMask(false);
5598 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5599 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
5601 R_Mesh_TexBind(7, R_GetTexture(r_texture_grey128));
5602 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
5603 R_Mesh_ColorPointer(NULL, 0, 0);
5605 else if (rsurface.uselightmaptexture)
5607 R_Mesh_TexBind(7, R_GetTexture(texturesurfacelist[0]->lightmaptexture));
5608 R_Mesh_TexBind(8, R_GetTexture(texturesurfacelist[0]->deluxemaptexture));
5609 R_Mesh_ColorPointer(NULL, 0, 0);
5613 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
5614 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
5615 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
5617 R_Mesh_TexBind(11, R_GetTexture(r_texture_white)); // changed per surface
5618 R_Mesh_TexBind(12, R_GetTexture(r_texture_white)); // changed per surface
5621 R_SetupSurfaceShader(vec3_origin, rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE);
5622 if (!r_glsl_permutation)
5625 RSurf_PrepareVerticesForBatch(r_glsl_permutation->loc_Texture_Normal >= 0 || r_glsl_permutation->loc_LightDir >= 0, r_glsl_permutation->loc_Texture_Normal >= 0, texturenumsurfaces, texturesurfacelist);
5626 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
5627 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
5628 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
5629 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
5630 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
5632 if (r_glsl_permutation->loc_Texture_Refraction >= 0)
5634 GL_BlendFunc(GL_ONE, GL_ZERO);
5636 GL_AlphaTest(false);
5639 if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
5641 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
5642 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);
5644 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 7, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? 8 : -1);
5648 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
5649 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);
5651 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5653 if (rsurface.texture->backgroundnumskinframes && !(rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED))
5658 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, msurface_t **texturesurfacelist)
5660 // OpenGL 1.3 path - anything not completely ancient
5661 int texturesurfaceindex;
5662 qboolean applycolor;
5666 const texturelayer_t *layer;
5667 if (rsurface.mode != RSURFMODE_MULTIPASS)
5668 rsurface.mode = RSURFMODE_MULTIPASS;
5669 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
5671 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
5674 int layertexrgbscale;
5675 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5677 if (layerindex == 0)
5681 GL_AlphaTest(false);
5682 qglDepthFunc(GL_EQUAL);CHECKGLERROR
5685 GL_DepthMask(layer->depthmask);
5686 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
5687 if ((layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2) && (gl_combine.integer || layer->depthmask))
5689 layertexrgbscale = 4;
5690 VectorScale(layer->color, 0.25f, layercolor);
5692 else if ((layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1) && (gl_combine.integer || layer->depthmask))
5694 layertexrgbscale = 2;
5695 VectorScale(layer->color, 0.5f, layercolor);
5699 layertexrgbscale = 1;
5700 VectorScale(layer->color, 1.0f, layercolor);
5702 layercolor[3] = layer->color[3];
5703 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
5704 R_Mesh_ColorPointer(NULL, 0, 0);
5705 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
5706 switch (layer->type)
5708 case TEXTURELAYERTYPE_LITTEXTURE:
5709 memset(&m, 0, sizeof(m));
5710 m.tex[0] = R_GetTexture(r_texture_white);
5711 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
5712 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
5713 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
5714 m.tex[1] = R_GetTexture(layer->texture);
5715 m.texmatrix[1] = layer->texmatrix;
5716 m.texrgbscale[1] = layertexrgbscale;
5717 m.pointer_texcoord[1] = rsurface.texcoordtexture2f;
5718 m.pointer_texcoord_bufferobject[1] = rsurface.texcoordtexture2f_bufferobject;
5719 m.pointer_texcoord_bufferoffset[1] = rsurface.texcoordtexture2f_bufferoffset;
5720 R_Mesh_TextureState(&m);
5721 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
5722 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
5723 else if (rsurface.uselightmaptexture)
5724 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
5726 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
5728 case TEXTURELAYERTYPE_TEXTURE:
5729 memset(&m, 0, sizeof(m));
5730 m.tex[0] = R_GetTexture(layer->texture);
5731 m.texmatrix[0] = layer->texmatrix;
5732 m.texrgbscale[0] = layertexrgbscale;
5733 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5734 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5735 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5736 R_Mesh_TextureState(&m);
5737 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
5739 case TEXTURELAYERTYPE_FOG:
5740 memset(&m, 0, sizeof(m));
5741 m.texrgbscale[0] = layertexrgbscale;
5744 m.tex[0] = R_GetTexture(layer->texture);
5745 m.texmatrix[0] = layer->texmatrix;
5746 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5747 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5748 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5750 R_Mesh_TextureState(&m);
5751 // generate a color array for the fog pass
5752 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
5753 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5757 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5758 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)
5760 f = 1 - FogPoint_Model(v);
5761 c[0] = layercolor[0];
5762 c[1] = layercolor[1];
5763 c[2] = layercolor[2];
5764 c[3] = f * layercolor[3];
5767 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5770 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
5772 GL_LockArrays(0, 0);
5775 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5777 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
5778 GL_AlphaTest(false);
5782 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, msurface_t **texturesurfacelist)
5784 // OpenGL 1.1 - crusty old voodoo path
5785 int texturesurfaceindex;
5789 const texturelayer_t *layer;
5790 if (rsurface.mode != RSURFMODE_MULTIPASS)
5791 rsurface.mode = RSURFMODE_MULTIPASS;
5792 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
5794 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
5796 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5798 if (layerindex == 0)
5802 GL_AlphaTest(false);
5803 qglDepthFunc(GL_EQUAL);CHECKGLERROR
5806 GL_DepthMask(layer->depthmask);
5807 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
5808 R_Mesh_ColorPointer(NULL, 0, 0);
5809 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
5810 switch (layer->type)
5812 case TEXTURELAYERTYPE_LITTEXTURE:
5813 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
5815 // two-pass lit texture with 2x rgbscale
5816 // first the lightmap pass
5817 memset(&m, 0, sizeof(m));
5818 m.tex[0] = R_GetTexture(r_texture_white);
5819 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
5820 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
5821 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
5822 R_Mesh_TextureState(&m);
5823 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
5824 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5825 else if (rsurface.uselightmaptexture)
5826 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5828 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5829 GL_LockArrays(0, 0);
5830 // then apply the texture to it
5831 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
5832 memset(&m, 0, sizeof(m));
5833 m.tex[0] = R_GetTexture(layer->texture);
5834 m.texmatrix[0] = layer->texmatrix;
5835 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5836 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5837 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5838 R_Mesh_TextureState(&m);
5839 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);
5843 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
5844 memset(&m, 0, sizeof(m));
5845 m.tex[0] = R_GetTexture(layer->texture);
5846 m.texmatrix[0] = layer->texmatrix;
5847 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5848 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5849 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5850 R_Mesh_TextureState(&m);
5851 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
5852 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);
5854 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);
5857 case TEXTURELAYERTYPE_TEXTURE:
5858 // singletexture unlit texture with transparency support
5859 memset(&m, 0, sizeof(m));
5860 m.tex[0] = R_GetTexture(layer->texture);
5861 m.texmatrix[0] = layer->texmatrix;
5862 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5863 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5864 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5865 R_Mesh_TextureState(&m);
5866 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);
5868 case TEXTURELAYERTYPE_FOG:
5869 // singletexture fogging
5870 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
5873 memset(&m, 0, sizeof(m));
5874 m.tex[0] = R_GetTexture(layer->texture);
5875 m.texmatrix[0] = layer->texmatrix;
5876 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5877 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5878 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5879 R_Mesh_TextureState(&m);
5882 R_Mesh_ResetTextureState();
5883 // generate a color array for the fog pass
5884 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5888 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5889 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)
5891 f = 1 - FogPoint_Model(v);
5892 c[0] = layer->color[0];
5893 c[1] = layer->color[1];
5894 c[2] = layer->color[2];
5895 c[3] = f * layer->color[3];
5898 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5901 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
5903 GL_LockArrays(0, 0);
5906 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5908 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
5909 GL_AlphaTest(false);
5913 static void R_DrawTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly)
5915 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW)
5917 rsurface.rtlight = NULL;
5921 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
5923 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
5925 if (rsurface.mode != RSURFMODE_MULTIPASS)
5926 rsurface.mode = RSURFMODE_MULTIPASS;
5927 if (r_depthfirst.integer == 3)
5929 int i = (int)(texturesurfacelist[0] - rsurface.modelsurfaces);
5930 if (!r_view.showdebug)
5931 GL_Color(0, 0, 0, 1);
5933 GL_Color(((i >> 6) & 7) / 7.0f, ((i >> 3) & 7) / 7.0f, (i & 7) / 7.0f,1);
5937 GL_ColorMask(0,0,0,0);
5940 RSurf_SetupDepthAndCulling();
5942 GL_BlendFunc(GL_ONE, GL_ZERO);
5944 GL_AlphaTest(false);
5945 R_Mesh_ColorPointer(NULL, 0, 0);
5946 R_Mesh_ResetTextureState();
5947 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
5948 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5949 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
5951 else if (r_depthfirst.integer == 3)
5953 else if (!r_view.showdebug && (r_showsurfaces.integer || gl_lightmaps.integer))
5955 GL_Color(0, 0, 0, 1);
5956 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5958 else if (r_showsurfaces.integer)
5960 if (rsurface.mode != RSURFMODE_MULTIPASS)
5961 rsurface.mode = RSURFMODE_MULTIPASS;
5962 RSurf_SetupDepthAndCulling();
5964 GL_BlendFunc(GL_ONE, GL_ZERO);
5965 GL_DepthMask(writedepth);
5967 GL_AlphaTest(false);
5968 R_Mesh_ColorPointer(NULL, 0, 0);
5969 R_Mesh_ResetTextureState();
5970 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
5971 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
5973 else if (gl_lightmaps.integer)
5976 if (rsurface.mode != RSURFMODE_MULTIPASS)
5977 rsurface.mode = RSURFMODE_MULTIPASS;
5978 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5980 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_view.cullface_back);
5981 GL_BlendFunc(GL_ONE, GL_ZERO);
5982 GL_DepthMask(writedepth);
5984 GL_AlphaTest(false);
5985 R_Mesh_ColorPointer(NULL, 0, 0);
5986 memset(&m, 0, sizeof(m));
5987 m.tex[0] = R_GetTexture(r_texture_white);
5988 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
5989 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
5990 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
5991 R_Mesh_TextureState(&m);
5992 RSurf_PrepareVerticesForBatch(rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT, false, texturenumsurfaces, texturesurfacelist);
5993 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
5994 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5995 else if (rsurface.uselightmaptexture)
5996 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5998 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
6000 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
6001 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
6002 else if (rsurface.texture->currentnumlayers)
6004 // write depth for anything we skipped on the depth-only pass earlier
6005 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
6007 RSurf_SetupDepthAndCulling();
6008 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
6009 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
6010 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
6011 if (r_glsl.integer && gl_support_fragment_shader)
6012 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist);
6013 else if (gl_combine.integer && r_textureunits.integer >= 2)
6014 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist);
6016 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist);
6019 GL_LockArrays(0, 0);
6022 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6025 int texturenumsurfaces, endsurface;
6027 msurface_t *surface;
6028 msurface_t *texturesurfacelist[1024];
6030 // if the model is static it doesn't matter what value we give for
6031 // wantnormals and wanttangents, so this logic uses only rules applicable
6032 // to a model, knowing that they are meaningless otherwise
6033 if (ent == r_refdef.worldentity)
6034 RSurf_ActiveWorldEntity();
6035 else if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
6036 RSurf_ActiveModelEntity(ent, false, false);
6038 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
6040 for (i = 0;i < numsurfaces;i = j)
6043 surface = rsurface.modelsurfaces + surfacelist[i];
6044 texture = surface->texture;
6045 R_UpdateTextureInfo(ent, texture);
6046 rsurface.texture = texture->currentframe;
6047 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
6048 // scan ahead until we find a different texture
6049 endsurface = min(i + 1024, numsurfaces);
6050 texturenumsurfaces = 0;
6051 texturesurfacelist[texturenumsurfaces++] = surface;
6052 for (;j < endsurface;j++)
6054 surface = rsurface.modelsurfaces + surfacelist[j];
6055 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
6057 texturesurfacelist[texturenumsurfaces++] = surface;
6059 // render the range of surfaces
6060 R_DrawTextureSurfaceList(texturenumsurfaces, texturesurfacelist, true, false);
6066 void R_QueueSurfaceList(entity_render_t *ent, int numsurfaces, msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes)
6069 vec3_t tempcenter, center;
6071 // if we're rendering water textures (extra scene renders), use a separate loop to avoid burdening the main one
6074 for (i = 0;i < numsurfaces;i++)
6075 if (surfacelist[i]->texture->currentframe->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION))
6076 R_Water_AddWaterPlane(surfacelist[i]);
6079 // break the surface list down into batches by texture and use of lightmapping
6080 for (i = 0;i < numsurfaces;i = j)
6083 // texture is the base texture pointer, rsurface.texture is the
6084 // current frame/skin the texture is directing us to use (for example
6085 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
6086 // use skin 1 instead)
6087 texture = surfacelist[i]->texture;
6088 rsurface.texture = texture->currentframe;
6089 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
6090 if (!(rsurface.texture->currentmaterialflags & flagsmask))
6092 // if this texture is not the kind we want, skip ahead to the next one
6093 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
6097 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
6099 // transparent surfaces get pushed off into the transparent queue
6100 const msurface_t *surface = surfacelist[i];
6103 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
6104 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
6105 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
6106 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
6107 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_view.origin : center, R_DrawSurface_TransparentCallback, ent, surface - rsurface.modelsurfaces, rsurface.rtlight);
6111 // simply scan ahead until we find a different texture or lightmap state
6112 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
6114 // render the range of surfaces
6115 R_DrawTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly);
6120 float locboxvertex3f[6*4*3] =
6122 1,0,1, 1,0,0, 1,1,0, 1,1,1,
6123 0,1,1, 0,1,0, 0,0,0, 0,0,1,
6124 1,1,1, 1,1,0, 0,1,0, 0,1,1,
6125 0,0,1, 0,0,0, 1,0,0, 1,0,1,
6126 0,0,1, 1,0,1, 1,1,1, 0,1,1,
6127 1,0,0, 0,0,0, 0,1,0, 1,1,0
6130 int locboxelement3i[6*2*3] =
6140 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6143 cl_locnode_t *loc = (cl_locnode_t *)ent;
6145 float vertex3f[6*4*3];
6147 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6148 GL_DepthMask(false);
6149 GL_DepthRange(0, 1);
6150 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6152 GL_CullFace(GL_NONE);
6153 R_Mesh_Matrix(&identitymatrix);
6155 R_Mesh_VertexPointer(vertex3f, 0, 0);
6156 R_Mesh_ColorPointer(NULL, 0, 0);
6157 R_Mesh_ResetTextureState();
6160 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_view.colorscale,
6161 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_view.colorscale,
6162 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_view.colorscale,
6163 surfacelist[0] < 0 ? 0.5f : 0.125f);
6165 if (VectorCompare(loc->mins, loc->maxs))
6167 VectorSet(size, 2, 2, 2);
6168 VectorMA(loc->mins, -0.5f, size, mins);
6172 VectorCopy(loc->mins, mins);
6173 VectorSubtract(loc->maxs, loc->mins, size);
6176 for (i = 0;i < 6*4*3;)
6177 for (j = 0;j < 3;j++, i++)
6178 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
6180 R_Mesh_Draw(0, 6*4, 6*2, locboxelement3i, 0, 0);
6183 void R_DrawLocs(void)
6186 cl_locnode_t *loc, *nearestloc;
6188 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
6189 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
6191 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
6192 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
6196 void R_DrawDebugModel(entity_render_t *ent)
6198 int i, j, k, l, flagsmask;
6199 const int *elements;
6201 msurface_t *surface;
6202 model_t *model = ent->model;
6205 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WATER | MATERIALFLAG_WALL;
6207 R_Mesh_ColorPointer(NULL, 0, 0);
6208 R_Mesh_ResetTextureState();
6209 GL_DepthRange(0, 1);
6210 GL_DepthTest(!r_showdisabledepthtest.integer);
6211 GL_DepthMask(false);
6212 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6214 if (r_showcollisionbrushes.value > 0 && model->brush.num_brushes)
6216 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
6217 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
6219 if (brush->colbrushf && brush->colbrushf->numtriangles)
6221 R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
6222 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);
6223 R_Mesh_Draw(0, brush->colbrushf->numpoints, brush->colbrushf->numtriangles, brush->colbrushf->elements, 0, 0);
6226 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
6228 if (surface->num_collisiontriangles)
6230 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
6231 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);
6232 R_Mesh_Draw(0, surface->num_collisionvertices, surface->num_collisiontriangles, surface->data_collisionelement3i, 0, 0);
6237 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6239 if (r_showtris.integer || r_shownormals.integer)
6241 if (r_showdisabledepthtest.integer)
6243 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6244 GL_DepthMask(false);
6248 GL_BlendFunc(GL_ONE, GL_ZERO);
6251 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
6253 if (ent == r_refdef.worldentity && !r_viewcache.world_surfacevisible[j])
6255 rsurface.texture = surface->texture->currentframe;
6256 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
6258 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
6259 if (r_showtris.value > 0)
6261 if (!rsurface.texture->currentlayers->depthmask)
6262 GL_Color(r_view.colorscale, 0, 0, r_showtris.value);
6263 else if (ent == r_refdef.worldentity)
6264 GL_Color(r_view.colorscale, r_view.colorscale, r_view.colorscale, r_showtris.value);
6266 GL_Color(0, r_view.colorscale, 0, r_showtris.value);
6267 elements = (ent->model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
6270 for (k = 0;k < surface->num_triangles;k++, elements += 3)
6272 #define GLVERTEXELEMENT(n) qglVertex3f(rsurface.vertex3f[elements[n]*3+0], rsurface.vertex3f[elements[n]*3+1], rsurface.vertex3f[elements[n]*3+2])
6273 GLVERTEXELEMENT(0);GLVERTEXELEMENT(1);
6274 GLVERTEXELEMENT(1);GLVERTEXELEMENT(2);
6275 GLVERTEXELEMENT(2);GLVERTEXELEMENT(0);
6280 if (r_shownormals.value > 0)
6283 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
6285 VectorCopy(rsurface.vertex3f + l * 3, v);
6286 GL_Color(r_view.colorscale, 0, 0, 1);
6287 qglVertex3f(v[0], v[1], v[2]);
6288 VectorMA(v, r_shownormals.value, rsurface.svector3f + l * 3, v);
6289 GL_Color(r_view.colorscale, 1, 1, 1);
6290 qglVertex3f(v[0], v[1], v[2]);
6295 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
6297 VectorCopy(rsurface.vertex3f + l * 3, v);
6298 GL_Color(0, r_view.colorscale, 0, 1);
6299 qglVertex3f(v[0], v[1], v[2]);
6300 VectorMA(v, r_shownormals.value, rsurface.tvector3f + l * 3, v);
6301 GL_Color(r_view.colorscale, 1, 1, 1);
6302 qglVertex3f(v[0], v[1], v[2]);
6307 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
6309 VectorCopy(rsurface.vertex3f + l * 3, v);
6310 GL_Color(0, 0, r_view.colorscale, 1);
6311 qglVertex3f(v[0], v[1], v[2]);
6312 VectorMA(v, r_shownormals.value, rsurface.normal3f + l * 3, v);
6313 GL_Color(r_view.colorscale, 1, 1, 1);
6314 qglVertex3f(v[0], v[1], v[2]);
6321 rsurface.texture = NULL;
6325 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
6326 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes, qboolean debug)
6328 int i, j, endj, f, flagsmask;
6329 msurface_t *surface;
6331 model_t *model = r_refdef.worldmodel;
6332 const int maxsurfacelist = 1024;
6333 int numsurfacelist = 0;
6334 msurface_t *surfacelist[1024];
6338 RSurf_ActiveWorldEntity();
6340 // update light styles on this submodel
6341 if (!skysurfaces && !depthonly && !addwaterplanes && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
6343 model_brush_lightstyleinfo_t *style;
6344 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
6346 if (style->value != r_refdef.lightstylevalue[style->style])
6348 msurface_t *surfaces = model->data_surfaces;
6349 int *list = style->surfacelist;
6350 style->value = r_refdef.lightstylevalue[style->style];
6351 for (j = 0;j < style->numsurfaces;j++)
6352 surfaces[list[j]].cached_dlight = true;
6357 R_UpdateAllTextureInfo(r_refdef.worldentity);
6358 flagsmask = addwaterplanes ? (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) : (skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL));
6362 R_DrawDebugModel(r_refdef.worldentity);
6368 rsurface.uselightmaptexture = false;
6369 rsurface.texture = NULL;
6371 j = model->firstmodelsurface;
6372 endj = j + model->nummodelsurfaces;
6375 // quickly skip over non-visible surfaces
6376 for (;j < endj && !r_viewcache.world_surfacevisible[j];j++)
6378 // quickly iterate over visible surfaces
6379 for (;j < endj && r_viewcache.world_surfacevisible[j];j++)
6381 // process this surface
6382 surface = model->data_surfaces + j;
6383 // if this surface fits the criteria, add it to the list
6384 if (surface->num_triangles)
6386 // if lightmap parameters changed, rebuild lightmap texture
6387 if (surface->cached_dlight)
6388 R_BuildLightMap(r_refdef.worldentity, surface);
6389 // add face to draw list
6390 surfacelist[numsurfacelist++] = surface;
6391 r_refdef.stats.world_triangles += surface->num_triangles;
6392 if (numsurfacelist >= maxsurfacelist)
6394 r_refdef.stats.world_surfaces += numsurfacelist;
6395 R_QueueSurfaceList(r_refdef.worldentity, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
6401 r_refdef.stats.world_surfaces += numsurfacelist;
6403 R_QueueSurfaceList(r_refdef.worldentity, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
6407 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes, qboolean debug)
6409 int i, j, f, flagsmask;
6410 msurface_t *surface, *endsurface;
6412 model_t *model = ent->model;
6413 const int maxsurfacelist = 1024;
6414 int numsurfacelist = 0;
6415 msurface_t *surfacelist[1024];
6419 // if the model is static it doesn't matter what value we give for
6420 // wantnormals and wanttangents, so this logic uses only rules applicable
6421 // to a model, knowing that they are meaningless otherwise
6422 if (ent == r_refdef.worldentity)
6423 RSurf_ActiveWorldEntity();
6424 else if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
6425 RSurf_ActiveModelEntity(ent, false, false);
6427 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader && !depthonly);
6429 // update light styles
6430 if (!skysurfaces && !depthonly && !addwaterplanes && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
6432 model_brush_lightstyleinfo_t *style;
6433 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
6435 if (style->value != r_refdef.lightstylevalue[style->style])
6437 msurface_t *surfaces = model->data_surfaces;
6438 int *list = style->surfacelist;
6439 style->value = r_refdef.lightstylevalue[style->style];
6440 for (j = 0;j < style->numsurfaces;j++)
6441 surfaces[list[j]].cached_dlight = true;
6446 R_UpdateAllTextureInfo(ent);
6447 flagsmask = addwaterplanes ? (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) : (skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL));
6451 R_DrawDebugModel(ent);
6457 rsurface.uselightmaptexture = false;
6458 rsurface.texture = NULL;
6460 surface = model->data_surfaces + model->firstmodelsurface;
6461 endsurface = surface + model->nummodelsurfaces;
6462 for (;surface < endsurface;surface++)
6464 // if this surface fits the criteria, add it to the list
6465 if (surface->num_triangles)
6467 // if lightmap parameters changed, rebuild lightmap texture
6468 if (surface->cached_dlight)
6469 R_BuildLightMap(ent, surface);
6470 // add face to draw list
6471 surfacelist[numsurfacelist++] = surface;
6472 r_refdef.stats.entities_triangles += surface->num_triangles;
6473 if (numsurfacelist >= maxsurfacelist)
6475 r_refdef.stats.entities_surfaces += numsurfacelist;
6476 R_QueueSurfaceList(ent, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
6481 r_refdef.stats.entities_surfaces += numsurfacelist;
6483 R_QueueSurfaceList(ent, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);