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, t->lightmapcolor[0], t->lightmapcolor[1], t->lightmapcolor[2], t->lightmapcolor[3]);
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] * t->lightmapcolor[0], ent->colormap_pantscolor[1] * t->lightmapcolor[1], ent->colormap_pantscolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
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] * t->lightmapcolor[0], ent->colormap_shirtcolor[1] * t->lightmapcolor[1], ent->colormap_shirtcolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
4277 vec3_t ambientcolor;
4279 // set the color tint used for lights affecting this surface
4280 VectorSet(t->dlightcolor, ent->colormod[0] * t->lightmapcolor[3], ent->colormod[1] * t->lightmapcolor[3], ent->colormod[2] * t->lightmapcolor[3]);
4282 // q3bsp has no lightmap updates, so the lightstylevalue that
4283 // would normally be baked into the lightmap must be
4284 // applied to the color
4285 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
4286 if (ent->model->type == mod_brushq3)
4287 colorscale *= r_refdef.rtlightstylevalue[0];
4288 colorscale *= r_refdef.lightmapintensity;
4289 VectorScale(t->lightmapcolor, r_ambient.value * (1.0f / 64.0f), ambientcolor);
4290 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
4291 // basic lit geometry
4292 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_LITTEXTURE, currentbasetexture, &t->currenttexmatrix, t->lightmapcolor[0], t->lightmapcolor[1], t->lightmapcolor[2], t->lightmapcolor[3]);
4293 // add pants/shirt if needed
4294 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
4295 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->currentskinframe->pants, &t->currenttexmatrix, ent->colormap_pantscolor[0] * t->lightmapcolor[0], ent->colormap_pantscolor[1] * t->lightmapcolor[1], ent->colormap_pantscolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
4296 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
4297 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->currentskinframe->shirt, &t->currenttexmatrix, ent->colormap_shirtcolor[0] * t->lightmapcolor[0], ent->colormap_shirtcolor[1] * t->lightmapcolor[1], ent->colormap_shirtcolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
4298 // now add ambient passes if needed
4299 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
4301 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ambientcolor[0], ambientcolor[1], ambientcolor[2], t->lightmapcolor[3]);
4302 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
4303 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->pants, &t->currenttexmatrix, ent->colormap_pantscolor[0] * ambientcolor[0], ent->colormap_pantscolor[1] * ambientcolor[1], ent->colormap_pantscolor[2] * ambientcolor[2], t->lightmapcolor[3]);
4304 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
4305 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->shirt, &t->currenttexmatrix, ent->colormap_shirtcolor[0] * ambientcolor[0], ent->colormap_shirtcolor[1] * ambientcolor[1], ent->colormap_shirtcolor[2] * ambientcolor[2], t->lightmapcolor[3]);
4308 if (t->currentskinframe->glow != NULL)
4309 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->glow, &t->currenttexmatrix, r_hdr_glowintensity.value, r_hdr_glowintensity.value, r_hdr_glowintensity.value, t->lightmapcolor[3]);
4310 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
4312 // if this is opaque use alpha blend which will darken the earlier
4315 // if this is an alpha blended material, all the earlier passes
4316 // were darkened by fog already, so we only need to add the fog
4317 // color ontop through the fog mask texture
4319 // if this is an additive blended material, all the earlier passes
4320 // were darkened by fog already, and we should not add fog color
4321 // (because the background was not darkened, there is no fog color
4322 // that was lost behind it).
4323 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, (t->currentmaterialflags & MATERIALFLAG_BLENDED) ? GL_ONE : GL_ONE_MINUS_SRC_ALPHA, TEXTURELAYERTYPE_FOG, t->currentskinframe->fog, &identitymatrix, r_refdef.fogcolor[0] / r_view.colorscale, r_refdef.fogcolor[1] / r_view.colorscale, r_refdef.fogcolor[2] / r_view.colorscale, t->lightmapcolor[3]);
4330 void R_UpdateAllTextureInfo(entity_render_t *ent)
4334 for (i = 0;i < ent->model->num_texturesperskin;i++)
4335 R_UpdateTextureInfo(ent, ent->model->data_textures + i);
4338 rsurfacestate_t rsurface;
4340 void R_Mesh_ResizeArrays(int newvertices)
4343 if (rsurface.array_size >= newvertices)
4345 if (rsurface.array_modelvertex3f)
4346 Mem_Free(rsurface.array_modelvertex3f);
4347 rsurface.array_size = (newvertices + 1023) & ~1023;
4348 base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
4349 rsurface.array_modelvertex3f = base + rsurface.array_size * 0;
4350 rsurface.array_modelsvector3f = base + rsurface.array_size * 3;
4351 rsurface.array_modeltvector3f = base + rsurface.array_size * 6;
4352 rsurface.array_modelnormal3f = base + rsurface.array_size * 9;
4353 rsurface.array_deformedvertex3f = base + rsurface.array_size * 12;
4354 rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
4355 rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
4356 rsurface.array_deformednormal3f = base + rsurface.array_size * 21;
4357 rsurface.array_texcoord3f = base + rsurface.array_size * 24;
4358 rsurface.array_color4f = base + rsurface.array_size * 27;
4359 rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
4362 void RSurf_CleanUp(void)
4365 if (rsurface.mode == RSURFMODE_GLSL)
4367 qglUseProgramObjectARB(0);CHECKGLERROR
4369 GL_AlphaTest(false);
4370 rsurface.mode = RSURFMODE_NONE;
4371 rsurface.uselightmaptexture = false;
4372 rsurface.texture = NULL;
4375 void RSurf_ActiveWorldEntity(void)
4377 model_t *model = r_refdef.worldmodel;
4379 if (rsurface.array_size < model->surfmesh.num_vertices)
4380 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
4381 rsurface.matrix = identitymatrix;
4382 rsurface.inversematrix = identitymatrix;
4383 R_Mesh_Matrix(&identitymatrix);
4384 VectorCopy(r_view.origin, rsurface.modelorg);
4385 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
4386 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
4387 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
4388 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
4389 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
4390 rsurface.frameblend[0].frame = 0;
4391 rsurface.frameblend[0].lerp = 1;
4392 rsurface.frameblend[1].frame = 0;
4393 rsurface.frameblend[1].lerp = 0;
4394 rsurface.frameblend[2].frame = 0;
4395 rsurface.frameblend[2].lerp = 0;
4396 rsurface.frameblend[3].frame = 0;
4397 rsurface.frameblend[3].lerp = 0;
4398 rsurface.basepolygonfactor = r_refdef.polygonfactor;
4399 rsurface.basepolygonoffset = r_refdef.polygonoffset;
4400 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
4401 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
4402 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
4403 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
4404 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
4405 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
4406 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
4407 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
4408 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
4409 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
4410 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
4411 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
4412 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
4413 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
4414 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
4415 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
4416 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
4417 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
4418 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
4419 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
4420 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
4421 rsurface.modelelement3i = model->surfmesh.data_element3i;
4422 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo;
4423 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
4424 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
4425 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
4426 rsurface.modelsurfaces = model->data_surfaces;
4427 rsurface.generatedvertex = false;
4428 rsurface.vertex3f = rsurface.modelvertex3f;
4429 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
4430 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
4431 rsurface.svector3f = rsurface.modelsvector3f;
4432 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
4433 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
4434 rsurface.tvector3f = rsurface.modeltvector3f;
4435 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
4436 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
4437 rsurface.normal3f = rsurface.modelnormal3f;
4438 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
4439 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
4440 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
4443 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4445 model_t *model = ent->model;
4447 if (rsurface.array_size < model->surfmesh.num_vertices)
4448 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
4449 rsurface.matrix = ent->matrix;
4450 rsurface.inversematrix = ent->inversematrix;
4451 R_Mesh_Matrix(&rsurface.matrix);
4452 Matrix4x4_Transform(&rsurface.inversematrix, r_view.origin, rsurface.modelorg);
4453 rsurface.modellight_ambient[0] = ent->modellight_ambient[0] * ent->colormod[0];
4454 rsurface.modellight_ambient[1] = ent->modellight_ambient[1] * ent->colormod[1];
4455 rsurface.modellight_ambient[2] = ent->modellight_ambient[2] * ent->colormod[2];
4456 rsurface.modellight_diffuse[0] = ent->modellight_diffuse[0] * ent->colormod[0];
4457 rsurface.modellight_diffuse[1] = ent->modellight_diffuse[1] * ent->colormod[1];
4458 rsurface.modellight_diffuse[2] = ent->modellight_diffuse[2] * ent->colormod[2];
4459 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
4460 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
4461 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
4462 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
4463 rsurface.frameblend[0] = ent->frameblend[0];
4464 rsurface.frameblend[1] = ent->frameblend[1];
4465 rsurface.frameblend[2] = ent->frameblend[2];
4466 rsurface.frameblend[3] = ent->frameblend[3];
4467 rsurface.basepolygonfactor = r_refdef.polygonfactor;
4468 rsurface.basepolygonoffset = r_refdef.polygonoffset;
4469 if (ent->model->brush.submodel)
4471 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
4472 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
4474 if (model->surfmesh.isanimated && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].frame != 0))
4478 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
4479 rsurface.modelsvector3f = rsurface.array_modelsvector3f;
4480 rsurface.modeltvector3f = rsurface.array_modeltvector3f;
4481 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
4482 Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
4484 else if (wantnormals)
4486 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
4487 rsurface.modelsvector3f = NULL;
4488 rsurface.modeltvector3f = NULL;
4489 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
4490 Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
4494 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
4495 rsurface.modelsvector3f = NULL;
4496 rsurface.modeltvector3f = NULL;
4497 rsurface.modelnormal3f = NULL;
4498 Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, NULL, NULL, NULL);
4500 rsurface.modelvertex3f_bufferobject = 0;
4501 rsurface.modelvertex3f_bufferoffset = 0;
4502 rsurface.modelsvector3f_bufferobject = 0;
4503 rsurface.modelsvector3f_bufferoffset = 0;
4504 rsurface.modeltvector3f_bufferobject = 0;
4505 rsurface.modeltvector3f_bufferoffset = 0;
4506 rsurface.modelnormal3f_bufferobject = 0;
4507 rsurface.modelnormal3f_bufferoffset = 0;
4508 rsurface.generatedvertex = true;
4512 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
4513 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
4514 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
4515 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
4516 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
4517 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
4518 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
4519 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
4520 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
4521 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
4522 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
4523 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
4524 rsurface.generatedvertex = false;
4526 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
4527 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
4528 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
4529 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
4530 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
4531 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
4532 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
4533 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
4534 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
4535 rsurface.modelelement3i = model->surfmesh.data_element3i;
4536 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo;
4537 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
4538 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
4539 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
4540 rsurface.modelsurfaces = model->data_surfaces;
4541 rsurface.vertex3f = rsurface.modelvertex3f;
4542 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
4543 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
4544 rsurface.svector3f = rsurface.modelsvector3f;
4545 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
4546 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
4547 rsurface.tvector3f = rsurface.modeltvector3f;
4548 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
4549 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
4550 rsurface.normal3f = rsurface.modelnormal3f;
4551 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
4552 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
4553 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
4556 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
4557 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, msurface_t **texturesurfacelist)
4560 int texturesurfaceindex;
4565 const float *v1, *in_tc;
4567 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
4569 q3shaderinfo_deform_t *deform;
4570 // 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
4571 if (rsurface.generatedvertex)
4573 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
4574 generatenormals = true;
4575 for (i = 0;i < Q3MAXDEFORMS;i++)
4577 if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
4579 generatetangents = true;
4580 generatenormals = true;
4582 if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
4583 generatenormals = true;
4585 if (generatenormals && !rsurface.modelnormal3f)
4587 rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
4588 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
4589 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
4590 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer);
4592 if (generatetangents && !rsurface.modelsvector3f)
4594 rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
4595 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
4596 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
4597 rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
4598 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
4599 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
4600 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);
4603 rsurface.vertex3f = rsurface.modelvertex3f;
4604 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
4605 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
4606 rsurface.svector3f = rsurface.modelsvector3f;
4607 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
4608 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
4609 rsurface.tvector3f = rsurface.modeltvector3f;
4610 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
4611 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
4612 rsurface.normal3f = rsurface.modelnormal3f;
4613 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
4614 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
4615 // if vertices are deformed (sprite flares and things in maps, possibly
4616 // water waves, bulges and other deformations), generate them into
4617 // rsurface.deform* arrays from whatever the rsurface.* arrays point to
4618 // (may be static model data or generated data for an animated model, or
4619 // the previous deform pass)
4620 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
4622 switch (deform->deform)
4625 case Q3DEFORM_PROJECTIONSHADOW:
4626 case Q3DEFORM_TEXT0:
4627 case Q3DEFORM_TEXT1:
4628 case Q3DEFORM_TEXT2:
4629 case Q3DEFORM_TEXT3:
4630 case Q3DEFORM_TEXT4:
4631 case Q3DEFORM_TEXT5:
4632 case Q3DEFORM_TEXT6:
4633 case Q3DEFORM_TEXT7:
4636 case Q3DEFORM_AUTOSPRITE:
4637 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.forward, newforward);
4638 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.right, newright);
4639 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.up, newup);
4640 VectorNormalize(newforward);
4641 VectorNormalize(newright);
4642 VectorNormalize(newup);
4643 // make deformed versions of only the model vertices used by the specified surfaces
4644 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4646 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4647 // a single autosprite surface can contain multiple sprites...
4648 for (j = 0;j < surface->num_vertices - 3;j += 4)
4650 VectorClear(center);
4651 for (i = 0;i < 4;i++)
4652 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
4653 VectorScale(center, 0.25f, center);
4654 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, forward);
4655 VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
4656 VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
4657 for (i = 0;i < 4;i++)
4659 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
4660 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
4663 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);
4664 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);
4666 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4667 rsurface.vertex3f_bufferobject = 0;
4668 rsurface.vertex3f_bufferoffset = 0;
4669 rsurface.svector3f = rsurface.array_deformedsvector3f;
4670 rsurface.svector3f_bufferobject = 0;
4671 rsurface.svector3f_bufferoffset = 0;
4672 rsurface.tvector3f = rsurface.array_deformedtvector3f;
4673 rsurface.tvector3f_bufferobject = 0;
4674 rsurface.tvector3f_bufferoffset = 0;
4675 rsurface.normal3f = rsurface.array_deformednormal3f;
4676 rsurface.normal3f_bufferobject = 0;
4677 rsurface.normal3f_bufferoffset = 0;
4679 case Q3DEFORM_AUTOSPRITE2:
4680 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.forward, newforward);
4681 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.right, newright);
4682 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.up, newup);
4683 VectorNormalize(newforward);
4684 VectorNormalize(newright);
4685 VectorNormalize(newup);
4686 // make deformed versions of only the model vertices used by the specified surfaces
4687 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4689 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4690 const float *v1, *v2;
4700 memset(shortest, 0, sizeof(shortest));
4701 // a single autosprite surface can contain multiple sprites...
4702 for (j = 0;j < surface->num_vertices - 3;j += 4)
4704 VectorClear(center);
4705 for (i = 0;i < 4;i++)
4706 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
4707 VectorScale(center, 0.25f, center);
4708 // find the two shortest edges, then use them to define the
4709 // axis vectors for rotating around the central axis
4710 for (i = 0;i < 6;i++)
4712 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
4713 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
4715 Debug_PolygonBegin(NULL, 0, false, 0);
4716 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
4717 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);
4718 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
4721 l = VectorDistance2(v1, v2);
4722 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
4724 l += (1.0f / 1024.0f);
4725 if (shortest[0].length2 > l || i == 0)
4727 shortest[1] = shortest[0];
4728 shortest[0].length2 = l;
4729 shortest[0].v1 = v1;
4730 shortest[0].v2 = v2;
4732 else if (shortest[1].length2 > l || i == 1)
4734 shortest[1].length2 = l;
4735 shortest[1].v1 = v1;
4736 shortest[1].v2 = v2;
4739 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
4740 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
4742 Debug_PolygonBegin(NULL, 0, false, 0);
4743 Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
4744 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);
4745 Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
4748 // this calculates the right vector from the shortest edge
4749 // and the up vector from the edge midpoints
4750 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
4751 VectorNormalize(right);
4752 VectorSubtract(end, start, up);
4753 VectorNormalize(up);
4754 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
4755 //VectorSubtract(rsurface.modelorg, center, forward);
4756 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.forward, forward);
4757 VectorNegate(forward, forward);
4758 VectorReflect(forward, 0, up, forward);
4759 VectorNormalize(forward);
4760 CrossProduct(up, forward, newright);
4761 VectorNormalize(newright);
4763 Debug_PolygonBegin(NULL, 0, false, 0);
4764 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);
4765 Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
4766 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
4770 Debug_PolygonBegin(NULL, 0, false, 0);
4771 Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
4772 Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
4773 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
4776 // rotate the quad around the up axis vector, this is made
4777 // especially easy by the fact we know the quad is flat,
4778 // so we only have to subtract the center position and
4779 // measure distance along the right vector, and then
4780 // multiply that by the newright vector and add back the
4782 // we also need to subtract the old position to undo the
4783 // displacement from the center, which we do with a
4784 // DotProduct, the subtraction/addition of center is also
4785 // optimized into DotProducts here
4786 l = DotProduct(right, center);
4787 for (i = 0;i < 4;i++)
4789 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
4790 f = DotProduct(right, v1) - l;
4791 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
4794 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);
4795 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);
4797 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4798 rsurface.vertex3f_bufferobject = 0;
4799 rsurface.vertex3f_bufferoffset = 0;
4800 rsurface.svector3f = rsurface.array_deformedsvector3f;
4801 rsurface.svector3f_bufferobject = 0;
4802 rsurface.svector3f_bufferoffset = 0;
4803 rsurface.tvector3f = rsurface.array_deformedtvector3f;
4804 rsurface.tvector3f_bufferobject = 0;
4805 rsurface.tvector3f_bufferoffset = 0;
4806 rsurface.normal3f = rsurface.array_deformednormal3f;
4807 rsurface.normal3f_bufferobject = 0;
4808 rsurface.normal3f_bufferoffset = 0;
4810 case Q3DEFORM_NORMAL:
4811 // deform the normals to make reflections wavey
4812 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4814 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4815 for (j = 0;j < surface->num_vertices;j++)
4818 float *normal = (rsurface.array_deformednormal3f + 3 * surface->num_firstvertex) + j*3;
4819 VectorScale((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
4820 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, normal);
4821 normal[0] += deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.time * deform->parms[1]);
4822 normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.time * deform->parms[1]);
4823 normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.time * deform->parms[1]);
4824 VectorNormalize(normal);
4826 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);
4828 rsurface.svector3f = rsurface.array_deformedsvector3f;
4829 rsurface.svector3f_bufferobject = 0;
4830 rsurface.svector3f_bufferoffset = 0;
4831 rsurface.tvector3f = rsurface.array_deformedtvector3f;
4832 rsurface.tvector3f_bufferobject = 0;
4833 rsurface.tvector3f_bufferoffset = 0;
4834 rsurface.normal3f = rsurface.array_deformednormal3f;
4835 rsurface.normal3f_bufferobject = 0;
4836 rsurface.normal3f_bufferoffset = 0;
4839 // deform vertex array to make wavey water and flags and such
4840 waveparms[0] = deform->waveparms[0];
4841 waveparms[1] = deform->waveparms[1];
4842 waveparms[2] = deform->waveparms[2];
4843 waveparms[3] = deform->waveparms[3];
4844 // this is how a divisor of vertex influence on deformation
4845 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
4846 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
4847 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4849 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4850 for (j = 0;j < surface->num_vertices;j++)
4852 float *vertex = (rsurface.array_deformedvertex3f + 3 * surface->num_firstvertex) + j*3;
4853 VectorCopy((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, vertex);
4854 // if the wavefunc depends on time, evaluate it per-vertex
4857 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
4858 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
4860 VectorMA(vertex, scale, (rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, vertex);
4863 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4864 rsurface.vertex3f_bufferobject = 0;
4865 rsurface.vertex3f_bufferoffset = 0;
4867 case Q3DEFORM_BULGE:
4868 // deform vertex array to make the surface have moving bulges
4869 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4871 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4872 for (j = 0;j < surface->num_vertices;j++)
4874 scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.time * deform->parms[2])) * deform->parms[1];
4875 VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
4878 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4879 rsurface.vertex3f_bufferobject = 0;
4880 rsurface.vertex3f_bufferoffset = 0;
4883 // deform vertex array
4884 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
4885 VectorScale(deform->parms, scale, waveparms);
4886 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4888 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4889 for (j = 0;j < surface->num_vertices;j++)
4890 VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
4892 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4893 rsurface.vertex3f_bufferobject = 0;
4894 rsurface.vertex3f_bufferoffset = 0;
4898 // generate texcoords based on the chosen texcoord source
4899 switch(rsurface.texture->tcgen.tcgen)
4902 case Q3TCGEN_TEXTURE:
4903 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
4904 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordtexture2f_bufferobject;
4905 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
4907 case Q3TCGEN_LIGHTMAP:
4908 rsurface.texcoordtexture2f = rsurface.modeltexcoordlightmap2f;
4909 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
4910 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
4912 case Q3TCGEN_VECTOR:
4913 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4915 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4916 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)
4918 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
4919 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
4922 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
4923 rsurface.texcoordtexture2f_bufferobject = 0;
4924 rsurface.texcoordtexture2f_bufferoffset = 0;
4926 case Q3TCGEN_ENVIRONMENT:
4927 // make environment reflections using a spheremap
4928 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4930 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4931 const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
4932 const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
4933 float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
4934 for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
4936 float l, d, eyedir[3];
4937 VectorSubtract(rsurface.modelorg, vertex, eyedir);
4938 l = 0.5f / VectorLength(eyedir);
4939 d = DotProduct(normal, eyedir)*2;
4940 out_tc[0] = 0.5f + (normal[1]*d - eyedir[1])*l;
4941 out_tc[1] = 0.5f - (normal[2]*d - eyedir[2])*l;
4944 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
4945 rsurface.texcoordtexture2f_bufferobject = 0;
4946 rsurface.texcoordtexture2f_bufferoffset = 0;
4949 // the only tcmod that needs software vertex processing is turbulent, so
4950 // check for it here and apply the changes if needed
4951 // and we only support that as the first one
4952 // (handling a mixture of turbulent and other tcmods would be problematic
4953 // without punting it entirely to a software path)
4954 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
4956 amplitude = rsurface.texture->tcmods[0].parms[1];
4957 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.time * rsurface.texture->tcmods[0].parms[3];
4958 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4960 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4961 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)
4963 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
4964 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
4967 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
4968 rsurface.texcoordtexture2f_bufferobject = 0;
4969 rsurface.texcoordtexture2f_bufferoffset = 0;
4971 rsurface.texcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
4972 rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
4973 rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
4974 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
4977 void RSurf_DrawBatch_Simple(int texturenumsurfaces, msurface_t **texturesurfacelist)
4980 const msurface_t *surface = texturesurfacelist[0];
4981 const msurface_t *surface2;
4986 // TODO: lock all array ranges before render, rather than on each surface
4987 if (texturenumsurfaces == 1)
4989 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
4990 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));
4992 else if (r_batchmode.integer == 2)
4994 #define MAXBATCHTRIANGLES 4096
4995 int batchtriangles = 0;
4996 int batchelements[MAXBATCHTRIANGLES*3];
4997 for (i = 0;i < texturenumsurfaces;i = j)
4999 surface = texturesurfacelist[i];
5001 if (surface->num_triangles > MAXBATCHTRIANGLES)
5003 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));
5006 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
5007 batchtriangles = surface->num_triangles;
5008 firstvertex = surface->num_firstvertex;
5009 endvertex = surface->num_firstvertex + surface->num_vertices;
5010 for (;j < texturenumsurfaces;j++)
5012 surface2 = texturesurfacelist[j];
5013 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
5015 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
5016 batchtriangles += surface2->num_triangles;
5017 firstvertex = min(firstvertex, surface2->num_firstvertex);
5018 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
5020 surface2 = texturesurfacelist[j-1];
5021 numvertices = endvertex - firstvertex;
5022 R_Mesh_Draw(firstvertex, numvertices, batchtriangles, batchelements, 0, 0);
5025 else if (r_batchmode.integer == 1)
5027 for (i = 0;i < texturenumsurfaces;i = j)
5029 surface = texturesurfacelist[i];
5030 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
5031 if (texturesurfacelist[j] != surface2)
5033 surface2 = texturesurfacelist[j-1];
5034 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
5035 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
5036 GL_LockArrays(surface->num_firstvertex, numvertices);
5037 R_Mesh_Draw(surface->num_firstvertex, numvertices, numtriangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
5042 for (i = 0;i < texturenumsurfaces;i++)
5044 surface = texturesurfacelist[i];
5045 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5046 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));
5051 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit, int refractiontexunit, int reflectiontexunit)
5053 int i, planeindex, vertexindex;
5057 r_waterstate_waterplane_t *p, *bestp;
5058 msurface_t *surface;
5059 if (r_waterstate.renderingscene)
5061 for (i = 0;i < texturenumsurfaces;i++)
5063 surface = texturesurfacelist[i];
5064 if (lightmaptexunit >= 0)
5065 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5066 if (deluxemaptexunit >= 0)
5067 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5068 // pick the closest matching water plane
5071 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5074 for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
5076 Matrix4x4_Transform(&rsurface.matrix, v, vert);
5077 d += fabs(PlaneDiff(vert, &p->plane));
5079 if (bestd > d || !bestp)
5087 if (refractiontexunit >= 0)
5088 R_Mesh_TexBind(refractiontexunit, R_GetTexture(bestp->texture_refraction));
5089 if (reflectiontexunit >= 0)
5090 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(bestp->texture_reflection));
5094 if (refractiontexunit >= 0)
5095 R_Mesh_TexBind(refractiontexunit, R_GetTexture(r_texture_black));
5096 if (reflectiontexunit >= 0)
5097 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(r_texture_black));
5099 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5100 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));
5104 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit)
5108 const msurface_t *surface = texturesurfacelist[0];
5109 const msurface_t *surface2;
5114 // TODO: lock all array ranges before render, rather than on each surface
5115 if (texturenumsurfaces == 1)
5117 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5118 if (deluxemaptexunit >= 0)
5119 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5120 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5121 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));
5123 else if (r_batchmode.integer == 2)
5125 #define MAXBATCHTRIANGLES 4096
5126 int batchtriangles = 0;
5127 int batchelements[MAXBATCHTRIANGLES*3];
5128 for (i = 0;i < texturenumsurfaces;i = j)
5130 surface = texturesurfacelist[i];
5131 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5132 if (deluxemaptexunit >= 0)
5133 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5135 if (surface->num_triangles > MAXBATCHTRIANGLES)
5137 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));
5140 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
5141 batchtriangles = surface->num_triangles;
5142 firstvertex = surface->num_firstvertex;
5143 endvertex = surface->num_firstvertex + surface->num_vertices;
5144 for (;j < texturenumsurfaces;j++)
5146 surface2 = texturesurfacelist[j];
5147 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
5149 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
5150 batchtriangles += surface2->num_triangles;
5151 firstvertex = min(firstvertex, surface2->num_firstvertex);
5152 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
5154 surface2 = texturesurfacelist[j-1];
5155 numvertices = endvertex - firstvertex;
5156 R_Mesh_Draw(firstvertex, numvertices, batchtriangles, batchelements, 0, 0);
5159 else if (r_batchmode.integer == 1)
5162 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
5163 for (i = 0;i < texturenumsurfaces;i = j)
5165 surface = texturesurfacelist[i];
5166 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
5167 if (texturesurfacelist[j] != surface2)
5169 Con_Printf(" %i", j - i);
5172 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
5174 for (i = 0;i < texturenumsurfaces;i = j)
5176 surface = texturesurfacelist[i];
5177 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5178 if (deluxemaptexunit >= 0)
5179 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5180 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
5181 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
5184 Con_Printf(" %i", j - i);
5186 surface2 = texturesurfacelist[j-1];
5187 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
5188 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
5189 GL_LockArrays(surface->num_firstvertex, numvertices);
5190 R_Mesh_Draw(surface->num_firstvertex, numvertices, numtriangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
5198 for (i = 0;i < texturenumsurfaces;i++)
5200 surface = texturesurfacelist[i];
5201 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5202 if (deluxemaptexunit >= 0)
5203 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5204 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5205 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));
5210 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
5213 int texturesurfaceindex;
5214 if (r_showsurfaces.integer == 2)
5216 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5218 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5219 for (j = 0;j < surface->num_triangles;j++)
5221 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_view.colorscale;
5222 GL_Color(f, f, f, 1);
5223 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)));
5229 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5231 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5232 int k = (int)(((size_t)surface) / sizeof(msurface_t));
5233 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);
5234 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5235 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));
5240 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, msurface_t **texturesurfacelist)
5242 int texturesurfaceindex;
5246 if (rsurface.lightmapcolor4f)
5248 // generate color arrays for the surfaces in this list
5249 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5251 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5252 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)
5254 f = FogPoint_Model(v);
5264 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5266 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5267 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)
5269 f = FogPoint_Model(v);
5277 rsurface.lightmapcolor4f = rsurface.array_color4f;
5278 rsurface.lightmapcolor4f_bufferobject = 0;
5279 rsurface.lightmapcolor4f_bufferoffset = 0;
5282 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a)
5284 int texturesurfaceindex;
5287 if (!rsurface.lightmapcolor4f)
5289 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5291 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5292 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)
5300 rsurface.lightmapcolor4f = rsurface.array_color4f;
5301 rsurface.lightmapcolor4f_bufferobject = 0;
5302 rsurface.lightmapcolor4f_bufferoffset = 0;
5305 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5308 rsurface.lightmapcolor4f = NULL;
5309 rsurface.lightmapcolor4f_bufferobject = 0;
5310 rsurface.lightmapcolor4f_bufferoffset = 0;
5311 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5312 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5313 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5314 GL_Color(r, g, b, a);
5315 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 0, -1);
5318 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5320 // TODO: optimize applyfog && applycolor case
5321 // just apply fog if necessary, and tint the fog color array if necessary
5322 rsurface.lightmapcolor4f = NULL;
5323 rsurface.lightmapcolor4f_bufferobject = 0;
5324 rsurface.lightmapcolor4f_bufferoffset = 0;
5325 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5326 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5327 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5328 GL_Color(r, g, b, a);
5329 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5332 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5334 int texturesurfaceindex;
5338 if (texturesurfacelist[0]->lightmapinfo && texturesurfacelist[0]->lightmapinfo->stainsamples)
5340 // generate color arrays for the surfaces in this list
5341 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5343 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5344 for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
5346 if (surface->lightmapinfo->samples)
5348 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
5349 float scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
5350 VectorScale(lm, scale, c);
5351 if (surface->lightmapinfo->styles[1] != 255)
5353 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
5355 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
5356 VectorMA(c, scale, lm, c);
5357 if (surface->lightmapinfo->styles[2] != 255)
5360 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
5361 VectorMA(c, scale, lm, c);
5362 if (surface->lightmapinfo->styles[3] != 255)
5365 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
5366 VectorMA(c, scale, lm, c);
5376 rsurface.lightmapcolor4f = rsurface.array_color4f;
5377 rsurface.lightmapcolor4f_bufferobject = 0;
5378 rsurface.lightmapcolor4f_bufferoffset = 0;
5382 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
5383 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
5384 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
5386 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5387 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5388 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5389 GL_Color(r, g, b, a);
5390 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5393 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5395 int texturesurfaceindex;
5399 vec3_t ambientcolor;
5400 vec3_t diffusecolor;
5404 VectorCopy(rsurface.modellight_lightdir, lightdir);
5405 f = 0.5f * r_refdef.lightmapintensity;
5406 ambientcolor[0] = rsurface.modellight_ambient[0] * r * f;
5407 ambientcolor[1] = rsurface.modellight_ambient[1] * g * f;
5408 ambientcolor[2] = rsurface.modellight_ambient[2] * b * f;
5409 diffusecolor[0] = rsurface.modellight_diffuse[0] * r * f;
5410 diffusecolor[1] = rsurface.modellight_diffuse[1] * g * f;
5411 diffusecolor[2] = rsurface.modellight_diffuse[2] * b * f;
5412 if (VectorLength2(diffusecolor) > 0)
5414 // generate color arrays for the surfaces in this list
5415 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5417 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5418 int numverts = surface->num_vertices;
5419 v = rsurface.vertex3f + 3 * surface->num_firstvertex;
5420 c2 = rsurface.normal3f + 3 * surface->num_firstvertex;
5421 c = rsurface.array_color4f + 4 * surface->num_firstvertex;
5422 // q3-style directional shading
5423 for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
5425 if ((f = DotProduct(c2, lightdir)) > 0)
5426 VectorMA(ambientcolor, f, diffusecolor, c);
5428 VectorCopy(ambientcolor, c);
5437 rsurface.lightmapcolor4f = rsurface.array_color4f;
5438 rsurface.lightmapcolor4f_bufferobject = 0;
5439 rsurface.lightmapcolor4f_bufferoffset = 0;
5443 r = ambientcolor[0];
5444 g = ambientcolor[1];
5445 b = ambientcolor[2];
5446 rsurface.lightmapcolor4f = NULL;
5447 rsurface.lightmapcolor4f_bufferobject = 0;
5448 rsurface.lightmapcolor4f_bufferoffset = 0;
5450 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5451 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5452 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5453 GL_Color(r, g, b, a);
5454 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5457 void RSurf_SetupDepthAndCulling(void)
5459 // submodels are biased to avoid z-fighting with world surfaces that they
5460 // may be exactly overlapping (avoids z-fighting artifacts on certain
5461 // doors and things in Quake maps)
5462 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5463 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
5464 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
5465 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_view.cullface_back);
5468 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
5470 RSurf_SetupDepthAndCulling();
5471 if (rsurface.mode != RSURFMODE_SHOWSURFACES)
5473 rsurface.mode = RSURFMODE_SHOWSURFACES;
5475 GL_BlendFunc(GL_ONE, GL_ZERO);
5476 R_Mesh_ColorPointer(NULL, 0, 0);
5477 R_Mesh_ResetTextureState();
5479 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
5480 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
5483 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, msurface_t **texturesurfacelist)
5485 // transparent sky would be ridiculous
5486 if ((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED))
5488 if (rsurface.mode != RSURFMODE_SKY)
5490 if (rsurface.mode == RSURFMODE_GLSL)
5492 qglUseProgramObjectARB(0);CHECKGLERROR
5494 rsurface.mode = RSURFMODE_SKY;
5498 skyrendernow = false;
5500 // restore entity matrix
5501 R_Mesh_Matrix(&rsurface.matrix);
5503 RSurf_SetupDepthAndCulling();
5505 // LordHavoc: HalfLife maps have freaky skypolys so don't use
5506 // skymasking on them, and Quake3 never did sky masking (unlike
5507 // software Quake and software Quake2), so disable the sky masking
5508 // in Quake3 maps as it causes problems with q3map2 sky tricks,
5509 // and skymasking also looks very bad when noclipping outside the
5510 // level, so don't use it then either.
5511 if (r_refdef.worldmodel && r_refdef.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_viewcache.world_novis)
5513 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
5514 R_Mesh_ColorPointer(NULL, 0, 0);
5515 R_Mesh_ResetTextureState();
5516 if (skyrendermasked)
5518 // depth-only (masking)
5519 GL_ColorMask(0,0,0,0);
5520 // just to make sure that braindead drivers don't draw
5521 // anything despite that colormask...
5522 GL_BlendFunc(GL_ZERO, GL_ONE);
5527 GL_BlendFunc(GL_ONE, GL_ZERO);
5529 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
5530 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5531 if (skyrendermasked)
5532 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
5536 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, msurface_t **texturesurfacelist)
5538 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION)))
5541 if (rsurface.mode != RSURFMODE_GLSL)
5543 rsurface.mode = RSURFMODE_GLSL;
5544 R_Mesh_ResetTextureState();
5545 GL_Color(1, 1, 1, 1);
5548 R_Mesh_TexMatrix(0, &rsurface.texture->currenttexmatrix);
5549 R_Mesh_TexBind(0, R_GetTexture(rsurface.texture->currentskinframe->nmap));
5550 R_Mesh_TexBind(1, R_GetTexture(rsurface.texture->basetexture));
5551 R_Mesh_TexBind(2, R_GetTexture(rsurface.texture->glosstexture));
5552 R_Mesh_TexBind(4, R_GetTexture(r_texture_fogattenuation));
5553 R_Mesh_TexBind(5, R_GetTexture(rsurface.texture->currentskinframe->pants));
5554 R_Mesh_TexBind(6, R_GetTexture(rsurface.texture->currentskinframe->shirt));
5555 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
5557 R_Mesh_TexBind(7, R_GetTexture(r_texture_grey128));
5558 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
5559 R_Mesh_ColorPointer(NULL, 0, 0);
5561 else if (rsurface.uselightmaptexture)
5563 R_Mesh_TexBind(7, R_GetTexture(texturesurfacelist[0]->lightmaptexture));
5564 R_Mesh_TexBind(8, R_GetTexture(texturesurfacelist[0]->deluxemaptexture));
5565 R_Mesh_ColorPointer(NULL, 0, 0);
5569 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
5570 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
5571 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
5573 R_Mesh_TexBind(9, R_GetTexture(rsurface.texture->currentskinframe->glow));
5574 R_Mesh_TexBind(11, R_GetTexture(r_texture_white)); // changed per surface
5575 R_Mesh_TexBind(12, R_GetTexture(r_texture_white)); // changed per surface
5577 if (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5579 // render background
5580 GL_BlendFunc(GL_ONE, GL_ZERO);
5582 GL_AlphaTest(false);
5584 GL_Color(1, 1, 1, 1);
5585 R_Mesh_ColorPointer(NULL, 0, 0);
5587 R_SetupSurfaceShader(vec3_origin, rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
5588 if (r_glsl_permutation)
5590 RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
5591 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
5592 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
5593 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
5594 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
5595 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
5596 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist, -1, -1, r_glsl_permutation->loc_Texture_Refraction ? 11 : -1, r_glsl_permutation->loc_Texture_Reflection ? 12 : -1);
5599 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5600 GL_DepthMask(false);
5601 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5602 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
5604 R_Mesh_TexBind(7, R_GetTexture(r_texture_grey128));
5605 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
5606 R_Mesh_ColorPointer(NULL, 0, 0);
5608 else if (rsurface.uselightmaptexture)
5610 R_Mesh_TexBind(7, R_GetTexture(texturesurfacelist[0]->lightmaptexture));
5611 R_Mesh_TexBind(8, R_GetTexture(texturesurfacelist[0]->deluxemaptexture));
5612 R_Mesh_ColorPointer(NULL, 0, 0);
5616 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
5617 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
5618 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
5620 R_Mesh_TexBind(11, R_GetTexture(r_texture_white)); // changed per surface
5621 R_Mesh_TexBind(12, R_GetTexture(r_texture_white)); // changed per surface
5624 R_SetupSurfaceShader(vec3_origin, rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE);
5625 if (!r_glsl_permutation)
5628 RSurf_PrepareVerticesForBatch(r_glsl_permutation->loc_Texture_Normal >= 0 || r_glsl_permutation->loc_LightDir >= 0, r_glsl_permutation->loc_Texture_Normal >= 0, texturenumsurfaces, texturesurfacelist);
5629 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
5630 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
5631 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
5632 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
5633 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
5635 if (r_glsl_permutation->loc_Texture_Refraction >= 0)
5637 GL_BlendFunc(GL_ONE, GL_ZERO);
5639 GL_AlphaTest(false);
5642 if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
5644 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
5645 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);
5647 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 7, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? 8 : -1);
5651 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
5652 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);
5654 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5656 if (rsurface.texture->backgroundnumskinframes && !(rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED))
5661 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, msurface_t **texturesurfacelist)
5663 // OpenGL 1.3 path - anything not completely ancient
5664 int texturesurfaceindex;
5665 qboolean applycolor;
5669 const texturelayer_t *layer;
5670 if (rsurface.mode != RSURFMODE_MULTIPASS)
5671 rsurface.mode = RSURFMODE_MULTIPASS;
5672 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
5674 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
5677 int layertexrgbscale;
5678 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5680 if (layerindex == 0)
5684 GL_AlphaTest(false);
5685 qglDepthFunc(GL_EQUAL);CHECKGLERROR
5688 GL_DepthMask(layer->depthmask);
5689 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
5690 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
5692 layertexrgbscale = 4;
5693 VectorScale(layer->color, 0.25f, layercolor);
5695 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
5697 layertexrgbscale = 2;
5698 VectorScale(layer->color, 0.5f, layercolor);
5702 layertexrgbscale = 1;
5703 VectorScale(layer->color, 1.0f, layercolor);
5705 layercolor[3] = layer->color[3];
5706 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
5707 R_Mesh_ColorPointer(NULL, 0, 0);
5708 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
5709 switch (layer->type)
5711 case TEXTURELAYERTYPE_LITTEXTURE:
5712 memset(&m, 0, sizeof(m));
5713 m.tex[0] = R_GetTexture(r_texture_white);
5714 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
5715 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
5716 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
5717 m.tex[1] = R_GetTexture(layer->texture);
5718 m.texmatrix[1] = layer->texmatrix;
5719 m.texrgbscale[1] = layertexrgbscale;
5720 m.pointer_texcoord[1] = rsurface.texcoordtexture2f;
5721 m.pointer_texcoord_bufferobject[1] = rsurface.texcoordtexture2f_bufferobject;
5722 m.pointer_texcoord_bufferoffset[1] = rsurface.texcoordtexture2f_bufferoffset;
5723 R_Mesh_TextureState(&m);
5724 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
5725 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
5726 else if (rsurface.uselightmaptexture)
5727 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
5729 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
5731 case TEXTURELAYERTYPE_TEXTURE:
5732 memset(&m, 0, sizeof(m));
5733 m.tex[0] = R_GetTexture(layer->texture);
5734 m.texmatrix[0] = layer->texmatrix;
5735 m.texrgbscale[0] = layertexrgbscale;
5736 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5737 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5738 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5739 R_Mesh_TextureState(&m);
5740 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
5742 case TEXTURELAYERTYPE_FOG:
5743 memset(&m, 0, sizeof(m));
5744 m.texrgbscale[0] = layertexrgbscale;
5747 m.tex[0] = R_GetTexture(layer->texture);
5748 m.texmatrix[0] = layer->texmatrix;
5749 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5750 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5751 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5753 R_Mesh_TextureState(&m);
5754 // generate a color array for the fog pass
5755 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
5756 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5760 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5761 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)
5763 f = 1 - FogPoint_Model(v);
5764 c[0] = layercolor[0];
5765 c[1] = layercolor[1];
5766 c[2] = layercolor[2];
5767 c[3] = f * layercolor[3];
5770 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5773 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
5775 GL_LockArrays(0, 0);
5778 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5780 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
5781 GL_AlphaTest(false);
5785 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, msurface_t **texturesurfacelist)
5787 // OpenGL 1.1 - crusty old voodoo path
5788 int texturesurfaceindex;
5792 const texturelayer_t *layer;
5793 if (rsurface.mode != RSURFMODE_MULTIPASS)
5794 rsurface.mode = RSURFMODE_MULTIPASS;
5795 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
5797 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
5799 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5801 if (layerindex == 0)
5805 GL_AlphaTest(false);
5806 qglDepthFunc(GL_EQUAL);CHECKGLERROR
5809 GL_DepthMask(layer->depthmask);
5810 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
5811 R_Mesh_ColorPointer(NULL, 0, 0);
5812 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
5813 switch (layer->type)
5815 case TEXTURELAYERTYPE_LITTEXTURE:
5816 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
5818 // two-pass lit texture with 2x rgbscale
5819 // first the lightmap pass
5820 memset(&m, 0, sizeof(m));
5821 m.tex[0] = R_GetTexture(r_texture_white);
5822 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
5823 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
5824 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
5825 R_Mesh_TextureState(&m);
5826 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
5827 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5828 else if (rsurface.uselightmaptexture)
5829 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5831 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5832 GL_LockArrays(0, 0);
5833 // then apply the texture to it
5834 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
5835 memset(&m, 0, sizeof(m));
5836 m.tex[0] = R_GetTexture(layer->texture);
5837 m.texmatrix[0] = layer->texmatrix;
5838 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5839 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5840 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5841 R_Mesh_TextureState(&m);
5842 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);
5846 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
5847 memset(&m, 0, sizeof(m));
5848 m.tex[0] = R_GetTexture(layer->texture);
5849 m.texmatrix[0] = layer->texmatrix;
5850 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5851 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5852 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5853 R_Mesh_TextureState(&m);
5854 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
5855 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);
5857 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);
5860 case TEXTURELAYERTYPE_TEXTURE:
5861 // singletexture unlit texture with transparency support
5862 memset(&m, 0, sizeof(m));
5863 m.tex[0] = R_GetTexture(layer->texture);
5864 m.texmatrix[0] = layer->texmatrix;
5865 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5866 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5867 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5868 R_Mesh_TextureState(&m);
5869 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);
5871 case TEXTURELAYERTYPE_FOG:
5872 // singletexture fogging
5873 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
5876 memset(&m, 0, sizeof(m));
5877 m.tex[0] = R_GetTexture(layer->texture);
5878 m.texmatrix[0] = layer->texmatrix;
5879 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5880 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5881 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5882 R_Mesh_TextureState(&m);
5885 R_Mesh_ResetTextureState();
5886 // generate a color array for the fog pass
5887 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5891 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5892 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)
5894 f = 1 - FogPoint_Model(v);
5895 c[0] = layer->color[0];
5896 c[1] = layer->color[1];
5897 c[2] = layer->color[2];
5898 c[3] = f * layer->color[3];
5901 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5904 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
5906 GL_LockArrays(0, 0);
5909 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5911 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
5912 GL_AlphaTest(false);
5916 static void R_DrawTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly)
5918 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW)
5920 rsurface.rtlight = NULL;
5924 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
5926 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
5928 if (rsurface.mode != RSURFMODE_MULTIPASS)
5929 rsurface.mode = RSURFMODE_MULTIPASS;
5930 if (r_depthfirst.integer == 3)
5932 int i = (int)(texturesurfacelist[0] - rsurface.modelsurfaces);
5933 if (!r_view.showdebug)
5934 GL_Color(0, 0, 0, 1);
5936 GL_Color(((i >> 6) & 7) / 7.0f, ((i >> 3) & 7) / 7.0f, (i & 7) / 7.0f,1);
5940 GL_ColorMask(0,0,0,0);
5943 RSurf_SetupDepthAndCulling();
5945 GL_BlendFunc(GL_ONE, GL_ZERO);
5947 GL_AlphaTest(false);
5948 R_Mesh_ColorPointer(NULL, 0, 0);
5949 R_Mesh_ResetTextureState();
5950 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
5951 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5952 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
5954 else if (r_depthfirst.integer == 3)
5956 else if (!r_view.showdebug && (r_showsurfaces.integer || gl_lightmaps.integer))
5958 GL_Color(0, 0, 0, 1);
5959 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5961 else if (r_showsurfaces.integer)
5963 if (rsurface.mode != RSURFMODE_MULTIPASS)
5964 rsurface.mode = RSURFMODE_MULTIPASS;
5965 RSurf_SetupDepthAndCulling();
5967 GL_BlendFunc(GL_ONE, GL_ZERO);
5968 GL_DepthMask(writedepth);
5970 GL_AlphaTest(false);
5971 R_Mesh_ColorPointer(NULL, 0, 0);
5972 R_Mesh_ResetTextureState();
5973 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
5974 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
5976 else if (gl_lightmaps.integer)
5979 if (rsurface.mode != RSURFMODE_MULTIPASS)
5980 rsurface.mode = RSURFMODE_MULTIPASS;
5981 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5983 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_view.cullface_back);
5984 GL_BlendFunc(GL_ONE, GL_ZERO);
5985 GL_DepthMask(writedepth);
5987 GL_AlphaTest(false);
5988 R_Mesh_ColorPointer(NULL, 0, 0);
5989 memset(&m, 0, sizeof(m));
5990 m.tex[0] = R_GetTexture(r_texture_white);
5991 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
5992 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
5993 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
5994 R_Mesh_TextureState(&m);
5995 RSurf_PrepareVerticesForBatch(rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT, false, texturenumsurfaces, texturesurfacelist);
5996 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
5997 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5998 else if (rsurface.uselightmaptexture)
5999 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
6001 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
6003 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
6004 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
6005 else if (rsurface.texture->currentnumlayers)
6007 // write depth for anything we skipped on the depth-only pass earlier
6008 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
6010 RSurf_SetupDepthAndCulling();
6011 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
6012 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
6013 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
6014 if (r_glsl.integer && gl_support_fragment_shader)
6015 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist);
6016 else if (gl_combine.integer && r_textureunits.integer >= 2)
6017 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist);
6019 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist);
6022 GL_LockArrays(0, 0);
6025 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6028 int texturenumsurfaces, endsurface;
6030 msurface_t *surface;
6031 msurface_t *texturesurfacelist[1024];
6033 // if the model is static it doesn't matter what value we give for
6034 // wantnormals and wanttangents, so this logic uses only rules applicable
6035 // to a model, knowing that they are meaningless otherwise
6036 if (ent == r_refdef.worldentity)
6037 RSurf_ActiveWorldEntity();
6038 else if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
6039 RSurf_ActiveModelEntity(ent, false, false);
6041 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
6043 for (i = 0;i < numsurfaces;i = j)
6046 surface = rsurface.modelsurfaces + surfacelist[i];
6047 texture = surface->texture;
6048 R_UpdateTextureInfo(ent, texture);
6049 rsurface.texture = texture->currentframe;
6050 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
6051 // scan ahead until we find a different texture
6052 endsurface = min(i + 1024, numsurfaces);
6053 texturenumsurfaces = 0;
6054 texturesurfacelist[texturenumsurfaces++] = surface;
6055 for (;j < endsurface;j++)
6057 surface = rsurface.modelsurfaces + surfacelist[j];
6058 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
6060 texturesurfacelist[texturenumsurfaces++] = surface;
6062 // render the range of surfaces
6063 R_DrawTextureSurfaceList(texturenumsurfaces, texturesurfacelist, true, false);
6069 void R_QueueSurfaceList(entity_render_t *ent, int numsurfaces, msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes)
6072 vec3_t tempcenter, center;
6074 // if we're rendering water textures (extra scene renders), use a separate loop to avoid burdening the main one
6077 for (i = 0;i < numsurfaces;i++)
6078 if (surfacelist[i]->texture->currentframe->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION))
6079 R_Water_AddWaterPlane(surfacelist[i]);
6082 // break the surface list down into batches by texture and use of lightmapping
6083 for (i = 0;i < numsurfaces;i = j)
6086 // texture is the base texture pointer, rsurface.texture is the
6087 // current frame/skin the texture is directing us to use (for example
6088 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
6089 // use skin 1 instead)
6090 texture = surfacelist[i]->texture;
6091 rsurface.texture = texture->currentframe;
6092 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
6093 if (!(rsurface.texture->currentmaterialflags & flagsmask))
6095 // if this texture is not the kind we want, skip ahead to the next one
6096 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
6100 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
6102 // transparent surfaces get pushed off into the transparent queue
6103 const msurface_t *surface = surfacelist[i];
6106 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
6107 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
6108 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
6109 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
6110 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_view.origin : center, R_DrawSurface_TransparentCallback, ent, surface - rsurface.modelsurfaces, rsurface.rtlight);
6114 // simply scan ahead until we find a different texture or lightmap state
6115 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
6117 // render the range of surfaces
6118 R_DrawTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly);
6123 float locboxvertex3f[6*4*3] =
6125 1,0,1, 1,0,0, 1,1,0, 1,1,1,
6126 0,1,1, 0,1,0, 0,0,0, 0,0,1,
6127 1,1,1, 1,1,0, 0,1,0, 0,1,1,
6128 0,0,1, 0,0,0, 1,0,0, 1,0,1,
6129 0,0,1, 1,0,1, 1,1,1, 0,1,1,
6130 1,0,0, 0,0,0, 0,1,0, 1,1,0
6133 int locboxelement3i[6*2*3] =
6143 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6146 cl_locnode_t *loc = (cl_locnode_t *)ent;
6148 float vertex3f[6*4*3];
6150 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6151 GL_DepthMask(false);
6152 GL_DepthRange(0, 1);
6153 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6155 GL_CullFace(GL_NONE);
6156 R_Mesh_Matrix(&identitymatrix);
6158 R_Mesh_VertexPointer(vertex3f, 0, 0);
6159 R_Mesh_ColorPointer(NULL, 0, 0);
6160 R_Mesh_ResetTextureState();
6163 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_view.colorscale,
6164 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_view.colorscale,
6165 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_view.colorscale,
6166 surfacelist[0] < 0 ? 0.5f : 0.125f);
6168 if (VectorCompare(loc->mins, loc->maxs))
6170 VectorSet(size, 2, 2, 2);
6171 VectorMA(loc->mins, -0.5f, size, mins);
6175 VectorCopy(loc->mins, mins);
6176 VectorSubtract(loc->maxs, loc->mins, size);
6179 for (i = 0;i < 6*4*3;)
6180 for (j = 0;j < 3;j++, i++)
6181 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
6183 R_Mesh_Draw(0, 6*4, 6*2, locboxelement3i, 0, 0);
6186 void R_DrawLocs(void)
6189 cl_locnode_t *loc, *nearestloc;
6191 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
6192 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
6194 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
6195 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
6199 void R_DrawDebugModel(entity_render_t *ent)
6201 int i, j, k, l, flagsmask;
6202 const int *elements;
6204 msurface_t *surface;
6205 model_t *model = ent->model;
6208 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WATER | MATERIALFLAG_WALL;
6210 R_Mesh_ColorPointer(NULL, 0, 0);
6211 R_Mesh_ResetTextureState();
6212 GL_DepthRange(0, 1);
6213 GL_DepthTest(!r_showdisabledepthtest.integer);
6214 GL_DepthMask(false);
6215 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6217 if (r_showcollisionbrushes.value > 0 && model->brush.num_brushes)
6219 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
6220 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
6222 if (brush->colbrushf && brush->colbrushf->numtriangles)
6224 R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
6225 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);
6226 R_Mesh_Draw(0, brush->colbrushf->numpoints, brush->colbrushf->numtriangles, brush->colbrushf->elements, 0, 0);
6229 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
6231 if (surface->num_collisiontriangles)
6233 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
6234 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);
6235 R_Mesh_Draw(0, surface->num_collisionvertices, surface->num_collisiontriangles, surface->data_collisionelement3i, 0, 0);
6240 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6242 if (r_showtris.integer || r_shownormals.integer)
6244 if (r_showdisabledepthtest.integer)
6246 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6247 GL_DepthMask(false);
6251 GL_BlendFunc(GL_ONE, GL_ZERO);
6254 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
6256 if (ent == r_refdef.worldentity && !r_viewcache.world_surfacevisible[j])
6258 rsurface.texture = surface->texture->currentframe;
6259 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
6261 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
6262 if (r_showtris.value > 0)
6264 if (!rsurface.texture->currentlayers->depthmask)
6265 GL_Color(r_view.colorscale, 0, 0, r_showtris.value);
6266 else if (ent == r_refdef.worldentity)
6267 GL_Color(r_view.colorscale, r_view.colorscale, r_view.colorscale, r_showtris.value);
6269 GL_Color(0, r_view.colorscale, 0, r_showtris.value);
6270 elements = (ent->model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
6273 for (k = 0;k < surface->num_triangles;k++, elements += 3)
6275 #define GLVERTEXELEMENT(n) qglVertex3f(rsurface.vertex3f[elements[n]*3+0], rsurface.vertex3f[elements[n]*3+1], rsurface.vertex3f[elements[n]*3+2])
6276 GLVERTEXELEMENT(0);GLVERTEXELEMENT(1);
6277 GLVERTEXELEMENT(1);GLVERTEXELEMENT(2);
6278 GLVERTEXELEMENT(2);GLVERTEXELEMENT(0);
6283 if (r_shownormals.value > 0)
6286 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
6288 VectorCopy(rsurface.vertex3f + l * 3, v);
6289 GL_Color(r_view.colorscale, 0, 0, 1);
6290 qglVertex3f(v[0], v[1], v[2]);
6291 VectorMA(v, r_shownormals.value, rsurface.svector3f + l * 3, v);
6292 GL_Color(r_view.colorscale, 1, 1, 1);
6293 qglVertex3f(v[0], v[1], v[2]);
6298 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
6300 VectorCopy(rsurface.vertex3f + l * 3, v);
6301 GL_Color(0, r_view.colorscale, 0, 1);
6302 qglVertex3f(v[0], v[1], v[2]);
6303 VectorMA(v, r_shownormals.value, rsurface.tvector3f + l * 3, v);
6304 GL_Color(r_view.colorscale, 1, 1, 1);
6305 qglVertex3f(v[0], v[1], v[2]);
6310 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
6312 VectorCopy(rsurface.vertex3f + l * 3, v);
6313 GL_Color(0, 0, r_view.colorscale, 1);
6314 qglVertex3f(v[0], v[1], v[2]);
6315 VectorMA(v, r_shownormals.value, rsurface.normal3f + l * 3, v);
6316 GL_Color(r_view.colorscale, 1, 1, 1);
6317 qglVertex3f(v[0], v[1], v[2]);
6324 rsurface.texture = NULL;
6328 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
6329 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes, qboolean debug)
6331 int i, j, endj, f, flagsmask;
6332 msurface_t *surface;
6334 model_t *model = r_refdef.worldmodel;
6335 const int maxsurfacelist = 1024;
6336 int numsurfacelist = 0;
6337 msurface_t *surfacelist[1024];
6341 RSurf_ActiveWorldEntity();
6343 // update light styles on this submodel
6344 if (!skysurfaces && !depthonly && !addwaterplanes && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
6346 model_brush_lightstyleinfo_t *style;
6347 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
6349 if (style->value != r_refdef.lightstylevalue[style->style])
6351 msurface_t *surfaces = model->data_surfaces;
6352 int *list = style->surfacelist;
6353 style->value = r_refdef.lightstylevalue[style->style];
6354 for (j = 0;j < style->numsurfaces;j++)
6355 surfaces[list[j]].cached_dlight = true;
6360 R_UpdateAllTextureInfo(r_refdef.worldentity);
6361 flagsmask = addwaterplanes ? (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) : (skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL));
6365 R_DrawDebugModel(r_refdef.worldentity);
6371 rsurface.uselightmaptexture = false;
6372 rsurface.texture = NULL;
6374 j = model->firstmodelsurface;
6375 endj = j + model->nummodelsurfaces;
6378 // quickly skip over non-visible surfaces
6379 for (;j < endj && !r_viewcache.world_surfacevisible[j];j++)
6381 // quickly iterate over visible surfaces
6382 for (;j < endj && r_viewcache.world_surfacevisible[j];j++)
6384 // process this surface
6385 surface = model->data_surfaces + j;
6386 // if this surface fits the criteria, add it to the list
6387 if (surface->num_triangles)
6389 // if lightmap parameters changed, rebuild lightmap texture
6390 if (surface->cached_dlight)
6391 R_BuildLightMap(r_refdef.worldentity, surface);
6392 // add face to draw list
6393 surfacelist[numsurfacelist++] = surface;
6394 r_refdef.stats.world_triangles += surface->num_triangles;
6395 if (numsurfacelist >= maxsurfacelist)
6397 r_refdef.stats.world_surfaces += numsurfacelist;
6398 R_QueueSurfaceList(r_refdef.worldentity, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
6404 r_refdef.stats.world_surfaces += numsurfacelist;
6406 R_QueueSurfaceList(r_refdef.worldentity, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
6410 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes, qboolean debug)
6412 int i, j, f, flagsmask;
6413 msurface_t *surface, *endsurface;
6415 model_t *model = ent->model;
6416 const int maxsurfacelist = 1024;
6417 int numsurfacelist = 0;
6418 msurface_t *surfacelist[1024];
6422 // if the model is static it doesn't matter what value we give for
6423 // wantnormals and wanttangents, so this logic uses only rules applicable
6424 // to a model, knowing that they are meaningless otherwise
6425 if (ent == r_refdef.worldentity)
6426 RSurf_ActiveWorldEntity();
6427 else if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
6428 RSurf_ActiveModelEntity(ent, false, false);
6430 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader && !depthonly);
6432 // update light styles
6433 if (!skysurfaces && !depthonly && !addwaterplanes && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
6435 model_brush_lightstyleinfo_t *style;
6436 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
6438 if (style->value != r_refdef.lightstylevalue[style->style])
6440 msurface_t *surfaces = model->data_surfaces;
6441 int *list = style->surfacelist;
6442 style->value = r_refdef.lightstylevalue[style->style];
6443 for (j = 0;j < style->numsurfaces;j++)
6444 surfaces[list[j]].cached_dlight = true;
6449 R_UpdateAllTextureInfo(ent);
6450 flagsmask = addwaterplanes ? (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) : (skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL));
6454 R_DrawDebugModel(ent);
6460 rsurface.uselightmaptexture = false;
6461 rsurface.texture = NULL;
6463 surface = model->data_surfaces + model->firstmodelsurface;
6464 endsurface = surface + model->nummodelsurfaces;
6465 for (;surface < endsurface;surface++)
6467 // if this surface fits the criteria, add it to the list
6468 if (surface->num_triangles)
6470 // if lightmap parameters changed, rebuild lightmap texture
6471 if (surface->cached_dlight)
6472 R_BuildLightMap(ent, surface);
6473 // add face to draw list
6474 surfacelist[numsurfacelist++] = surface;
6475 r_refdef.stats.entities_triangles += surface->num_triangles;
6476 if (numsurfacelist >= maxsurfacelist)
6478 r_refdef.stats.entities_surfaces += numsurfacelist;
6479 R_QueueSurfaceList(ent, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
6484 r_refdef.stats.entities_surfaces += numsurfacelist;
6486 R_QueueSurfaceList(ent, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);