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 Con_Printf("%f ", d);
415 if (r_fog_exp2.integer)
416 alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
418 alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
419 Con_Printf(" : %f ", alpha);
420 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
421 Con_Printf(" = %f\n", alpha);
422 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
425 for (x = 0;x < FOGWIDTH;x++)
427 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
432 //data2[x][0] = 255 - b;
433 //data2[x][1] = 255 - b;
434 //data2[x][2] = 255 - b;
437 if (r_texture_fogattenuation)
439 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, FOGWIDTH, 1);
440 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, FOGWIDTH, 1);
444 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);
445 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
449 static const char *builtinshaderstring =
450 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
451 "// written by Forest 'LordHavoc' Hale\n"
453 "// common definitions between vertex shader and fragment shader:\n"
455 "#ifdef __GLSL_CG_DATA_TYPES\n"
456 "# define myhalf half\n"
457 "# define myhvec2 hvec2\n"
458 "# define myhvec3 hvec3\n"
459 "# define myhvec4 hvec4\n"
461 "# define myhalf float\n"
462 "# define myhvec2 vec2\n"
463 "# define myhvec3 vec3\n"
464 "# define myhvec4 vec4\n"
467 "varying vec2 TexCoord;\n"
468 "varying vec2 TexCoordLightmap;\n"
470 "//#ifdef MODE_LIGHTSOURCE\n"
471 "varying vec3 CubeVector;\n"
474 "//#ifdef MODE_LIGHTSOURCE\n"
475 "varying vec3 LightVector;\n"
477 "//# ifdef MODE_LIGHTDIRECTION\n"
478 "//varying vec3 LightVector;\n"
482 "varying vec3 EyeVector;\n"
484 "varying vec3 EyeVectorModelSpace;\n"
487 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
488 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
489 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
491 "//#ifdef MODE_WATER\n"
492 "varying vec4 ModelViewProjectionPosition;\n"
494 "//# ifdef MODE_REFRACTION\n"
495 "//varying vec4 ModelViewProjectionPosition;\n"
497 "//# ifdef USEREFLECTION\n"
498 "//varying vec4 ModelViewProjectionPosition;\n"
507 "// vertex shader specific:\n"
508 "#ifdef VERTEX_SHADER\n"
510 "uniform vec3 LightPosition;\n"
511 "uniform vec3 EyePosition;\n"
512 "uniform vec3 LightDir;\n"
514 "// TODO: get rid of tangentt (texcoord2) and use a crossproduct to regenerate it from tangents (texcoord1) and normal (texcoord3)\n"
518 " gl_FrontColor = gl_Color;\n"
519 " // copy the surface texcoord\n"
520 " TexCoord = vec2(gl_TextureMatrix[0] * gl_MultiTexCoord0);\n"
521 "#ifndef MODE_LIGHTSOURCE\n"
522 "# ifndef MODE_LIGHTDIRECTION\n"
523 " TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
527 "#ifdef MODE_LIGHTSOURCE\n"
528 " // transform vertex position into light attenuation/cubemap space\n"
529 " // (-1 to +1 across the light box)\n"
530 " CubeVector = vec3(gl_TextureMatrix[3] * gl_Vertex);\n"
532 " // transform unnormalized light direction into tangent space\n"
533 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
534 " // normalize it per pixel)\n"
535 " vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
536 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
537 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
538 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
541 "#ifdef MODE_LIGHTDIRECTION\n"
542 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
543 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
544 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
547 " // transform unnormalized eye direction into tangent space\n"
549 " vec3 EyeVectorModelSpace;\n"
551 " EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
552 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
553 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
554 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
556 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
557 " VectorS = gl_MultiTexCoord1.xyz;\n"
558 " VectorT = gl_MultiTexCoord2.xyz;\n"
559 " VectorR = gl_MultiTexCoord3.xyz;\n"
562 "//#if defined(MODE_WATER) || defined(MODE_REFRACTION) || defined(USEREFLECTION)\n"
563 "// ModelViewProjectionPosition = gl_Vertex * gl_ModelViewProjectionMatrix;\n"
564 "// //ModelViewProjectionPosition_svector = (gl_Vertex + vec4(gl_MultiTexCoord1.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
565 "// //ModelViewProjectionPosition_tvector = (gl_Vertex + vec4(gl_MultiTexCoord2.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
568 "// transform vertex to camera space, using ftransform to match non-VS\n"
570 " gl_Position = ftransform();\n"
572 "#ifdef MODE_WATER\n"
573 " ModelViewProjectionPosition = gl_Position;\n"
575 "#ifdef MODE_REFRACTION\n"
576 " ModelViewProjectionPosition = gl_Position;\n"
578 "#ifdef USEREFLECTION\n"
579 " ModelViewProjectionPosition = gl_Position;\n"
583 "#endif // VERTEX_SHADER\n"
588 "// fragment shader specific:\n"
589 "#ifdef FRAGMENT_SHADER\n"
591 "// 13 textures, we can only use up to 16 on DX9-class hardware\n"
592 "uniform sampler2D Texture_Normal;\n"
593 "uniform sampler2D Texture_Color;\n"
594 "uniform sampler2D Texture_Gloss;\n"
595 "uniform samplerCube Texture_Cube;\n"
596 "uniform sampler2D Texture_Attenuation;\n"
597 "uniform sampler2D Texture_FogMask;\n"
598 "uniform sampler2D Texture_Pants;\n"
599 "uniform sampler2D Texture_Shirt;\n"
600 "uniform sampler2D Texture_Lightmap;\n"
601 "uniform sampler2D Texture_Deluxemap;\n"
602 "uniform sampler2D Texture_Glow;\n"
603 "uniform sampler2D Texture_Reflection;\n"
604 "uniform sampler2D Texture_Refraction;\n"
606 "uniform myhvec3 LightColor;\n"
607 "uniform myhvec3 AmbientColor;\n"
608 "uniform myhvec3 DiffuseColor;\n"
609 "uniform myhvec3 SpecularColor;\n"
610 "uniform myhvec3 Color_Pants;\n"
611 "uniform myhvec3 Color_Shirt;\n"
612 "uniform myhvec3 FogColor;\n"
614 "uniform myhvec4 TintColor;\n"
617 "//#ifdef MODE_WATER\n"
618 "uniform vec4 DistortScaleRefractReflect;\n"
619 "uniform vec4 ScreenScaleRefractReflect;\n"
620 "uniform vec4 ScreenCenterRefractReflect;\n"
621 "uniform myhvec4 RefractColor;\n"
622 "uniform myhvec4 ReflectColor;\n"
623 "uniform myhalf ReflectFactor;\n"
624 "uniform myhalf ReflectOffset;\n"
626 "//# ifdef MODE_REFRACTION\n"
627 "//uniform vec4 DistortScaleRefractReflect;\n"
628 "//uniform vec4 ScreenScaleRefractReflect;\n"
629 "//uniform vec4 ScreenCenterRefractReflect;\n"
630 "//uniform myhvec4 RefractColor;\n"
631 "//# ifdef USEREFLECTION\n"
632 "//uniform myhvec4 ReflectColor;\n"
635 "//# ifdef USEREFLECTION\n"
636 "//uniform vec4 DistortScaleRefractReflect;\n"
637 "//uniform vec4 ScreenScaleRefractReflect;\n"
638 "//uniform vec4 ScreenCenterRefractReflect;\n"
639 "//uniform myhvec4 ReflectColor;\n"
644 "uniform myhalf GlowScale;\n"
645 "uniform myhalf SceneBrightness;\n"
646 "#ifdef USECONTRASTBOOST\n"
647 "uniform myhalf ContrastBoostCoeff;\n"
650 "uniform float OffsetMapping_Scale;\n"
651 "uniform float OffsetMapping_Bias;\n"
652 "uniform float FogRangeRecip;\n"
654 "uniform myhalf AmbientScale;\n"
655 "uniform myhalf DiffuseScale;\n"
656 "uniform myhalf SpecularScale;\n"
657 "uniform myhalf SpecularPower;\n"
659 "#ifdef USEOFFSETMAPPING\n"
660 "vec2 OffsetMapping(vec2 TexCoord)\n"
662 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
663 " // 14 sample relief mapping: linear search and then binary search\n"
664 " // this basically steps forward a small amount repeatedly until it finds\n"
665 " // itself inside solid, then jitters forward and back using decreasing\n"
666 " // amounts to find the impact\n"
667 " //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
668 " //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
669 " vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
670 " vec3 RT = vec3(TexCoord, 1);\n"
671 " OffsetVector *= 0.1;\n"
672 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
673 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
674 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\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) - 0.5);\n"
682 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5 - 0.25);\n"
683 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25 - 0.125);\n"
684 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125 - 0.0625);\n"
685 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
688 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
689 " // this basically moves forward the full distance, and then backs up based\n"
690 " // on height of samples\n"
691 " //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
692 " //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
693 " vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
694 " TexCoord += OffsetVector;\n"
695 " OffsetVector *= 0.333;\n"
696 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
697 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
698 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
699 " return TexCoord;\n"
702 "#endif // USEOFFSETMAPPING\n"
704 "#ifdef MODE_WATER\n"
709 "#ifdef USEOFFSETMAPPING\n"
710 " // apply offsetmapping\n"
711 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
712 "#define TexCoord TexCoordOffset\n"
715 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
716 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
717 " vec4 ScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect + vec2(normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5))).xyxy * DistortScaleRefractReflect;\n"
718 " float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 5.0) * ReflectFactor + ReflectOffset;\n"
719 " gl_FragColor = mix(texture2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, texture2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
722 "#else // MODE_WATER\n"
723 "#ifdef MODE_REFRACTION\n"
725 "// refraction pass\n"
728 "#ifdef USEOFFSETMAPPING\n"
729 " // apply offsetmapping\n"
730 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
731 "#define TexCoord TexCoordOffset\n"
734 " vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
735 " //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
736 " vec2 ScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy + vec2(normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
737 " gl_FragColor = texture2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
740 "#else // MODE_REFRACTION\n"
743 "#ifdef USEOFFSETMAPPING\n"
744 " // apply offsetmapping\n"
745 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
746 "#define TexCoord TexCoordOffset\n"
749 " // combine the diffuse textures (base, pants, shirt)\n"
750 " myhvec4 color = myhvec4(texture2D(Texture_Color, TexCoord));\n"
751 "#ifdef USECOLORMAPPING\n"
752 " color.rgb += myhvec3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhvec3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
758 "#ifdef MODE_LIGHTSOURCE\n"
761 " // calculate surface normal, light normal, and specular normal\n"
762 " // compute color intensity for the two textures (colormap and glossmap)\n"
763 " // scale by light color and attenuation as efficiently as possible\n"
764 " // (do as much scalar math as possible rather than vector math)\n"
765 "# ifdef USESPECULAR\n"
766 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
767 " myhvec3 diffusenormal = myhvec3(normalize(LightVector));\n"
768 " myhvec3 specularnormal = normalize(diffusenormal + myhvec3(normalize(EyeVector)));\n"
770 " // calculate directional shading\n"
771 " 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"
773 "# ifdef USEDIFFUSE\n"
774 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
775 " myhvec3 diffusenormal = myhvec3(normalize(LightVector));\n"
777 " // calculate directional shading\n"
778 " 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"
780 " // calculate directionless shading\n"
781 " color.rgb = color.rgb * LightColor * myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
785 "# ifdef USECUBEFILTER\n"
786 " // apply light cubemap filter\n"
787 " //color.rgb *= normalize(CubeVector) * 0.5 + 0.5;//vec3(textureCube(Texture_Cube, CubeVector));\n"
788 " color.rgb *= myhvec3(textureCube(Texture_Cube, CubeVector));\n"
790 "#endif // MODE_LIGHTSOURCE\n"
795 "#ifdef MODE_LIGHTDIRECTION\n"
796 " // directional model lighting\n"
797 "# ifdef USESPECULAR\n"
798 " // get the surface normal and light normal\n"
799 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
800 " myhvec3 diffusenormal = myhvec3(LightVector);\n"
802 " // calculate directional shading\n"
803 " color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
804 " myhvec3 specularnormal = normalize(diffusenormal + myhvec3(normalize(EyeVector)));\n"
805 " color.rgb += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
807 "# ifdef USEDIFFUSE\n"
808 " // get the surface normal and light normal\n"
809 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
810 " myhvec3 diffusenormal = myhvec3(LightVector);\n"
812 " // calculate directional shading\n"
813 " color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
815 " color.rgb *= AmbientColor;\n"
819 " color.a *= TintColor.a;\n"
820 "#endif // MODE_LIGHTDIRECTION\n"
825 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
826 " // deluxemap lightmapping using light vectors in modelspace (evil q3map2)\n"
828 " // get the surface normal and light normal\n"
829 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
831 " myhvec3 diffusenormal_modelspace = myhvec3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - myhvec3(0.5);\n"
832 " myhvec3 diffusenormal = normalize(myhvec3(dot(diffusenormal_modelspace, myhvec3(VectorS)), dot(diffusenormal_modelspace, myhvec3(VectorT)), dot(diffusenormal_modelspace, myhvec3(VectorR))));\n"
833 " // calculate directional shading\n"
834 " myhvec3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0)));\n"
835 "# ifdef USESPECULAR\n"
836 " myhvec3 specularnormal = myhvec3(normalize(diffusenormal + myhvec3(normalize(EyeVector))));\n"
837 " tempcolor += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
840 " // apply lightmap color\n"
841 " color.rgb = color.rgb * AmbientScale + tempcolor * myhvec3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
843 " color *= TintColor;\n"
844 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
849 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
850 " // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
852 " // get the surface normal and light normal\n"
853 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
855 " myhvec3 diffusenormal = normalize(myhvec3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - myhvec3(0.5));\n"
856 " // calculate directional shading\n"
857 " myhvec3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0)));\n"
858 "# ifdef USESPECULAR\n"
859 " myhvec3 specularnormal = myhvec3(normalize(diffusenormal + myhvec3(normalize(EyeVector))));\n"
860 " tempcolor += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
863 " // apply lightmap color\n"
864 " color.rgb = color.rgb * AmbientScale + tempcolor * myhvec3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
866 " color *= TintColor;\n"
867 "#endif // MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
872 "#ifdef MODE_LIGHTMAP\n"
873 " // apply lightmap color\n"
874 " color.rgb = color.rgb * myhvec3(texture2D(Texture_Lightmap, TexCoordLightmap)) * DiffuseScale + color.rgb * AmbientScale;\n"
876 " color *= TintColor;\n"
877 "#endif // MODE_LIGHTMAP\n"
882 "#ifdef MODE_VERTEXCOLOR\n"
883 " // apply lightmap color\n"
884 " color.rgb = color.rgb * myhvec3(gl_Color.rgb) * DiffuseScale + color.rgb * AmbientScale;\n"
886 " color *= TintColor;\n"
887 "#endif // MODE_VERTEXCOLOR\n"
892 "#ifdef MODE_FLATCOLOR\n"
893 " color *= TintColor;\n"
894 "#endif // MODE_FLATCOLOR\n"
904 " color.rgb += myhvec3(texture2D(Texture_Glow, TexCoord)) * GlowScale;\n"
907 "#ifdef USECONTRASTBOOST\n"
908 " color.rgb = color.rgb / (ContrastBoostCoeff * color.rgb + myhvec3(1, 1, 1));\n"
911 " color.rgb *= SceneBrightness;\n"
913 " // apply fog after Contrastboost/SceneBrightness because its color is already modified appropriately\n"
915 " color.rgb = mix(FogColor, color.rgb, myhalf(texture2D(Texture_FogMask, myhvec2(length(EyeVectorModelSpace)*FogRangeRecip, 0.0))));\n"
918 " // 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"
919 "#ifdef USEREFLECTION\n"
920 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
921 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
922 " vec4 ScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect + vec3(normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5))).xyxy * DistortScaleRefractReflect;\n"
923 " color.rgb = mix(color.rgb, myhvec3(texture2D(Texture_Reflection, ScreenTexCoord.zw)) * ReflectColor.rgb, ReflectColor.a);\n"
926 " gl_FragColor = vec4(color);\n"
928 "#endif // MODE_REFRACTION\n"
929 "#endif // MODE_WATER\n"
931 "#endif // FRAGMENT_SHADER\n"
934 #define SHADERPERMUTATION_COLORMAPPING (1<<0) // indicates this is a colormapped skin
935 #define SHADERPERMUTATION_CONTRASTBOOST (1<<1) // r_glsl_contrastboost boosts the contrast at low color levels (similar to gamma)
936 #define SHADERPERMUTATION_FOG (1<<2) // tint the color by fog color or black if using additive blend mode
937 #define SHADERPERMUTATION_CUBEFILTER (1<<3) // (lightsource) use cubemap light filter
938 #define SHADERPERMUTATION_GLOW (1<<4) // (lightmap) blend in an additive glow texture
939 #define SHADERPERMUTATION_DIFFUSE (1<<5) // (lightsource) whether to use directional shading
940 #define SHADERPERMUTATION_SPECULAR (1<<6) // (lightsource or deluxemapping) render specular effects
941 #define SHADERPERMUTATION_REFLECTION (1<<7) // normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
942 #define SHADERPERMUTATION_OFFSETMAPPING (1<<8) // adjust texcoords to roughly simulate a displacement mapped surface
943 #define SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING (1<<9) // adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
944 #define SHADERPERMUTATION_MODEBASE (1<<10) // multiplier for the SHADERMODE_ values to get a valid index
946 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
947 const char *shaderpermutationinfo[][2] =
949 {"#define USECOLORMAPPING\n", " colormapping"},
950 {"#define USECONTRASTBOOST\n", " contrastboost"},
951 {"#define USEFOG\n", " fog"},
952 {"#define USECUBEFILTER\n", " cubefilter"},
953 {"#define USEGLOW\n", " glow"},
954 {"#define USEDIFFUSE\n", " diffuse"},
955 {"#define USESPECULAR\n", " specular"},
956 {"#define USEREFLECTION\n", " reflection"},
957 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
958 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
962 // this enum is multiplied by SHADERPERMUTATION_MODEBASE
963 typedef enum shadermode_e
965 SHADERMODE_FLATCOLOR, // (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
966 SHADERMODE_VERTEXCOLOR, // (lightmap) modulate texture by vertex colors (q3bsp)
967 SHADERMODE_LIGHTMAP, // (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
968 SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, // (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
969 SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, // (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
970 SHADERMODE_LIGHTDIRECTION, // (lightmap) use directional pixel shading from fixed light direction (q3bsp)
971 SHADERMODE_LIGHTSOURCE, // (lightsource) use directional pixel shading from light source (rtlight)
972 SHADERMODE_REFRACTION, // refract background (the material is rendered normally after this pass)
973 SHADERMODE_WATER, // refract background and reflection (the material is rendered normally after this pass)
978 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
979 const char *shadermodeinfo[][2] =
981 {"#define MODE_FLATCOLOR\n", " flatcolor"},
982 {"#define MODE_VERTEXCOLOR\n", " vertexcolor"},
983 {"#define MODE_LIGHTMAP\n", " lightmap"},
984 {"#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
985 {"#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
986 {"#define MODE_LIGHTDIRECTION\n", " lightdirection"},
987 {"#define MODE_LIGHTSOURCE\n", " lightsource"},
988 {"#define MODE_REFRACTION\n", " refraction"},
989 {"#define MODE_WATER\n", " water"},
993 #define SHADERPERMUTATION_INDICES (SHADERPERMUTATION_MODEBASE * SHADERMODE_COUNT)
995 typedef struct r_glsl_permutation_s
997 // indicates if we have tried compiling this permutation already
999 // 0 if compilation failed
1001 // locations of detected uniforms in program object, or -1 if not found
1002 int loc_Texture_Normal;
1003 int loc_Texture_Color;
1004 int loc_Texture_Gloss;
1005 int loc_Texture_Cube;
1006 int loc_Texture_Attenuation;
1007 int loc_Texture_FogMask;
1008 int loc_Texture_Pants;
1009 int loc_Texture_Shirt;
1010 int loc_Texture_Lightmap;
1011 int loc_Texture_Deluxemap;
1012 int loc_Texture_Glow;
1013 int loc_Texture_Refraction;
1014 int loc_Texture_Reflection;
1016 int loc_LightPosition;
1017 int loc_EyePosition;
1019 int loc_Color_Pants;
1020 int loc_Color_Shirt;
1021 int loc_FogRangeRecip;
1022 int loc_AmbientScale;
1023 int loc_DiffuseScale;
1024 int loc_SpecularScale;
1025 int loc_SpecularPower;
1027 int loc_SceneBrightness; // or: Scenebrightness * ContrastBoost
1028 int loc_OffsetMapping_Scale;
1030 int loc_AmbientColor;
1031 int loc_DiffuseColor;
1032 int loc_SpecularColor;
1034 int loc_ContrastBoostCoeff; // 1 - 1/ContrastBoost
1035 int loc_DistortScaleRefractReflect;
1036 int loc_ScreenScaleRefractReflect;
1037 int loc_ScreenCenterRefractReflect;
1038 int loc_RefractColor;
1039 int loc_ReflectColor;
1040 int loc_ReflectFactor;
1041 int loc_ReflectOffset;
1043 r_glsl_permutation_t;
1045 // information about each possible shader permutation
1046 r_glsl_permutation_t r_glsl_permutations[SHADERPERMUTATION_INDICES];
1047 // currently selected permutation
1048 r_glsl_permutation_t *r_glsl_permutation;
1050 // these are additional flags used only by R_GLSL_CompilePermutation
1051 #define SHADERTYPE_USES_VERTEXSHADER (1<<0)
1052 #define SHADERTYPE_USES_GEOMETRYSHADER (1<<1)
1053 #define SHADERTYPE_USES_FRAGMENTSHADER (1<<2)
1055 static void R_GLSL_CompilePermutation(const char *filename, int permutation, int shadertype)
1058 qboolean shaderfound;
1059 r_glsl_permutation_t *p = r_glsl_permutations + permutation;
1060 int vertstrings_count;
1061 int geomstrings_count;
1062 int fragstrings_count;
1064 const char *vertstrings_list[32+1];
1065 const char *geomstrings_list[32+1];
1066 const char *fragstrings_list[32+1];
1067 char permutationname[256];
1072 vertstrings_list[0] = "#define VERTEX_SHADER\n";
1073 geomstrings_list[0] = "#define GEOMETRY_SHADER\n";
1074 fragstrings_list[0] = "#define FRAGMENT_SHADER\n";
1075 vertstrings_count = 1;
1076 geomstrings_count = 1;
1077 fragstrings_count = 1;
1078 permutationname[0] = 0;
1079 i = permutation / SHADERPERMUTATION_MODEBASE;
1080 vertstrings_list[vertstrings_count++] = shadermodeinfo[i][0];
1081 geomstrings_list[geomstrings_count++] = shadermodeinfo[i][0];
1082 fragstrings_list[fragstrings_count++] = shadermodeinfo[i][0];
1083 strlcat(permutationname, shadermodeinfo[i][1], sizeof(permutationname));
1084 for (i = 0;shaderpermutationinfo[i][0];i++)
1086 if (permutation & (1<<i))
1088 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i][0];
1089 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i][0];
1090 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i][0];
1091 strlcat(permutationname, shaderpermutationinfo[i][1], sizeof(permutationname));
1095 // keep line numbers correct
1096 vertstrings_list[vertstrings_count++] = "\n";
1097 geomstrings_list[geomstrings_count++] = "\n";
1098 fragstrings_list[fragstrings_count++] = "\n";
1101 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1102 shaderfound = false;
1105 Con_DPrint("from disk... ");
1106 vertstrings_list[vertstrings_count++] = shaderstring;
1107 geomstrings_list[geomstrings_count++] = shaderstring;
1108 fragstrings_list[fragstrings_count++] = shaderstring;
1111 else if (!strcmp(filename, "glsl/default.glsl"))
1113 vertstrings_list[vertstrings_count++] = builtinshaderstring;
1114 geomstrings_list[geomstrings_count++] = builtinshaderstring;
1115 fragstrings_list[fragstrings_count++] = builtinshaderstring;
1118 // clear any lists that are not needed by this shader
1119 if (!(shadertype & SHADERTYPE_USES_VERTEXSHADER))
1120 vertstrings_count = 0;
1121 if (!(shadertype & SHADERTYPE_USES_GEOMETRYSHADER))
1122 geomstrings_count = 0;
1123 if (!(shadertype & SHADERTYPE_USES_FRAGMENTSHADER))
1124 fragstrings_count = 0;
1125 // compile the shader program
1126 if (shaderfound && vertstrings_count + geomstrings_count + fragstrings_count)
1127 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1131 qglUseProgramObjectARB(p->program);CHECKGLERROR
1132 // look up all the uniform variable names we care about, so we don't
1133 // have to look them up every time we set them
1134 p->loc_Texture_Normal = qglGetUniformLocationARB(p->program, "Texture_Normal");
1135 p->loc_Texture_Color = qglGetUniformLocationARB(p->program, "Texture_Color");
1136 p->loc_Texture_Gloss = qglGetUniformLocationARB(p->program, "Texture_Gloss");
1137 p->loc_Texture_Cube = qglGetUniformLocationARB(p->program, "Texture_Cube");
1138 p->loc_Texture_Attenuation = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
1139 p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
1140 p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
1141 p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
1142 p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
1143 p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
1144 p->loc_Texture_Glow = qglGetUniformLocationARB(p->program, "Texture_Glow");
1145 p->loc_Texture_Refraction = qglGetUniformLocationARB(p->program, "Texture_Refraction");
1146 p->loc_Texture_Reflection = qglGetUniformLocationARB(p->program, "Texture_Reflection");
1147 p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
1148 p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
1149 p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
1150 p->loc_LightColor = qglGetUniformLocationARB(p->program, "LightColor");
1151 p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants");
1152 p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt");
1153 p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip");
1154 p->loc_AmbientScale = qglGetUniformLocationARB(p->program, "AmbientScale");
1155 p->loc_DiffuseScale = qglGetUniformLocationARB(p->program, "DiffuseScale");
1156 p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
1157 p->loc_SpecularScale = qglGetUniformLocationARB(p->program, "SpecularScale");
1158 p->loc_GlowScale = qglGetUniformLocationARB(p->program, "GlowScale");
1159 p->loc_SceneBrightness = qglGetUniformLocationARB(p->program, "SceneBrightness");
1160 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
1161 p->loc_TintColor = qglGetUniformLocationARB(p->program, "TintColor");
1162 p->loc_AmbientColor = qglGetUniformLocationARB(p->program, "AmbientColor");
1163 p->loc_DiffuseColor = qglGetUniformLocationARB(p->program, "DiffuseColor");
1164 p->loc_SpecularColor = qglGetUniformLocationARB(p->program, "SpecularColor");
1165 p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
1166 p->loc_ContrastBoostCoeff = qglGetUniformLocationARB(p->program, "ContrastBoostCoeff");
1167 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
1168 p->loc_ScreenScaleRefractReflect = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
1169 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
1170 p->loc_RefractColor = qglGetUniformLocationARB(p->program, "RefractColor");
1171 p->loc_ReflectColor = qglGetUniformLocationARB(p->program, "ReflectColor");
1172 p->loc_ReflectFactor = qglGetUniformLocationARB(p->program, "ReflectFactor");
1173 p->loc_ReflectOffset = qglGetUniformLocationARB(p->program, "ReflectOffset");
1174 // initialize the samplers to refer to the texture units we use
1175 if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal, 0);
1176 if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color, 1);
1177 if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss, 2);
1178 if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube, 3);
1179 if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask, 4);
1180 if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants, 5);
1181 if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt, 6);
1182 if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap, 7);
1183 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap, 8);
1184 if (p->loc_Texture_Glow >= 0) qglUniform1iARB(p->loc_Texture_Glow, 9);
1185 if (p->loc_Texture_Attenuation >= 0) qglUniform1iARB(p->loc_Texture_Attenuation, 10);
1186 if (p->loc_Texture_Refraction >= 0) qglUniform1iARB(p->loc_Texture_Refraction, 11);
1187 if (p->loc_Texture_Reflection >= 0) qglUniform1iARB(p->loc_Texture_Reflection, 12);
1189 qglUseProgramObjectARB(0);CHECKGLERROR
1190 if (developer.integer)
1191 Con_Printf("GLSL shader %s :%s compiled.\n", filename, permutationname);
1195 if (developer.integer)
1196 Con_Printf("GLSL shader %s :%s failed! source code line offset for above errors is %i.\n", permutationname, filename, -(vertstrings_count - 1));
1198 Con_Printf("GLSL shader %s :%s failed! some features may not work properly.\n", permutationname, filename);
1201 Mem_Free(shaderstring);
1204 void R_GLSL_Restart_f(void)
1207 for (i = 0;i < SHADERPERMUTATION_INDICES;i++)
1208 if (r_glsl_permutations[i].program)
1209 GL_Backend_FreeProgram(r_glsl_permutations[i].program);
1210 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
1213 void R_GLSL_DumpShader_f(void)
1217 qfile_t *file = FS_Open("glsl/default.glsl", "w", false, false);
1220 Con_Printf("failed to write to glsl/default.glsl\n");
1224 FS_Print(file, "// The engine may define the following macros:\n");
1225 FS_Print(file, "// #define VERTEX_SHADER\n// #define GEOMETRY_SHADER\n// #define FRAGMENT_SHADER\n");
1226 for (i = 0;shadermodeinfo[i][0];i++)
1227 FS_Printf(file, "// %s", shadermodeinfo[i][0]);
1228 for (i = 0;shaderpermutationinfo[i][0];i++)
1229 FS_Printf(file, "// %s", shaderpermutationinfo[i][0]);
1230 FS_Print(file, "\n");
1231 FS_Print(file, builtinshaderstring);
1234 Con_Printf("glsl/default.glsl written\n");
1237 extern rtexture_t *r_shadow_attenuationgradienttexture;
1238 extern rtexture_t *r_shadow_attenuation2dtexture;
1239 extern rtexture_t *r_shadow_attenuation3dtexture;
1240 int R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass)
1242 // select a permutation of the lighting shader appropriate to this
1243 // combination of texture, entity, light source, and fogging, only use the
1244 // minimum features necessary to avoid wasting rendering time in the
1245 // fragment shader on features that are not being used
1246 const char *shaderfilename = NULL;
1247 unsigned int permutation = 0;
1248 unsigned int shadertype = 0;
1249 shadermode_t mode = 0;
1250 r_glsl_permutation = NULL;
1251 shaderfilename = "glsl/default.glsl";
1252 shadertype = SHADERTYPE_USES_VERTEXSHADER | SHADERTYPE_USES_FRAGMENTSHADER;
1253 // TODO: implement geometry-shader based shadow volumes someday
1254 if (r_glsl_offsetmapping.integer)
1256 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
1257 if (r_glsl_offsetmapping_reliefmapping.integer)
1258 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
1260 if (rsurfacepass == RSURFPASS_BACKGROUND)
1262 // distorted background
1263 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
1264 mode = SHADERMODE_WATER;
1266 mode = SHADERMODE_REFRACTION;
1268 else if (rsurfacepass == RSURFPASS_RTLIGHT)
1271 mode = SHADERMODE_LIGHTSOURCE;
1272 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
1273 permutation |= SHADERPERMUTATION_CUBEFILTER;
1274 if (diffusescale > 0)
1275 permutation |= SHADERPERMUTATION_DIFFUSE;
1276 if (specularscale > 0)
1277 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
1278 if (r_refdef.fogenabled)
1279 permutation |= SHADERPERMUTATION_FOG;
1280 if (rsurface.texture->colormapping)
1281 permutation |= SHADERPERMUTATION_COLORMAPPING;
1282 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1283 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1285 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
1287 // unshaded geometry (fullbright or ambient model lighting)
1288 mode = SHADERMODE_FLATCOLOR;
1289 if (rsurface.texture->currentskinframe->glow)
1290 permutation |= SHADERPERMUTATION_GLOW;
1291 if (r_refdef.fogenabled)
1292 permutation |= SHADERPERMUTATION_FOG;
1293 if (rsurface.texture->colormapping)
1294 permutation |= SHADERPERMUTATION_COLORMAPPING;
1295 if (r_glsl_offsetmapping.integer)
1297 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
1298 if (r_glsl_offsetmapping_reliefmapping.integer)
1299 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
1301 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1302 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1303 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1304 permutation |= SHADERPERMUTATION_REFLECTION;
1306 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
1308 // directional model lighting
1309 mode = SHADERMODE_LIGHTDIRECTION;
1310 if (rsurface.texture->currentskinframe->glow)
1311 permutation |= SHADERPERMUTATION_GLOW;
1312 permutation |= SHADERPERMUTATION_DIFFUSE;
1313 if (specularscale > 0)
1314 permutation |= SHADERPERMUTATION_SPECULAR;
1315 if (r_refdef.fogenabled)
1316 permutation |= SHADERPERMUTATION_FOG;
1317 if (rsurface.texture->colormapping)
1318 permutation |= SHADERPERMUTATION_COLORMAPPING;
1319 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1320 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1321 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1322 permutation |= SHADERPERMUTATION_REFLECTION;
1324 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
1326 // ambient model lighting
1327 mode = SHADERMODE_LIGHTDIRECTION;
1328 if (rsurface.texture->currentskinframe->glow)
1329 permutation |= SHADERPERMUTATION_GLOW;
1330 if (r_refdef.fogenabled)
1331 permutation |= SHADERPERMUTATION_FOG;
1332 if (rsurface.texture->colormapping)
1333 permutation |= SHADERPERMUTATION_COLORMAPPING;
1334 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1335 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1336 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1337 permutation |= SHADERPERMUTATION_REFLECTION;
1342 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.worldmodel && r_refdef.worldmodel->brushq3.deluxemapping)
1344 // deluxemapping (light direction texture)
1345 if (rsurface.uselightmaptexture && r_refdef.worldmodel && r_refdef.worldmodel->brushq3.deluxemapping && r_refdef.worldmodel->brushq3.deluxemapping_modelspace)
1346 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
1348 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
1349 if (specularscale > 0)
1350 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
1352 else if (r_glsl_deluxemapping.integer >= 2)
1354 // fake deluxemapping (uniform light direction in tangentspace)
1355 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
1356 if (specularscale > 0)
1357 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
1359 else if (rsurface.uselightmaptexture)
1361 // ordinary lightmapping (q1bsp, q3bsp)
1362 mode = SHADERMODE_LIGHTMAP;
1366 // ordinary vertex coloring (q3bsp)
1367 mode = SHADERMODE_VERTEXCOLOR;
1369 if (rsurface.texture->currentskinframe->glow)
1370 permutation |= SHADERPERMUTATION_GLOW;
1371 if (r_refdef.fogenabled)
1372 permutation |= SHADERPERMUTATION_FOG;
1373 if (rsurface.texture->colormapping)
1374 permutation |= SHADERPERMUTATION_COLORMAPPING;
1375 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1376 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1377 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1378 permutation |= SHADERPERMUTATION_REFLECTION;
1380 permutation |= mode * SHADERPERMUTATION_MODEBASE;
1381 if (!r_glsl_permutations[permutation].program)
1383 if (!r_glsl_permutations[permutation].compiled)
1384 R_GLSL_CompilePermutation(shaderfilename, permutation, shadertype);
1385 if (!r_glsl_permutations[permutation].program)
1387 // remove features until we find a valid permutation
1389 for (i = (SHADERPERMUTATION_MODEBASE >> 1);;i>>=1)
1393 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");
1394 Cvar_SetValueQuick(&r_glsl, 0);
1395 return 0; // no bit left to clear
1397 // reduce i more quickly whenever it would not remove any bits
1398 if (!(permutation & i))
1401 if (!r_glsl_permutations[permutation].compiled)
1402 R_GLSL_CompilePermutation(shaderfilename, permutation, shadertype);
1403 if (r_glsl_permutations[permutation].program)
1408 r_glsl_permutation = r_glsl_permutations + permutation;
1410 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
1411 if (mode == SHADERMODE_LIGHTSOURCE)
1413 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
1414 if (permutation & SHADERPERMUTATION_DIFFUSE)
1416 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
1417 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, ambientscale);
1418 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, diffusescale);
1419 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, specularscale);
1423 // ambient only is simpler
1424 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0] * ambientscale, lightcolorbase[1] * ambientscale, lightcolorbase[2] * ambientscale);
1425 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, 1);
1426 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, 0);
1427 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, 0);
1430 else if (mode == SHADERMODE_LIGHTDIRECTION)
1432 if (r_glsl_permutation->loc_AmbientColor >= 0)
1433 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);
1434 if (r_glsl_permutation->loc_DiffuseColor >= 0)
1435 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);
1436 if (r_glsl_permutation->loc_SpecularColor >= 0)
1437 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);
1438 if (r_glsl_permutation->loc_LightDir >= 0)
1439 qglUniform3fARB(r_glsl_permutation->loc_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
1443 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_ambient.value * 1.0f / 128.0f);
1444 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_refdef.lightmapintensity);
1445 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, r_refdef.lightmapintensity * specularscale);
1447 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]);
1448 if (r_glsl_permutation->loc_GlowScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_GlowScale, r_hdr_glowintensity.value);
1449 if (r_glsl_permutation->loc_ContrastBoostCoeff >= 0)
1451 // The formula used is actually:
1452 // color.rgb *= SceneBrightness;
1453 // color.rgb *= ContrastBoost / ((ContrastBoost - 1) * color.rgb + 1);
1454 // I simplify that to
1455 // color.rgb *= [[SceneBrightness * ContrastBoost]];
1456 // color.rgb /= [[(ContrastBoost - 1) / ContrastBoost]] * color.rgb + 1;
1458 // color.rgb = [[SceneBrightness * ContrastBoost]] * color.rgb / ([[(ContrastBoost - 1) * SceneBrightness]] * color.rgb + 1);
1459 // and do [[calculations]] here in the engine
1460 qglUniform1fARB(r_glsl_permutation->loc_ContrastBoostCoeff, (r_glsl_contrastboost.value - 1) * r_view.colorscale);
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 // color.rgb *= SceneBrightness;
3251 VectorScale(fogvec, r_view.colorscale, fogvec);
3252 if(r_glsl.integer && (r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)) // need to support contrast boost
3254 // color.rgb *= ContrastBoost / ((ContrastBoost - 1) * color.rgb + 1);
3255 fogvec[0] *= r_glsl_contrastboost.value / ((r_glsl_contrastboost.value - 1) * fogvec[0] + 1);
3256 fogvec[1] *= r_glsl_contrastboost.value / ((r_glsl_contrastboost.value - 1) * fogvec[1] + 1);
3257 fogvec[2] *= r_glsl_contrastboost.value / ((r_glsl_contrastboost.value - 1) * fogvec[2] + 1);
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 VectorClear(t->dlightcolor);
4231 t->currentnumlayers = 0;
4232 if (!(t->currentmaterialflags & MATERIALFLAG_NODRAW))
4234 if (!(t->currentmaterialflags & MATERIALFLAG_SKY))
4236 int blendfunc1, blendfunc2, depthmask;
4237 if (t->currentmaterialflags & MATERIALFLAG_ADD)
4239 blendfunc1 = GL_SRC_ALPHA;
4240 blendfunc2 = GL_ONE;
4242 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
4244 blendfunc1 = GL_SRC_ALPHA;
4245 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
4247 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
4249 blendfunc1 = t->customblendfunc[0];
4250 blendfunc2 = t->customblendfunc[1];
4254 blendfunc1 = GL_ONE;
4255 blendfunc2 = GL_ZERO;
4257 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
4258 if (t->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL))
4260 rtexture_t *currentbasetexture;
4262 if (r_refdef.fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED))
4263 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
4264 currentbasetexture = (VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) < (1.0f / 1048576.0f) && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
4265 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
4267 // fullbright is not affected by r_refdef.lightmapintensity
4268 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
4269 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
4270 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->pants, &t->currenttexmatrix, ent->colormap_pantscolor[0] * ent->colormod[0], ent->colormap_pantscolor[1] * ent->colormod[1], ent->colormap_pantscolor[2] * ent->colormod[2], t->currentalpha);
4271 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
4272 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->shirt, &t->currenttexmatrix, ent->colormap_shirtcolor[0] * ent->colormod[0], ent->colormap_shirtcolor[1] * ent->colormod[1], ent->colormap_shirtcolor[2] * ent->colormod[2], t->currentalpha);
4277 // set the color tint used for lights affecting this surface
4278 VectorSet(t->dlightcolor, ent->colormod[0] * t->currentalpha, ent->colormod[1] * t->currentalpha, ent->colormod[2] * t->currentalpha);
4280 // q3bsp has no lightmap updates, so the lightstylevalue that
4281 // would normally be baked into the lightmap must be
4282 // applied to the color
4283 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
4284 if (ent->model->type == mod_brushq3)
4285 colorscale *= r_refdef.rtlightstylevalue[0];
4286 colorscale *= r_refdef.lightmapintensity;
4287 Vector4Set(t->lightmapcolor, ent->colormod[0] * colorscale, ent->colormod[1] * colorscale, ent->colormod[2] * colorscale, t->currentalpha);
4288 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_LITTEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0] * colorscale, ent->colormod[1] * colorscale, ent->colormod[2] * colorscale, t->currentalpha);
4289 if (r_ambient.value >= (1.0f/64.0f))
4290 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0] * r_ambient.value * (1.0f / 64.0f), ent->colormod[1] * r_ambient.value * (1.0f / 64.0f), ent->colormod[2] * r_ambient.value * (1.0f / 64.0f), t->currentalpha);
4291 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
4293 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->currentskinframe->pants, &t->currenttexmatrix, ent->colormap_pantscolor[0] * ent->colormod[0] * colorscale, ent->colormap_pantscolor[1] * ent->colormod[1] * colorscale, ent->colormap_pantscolor[2] * ent->colormod[2] * colorscale, t->currentalpha);
4294 if (r_ambient.value >= (1.0f/64.0f))
4295 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->pants, &t->currenttexmatrix, ent->colormap_pantscolor[0] * ent->colormod[0] * r_ambient.value * (1.0f / 64.0f), ent->colormap_pantscolor[1] * ent->colormod[1] * r_ambient.value * (1.0f / 64.0f), ent->colormap_pantscolor[2] * ent->colormod[2] * r_ambient.value * (1.0f / 64.0f), t->currentalpha);
4297 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
4299 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->currentskinframe->shirt, &t->currenttexmatrix, ent->colormap_shirtcolor[0] * ent->colormod[0] * colorscale, ent->colormap_shirtcolor[1] * ent->colormod[1] * colorscale, ent->colormap_shirtcolor[2] * ent->colormod[2] * colorscale, t->currentalpha);
4300 if (r_ambient.value >= (1.0f/64.0f))
4301 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->shirt, &t->currenttexmatrix, ent->colormap_shirtcolor[0] * ent->colormod[0] * r_ambient.value * (1.0f / 64.0f), ent->colormap_shirtcolor[1] * ent->colormod[1] * r_ambient.value * (1.0f / 64.0f), ent->colormap_shirtcolor[2] * ent->colormod[2] * r_ambient.value * (1.0f / 64.0f), t->currentalpha);
4304 if (t->currentskinframe->glow != NULL)
4305 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->glow, &t->currenttexmatrix, r_hdr_glowintensity.value, r_hdr_glowintensity.value, r_hdr_glowintensity.value, t->currentalpha);
4306 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
4308 // if this is opaque use alpha blend which will darken the earlier
4311 // if this is an alpha blended material, all the earlier passes
4312 // were darkened by fog already, so we only need to add the fog
4313 // color ontop through the fog mask texture
4315 // if this is an additive blended material, all the earlier passes
4316 // were darkened by fog already, and we should not add fog color
4317 // (because the background was not darkened, there is no fog color
4318 // that was lost behind it).
4319 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, (t->currentmaterialflags & MATERIALFLAG_BLENDED) ? GL_ONE : GL_ONE_MINUS_SRC_ALPHA, TEXTURELAYERTYPE_FOG, t->currentskinframe->fog, &identitymatrix, r_refdef.fogcolor[0] / r_view.colorscale, r_refdef.fogcolor[1] / r_view.colorscale, r_refdef.fogcolor[2] / r_view.colorscale, t->currentalpha);
4326 void R_UpdateAllTextureInfo(entity_render_t *ent)
4330 for (i = 0;i < ent->model->num_texturesperskin;i++)
4331 R_UpdateTextureInfo(ent, ent->model->data_textures + i);
4334 rsurfacestate_t rsurface;
4336 void R_Mesh_ResizeArrays(int newvertices)
4339 if (rsurface.array_size >= newvertices)
4341 if (rsurface.array_modelvertex3f)
4342 Mem_Free(rsurface.array_modelvertex3f);
4343 rsurface.array_size = (newvertices + 1023) & ~1023;
4344 base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
4345 rsurface.array_modelvertex3f = base + rsurface.array_size * 0;
4346 rsurface.array_modelsvector3f = base + rsurface.array_size * 3;
4347 rsurface.array_modeltvector3f = base + rsurface.array_size * 6;
4348 rsurface.array_modelnormal3f = base + rsurface.array_size * 9;
4349 rsurface.array_deformedvertex3f = base + rsurface.array_size * 12;
4350 rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
4351 rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
4352 rsurface.array_deformednormal3f = base + rsurface.array_size * 21;
4353 rsurface.array_texcoord3f = base + rsurface.array_size * 24;
4354 rsurface.array_color4f = base + rsurface.array_size * 27;
4355 rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
4358 void RSurf_CleanUp(void)
4361 if (rsurface.mode == RSURFMODE_GLSL)
4363 qglUseProgramObjectARB(0);CHECKGLERROR
4365 GL_AlphaTest(false);
4366 rsurface.mode = RSURFMODE_NONE;
4367 rsurface.uselightmaptexture = false;
4368 rsurface.texture = NULL;
4371 void RSurf_ActiveWorldEntity(void)
4373 model_t *model = r_refdef.worldmodel;
4375 if (rsurface.array_size < model->surfmesh.num_vertices)
4376 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
4377 rsurface.matrix = identitymatrix;
4378 rsurface.inversematrix = identitymatrix;
4379 R_Mesh_Matrix(&identitymatrix);
4380 VectorCopy(r_view.origin, rsurface.modelorg);
4381 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
4382 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
4383 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
4384 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
4385 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
4386 rsurface.frameblend[0].frame = 0;
4387 rsurface.frameblend[0].lerp = 1;
4388 rsurface.frameblend[1].frame = 0;
4389 rsurface.frameblend[1].lerp = 0;
4390 rsurface.frameblend[2].frame = 0;
4391 rsurface.frameblend[2].lerp = 0;
4392 rsurface.frameblend[3].frame = 0;
4393 rsurface.frameblend[3].lerp = 0;
4394 rsurface.basepolygonfactor = r_refdef.polygonfactor;
4395 rsurface.basepolygonoffset = r_refdef.polygonoffset;
4396 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
4397 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
4398 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
4399 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
4400 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
4401 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
4402 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
4403 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
4404 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
4405 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
4406 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
4407 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
4408 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
4409 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
4410 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
4411 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
4412 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
4413 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
4414 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
4415 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
4416 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
4417 rsurface.modelelement3i = model->surfmesh.data_element3i;
4418 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo;
4419 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
4420 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
4421 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
4422 rsurface.modelsurfaces = model->data_surfaces;
4423 rsurface.generatedvertex = false;
4424 rsurface.vertex3f = rsurface.modelvertex3f;
4425 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
4426 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
4427 rsurface.svector3f = rsurface.modelsvector3f;
4428 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
4429 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
4430 rsurface.tvector3f = rsurface.modeltvector3f;
4431 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
4432 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
4433 rsurface.normal3f = rsurface.modelnormal3f;
4434 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
4435 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
4436 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
4439 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4441 model_t *model = ent->model;
4443 if (rsurface.array_size < model->surfmesh.num_vertices)
4444 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
4445 rsurface.matrix = ent->matrix;
4446 rsurface.inversematrix = ent->inversematrix;
4447 R_Mesh_Matrix(&rsurface.matrix);
4448 Matrix4x4_Transform(&rsurface.inversematrix, r_view.origin, rsurface.modelorg);
4449 rsurface.modellight_ambient[0] = ent->modellight_ambient[0] * ent->colormod[0];
4450 rsurface.modellight_ambient[1] = ent->modellight_ambient[1] * ent->colormod[1];
4451 rsurface.modellight_ambient[2] = ent->modellight_ambient[2] * ent->colormod[2];
4452 rsurface.modellight_diffuse[0] = ent->modellight_diffuse[0] * ent->colormod[0];
4453 rsurface.modellight_diffuse[1] = ent->modellight_diffuse[1] * ent->colormod[1];
4454 rsurface.modellight_diffuse[2] = ent->modellight_diffuse[2] * ent->colormod[2];
4455 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
4456 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
4457 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
4458 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
4459 rsurface.frameblend[0] = ent->frameblend[0];
4460 rsurface.frameblend[1] = ent->frameblend[1];
4461 rsurface.frameblend[2] = ent->frameblend[2];
4462 rsurface.frameblend[3] = ent->frameblend[3];
4463 rsurface.basepolygonfactor = r_refdef.polygonfactor;
4464 rsurface.basepolygonoffset = r_refdef.polygonoffset;
4465 if (ent->model->brush.submodel)
4467 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
4468 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
4470 if (model->surfmesh.isanimated && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].frame != 0))
4474 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
4475 rsurface.modelsvector3f = rsurface.array_modelsvector3f;
4476 rsurface.modeltvector3f = rsurface.array_modeltvector3f;
4477 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
4478 Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
4480 else if (wantnormals)
4482 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
4483 rsurface.modelsvector3f = NULL;
4484 rsurface.modeltvector3f = NULL;
4485 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
4486 Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
4490 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
4491 rsurface.modelsvector3f = NULL;
4492 rsurface.modeltvector3f = NULL;
4493 rsurface.modelnormal3f = NULL;
4494 Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, NULL, NULL, NULL);
4496 rsurface.modelvertex3f_bufferobject = 0;
4497 rsurface.modelvertex3f_bufferoffset = 0;
4498 rsurface.modelsvector3f_bufferobject = 0;
4499 rsurface.modelsvector3f_bufferoffset = 0;
4500 rsurface.modeltvector3f_bufferobject = 0;
4501 rsurface.modeltvector3f_bufferoffset = 0;
4502 rsurface.modelnormal3f_bufferobject = 0;
4503 rsurface.modelnormal3f_bufferoffset = 0;
4504 rsurface.generatedvertex = true;
4508 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
4509 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
4510 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
4511 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
4512 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
4513 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
4514 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
4515 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
4516 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
4517 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
4518 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
4519 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
4520 rsurface.generatedvertex = false;
4522 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
4523 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
4524 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
4525 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
4526 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
4527 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
4528 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
4529 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
4530 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
4531 rsurface.modelelement3i = model->surfmesh.data_element3i;
4532 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo;
4533 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
4534 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
4535 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
4536 rsurface.modelsurfaces = model->data_surfaces;
4537 rsurface.vertex3f = rsurface.modelvertex3f;
4538 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
4539 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
4540 rsurface.svector3f = rsurface.modelsvector3f;
4541 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
4542 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
4543 rsurface.tvector3f = rsurface.modeltvector3f;
4544 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
4545 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
4546 rsurface.normal3f = rsurface.modelnormal3f;
4547 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
4548 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
4549 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
4552 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
4553 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, msurface_t **texturesurfacelist)
4556 int texturesurfaceindex;
4561 const float *v1, *in_tc;
4563 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
4565 q3shaderinfo_deform_t *deform;
4566 // 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
4567 if (rsurface.generatedvertex)
4569 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
4570 generatenormals = true;
4571 for (i = 0;i < Q3MAXDEFORMS;i++)
4573 if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
4575 generatetangents = true;
4576 generatenormals = true;
4578 if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
4579 generatenormals = true;
4581 if (generatenormals && !rsurface.modelnormal3f)
4583 rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
4584 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
4585 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
4586 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer);
4588 if (generatetangents && !rsurface.modelsvector3f)
4590 rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
4591 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
4592 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
4593 rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
4594 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
4595 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
4596 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);
4599 rsurface.vertex3f = rsurface.modelvertex3f;
4600 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
4601 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
4602 rsurface.svector3f = rsurface.modelsvector3f;
4603 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
4604 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
4605 rsurface.tvector3f = rsurface.modeltvector3f;
4606 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
4607 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
4608 rsurface.normal3f = rsurface.modelnormal3f;
4609 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
4610 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
4611 // if vertices are deformed (sprite flares and things in maps, possibly
4612 // water waves, bulges and other deformations), generate them into
4613 // rsurface.deform* arrays from whatever the rsurface.* arrays point to
4614 // (may be static model data or generated data for an animated model, or
4615 // the previous deform pass)
4616 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
4618 switch (deform->deform)
4621 case Q3DEFORM_PROJECTIONSHADOW:
4622 case Q3DEFORM_TEXT0:
4623 case Q3DEFORM_TEXT1:
4624 case Q3DEFORM_TEXT2:
4625 case Q3DEFORM_TEXT3:
4626 case Q3DEFORM_TEXT4:
4627 case Q3DEFORM_TEXT5:
4628 case Q3DEFORM_TEXT6:
4629 case Q3DEFORM_TEXT7:
4632 case Q3DEFORM_AUTOSPRITE:
4633 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.forward, newforward);
4634 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.right, newright);
4635 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.up, newup);
4636 VectorNormalize(newforward);
4637 VectorNormalize(newright);
4638 VectorNormalize(newup);
4639 // make deformed versions of only the model vertices used by the specified surfaces
4640 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4642 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4643 // a single autosprite surface can contain multiple sprites...
4644 for (j = 0;j < surface->num_vertices - 3;j += 4)
4646 VectorClear(center);
4647 for (i = 0;i < 4;i++)
4648 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
4649 VectorScale(center, 0.25f, center);
4650 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, forward);
4651 VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
4652 VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
4653 for (i = 0;i < 4;i++)
4655 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
4656 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
4659 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);
4660 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);
4662 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4663 rsurface.vertex3f_bufferobject = 0;
4664 rsurface.vertex3f_bufferoffset = 0;
4665 rsurface.svector3f = rsurface.array_deformedsvector3f;
4666 rsurface.svector3f_bufferobject = 0;
4667 rsurface.svector3f_bufferoffset = 0;
4668 rsurface.tvector3f = rsurface.array_deformedtvector3f;
4669 rsurface.tvector3f_bufferobject = 0;
4670 rsurface.tvector3f_bufferoffset = 0;
4671 rsurface.normal3f = rsurface.array_deformednormal3f;
4672 rsurface.normal3f_bufferobject = 0;
4673 rsurface.normal3f_bufferoffset = 0;
4675 case Q3DEFORM_AUTOSPRITE2:
4676 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.forward, newforward);
4677 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.right, newright);
4678 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.up, newup);
4679 VectorNormalize(newforward);
4680 VectorNormalize(newright);
4681 VectorNormalize(newup);
4682 // make deformed versions of only the model vertices used by the specified surfaces
4683 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4685 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4686 const float *v1, *v2;
4696 memset(shortest, 0, sizeof(shortest));
4697 // a single autosprite surface can contain multiple sprites...
4698 for (j = 0;j < surface->num_vertices - 3;j += 4)
4700 VectorClear(center);
4701 for (i = 0;i < 4;i++)
4702 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
4703 VectorScale(center, 0.25f, center);
4704 // find the two shortest edges, then use them to define the
4705 // axis vectors for rotating around the central axis
4706 for (i = 0;i < 6;i++)
4708 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
4709 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
4711 Debug_PolygonBegin(NULL, 0, false, 0);
4712 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
4713 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);
4714 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
4717 l = VectorDistance2(v1, v2);
4718 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
4720 l += (1.0f / 1024.0f);
4721 if (shortest[0].length2 > l || i == 0)
4723 shortest[1] = shortest[0];
4724 shortest[0].length2 = l;
4725 shortest[0].v1 = v1;
4726 shortest[0].v2 = v2;
4728 else if (shortest[1].length2 > l || i == 1)
4730 shortest[1].length2 = l;
4731 shortest[1].v1 = v1;
4732 shortest[1].v2 = v2;
4735 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
4736 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
4738 Debug_PolygonBegin(NULL, 0, false, 0);
4739 Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
4740 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);
4741 Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
4744 // this calculates the right vector from the shortest edge
4745 // and the up vector from the edge midpoints
4746 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
4747 VectorNormalize(right);
4748 VectorSubtract(end, start, up);
4749 VectorNormalize(up);
4750 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
4751 //VectorSubtract(rsurface.modelorg, center, forward);
4752 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.forward, forward);
4753 VectorNegate(forward, forward);
4754 VectorReflect(forward, 0, up, forward);
4755 VectorNormalize(forward);
4756 CrossProduct(up, forward, newright);
4757 VectorNormalize(newright);
4759 Debug_PolygonBegin(NULL, 0, false, 0);
4760 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);
4761 Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
4762 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
4766 Debug_PolygonBegin(NULL, 0, false, 0);
4767 Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
4768 Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
4769 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
4772 // rotate the quad around the up axis vector, this is made
4773 // especially easy by the fact we know the quad is flat,
4774 // so we only have to subtract the center position and
4775 // measure distance along the right vector, and then
4776 // multiply that by the newright vector and add back the
4778 // we also need to subtract the old position to undo the
4779 // displacement from the center, which we do with a
4780 // DotProduct, the subtraction/addition of center is also
4781 // optimized into DotProducts here
4782 l = DotProduct(right, center);
4783 for (i = 0;i < 4;i++)
4785 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
4786 f = DotProduct(right, v1) - l;
4787 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
4790 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);
4791 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);
4793 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4794 rsurface.vertex3f_bufferobject = 0;
4795 rsurface.vertex3f_bufferoffset = 0;
4796 rsurface.svector3f = rsurface.array_deformedsvector3f;
4797 rsurface.svector3f_bufferobject = 0;
4798 rsurface.svector3f_bufferoffset = 0;
4799 rsurface.tvector3f = rsurface.array_deformedtvector3f;
4800 rsurface.tvector3f_bufferobject = 0;
4801 rsurface.tvector3f_bufferoffset = 0;
4802 rsurface.normal3f = rsurface.array_deformednormal3f;
4803 rsurface.normal3f_bufferobject = 0;
4804 rsurface.normal3f_bufferoffset = 0;
4806 case Q3DEFORM_NORMAL:
4807 // deform the normals to make reflections wavey
4808 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4810 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4811 for (j = 0;j < surface->num_vertices;j++)
4814 float *normal = (rsurface.array_deformednormal3f + 3 * surface->num_firstvertex) + j*3;
4815 VectorScale((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
4816 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, normal);
4817 normal[0] += deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.time * deform->parms[1]);
4818 normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.time * deform->parms[1]);
4819 normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.time * deform->parms[1]);
4820 VectorNormalize(normal);
4822 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);
4824 rsurface.svector3f = rsurface.array_deformedsvector3f;
4825 rsurface.svector3f_bufferobject = 0;
4826 rsurface.svector3f_bufferoffset = 0;
4827 rsurface.tvector3f = rsurface.array_deformedtvector3f;
4828 rsurface.tvector3f_bufferobject = 0;
4829 rsurface.tvector3f_bufferoffset = 0;
4830 rsurface.normal3f = rsurface.array_deformednormal3f;
4831 rsurface.normal3f_bufferobject = 0;
4832 rsurface.normal3f_bufferoffset = 0;
4835 // deform vertex array to make wavey water and flags and such
4836 waveparms[0] = deform->waveparms[0];
4837 waveparms[1] = deform->waveparms[1];
4838 waveparms[2] = deform->waveparms[2];
4839 waveparms[3] = deform->waveparms[3];
4840 // this is how a divisor of vertex influence on deformation
4841 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
4842 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
4843 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4845 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4846 for (j = 0;j < surface->num_vertices;j++)
4848 float *vertex = (rsurface.array_deformedvertex3f + 3 * surface->num_firstvertex) + j*3;
4849 VectorCopy((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, vertex);
4850 // if the wavefunc depends on time, evaluate it per-vertex
4853 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
4854 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
4856 VectorMA(vertex, scale, (rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, vertex);
4859 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4860 rsurface.vertex3f_bufferobject = 0;
4861 rsurface.vertex3f_bufferoffset = 0;
4863 case Q3DEFORM_BULGE:
4864 // deform vertex array to make the surface have moving bulges
4865 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4867 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4868 for (j = 0;j < surface->num_vertices;j++)
4870 scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.time * deform->parms[2])) * deform->parms[1];
4871 VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
4874 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4875 rsurface.vertex3f_bufferobject = 0;
4876 rsurface.vertex3f_bufferoffset = 0;
4879 // deform vertex array
4880 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
4881 VectorScale(deform->parms, scale, waveparms);
4882 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4884 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4885 for (j = 0;j < surface->num_vertices;j++)
4886 VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
4888 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4889 rsurface.vertex3f_bufferobject = 0;
4890 rsurface.vertex3f_bufferoffset = 0;
4894 // generate texcoords based on the chosen texcoord source
4895 switch(rsurface.texture->tcgen.tcgen)
4898 case Q3TCGEN_TEXTURE:
4899 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
4900 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordtexture2f_bufferobject;
4901 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
4903 case Q3TCGEN_LIGHTMAP:
4904 rsurface.texcoordtexture2f = rsurface.modeltexcoordlightmap2f;
4905 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
4906 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
4908 case Q3TCGEN_VECTOR:
4909 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4911 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4912 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)
4914 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
4915 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
4918 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
4919 rsurface.texcoordtexture2f_bufferobject = 0;
4920 rsurface.texcoordtexture2f_bufferoffset = 0;
4922 case Q3TCGEN_ENVIRONMENT:
4923 // make environment reflections using a spheremap
4924 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4926 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4927 const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
4928 const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
4929 float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
4930 for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
4932 float l, d, eyedir[3];
4933 VectorSubtract(rsurface.modelorg, vertex, eyedir);
4934 l = 0.5f / VectorLength(eyedir);
4935 d = DotProduct(normal, eyedir)*2;
4936 out_tc[0] = 0.5f + (normal[1]*d - eyedir[1])*l;
4937 out_tc[1] = 0.5f - (normal[2]*d - eyedir[2])*l;
4940 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
4941 rsurface.texcoordtexture2f_bufferobject = 0;
4942 rsurface.texcoordtexture2f_bufferoffset = 0;
4945 // the only tcmod that needs software vertex processing is turbulent, so
4946 // check for it here and apply the changes if needed
4947 // and we only support that as the first one
4948 // (handling a mixture of turbulent and other tcmods would be problematic
4949 // without punting it entirely to a software path)
4950 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
4952 amplitude = rsurface.texture->tcmods[0].parms[1];
4953 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.time * rsurface.texture->tcmods[0].parms[3];
4954 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4956 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4957 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)
4959 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
4960 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
4963 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
4964 rsurface.texcoordtexture2f_bufferobject = 0;
4965 rsurface.texcoordtexture2f_bufferoffset = 0;
4967 rsurface.texcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
4968 rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
4969 rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
4970 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
4973 void RSurf_DrawBatch_Simple(int texturenumsurfaces, msurface_t **texturesurfacelist)
4976 const msurface_t *surface = texturesurfacelist[0];
4977 const msurface_t *surface2;
4982 // TODO: lock all array ranges before render, rather than on each surface
4983 if (texturenumsurfaces == 1)
4985 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
4986 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));
4988 else if (r_batchmode.integer == 2)
4990 #define MAXBATCHTRIANGLES 4096
4991 int batchtriangles = 0;
4992 int batchelements[MAXBATCHTRIANGLES*3];
4993 for (i = 0;i < texturenumsurfaces;i = j)
4995 surface = texturesurfacelist[i];
4997 if (surface->num_triangles > MAXBATCHTRIANGLES)
4999 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));
5002 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
5003 batchtriangles = surface->num_triangles;
5004 firstvertex = surface->num_firstvertex;
5005 endvertex = surface->num_firstvertex + surface->num_vertices;
5006 for (;j < texturenumsurfaces;j++)
5008 surface2 = texturesurfacelist[j];
5009 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
5011 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
5012 batchtriangles += surface2->num_triangles;
5013 firstvertex = min(firstvertex, surface2->num_firstvertex);
5014 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
5016 surface2 = texturesurfacelist[j-1];
5017 numvertices = endvertex - firstvertex;
5018 R_Mesh_Draw(firstvertex, numvertices, batchtriangles, batchelements, 0, 0);
5021 else if (r_batchmode.integer == 1)
5023 for (i = 0;i < texturenumsurfaces;i = j)
5025 surface = texturesurfacelist[i];
5026 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
5027 if (texturesurfacelist[j] != surface2)
5029 surface2 = texturesurfacelist[j-1];
5030 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
5031 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
5032 GL_LockArrays(surface->num_firstvertex, numvertices);
5033 R_Mesh_Draw(surface->num_firstvertex, numvertices, numtriangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
5038 for (i = 0;i < texturenumsurfaces;i++)
5040 surface = texturesurfacelist[i];
5041 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5042 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));
5047 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit, int refractiontexunit, int reflectiontexunit)
5049 int i, planeindex, vertexindex;
5053 r_waterstate_waterplane_t *p, *bestp;
5054 msurface_t *surface;
5055 if (r_waterstate.renderingscene)
5057 for (i = 0;i < texturenumsurfaces;i++)
5059 surface = texturesurfacelist[i];
5060 if (lightmaptexunit >= 0)
5061 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5062 if (deluxemaptexunit >= 0)
5063 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5064 // pick the closest matching water plane
5067 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5070 for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
5072 Matrix4x4_Transform(&rsurface.matrix, v, vert);
5073 d += fabs(PlaneDiff(vert, &p->plane));
5075 if (bestd > d || !bestp)
5083 if (refractiontexunit >= 0)
5084 R_Mesh_TexBind(refractiontexunit, R_GetTexture(bestp->texture_refraction));
5085 if (reflectiontexunit >= 0)
5086 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(bestp->texture_reflection));
5090 if (refractiontexunit >= 0)
5091 R_Mesh_TexBind(refractiontexunit, R_GetTexture(r_texture_black));
5092 if (reflectiontexunit >= 0)
5093 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(r_texture_black));
5095 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5096 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));
5100 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit)
5104 const msurface_t *surface = texturesurfacelist[0];
5105 const msurface_t *surface2;
5110 // TODO: lock all array ranges before render, rather than on each surface
5111 if (texturenumsurfaces == 1)
5113 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5114 if (deluxemaptexunit >= 0)
5115 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5116 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5117 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));
5119 else if (r_batchmode.integer == 2)
5121 #define MAXBATCHTRIANGLES 4096
5122 int batchtriangles = 0;
5123 int batchelements[MAXBATCHTRIANGLES*3];
5124 for (i = 0;i < texturenumsurfaces;i = j)
5126 surface = texturesurfacelist[i];
5127 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5128 if (deluxemaptexunit >= 0)
5129 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5131 if (surface->num_triangles > MAXBATCHTRIANGLES)
5133 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));
5136 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
5137 batchtriangles = surface->num_triangles;
5138 firstvertex = surface->num_firstvertex;
5139 endvertex = surface->num_firstvertex + surface->num_vertices;
5140 for (;j < texturenumsurfaces;j++)
5142 surface2 = texturesurfacelist[j];
5143 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
5145 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
5146 batchtriangles += surface2->num_triangles;
5147 firstvertex = min(firstvertex, surface2->num_firstvertex);
5148 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
5150 surface2 = texturesurfacelist[j-1];
5151 numvertices = endvertex - firstvertex;
5152 R_Mesh_Draw(firstvertex, numvertices, batchtriangles, batchelements, 0, 0);
5155 else if (r_batchmode.integer == 1)
5158 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
5159 for (i = 0;i < texturenumsurfaces;i = j)
5161 surface = texturesurfacelist[i];
5162 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
5163 if (texturesurfacelist[j] != surface2)
5165 Con_Printf(" %i", j - i);
5168 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
5170 for (i = 0;i < texturenumsurfaces;i = j)
5172 surface = texturesurfacelist[i];
5173 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5174 if (deluxemaptexunit >= 0)
5175 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5176 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
5177 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
5180 Con_Printf(" %i", j - i);
5182 surface2 = texturesurfacelist[j-1];
5183 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
5184 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
5185 GL_LockArrays(surface->num_firstvertex, numvertices);
5186 R_Mesh_Draw(surface->num_firstvertex, numvertices, numtriangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
5194 for (i = 0;i < texturenumsurfaces;i++)
5196 surface = texturesurfacelist[i];
5197 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5198 if (deluxemaptexunit >= 0)
5199 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5200 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5201 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));
5206 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
5209 int texturesurfaceindex;
5210 if (r_showsurfaces.integer == 2)
5212 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5214 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5215 for (j = 0;j < surface->num_triangles;j++)
5217 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_view.colorscale;
5218 GL_Color(f, f, f, 1);
5219 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)));
5225 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5227 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5228 int k = (int)(((size_t)surface) / sizeof(msurface_t));
5229 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);
5230 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5231 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));
5236 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, msurface_t **texturesurfacelist)
5238 int texturesurfaceindex;
5242 if (rsurface.lightmapcolor4f)
5244 // generate color arrays for the surfaces in this list
5245 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5247 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5248 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)
5250 f = FogPoint_Model(v);
5260 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5262 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5263 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)
5265 f = FogPoint_Model(v);
5273 rsurface.lightmapcolor4f = rsurface.array_color4f;
5274 rsurface.lightmapcolor4f_bufferobject = 0;
5275 rsurface.lightmapcolor4f_bufferoffset = 0;
5278 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a)
5280 int texturesurfaceindex;
5283 if (!rsurface.lightmapcolor4f)
5285 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5287 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5288 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)
5296 rsurface.lightmapcolor4f = rsurface.array_color4f;
5297 rsurface.lightmapcolor4f_bufferobject = 0;
5298 rsurface.lightmapcolor4f_bufferoffset = 0;
5301 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5304 rsurface.lightmapcolor4f = NULL;
5305 rsurface.lightmapcolor4f_bufferobject = 0;
5306 rsurface.lightmapcolor4f_bufferoffset = 0;
5307 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5308 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5309 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5310 GL_Color(r, g, b, a);
5311 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 0, -1);
5314 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5316 // TODO: optimize applyfog && applycolor case
5317 // just apply fog if necessary, and tint the fog color array if necessary
5318 rsurface.lightmapcolor4f = NULL;
5319 rsurface.lightmapcolor4f_bufferobject = 0;
5320 rsurface.lightmapcolor4f_bufferoffset = 0;
5321 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5322 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5323 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5324 GL_Color(r, g, b, a);
5325 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5328 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5330 int texturesurfaceindex;
5334 if (texturesurfacelist[0]->lightmapinfo && texturesurfacelist[0]->lightmapinfo->stainsamples)
5336 // generate color arrays for the surfaces in this list
5337 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5339 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5340 for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
5342 if (surface->lightmapinfo->samples)
5344 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
5345 float scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
5346 VectorScale(lm, scale, c);
5347 if (surface->lightmapinfo->styles[1] != 255)
5349 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
5351 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
5352 VectorMA(c, scale, lm, c);
5353 if (surface->lightmapinfo->styles[2] != 255)
5356 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
5357 VectorMA(c, scale, lm, c);
5358 if (surface->lightmapinfo->styles[3] != 255)
5361 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
5362 VectorMA(c, scale, lm, c);
5372 rsurface.lightmapcolor4f = rsurface.array_color4f;
5373 rsurface.lightmapcolor4f_bufferobject = 0;
5374 rsurface.lightmapcolor4f_bufferoffset = 0;
5378 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
5379 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
5380 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
5382 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5383 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5384 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5385 GL_Color(r, g, b, a);
5386 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5389 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5391 int texturesurfaceindex;
5395 vec3_t ambientcolor;
5396 vec3_t diffusecolor;
5400 VectorCopy(rsurface.modellight_lightdir, lightdir);
5401 f = 0.5f * r_refdef.lightmapintensity;
5402 ambientcolor[0] = rsurface.modellight_ambient[0] * r * f;
5403 ambientcolor[1] = rsurface.modellight_ambient[1] * g * f;
5404 ambientcolor[2] = rsurface.modellight_ambient[2] * b * f;
5405 diffusecolor[0] = rsurface.modellight_diffuse[0] * r * f;
5406 diffusecolor[1] = rsurface.modellight_diffuse[1] * g * f;
5407 diffusecolor[2] = rsurface.modellight_diffuse[2] * b * f;
5408 if (VectorLength2(diffusecolor) > 0)
5410 // generate color arrays for the surfaces in this list
5411 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5413 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5414 int numverts = surface->num_vertices;
5415 v = rsurface.vertex3f + 3 * surface->num_firstvertex;
5416 c2 = rsurface.normal3f + 3 * surface->num_firstvertex;
5417 c = rsurface.array_color4f + 4 * surface->num_firstvertex;
5418 // q3-style directional shading
5419 for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
5421 if ((f = DotProduct(c2, lightdir)) > 0)
5422 VectorMA(ambientcolor, f, diffusecolor, c);
5424 VectorCopy(ambientcolor, c);
5433 rsurface.lightmapcolor4f = rsurface.array_color4f;
5434 rsurface.lightmapcolor4f_bufferobject = 0;
5435 rsurface.lightmapcolor4f_bufferoffset = 0;
5439 r = ambientcolor[0];
5440 g = ambientcolor[1];
5441 b = ambientcolor[2];
5442 rsurface.lightmapcolor4f = NULL;
5443 rsurface.lightmapcolor4f_bufferobject = 0;
5444 rsurface.lightmapcolor4f_bufferoffset = 0;
5446 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5447 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5448 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5449 GL_Color(r, g, b, a);
5450 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5453 void RSurf_SetupDepthAndCulling(void)
5455 // submodels are biased to avoid z-fighting with world surfaces that they
5456 // may be exactly overlapping (avoids z-fighting artifacts on certain
5457 // doors and things in Quake maps)
5458 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5459 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
5460 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
5461 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_view.cullface_back);
5464 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
5466 RSurf_SetupDepthAndCulling();
5467 if (rsurface.mode != RSURFMODE_SHOWSURFACES)
5469 rsurface.mode = RSURFMODE_SHOWSURFACES;
5471 GL_BlendFunc(GL_ONE, GL_ZERO);
5472 R_Mesh_ColorPointer(NULL, 0, 0);
5473 R_Mesh_ResetTextureState();
5475 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
5476 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
5479 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, msurface_t **texturesurfacelist)
5481 // transparent sky would be ridiculous
5482 if ((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED))
5484 if (rsurface.mode != RSURFMODE_SKY)
5486 if (rsurface.mode == RSURFMODE_GLSL)
5488 qglUseProgramObjectARB(0);CHECKGLERROR
5490 rsurface.mode = RSURFMODE_SKY;
5494 skyrendernow = false;
5496 // restore entity matrix
5497 R_Mesh_Matrix(&rsurface.matrix);
5499 RSurf_SetupDepthAndCulling();
5501 // LordHavoc: HalfLife maps have freaky skypolys so don't use
5502 // skymasking on them, and Quake3 never did sky masking (unlike
5503 // software Quake and software Quake2), so disable the sky masking
5504 // in Quake3 maps as it causes problems with q3map2 sky tricks,
5505 // and skymasking also looks very bad when noclipping outside the
5506 // level, so don't use it then either.
5507 if (r_refdef.worldmodel && r_refdef.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_viewcache.world_novis)
5509 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
5510 R_Mesh_ColorPointer(NULL, 0, 0);
5511 R_Mesh_ResetTextureState();
5512 if (skyrendermasked)
5514 // depth-only (masking)
5515 GL_ColorMask(0,0,0,0);
5516 // just to make sure that braindead drivers don't draw
5517 // anything despite that colormask...
5518 GL_BlendFunc(GL_ZERO, GL_ONE);
5523 GL_BlendFunc(GL_ONE, GL_ZERO);
5525 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
5526 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5527 if (skyrendermasked)
5528 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
5532 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, msurface_t **texturesurfacelist)
5534 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION)))
5537 if (rsurface.mode != RSURFMODE_GLSL)
5539 rsurface.mode = RSURFMODE_GLSL;
5540 R_Mesh_ResetTextureState();
5541 GL_Color(1, 1, 1, 1);
5544 R_Mesh_TexMatrix(0, &rsurface.texture->currenttexmatrix);
5545 R_Mesh_TexBind(0, R_GetTexture(rsurface.texture->currentskinframe->nmap));
5546 R_Mesh_TexBind(1, R_GetTexture(rsurface.texture->basetexture));
5547 R_Mesh_TexBind(2, R_GetTexture(rsurface.texture->glosstexture));
5548 R_Mesh_TexBind(4, R_GetTexture(r_texture_fogattenuation));
5549 R_Mesh_TexBind(5, R_GetTexture(rsurface.texture->currentskinframe->pants));
5550 R_Mesh_TexBind(6, R_GetTexture(rsurface.texture->currentskinframe->shirt));
5551 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
5553 R_Mesh_TexBind(7, R_GetTexture(r_texture_grey128));
5554 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
5555 R_Mesh_ColorPointer(NULL, 0, 0);
5557 else if (rsurface.uselightmaptexture)
5559 R_Mesh_TexBind(7, R_GetTexture(texturesurfacelist[0]->lightmaptexture));
5560 R_Mesh_TexBind(8, R_GetTexture(texturesurfacelist[0]->deluxemaptexture));
5561 R_Mesh_ColorPointer(NULL, 0, 0);
5565 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
5566 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
5567 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
5569 R_Mesh_TexBind(9, R_GetTexture(rsurface.texture->currentskinframe->glow));
5570 R_Mesh_TexBind(11, R_GetTexture(r_texture_white)); // changed per surface
5571 R_Mesh_TexBind(12, R_GetTexture(r_texture_white)); // changed per surface
5573 if (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5575 // render background
5576 GL_BlendFunc(GL_ONE, GL_ZERO);
5578 GL_AlphaTest(false);
5580 GL_Color(1, 1, 1, 1);
5581 R_Mesh_ColorPointer(NULL, 0, 0);
5583 R_SetupSurfaceShader(vec3_origin, rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
5584 if (r_glsl_permutation)
5586 RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
5587 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
5588 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
5589 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
5590 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
5591 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
5592 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist, -1, -1, r_glsl_permutation->loc_Texture_Refraction ? 11 : -1, r_glsl_permutation->loc_Texture_Reflection ? 12 : -1);
5595 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5596 GL_DepthMask(false);
5597 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5598 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
5600 R_Mesh_TexBind(7, R_GetTexture(r_texture_grey128));
5601 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
5602 R_Mesh_ColorPointer(NULL, 0, 0);
5604 else if (rsurface.uselightmaptexture)
5606 R_Mesh_TexBind(7, R_GetTexture(texturesurfacelist[0]->lightmaptexture));
5607 R_Mesh_TexBind(8, R_GetTexture(texturesurfacelist[0]->deluxemaptexture));
5608 R_Mesh_ColorPointer(NULL, 0, 0);
5612 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
5613 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
5614 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
5616 R_Mesh_TexBind(11, R_GetTexture(r_texture_white)); // changed per surface
5617 R_Mesh_TexBind(12, R_GetTexture(r_texture_white)); // changed per surface
5620 R_SetupSurfaceShader(vec3_origin, rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE);
5621 if (!r_glsl_permutation)
5624 RSurf_PrepareVerticesForBatch(r_glsl_permutation->loc_Texture_Normal >= 0 || r_glsl_permutation->loc_LightDir >= 0, r_glsl_permutation->loc_Texture_Normal >= 0, texturenumsurfaces, texturesurfacelist);
5625 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
5626 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
5627 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
5628 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
5629 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
5631 if (r_glsl_permutation->loc_Texture_Refraction >= 0)
5633 GL_BlendFunc(GL_ONE, GL_ZERO);
5635 GL_AlphaTest(false);
5638 if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
5640 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
5641 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);
5643 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 7, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? 8 : -1);
5647 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
5648 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);
5650 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5652 if (rsurface.texture->backgroundnumskinframes && !(rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED))
5657 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, msurface_t **texturesurfacelist)
5659 // OpenGL 1.3 path - anything not completely ancient
5660 int texturesurfaceindex;
5661 qboolean applycolor;
5665 const texturelayer_t *layer;
5666 if (rsurface.mode != RSURFMODE_MULTIPASS)
5667 rsurface.mode = RSURFMODE_MULTIPASS;
5668 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
5670 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
5673 int layertexrgbscale;
5674 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5676 if (layerindex == 0)
5680 GL_AlphaTest(false);
5681 qglDepthFunc(GL_EQUAL);CHECKGLERROR
5684 GL_DepthMask(layer->depthmask);
5685 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
5686 if ((layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2) && (gl_combine.integer || layer->depthmask))
5688 layertexrgbscale = 4;
5689 VectorScale(layer->color, 0.25f, layercolor);
5691 else if ((layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1) && (gl_combine.integer || layer->depthmask))
5693 layertexrgbscale = 2;
5694 VectorScale(layer->color, 0.5f, layercolor);
5698 layertexrgbscale = 1;
5699 VectorScale(layer->color, 1.0f, layercolor);
5701 layercolor[3] = layer->color[3];
5702 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
5703 R_Mesh_ColorPointer(NULL, 0, 0);
5704 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
5705 switch (layer->type)
5707 case TEXTURELAYERTYPE_LITTEXTURE:
5708 memset(&m, 0, sizeof(m));
5709 m.tex[0] = R_GetTexture(r_texture_white);
5710 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
5711 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
5712 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
5713 m.tex[1] = R_GetTexture(layer->texture);
5714 m.texmatrix[1] = layer->texmatrix;
5715 m.texrgbscale[1] = layertexrgbscale;
5716 m.pointer_texcoord[1] = rsurface.texcoordtexture2f;
5717 m.pointer_texcoord_bufferobject[1] = rsurface.texcoordtexture2f_bufferobject;
5718 m.pointer_texcoord_bufferoffset[1] = rsurface.texcoordtexture2f_bufferoffset;
5719 R_Mesh_TextureState(&m);
5720 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
5721 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
5722 else if (rsurface.uselightmaptexture)
5723 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
5725 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
5727 case TEXTURELAYERTYPE_TEXTURE:
5728 memset(&m, 0, sizeof(m));
5729 m.tex[0] = R_GetTexture(layer->texture);
5730 m.texmatrix[0] = layer->texmatrix;
5731 m.texrgbscale[0] = layertexrgbscale;
5732 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5733 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5734 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5735 R_Mesh_TextureState(&m);
5736 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
5738 case TEXTURELAYERTYPE_FOG:
5739 memset(&m, 0, sizeof(m));
5740 m.texrgbscale[0] = layertexrgbscale;
5743 m.tex[0] = R_GetTexture(layer->texture);
5744 m.texmatrix[0] = layer->texmatrix;
5745 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5746 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5747 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5749 R_Mesh_TextureState(&m);
5750 // generate a color array for the fog pass
5751 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
5752 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5756 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5757 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)
5759 f = 1 - FogPoint_Model(v);
5760 c[0] = layercolor[0];
5761 c[1] = layercolor[1];
5762 c[2] = layercolor[2];
5763 c[3] = f * layercolor[3];
5766 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5769 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
5771 GL_LockArrays(0, 0);
5774 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5776 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
5777 GL_AlphaTest(false);
5781 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, msurface_t **texturesurfacelist)
5783 // OpenGL 1.1 - crusty old voodoo path
5784 int texturesurfaceindex;
5788 const texturelayer_t *layer;
5789 if (rsurface.mode != RSURFMODE_MULTIPASS)
5790 rsurface.mode = RSURFMODE_MULTIPASS;
5791 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
5793 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
5795 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5797 if (layerindex == 0)
5801 GL_AlphaTest(false);
5802 qglDepthFunc(GL_EQUAL);CHECKGLERROR
5805 GL_DepthMask(layer->depthmask);
5806 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
5807 R_Mesh_ColorPointer(NULL, 0, 0);
5808 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
5809 switch (layer->type)
5811 case TEXTURELAYERTYPE_LITTEXTURE:
5812 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
5814 // two-pass lit texture with 2x rgbscale
5815 // first the lightmap pass
5816 memset(&m, 0, sizeof(m));
5817 m.tex[0] = R_GetTexture(r_texture_white);
5818 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
5819 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
5820 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
5821 R_Mesh_TextureState(&m);
5822 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
5823 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5824 else if (rsurface.uselightmaptexture)
5825 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5827 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5828 GL_LockArrays(0, 0);
5829 // then apply the texture to it
5830 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
5831 memset(&m, 0, sizeof(m));
5832 m.tex[0] = R_GetTexture(layer->texture);
5833 m.texmatrix[0] = layer->texmatrix;
5834 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5835 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5836 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5837 R_Mesh_TextureState(&m);
5838 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);
5842 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
5843 memset(&m, 0, sizeof(m));
5844 m.tex[0] = R_GetTexture(layer->texture);
5845 m.texmatrix[0] = layer->texmatrix;
5846 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5847 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5848 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5849 R_Mesh_TextureState(&m);
5850 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
5851 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);
5853 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);
5856 case TEXTURELAYERTYPE_TEXTURE:
5857 // singletexture unlit texture with transparency support
5858 memset(&m, 0, sizeof(m));
5859 m.tex[0] = R_GetTexture(layer->texture);
5860 m.texmatrix[0] = layer->texmatrix;
5861 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5862 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5863 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5864 R_Mesh_TextureState(&m);
5865 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);
5867 case TEXTURELAYERTYPE_FOG:
5868 // singletexture fogging
5869 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
5872 memset(&m, 0, sizeof(m));
5873 m.tex[0] = R_GetTexture(layer->texture);
5874 m.texmatrix[0] = layer->texmatrix;
5875 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5876 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5877 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5878 R_Mesh_TextureState(&m);
5881 R_Mesh_ResetTextureState();
5882 // generate a color array for the fog pass
5883 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5887 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5888 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)
5890 f = 1 - FogPoint_Model(v);
5891 c[0] = layer->color[0];
5892 c[1] = layer->color[1];
5893 c[2] = layer->color[2];
5894 c[3] = f * layer->color[3];
5897 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5900 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
5902 GL_LockArrays(0, 0);
5905 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5907 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
5908 GL_AlphaTest(false);
5912 static void R_DrawTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly)
5914 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW)
5916 rsurface.rtlight = NULL;
5920 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
5922 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
5924 if (rsurface.mode != RSURFMODE_MULTIPASS)
5925 rsurface.mode = RSURFMODE_MULTIPASS;
5926 if (r_depthfirst.integer == 3)
5928 int i = (int)(texturesurfacelist[0] - rsurface.modelsurfaces);
5929 if (!r_view.showdebug)
5930 GL_Color(0, 0, 0, 1);
5932 GL_Color(((i >> 6) & 7) / 7.0f, ((i >> 3) & 7) / 7.0f, (i & 7) / 7.0f,1);
5936 GL_ColorMask(0,0,0,0);
5939 RSurf_SetupDepthAndCulling();
5941 GL_BlendFunc(GL_ONE, GL_ZERO);
5943 GL_AlphaTest(false);
5944 R_Mesh_ColorPointer(NULL, 0, 0);
5945 R_Mesh_ResetTextureState();
5946 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
5947 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5948 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
5950 else if (r_depthfirst.integer == 3)
5952 else if (!r_view.showdebug && (r_showsurfaces.integer || gl_lightmaps.integer))
5954 GL_Color(0, 0, 0, 1);
5955 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5957 else if (r_showsurfaces.integer)
5959 if (rsurface.mode != RSURFMODE_MULTIPASS)
5960 rsurface.mode = RSURFMODE_MULTIPASS;
5961 RSurf_SetupDepthAndCulling();
5963 GL_BlendFunc(GL_ONE, GL_ZERO);
5964 GL_DepthMask(writedepth);
5966 GL_AlphaTest(false);
5967 R_Mesh_ColorPointer(NULL, 0, 0);
5968 R_Mesh_ResetTextureState();
5969 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
5970 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
5972 else if (gl_lightmaps.integer)
5975 if (rsurface.mode != RSURFMODE_MULTIPASS)
5976 rsurface.mode = RSURFMODE_MULTIPASS;
5977 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5979 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_view.cullface_back);
5980 GL_BlendFunc(GL_ONE, GL_ZERO);
5981 GL_DepthMask(writedepth);
5983 GL_AlphaTest(false);
5984 R_Mesh_ColorPointer(NULL, 0, 0);
5985 memset(&m, 0, sizeof(m));
5986 m.tex[0] = R_GetTexture(r_texture_white);
5987 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
5988 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
5989 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
5990 R_Mesh_TextureState(&m);
5991 RSurf_PrepareVerticesForBatch(rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT, false, texturenumsurfaces, texturesurfacelist);
5992 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
5993 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5994 else if (rsurface.uselightmaptexture)
5995 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5997 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5999 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
6000 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
6001 else if (rsurface.texture->currentnumlayers)
6003 // write depth for anything we skipped on the depth-only pass earlier
6004 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
6006 RSurf_SetupDepthAndCulling();
6007 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
6008 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
6009 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
6010 if (r_glsl.integer && gl_support_fragment_shader)
6011 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist);
6012 else if (gl_combine.integer && r_textureunits.integer >= 2)
6013 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist);
6015 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist);
6018 GL_LockArrays(0, 0);
6021 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6024 int texturenumsurfaces, endsurface;
6026 msurface_t *surface;
6027 msurface_t *texturesurfacelist[1024];
6029 // if the model is static it doesn't matter what value we give for
6030 // wantnormals and wanttangents, so this logic uses only rules applicable
6031 // to a model, knowing that they are meaningless otherwise
6032 if (ent == r_refdef.worldentity)
6033 RSurf_ActiveWorldEntity();
6034 else if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
6035 RSurf_ActiveModelEntity(ent, false, false);
6037 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
6039 for (i = 0;i < numsurfaces;i = j)
6042 surface = rsurface.modelsurfaces + surfacelist[i];
6043 texture = surface->texture;
6044 R_UpdateTextureInfo(ent, texture);
6045 rsurface.texture = texture->currentframe;
6046 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
6047 // scan ahead until we find a different texture
6048 endsurface = min(i + 1024, numsurfaces);
6049 texturenumsurfaces = 0;
6050 texturesurfacelist[texturenumsurfaces++] = surface;
6051 for (;j < endsurface;j++)
6053 surface = rsurface.modelsurfaces + surfacelist[j];
6054 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
6056 texturesurfacelist[texturenumsurfaces++] = surface;
6058 // render the range of surfaces
6059 R_DrawTextureSurfaceList(texturenumsurfaces, texturesurfacelist, true, false);
6065 void R_QueueSurfaceList(entity_render_t *ent, int numsurfaces, msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes)
6068 vec3_t tempcenter, center;
6070 // if we're rendering water textures (extra scene renders), use a separate loop to avoid burdening the main one
6073 for (i = 0;i < numsurfaces;i++)
6074 if (surfacelist[i]->texture->currentframe->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION))
6075 R_Water_AddWaterPlane(surfacelist[i]);
6078 // break the surface list down into batches by texture and use of lightmapping
6079 for (i = 0;i < numsurfaces;i = j)
6082 // texture is the base texture pointer, rsurface.texture is the
6083 // current frame/skin the texture is directing us to use (for example
6084 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
6085 // use skin 1 instead)
6086 texture = surfacelist[i]->texture;
6087 rsurface.texture = texture->currentframe;
6088 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
6089 if (!(rsurface.texture->currentmaterialflags & flagsmask))
6091 // if this texture is not the kind we want, skip ahead to the next one
6092 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
6096 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
6098 // transparent surfaces get pushed off into the transparent queue
6099 const msurface_t *surface = surfacelist[i];
6102 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
6103 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
6104 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
6105 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
6106 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_view.origin : center, R_DrawSurface_TransparentCallback, ent, surface - rsurface.modelsurfaces, rsurface.rtlight);
6110 // simply scan ahead until we find a different texture or lightmap state
6111 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
6113 // render the range of surfaces
6114 R_DrawTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly);
6119 float locboxvertex3f[6*4*3] =
6121 1,0,1, 1,0,0, 1,1,0, 1,1,1,
6122 0,1,1, 0,1,0, 0,0,0, 0,0,1,
6123 1,1,1, 1,1,0, 0,1,0, 0,1,1,
6124 0,0,1, 0,0,0, 1,0,0, 1,0,1,
6125 0,0,1, 1,0,1, 1,1,1, 0,1,1,
6126 1,0,0, 0,0,0, 0,1,0, 1,1,0
6129 int locboxelement3i[6*2*3] =
6139 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6142 cl_locnode_t *loc = (cl_locnode_t *)ent;
6144 float vertex3f[6*4*3];
6146 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6147 GL_DepthMask(false);
6148 GL_DepthRange(0, 1);
6149 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6151 GL_CullFace(GL_NONE);
6152 R_Mesh_Matrix(&identitymatrix);
6154 R_Mesh_VertexPointer(vertex3f, 0, 0);
6155 R_Mesh_ColorPointer(NULL, 0, 0);
6156 R_Mesh_ResetTextureState();
6159 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_view.colorscale,
6160 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_view.colorscale,
6161 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_view.colorscale,
6162 surfacelist[0] < 0 ? 0.5f : 0.125f);
6164 if (VectorCompare(loc->mins, loc->maxs))
6166 VectorSet(size, 2, 2, 2);
6167 VectorMA(loc->mins, -0.5f, size, mins);
6171 VectorCopy(loc->mins, mins);
6172 VectorSubtract(loc->maxs, loc->mins, size);
6175 for (i = 0;i < 6*4*3;)
6176 for (j = 0;j < 3;j++, i++)
6177 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
6179 R_Mesh_Draw(0, 6*4, 6*2, locboxelement3i, 0, 0);
6182 void R_DrawLocs(void)
6185 cl_locnode_t *loc, *nearestloc;
6187 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
6188 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
6190 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
6191 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
6195 void R_DrawDebugModel(entity_render_t *ent)
6197 int i, j, k, l, flagsmask;
6198 const int *elements;
6200 msurface_t *surface;
6201 model_t *model = ent->model;
6204 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WATER | MATERIALFLAG_WALL;
6206 R_Mesh_ColorPointer(NULL, 0, 0);
6207 R_Mesh_ResetTextureState();
6208 GL_DepthRange(0, 1);
6209 GL_DepthTest(!r_showdisabledepthtest.integer);
6210 GL_DepthMask(false);
6211 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6213 if (r_showcollisionbrushes.value > 0 && model->brush.num_brushes)
6215 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
6216 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
6218 if (brush->colbrushf && brush->colbrushf->numtriangles)
6220 R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
6221 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);
6222 R_Mesh_Draw(0, brush->colbrushf->numpoints, brush->colbrushf->numtriangles, brush->colbrushf->elements, 0, 0);
6225 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
6227 if (surface->num_collisiontriangles)
6229 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
6230 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);
6231 R_Mesh_Draw(0, surface->num_collisionvertices, surface->num_collisiontriangles, surface->data_collisionelement3i, 0, 0);
6236 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6238 if (r_showtris.integer || r_shownormals.integer)
6240 if (r_showdisabledepthtest.integer)
6242 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6243 GL_DepthMask(false);
6247 GL_BlendFunc(GL_ONE, GL_ZERO);
6250 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
6252 if (ent == r_refdef.worldentity && !r_viewcache.world_surfacevisible[j])
6254 rsurface.texture = surface->texture->currentframe;
6255 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
6257 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
6258 if (r_showtris.value > 0)
6260 if (!rsurface.texture->currentlayers->depthmask)
6261 GL_Color(r_view.colorscale, 0, 0, r_showtris.value);
6262 else if (ent == r_refdef.worldentity)
6263 GL_Color(r_view.colorscale, r_view.colorscale, r_view.colorscale, r_showtris.value);
6265 GL_Color(0, r_view.colorscale, 0, r_showtris.value);
6266 elements = (ent->model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
6269 for (k = 0;k < surface->num_triangles;k++, elements += 3)
6271 #define GLVERTEXELEMENT(n) qglVertex3f(rsurface.vertex3f[elements[n]*3+0], rsurface.vertex3f[elements[n]*3+1], rsurface.vertex3f[elements[n]*3+2])
6272 GLVERTEXELEMENT(0);GLVERTEXELEMENT(1);
6273 GLVERTEXELEMENT(1);GLVERTEXELEMENT(2);
6274 GLVERTEXELEMENT(2);GLVERTEXELEMENT(0);
6279 if (r_shownormals.value > 0)
6282 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
6284 VectorCopy(rsurface.vertex3f + l * 3, v);
6285 GL_Color(r_view.colorscale, 0, 0, 1);
6286 qglVertex3f(v[0], v[1], v[2]);
6287 VectorMA(v, r_shownormals.value, rsurface.svector3f + l * 3, v);
6288 GL_Color(r_view.colorscale, 1, 1, 1);
6289 qglVertex3f(v[0], v[1], v[2]);
6294 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
6296 VectorCopy(rsurface.vertex3f + l * 3, v);
6297 GL_Color(0, r_view.colorscale, 0, 1);
6298 qglVertex3f(v[0], v[1], v[2]);
6299 VectorMA(v, r_shownormals.value, rsurface.tvector3f + l * 3, v);
6300 GL_Color(r_view.colorscale, 1, 1, 1);
6301 qglVertex3f(v[0], v[1], v[2]);
6306 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
6308 VectorCopy(rsurface.vertex3f + l * 3, v);
6309 GL_Color(0, 0, r_view.colorscale, 1);
6310 qglVertex3f(v[0], v[1], v[2]);
6311 VectorMA(v, r_shownormals.value, rsurface.normal3f + l * 3, v);
6312 GL_Color(r_view.colorscale, 1, 1, 1);
6313 qglVertex3f(v[0], v[1], v[2]);
6320 rsurface.texture = NULL;
6324 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
6325 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes, qboolean debug)
6327 int i, j, endj, f, flagsmask;
6328 msurface_t *surface;
6330 model_t *model = r_refdef.worldmodel;
6331 const int maxsurfacelist = 1024;
6332 int numsurfacelist = 0;
6333 msurface_t *surfacelist[1024];
6337 RSurf_ActiveWorldEntity();
6339 // update light styles on this submodel
6340 if (!skysurfaces && !depthonly && !addwaterplanes && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
6342 model_brush_lightstyleinfo_t *style;
6343 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
6345 if (style->value != r_refdef.lightstylevalue[style->style])
6347 msurface_t *surfaces = model->data_surfaces;
6348 int *list = style->surfacelist;
6349 style->value = r_refdef.lightstylevalue[style->style];
6350 for (j = 0;j < style->numsurfaces;j++)
6351 surfaces[list[j]].cached_dlight = true;
6356 R_UpdateAllTextureInfo(r_refdef.worldentity);
6357 flagsmask = addwaterplanes ? (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) : (skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL));
6361 R_DrawDebugModel(r_refdef.worldentity);
6367 rsurface.uselightmaptexture = false;
6368 rsurface.texture = NULL;
6370 j = model->firstmodelsurface;
6371 endj = j + model->nummodelsurfaces;
6374 // quickly skip over non-visible surfaces
6375 for (;j < endj && !r_viewcache.world_surfacevisible[j];j++)
6377 // quickly iterate over visible surfaces
6378 for (;j < endj && r_viewcache.world_surfacevisible[j];j++)
6380 // process this surface
6381 surface = model->data_surfaces + j;
6382 // if this surface fits the criteria, add it to the list
6383 if (surface->num_triangles)
6385 // if lightmap parameters changed, rebuild lightmap texture
6386 if (surface->cached_dlight)
6387 R_BuildLightMap(r_refdef.worldentity, surface);
6388 // add face to draw list
6389 surfacelist[numsurfacelist++] = surface;
6390 r_refdef.stats.world_triangles += surface->num_triangles;
6391 if (numsurfacelist >= maxsurfacelist)
6393 r_refdef.stats.world_surfaces += numsurfacelist;
6394 R_QueueSurfaceList(r_refdef.worldentity, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
6400 r_refdef.stats.world_surfaces += numsurfacelist;
6402 R_QueueSurfaceList(r_refdef.worldentity, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
6406 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes, qboolean debug)
6408 int i, j, f, flagsmask;
6409 msurface_t *surface, *endsurface;
6411 model_t *model = ent->model;
6412 const int maxsurfacelist = 1024;
6413 int numsurfacelist = 0;
6414 msurface_t *surfacelist[1024];
6418 // if the model is static it doesn't matter what value we give for
6419 // wantnormals and wanttangents, so this logic uses only rules applicable
6420 // to a model, knowing that they are meaningless otherwise
6421 if (ent == r_refdef.worldentity)
6422 RSurf_ActiveWorldEntity();
6423 else if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
6424 RSurf_ActiveModelEntity(ent, false, false);
6426 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader && !depthonly);
6428 // update light styles
6429 if (!skysurfaces && !depthonly && !addwaterplanes && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
6431 model_brush_lightstyleinfo_t *style;
6432 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
6434 if (style->value != r_refdef.lightstylevalue[style->style])
6436 msurface_t *surfaces = model->data_surfaces;
6437 int *list = style->surfacelist;
6438 style->value = r_refdef.lightstylevalue[style->style];
6439 for (j = 0;j < style->numsurfaces;j++)
6440 surfaces[list[j]].cached_dlight = true;
6445 R_UpdateAllTextureInfo(ent);
6446 flagsmask = addwaterplanes ? (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) : (skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL));
6450 R_DrawDebugModel(ent);
6456 rsurface.uselightmaptexture = false;
6457 rsurface.texture = NULL;
6459 surface = model->data_surfaces + model->firstmodelsurface;
6460 endsurface = surface + model->nummodelsurfaces;
6461 for (;surface < endsurface;surface++)
6463 // if this surface fits the criteria, add it to the list
6464 if (surface->num_triangles)
6466 // if lightmap parameters changed, rebuild lightmap texture
6467 if (surface->cached_dlight)
6468 R_BuildLightMap(ent, surface);
6469 // add face to draw list
6470 surfacelist[numsurfacelist++] = surface;
6471 r_refdef.stats.entities_triangles += surface->num_triangles;
6472 if (numsurfacelist >= maxsurfacelist)
6474 r_refdef.stats.entities_surfaces += numsurfacelist;
6475 R_QueueSurfaceList(ent, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
6480 r_refdef.stats.entities_surfaces += numsurfacelist;
6482 R_QueueSurfaceList(ent, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);