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 *= ContrastBoost / ((ContrastBoost - 1) * color.rgb + 1);
1453 // color.rgb *= SceneBrightness;
1455 // color.rgb = [[SceneBrightness * ContrastBoost]] * color.rgb / ([[ContrastBoost - 1]] * color.rgb + 1);
1456 // and do [[calculations]] here in the engine
1457 qglUniform1fARB(r_glsl_permutation->loc_ContrastBoostCoeff, r_glsl_contrastboost.value - 1);
1458 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_view.colorscale * r_glsl_contrastboost.value);
1461 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_view.colorscale);
1462 if (r_glsl_permutation->loc_FogColor >= 0)
1464 // additive passes are only darkened by fog, not tinted
1465 if (rsurface.rtlight || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD))
1466 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
1468 qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
1470 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.modelorg[0], rsurface.modelorg[1], rsurface.modelorg[2]);
1471 if (r_glsl_permutation->loc_Color_Pants >= 0)
1473 if (rsurface.texture->currentskinframe->pants)
1474 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
1476 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
1478 if (r_glsl_permutation->loc_Color_Shirt >= 0)
1480 if (rsurface.texture->currentskinframe->shirt)
1481 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
1483 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
1485 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, r_refdef.fograngerecip);
1486 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower);
1487 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
1488 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);
1489 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]);
1490 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]);
1491 if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f);
1492 if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f);
1493 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
1494 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
1499 #define SKINFRAME_HASH 1024
1503 int loadsequence; // incremented each level change
1504 memexpandablearray_t array;
1505 skinframe_t *hash[SKINFRAME_HASH];
1509 void R_SkinFrame_PrepareForPurge(void)
1511 r_skinframe.loadsequence++;
1512 // wrap it without hitting zero
1513 if (r_skinframe.loadsequence >= 200)
1514 r_skinframe.loadsequence = 1;
1517 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
1521 // mark the skinframe as used for the purging code
1522 skinframe->loadsequence = r_skinframe.loadsequence;
1525 void R_SkinFrame_Purge(void)
1529 for (i = 0;i < SKINFRAME_HASH;i++)
1531 for (s = r_skinframe.hash[i];s;s = s->next)
1533 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
1535 if (s->merged == s->base)
1537 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
1538 R_PurgeTexture(s->stain );s->stain = NULL;
1539 R_PurgeTexture(s->merged);s->merged = NULL;
1540 R_PurgeTexture(s->base );s->base = NULL;
1541 R_PurgeTexture(s->pants );s->pants = NULL;
1542 R_PurgeTexture(s->shirt );s->shirt = NULL;
1543 R_PurgeTexture(s->nmap );s->nmap = NULL;
1544 R_PurgeTexture(s->gloss );s->gloss = NULL;
1545 R_PurgeTexture(s->glow );s->glow = NULL;
1546 R_PurgeTexture(s->fog );s->fog = NULL;
1547 s->loadsequence = 0;
1553 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
1555 char basename[MAX_QPATH];
1557 Image_StripImageExtension(name, basename, sizeof(basename));
1559 if( last == NULL ) {
1561 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
1562 item = r_skinframe.hash[hashindex];
1567 // linearly search through the hash bucket
1568 for( ; item ; item = item->next ) {
1569 if( !strcmp( item->basename, basename ) ) {
1576 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
1580 char basename[MAX_QPATH];
1582 Image_StripImageExtension(name, basename, sizeof(basename));
1584 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
1585 for (item = r_skinframe.hash[hashindex];item;item = item->next)
1586 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
1590 rtexture_t *dyntexture;
1591 // check whether its a dynamic texture
1592 dyntexture = CL_GetDynTexture( basename );
1593 if (!add && !dyntexture)
1595 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
1596 memset(item, 0, sizeof(*item));
1597 strlcpy(item->basename, basename, sizeof(item->basename));
1598 item->base = dyntexture; // either NULL or dyntexture handle
1599 item->textureflags = textureflags;
1600 item->comparewidth = comparewidth;
1601 item->compareheight = compareheight;
1602 item->comparecrc = comparecrc;
1603 item->next = r_skinframe.hash[hashindex];
1604 r_skinframe.hash[hashindex] = item;
1606 else if( item->base == NULL )
1608 rtexture_t *dyntexture;
1609 // check whether its a dynamic texture
1610 // 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]
1611 dyntexture = CL_GetDynTexture( basename );
1612 item->base = dyntexture; // either NULL or dyntexture handle
1615 R_SkinFrame_MarkUsed(item);
1619 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
1621 // FIXME: it should be possible to disable loading various layers using
1622 // cvars, to prevent wasted loading time and memory usage if the user does
1624 qboolean loadnormalmap = true;
1625 qboolean loadgloss = true;
1626 qboolean loadpantsandshirt = true;
1627 qboolean loadglow = true;
1629 unsigned char *pixels;
1630 unsigned char *bumppixels;
1631 unsigned char *basepixels = NULL;
1632 int basepixels_width;
1633 int basepixels_height;
1634 skinframe_t *skinframe;
1636 if (cls.state == ca_dedicated)
1639 // return an existing skinframe if already loaded
1640 // if loading of the first image fails, don't make a new skinframe as it
1641 // would cause all future lookups of this to be missing
1642 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
1643 if (skinframe && skinframe->base)
1646 basepixels = loadimagepixelsbgra(name, complain, true);
1647 if (basepixels == NULL)
1650 // we've got some pixels to store, so really allocate this new texture now
1652 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
1653 skinframe->stain = NULL;
1654 skinframe->merged = NULL;
1655 skinframe->base = r_texture_notexture;
1656 skinframe->pants = NULL;
1657 skinframe->shirt = NULL;
1658 skinframe->nmap = r_texture_blanknormalmap;
1659 skinframe->gloss = NULL;
1660 skinframe->glow = NULL;
1661 skinframe->fog = NULL;
1663 basepixels_width = image_width;
1664 basepixels_height = image_height;
1665 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);
1667 if (textureflags & TEXF_ALPHA)
1669 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
1670 if (basepixels[j] < 255)
1672 if (j < basepixels_width * basepixels_height * 4)
1674 // has transparent pixels
1675 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
1676 for (j = 0;j < image_width * image_height * 4;j += 4)
1681 pixels[j+3] = basepixels[j+3];
1683 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);
1688 // _norm is the name used by tenebrae and has been adopted as standard
1691 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false)) != NULL)
1693 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);
1697 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false)) != NULL)
1699 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
1700 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
1701 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);
1703 Mem_Free(bumppixels);
1705 else if (r_shadow_bumpscale_basetexture.value > 0)
1707 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
1708 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
1709 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);
1713 // _luma is supported for tenebrae compatibility
1714 // (I think it's a very stupid name, but oh well)
1715 // _glow is the preferred name
1716 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;}
1717 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;}
1718 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;}
1719 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;}
1722 Mem_Free(basepixels);
1727 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)
1732 for (i = 0;i < width*height;i++)
1733 if (((unsigned char *)&palette[in[i]])[3] > 0)
1735 if (i == width*height)
1738 return R_LoadTexture2D (r_main_texturepool, name, width, height, in, TEXTYPE_PALETTE, textureflags, palette);
1741 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
1742 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
1745 unsigned char *temp1, *temp2;
1746 skinframe_t *skinframe;
1748 if (cls.state == ca_dedicated)
1751 // if already loaded just return it, otherwise make a new skinframe
1752 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
1753 if (skinframe && skinframe->base)
1756 skinframe->stain = NULL;
1757 skinframe->merged = NULL;
1758 skinframe->base = r_texture_notexture;
1759 skinframe->pants = NULL;
1760 skinframe->shirt = NULL;
1761 skinframe->nmap = r_texture_blanknormalmap;
1762 skinframe->gloss = NULL;
1763 skinframe->glow = NULL;
1764 skinframe->fog = NULL;
1766 // if no data was provided, then clearly the caller wanted to get a blank skinframe
1770 if (r_shadow_bumpscale_basetexture.value > 0)
1772 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
1773 temp2 = temp1 + width * height * 4;
1774 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
1775 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
1778 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, skinframe->textureflags, NULL);
1779 if (textureflags & TEXF_ALPHA)
1781 for (i = 3;i < width * height * 4;i += 4)
1782 if (skindata[i] < 255)
1784 if (i < width * height * 4)
1786 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
1787 memcpy(fogpixels, skindata, width * height * 4);
1788 for (i = 0;i < width * height * 4;i += 4)
1789 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
1790 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, skinframe->textureflags, NULL);
1791 Mem_Free(fogpixels);
1798 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
1801 unsigned char *temp1, *temp2;
1802 skinframe_t *skinframe;
1804 if (cls.state == ca_dedicated)
1807 // if already loaded just return it, otherwise make a new skinframe
1808 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
1809 if (skinframe && skinframe->base)
1812 skinframe->stain = NULL;
1813 skinframe->merged = NULL;
1814 skinframe->base = r_texture_notexture;
1815 skinframe->pants = NULL;
1816 skinframe->shirt = NULL;
1817 skinframe->nmap = r_texture_blanknormalmap;
1818 skinframe->gloss = NULL;
1819 skinframe->glow = NULL;
1820 skinframe->fog = NULL;
1822 // if no data was provided, then clearly the caller wanted to get a blank skinframe
1826 if (r_shadow_bumpscale_basetexture.value > 0)
1828 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
1829 temp2 = temp1 + width * height * 4;
1830 // use either a custom palette or the quake palette
1831 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
1832 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
1833 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
1836 // use either a custom palette, or the quake palette
1837 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
1838 if (loadglowtexture)
1839 skinframe->glow = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_glow", skinframe->basename), palette_bgra_onlyfullbrights, skinframe->textureflags, false); // glow
1840 if (loadpantsandshirt)
1842 skinframe->pants = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_pants", skinframe->basename), palette_bgra_pantsaswhite, skinframe->textureflags, false); // pants
1843 skinframe->shirt = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_shirt", skinframe->basename), palette_bgra_shirtaswhite, skinframe->textureflags, false); // shirt
1845 if (skinframe->pants || skinframe->shirt)
1846 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
1847 if (textureflags & TEXF_ALPHA)
1849 for (i = 0;i < width * height;i++)
1850 if (((unsigned char *)palette_bgra_alpha)[skindata[i]*4+3] < 255)
1852 if (i < width * height)
1853 skinframe->fog = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_fog", skinframe->basename), palette_bgra_alpha, skinframe->textureflags, true); // fog mask
1859 skinframe_t *R_SkinFrame_LoadMissing(void)
1861 skinframe_t *skinframe;
1863 if (cls.state == ca_dedicated)
1866 skinframe = R_SkinFrame_Find("missing", TEXF_PRECACHE, 0, 0, 0, true);
1867 skinframe->stain = NULL;
1868 skinframe->merged = NULL;
1869 skinframe->base = r_texture_notexture;
1870 skinframe->pants = NULL;
1871 skinframe->shirt = NULL;
1872 skinframe->nmap = r_texture_blanknormalmap;
1873 skinframe->gloss = NULL;
1874 skinframe->glow = NULL;
1875 skinframe->fog = NULL;
1880 void gl_main_start(void)
1882 memset(r_qwskincache, 0, sizeof(r_qwskincache));
1883 memset(r_qwskincache_skinframe, 0, sizeof(r_qwskincache_skinframe));
1885 // set up r_skinframe loading system for textures
1886 memset(&r_skinframe, 0, sizeof(r_skinframe));
1887 r_skinframe.loadsequence = 1;
1888 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
1890 r_main_texturepool = R_AllocTexturePool();
1891 R_BuildBlankTextures();
1893 if (gl_texturecubemap)
1896 R_BuildNormalizationCube();
1898 r_texture_fogattenuation = NULL;
1899 //r_texture_fogintensity = NULL;
1900 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
1901 memset(&r_waterstate, 0, sizeof(r_waterstate));
1902 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
1903 memset(&r_svbsp, 0, sizeof (r_svbsp));
1905 r_refdef.fogmasktable_density = 0;
1908 void gl_main_shutdown(void)
1910 memset(r_qwskincache, 0, sizeof(r_qwskincache));
1911 memset(r_qwskincache_skinframe, 0, sizeof(r_qwskincache_skinframe));
1913 // clear out the r_skinframe state
1914 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
1915 memset(&r_skinframe, 0, sizeof(r_skinframe));
1918 Mem_Free(r_svbsp.nodes);
1919 memset(&r_svbsp, 0, sizeof (r_svbsp));
1920 R_FreeTexturePool(&r_main_texturepool);
1921 r_texture_blanknormalmap = NULL;
1922 r_texture_white = NULL;
1923 r_texture_grey128 = NULL;
1924 r_texture_black = NULL;
1925 r_texture_whitecube = NULL;
1926 r_texture_normalizationcube = NULL;
1927 r_texture_fogattenuation = NULL;
1928 //r_texture_fogintensity = NULL;
1929 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
1930 memset(&r_waterstate, 0, sizeof(r_waterstate));
1934 extern void CL_ParseEntityLump(char *entitystring);
1935 void gl_main_newmap(void)
1937 // FIXME: move this code to client
1939 char *entities, entname[MAX_QPATH];
1942 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
1943 l = (int)strlen(entname) - 4;
1944 if (l >= 0 && !strcmp(entname + l, ".bsp"))
1946 memcpy(entname + l, ".ent", 5);
1947 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
1949 CL_ParseEntityLump(entities);
1954 if (cl.worldmodel->brush.entities)
1955 CL_ParseEntityLump(cl.worldmodel->brush.entities);
1959 void GL_Main_Init(void)
1961 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
1963 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
1964 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
1965 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
1966 if (gamemode == GAME_NEHAHRA)
1968 Cvar_RegisterVariable (&gl_fogenable);
1969 Cvar_RegisterVariable (&gl_fogdensity);
1970 Cvar_RegisterVariable (&gl_fogred);
1971 Cvar_RegisterVariable (&gl_foggreen);
1972 Cvar_RegisterVariable (&gl_fogblue);
1973 Cvar_RegisterVariable (&gl_fogstart);
1974 Cvar_RegisterVariable (&gl_fogend);
1975 Cvar_RegisterVariable (&gl_skyclip);
1977 Cvar_RegisterVariable(&r_depthfirst);
1978 Cvar_RegisterVariable(&r_nearclip);
1979 Cvar_RegisterVariable(&r_showbboxes);
1980 Cvar_RegisterVariable(&r_showsurfaces);
1981 Cvar_RegisterVariable(&r_showtris);
1982 Cvar_RegisterVariable(&r_shownormals);
1983 Cvar_RegisterVariable(&r_showlighting);
1984 Cvar_RegisterVariable(&r_showshadowvolumes);
1985 Cvar_RegisterVariable(&r_showcollisionbrushes);
1986 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
1987 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
1988 Cvar_RegisterVariable(&r_showdisabledepthtest);
1989 Cvar_RegisterVariable(&r_drawportals);
1990 Cvar_RegisterVariable(&r_drawentities);
1991 Cvar_RegisterVariable(&r_cullentities_trace);
1992 Cvar_RegisterVariable(&r_cullentities_trace_samples);
1993 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
1994 Cvar_RegisterVariable(&r_cullentities_trace_delay);
1995 Cvar_RegisterVariable(&r_drawviewmodel);
1996 Cvar_RegisterVariable(&r_speeds);
1997 Cvar_RegisterVariable(&r_fullbrights);
1998 Cvar_RegisterVariable(&r_wateralpha);
1999 Cvar_RegisterVariable(&r_dynamic);
2000 Cvar_RegisterVariable(&r_fullbright);
2001 Cvar_RegisterVariable(&r_shadows);
2002 Cvar_RegisterVariable(&r_shadows_throwdistance);
2003 Cvar_RegisterVariable(&r_q1bsp_skymasking);
2004 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
2005 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
2006 Cvar_RegisterVariable(&r_fog_exp2);
2007 Cvar_RegisterVariable(&r_textureunits);
2008 Cvar_RegisterVariable(&r_glsl);
2009 Cvar_RegisterVariable(&r_glsl_offsetmapping);
2010 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
2011 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
2012 Cvar_RegisterVariable(&r_glsl_deluxemapping);
2013 Cvar_RegisterVariable(&r_water);
2014 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
2015 Cvar_RegisterVariable(&r_water_clippingplanebias);
2016 Cvar_RegisterVariable(&r_water_refractdistort);
2017 Cvar_RegisterVariable(&r_water_reflectdistort);
2018 Cvar_RegisterVariable(&r_lerpsprites);
2019 Cvar_RegisterVariable(&r_lerpmodels);
2020 Cvar_RegisterVariable(&r_lerplightstyles);
2021 Cvar_RegisterVariable(&r_waterscroll);
2022 Cvar_RegisterVariable(&r_bloom);
2023 Cvar_RegisterVariable(&r_bloom_colorscale);
2024 Cvar_RegisterVariable(&r_bloom_brighten);
2025 Cvar_RegisterVariable(&r_bloom_blur);
2026 Cvar_RegisterVariable(&r_bloom_resolution);
2027 Cvar_RegisterVariable(&r_bloom_colorexponent);
2028 Cvar_RegisterVariable(&r_bloom_colorsubtract);
2029 Cvar_RegisterVariable(&r_hdr);
2030 Cvar_RegisterVariable(&r_hdr_scenebrightness);
2031 Cvar_RegisterVariable(&r_glsl_contrastboost);
2032 Cvar_RegisterVariable(&r_hdr_glowintensity);
2033 Cvar_RegisterVariable(&r_hdr_range);
2034 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
2035 Cvar_RegisterVariable(&developer_texturelogging);
2036 Cvar_RegisterVariable(&gl_lightmaps);
2037 Cvar_RegisterVariable(&r_test);
2038 Cvar_RegisterVariable(&r_batchmode);
2039 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
2040 Cvar_SetValue("r_fullbrights", 0);
2041 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
2043 Cvar_RegisterVariable(&r_track_sprites);
2044 Cvar_RegisterVariable(&r_track_sprites_flags);
2045 Cvar_RegisterVariable(&r_track_sprites_scalew);
2046 Cvar_RegisterVariable(&r_track_sprites_scaleh);
2049 extern void R_Textures_Init(void);
2050 extern void GL_Draw_Init(void);
2051 extern void GL_Main_Init(void);
2052 extern void R_Shadow_Init(void);
2053 extern void R_Sky_Init(void);
2054 extern void GL_Surf_Init(void);
2055 extern void R_Particles_Init(void);
2056 extern void R_Explosion_Init(void);
2057 extern void gl_backend_init(void);
2058 extern void Sbar_Init(void);
2059 extern void R_LightningBeams_Init(void);
2060 extern void Mod_RenderInit(void);
2062 void Render_Init(void)
2074 R_LightningBeams_Init();
2083 extern char *ENGINE_EXTENSIONS;
2086 VID_CheckExtensions();
2088 // LordHavoc: report supported extensions
2089 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
2091 // clear to black (loading plaque will be seen over this)
2093 qglClearColor(0,0,0,1);CHECKGLERROR
2094 qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
2097 int R_CullBox(const vec3_t mins, const vec3_t maxs)
2101 for (i = 0;i < r_view.numfrustumplanes;i++)
2103 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
2106 p = r_view.frustum + i;
2111 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2115 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2119 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2123 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2127 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2131 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2135 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2139 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2147 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
2151 for (i = 0;i < numplanes;i++)
2158 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2162 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2166 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2170 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2174 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2178 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2182 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2186 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2194 //==================================================================================
2196 static void R_View_UpdateEntityVisible (void)
2199 entity_render_t *ent;
2201 if (!r_drawentities.integer)
2204 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : ((chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL : RENDER_EXTERIORMODEL);
2205 if (r_refdef.worldmodel && r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs)
2207 // worldmodel can check visibility
2208 for (i = 0;i < r_refdef.numentities;i++)
2210 ent = r_refdef.entities[i];
2211 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));
2214 if(r_cullentities_trace.integer)
2216 for (i = 0;i < r_refdef.numentities;i++)
2218 ent = r_refdef.entities[i];
2219 if(r_viewcache.entityvisible[i] && !(ent->effects & EF_NODEPTHTEST) && !(ent->flags & RENDER_VIEWMODEL) && !(ent->model && (ent->model->name[0] == '*')))
2221 if(Mod_CanSeeBox_Trace(r_cullentities_trace_samples.integer, r_cullentities_trace_enlarge.value, r_refdef.worldmodel, r_view.origin, ent->mins, ent->maxs))
2222 ent->last_trace_visibility = realtime;
2223 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
2224 r_viewcache.entityvisible[i] = 0;
2231 // no worldmodel or it can't check visibility
2232 for (i = 0;i < r_refdef.numentities;i++)
2234 ent = r_refdef.entities[i];
2235 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));
2240 // only used if skyrendermasked, and normally returns false
2241 int R_DrawBrushModelsSky (void)
2244 entity_render_t *ent;
2246 if (!r_drawentities.integer)
2250 for (i = 0;i < r_refdef.numentities;i++)
2252 if (!r_viewcache.entityvisible[i])
2254 ent = r_refdef.entities[i];
2255 if (!ent->model || !ent->model->DrawSky)
2257 ent->model->DrawSky(ent);
2263 static void R_DrawNoModel(entity_render_t *ent);
2264 static void R_DrawModels(void)
2267 entity_render_t *ent;
2269 if (!r_drawentities.integer)
2272 for (i = 0;i < r_refdef.numentities;i++)
2274 if (!r_viewcache.entityvisible[i])
2276 ent = r_refdef.entities[i];
2277 r_refdef.stats.entities++;
2278 if (ent->model && ent->model->Draw != NULL)
2279 ent->model->Draw(ent);
2285 static void R_DrawModelsDepth(void)
2288 entity_render_t *ent;
2290 if (!r_drawentities.integer)
2293 for (i = 0;i < r_refdef.numentities;i++)
2295 if (!r_viewcache.entityvisible[i])
2297 ent = r_refdef.entities[i];
2298 if (ent->model && ent->model->DrawDepth != NULL)
2299 ent->model->DrawDepth(ent);
2303 static void R_DrawModelsDebug(void)
2306 entity_render_t *ent;
2308 if (!r_drawentities.integer)
2311 for (i = 0;i < r_refdef.numentities;i++)
2313 if (!r_viewcache.entityvisible[i])
2315 ent = r_refdef.entities[i];
2316 if (ent->model && ent->model->DrawDebug != NULL)
2317 ent->model->DrawDebug(ent);
2321 static void R_DrawModelsAddWaterPlanes(void)
2324 entity_render_t *ent;
2326 if (!r_drawentities.integer)
2329 for (i = 0;i < r_refdef.numentities;i++)
2331 if (!r_viewcache.entityvisible[i])
2333 ent = r_refdef.entities[i];
2334 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
2335 ent->model->DrawAddWaterPlanes(ent);
2339 static void R_View_SetFrustum(void)
2342 double slopex, slopey;
2344 // break apart the view matrix into vectors for various purposes
2345 Matrix4x4_ToVectors(&r_view.matrix, r_view.forward, r_view.left, r_view.up, r_view.origin);
2346 VectorNegate(r_view.left, r_view.right);
2349 r_view.frustum[0].normal[0] = 0 - 1.0 / r_view.frustum_x;
2350 r_view.frustum[0].normal[1] = 0 - 0;
2351 r_view.frustum[0].normal[2] = -1 - 0;
2352 r_view.frustum[1].normal[0] = 0 + 1.0 / r_view.frustum_x;
2353 r_view.frustum[1].normal[1] = 0 + 0;
2354 r_view.frustum[1].normal[2] = -1 + 0;
2355 r_view.frustum[2].normal[0] = 0 - 0;
2356 r_view.frustum[2].normal[1] = 0 - 1.0 / r_view.frustum_y;
2357 r_view.frustum[2].normal[2] = -1 - 0;
2358 r_view.frustum[3].normal[0] = 0 + 0;
2359 r_view.frustum[3].normal[1] = 0 + 1.0 / r_view.frustum_y;
2360 r_view.frustum[3].normal[2] = -1 + 0;
2364 zNear = r_refdef.nearclip;
2365 nudge = 1.0 - 1.0 / (1<<23);
2366 r_view.frustum[4].normal[0] = 0 - 0;
2367 r_view.frustum[4].normal[1] = 0 - 0;
2368 r_view.frustum[4].normal[2] = -1 - -nudge;
2369 r_view.frustum[4].dist = 0 - -2 * zNear * nudge;
2370 r_view.frustum[5].normal[0] = 0 + 0;
2371 r_view.frustum[5].normal[1] = 0 + 0;
2372 r_view.frustum[5].normal[2] = -1 + -nudge;
2373 r_view.frustum[5].dist = 0 + -2 * zNear * nudge;
2379 r_view.frustum[0].normal[0] = m[3] - m[0];
2380 r_view.frustum[0].normal[1] = m[7] - m[4];
2381 r_view.frustum[0].normal[2] = m[11] - m[8];
2382 r_view.frustum[0].dist = m[15] - m[12];
2384 r_view.frustum[1].normal[0] = m[3] + m[0];
2385 r_view.frustum[1].normal[1] = m[7] + m[4];
2386 r_view.frustum[1].normal[2] = m[11] + m[8];
2387 r_view.frustum[1].dist = m[15] + m[12];
2389 r_view.frustum[2].normal[0] = m[3] - m[1];
2390 r_view.frustum[2].normal[1] = m[7] - m[5];
2391 r_view.frustum[2].normal[2] = m[11] - m[9];
2392 r_view.frustum[2].dist = m[15] - m[13];
2394 r_view.frustum[3].normal[0] = m[3] + m[1];
2395 r_view.frustum[3].normal[1] = m[7] + m[5];
2396 r_view.frustum[3].normal[2] = m[11] + m[9];
2397 r_view.frustum[3].dist = m[15] + m[13];
2399 r_view.frustum[4].normal[0] = m[3] - m[2];
2400 r_view.frustum[4].normal[1] = m[7] - m[6];
2401 r_view.frustum[4].normal[2] = m[11] - m[10];
2402 r_view.frustum[4].dist = m[15] - m[14];
2404 r_view.frustum[5].normal[0] = m[3] + m[2];
2405 r_view.frustum[5].normal[1] = m[7] + m[6];
2406 r_view.frustum[5].normal[2] = m[11] + m[10];
2407 r_view.frustum[5].dist = m[15] + m[14];
2410 if (r_view.useperspective)
2412 slopex = 1.0 / r_view.frustum_x;
2413 slopey = 1.0 / r_view.frustum_y;
2414 VectorMA(r_view.forward, -slopex, r_view.left, r_view.frustum[0].normal);
2415 VectorMA(r_view.forward, slopex, r_view.left, r_view.frustum[1].normal);
2416 VectorMA(r_view.forward, -slopey, r_view.up , r_view.frustum[2].normal);
2417 VectorMA(r_view.forward, slopey, r_view.up , r_view.frustum[3].normal);
2418 VectorCopy(r_view.forward, r_view.frustum[4].normal);
2420 // Leaving those out was a mistake, those were in the old code, and they
2421 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
2422 // I couldn't reproduce it after adding those normalizations. --blub
2423 VectorNormalize(r_view.frustum[0].normal);
2424 VectorNormalize(r_view.frustum[1].normal);
2425 VectorNormalize(r_view.frustum[2].normal);
2426 VectorNormalize(r_view.frustum[3].normal);
2428 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
2429 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, -1024 * slopex, r_view.left, -1024 * slopey, r_view.up, r_view.frustumcorner[0]);
2430 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, 1024 * slopex, r_view.left, -1024 * slopey, r_view.up, r_view.frustumcorner[1]);
2431 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, -1024 * slopex, r_view.left, 1024 * slopey, r_view.up, r_view.frustumcorner[2]);
2432 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, 1024 * slopex, r_view.left, 1024 * slopey, r_view.up, r_view.frustumcorner[3]);
2434 r_view.frustum[0].dist = DotProduct (r_view.origin, r_view.frustum[0].normal);
2435 r_view.frustum[1].dist = DotProduct (r_view.origin, r_view.frustum[1].normal);
2436 r_view.frustum[2].dist = DotProduct (r_view.origin, r_view.frustum[2].normal);
2437 r_view.frustum[3].dist = DotProduct (r_view.origin, r_view.frustum[3].normal);
2438 r_view.frustum[4].dist = DotProduct (r_view.origin, r_view.frustum[4].normal) + r_refdef.nearclip;
2442 VectorScale(r_view.left, -r_view.ortho_x, r_view.frustum[0].normal);
2443 VectorScale(r_view.left, r_view.ortho_x, r_view.frustum[1].normal);
2444 VectorScale(r_view.up, -r_view.ortho_y, r_view.frustum[2].normal);
2445 VectorScale(r_view.up, r_view.ortho_y, r_view.frustum[3].normal);
2446 VectorCopy(r_view.forward, r_view.frustum[4].normal);
2447 r_view.frustum[0].dist = DotProduct (r_view.origin, r_view.frustum[0].normal) + r_view.ortho_x;
2448 r_view.frustum[1].dist = DotProduct (r_view.origin, r_view.frustum[1].normal) + r_view.ortho_x;
2449 r_view.frustum[2].dist = DotProduct (r_view.origin, r_view.frustum[2].normal) + r_view.ortho_y;
2450 r_view.frustum[3].dist = DotProduct (r_view.origin, r_view.frustum[3].normal) + r_view.ortho_y;
2451 r_view.frustum[4].dist = DotProduct (r_view.origin, r_view.frustum[4].normal) + r_refdef.nearclip;
2453 r_view.numfrustumplanes = 5;
2455 if (r_view.useclipplane)
2457 r_view.numfrustumplanes = 6;
2458 r_view.frustum[5] = r_view.clipplane;
2461 for (i = 0;i < r_view.numfrustumplanes;i++)
2462 PlaneClassify(r_view.frustum + i);
2464 // LordHavoc: note to all quake engine coders, Quake had a special case
2465 // for 90 degrees which assumed a square view (wrong), so I removed it,
2466 // Quake2 has it disabled as well.
2468 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
2469 //RotatePointAroundVector( r_view.frustum[0].normal, r_view.up, r_view.forward, -(90 - r_refdef.fov_x / 2));
2470 //r_view.frustum[0].dist = DotProduct (r_view.origin, frustum[0].normal);
2471 //PlaneClassify(&frustum[0]);
2473 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
2474 //RotatePointAroundVector( r_view.frustum[1].normal, r_view.up, r_view.forward, (90 - r_refdef.fov_x / 2));
2475 //r_view.frustum[1].dist = DotProduct (r_view.origin, frustum[1].normal);
2476 //PlaneClassify(&frustum[1]);
2478 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
2479 //RotatePointAroundVector( r_view.frustum[2].normal, r_view.left, r_view.forward, -(90 - r_refdef.fov_y / 2));
2480 //r_view.frustum[2].dist = DotProduct (r_view.origin, frustum[2].normal);
2481 //PlaneClassify(&frustum[2]);
2483 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
2484 //RotatePointAroundVector( r_view.frustum[3].normal, r_view.left, r_view.forward, (90 - r_refdef.fov_y / 2));
2485 //r_view.frustum[3].dist = DotProduct (r_view.origin, frustum[3].normal);
2486 //PlaneClassify(&frustum[3]);
2489 //VectorCopy(r_view.forward, r_view.frustum[4].normal);
2490 //r_view.frustum[4].dist = DotProduct (r_view.origin, frustum[4].normal) + r_nearclip.value;
2491 //PlaneClassify(&frustum[4]);
2494 void R_View_Update(void)
2496 R_View_SetFrustum();
2497 R_View_WorldVisibility(r_view.useclipplane);
2498 R_View_UpdateEntityVisible();
2501 void R_SetupView(void)
2503 if (!r_view.useperspective)
2504 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);
2505 else if (r_refdef.rtworldshadows || r_refdef.rtdlightshadows)
2506 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_view.frustum_x, r_view.frustum_y, r_refdef.nearclip);
2508 GL_SetupView_Mode_Perspective(r_view.frustum_x, r_view.frustum_y, r_refdef.nearclip, r_refdef.farclip);
2510 GL_SetupView_Orientation_FromEntity(&r_view.matrix);
2512 if (r_view.useclipplane)
2514 // LordHavoc: couldn't figure out how to make this approach the
2515 vec_t dist = r_view.clipplane.dist - r_water_clippingplanebias.value;
2516 vec_t viewdist = DotProduct(r_view.origin, r_view.clipplane.normal);
2517 if (viewdist < r_view.clipplane.dist + r_water_clippingplanebias.value)
2518 dist = r_view.clipplane.dist;
2519 GL_SetupView_ApplyCustomNearClipPlane(r_view.clipplane.normal[0], r_view.clipplane.normal[1], r_view.clipplane.normal[2], dist);
2523 void R_ResetViewRendering2D(void)
2525 if (gl_support_fragment_shader)
2527 qglUseProgramObjectARB(0);CHECKGLERROR
2532 // GL is weird because it's bottom to top, r_view.y is top to bottom
2533 qglViewport(r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
2534 GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
2535 GL_Scissor(r_view.x, r_view.y, r_view.width, r_view.height);
2536 GL_Color(1, 1, 1, 1);
2537 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
2538 GL_BlendFunc(GL_ONE, GL_ZERO);
2539 GL_AlphaTest(false);
2540 GL_ScissorTest(false);
2541 GL_DepthMask(false);
2542 GL_DepthRange(0, 1);
2543 GL_DepthTest(false);
2544 R_Mesh_Matrix(&identitymatrix);
2545 R_Mesh_ResetTextureState();
2546 GL_PolygonOffset(0, 0);
2547 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
2548 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
2549 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
2550 qglStencilMask(~0);CHECKGLERROR
2551 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
2552 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
2553 GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
2556 void R_ResetViewRendering3D(void)
2558 if (gl_support_fragment_shader)
2560 qglUseProgramObjectARB(0);CHECKGLERROR
2565 // GL is weird because it's bottom to top, r_view.y is top to bottom
2566 qglViewport(r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
2568 GL_Scissor(r_view.x, r_view.y, r_view.width, r_view.height);
2569 GL_Color(1, 1, 1, 1);
2570 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
2571 GL_BlendFunc(GL_ONE, GL_ZERO);
2572 GL_AlphaTest(false);
2573 GL_ScissorTest(true);
2575 GL_DepthRange(0, 1);
2577 R_Mesh_Matrix(&identitymatrix);
2578 R_Mesh_ResetTextureState();
2579 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
2580 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
2581 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
2582 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
2583 qglStencilMask(~0);CHECKGLERROR
2584 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
2585 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
2586 GL_CullFace(r_view.cullface_back);
2590 R_Bloom_SetupShader(
2592 "// written by Forest 'LordHavoc' Hale\n"
2594 "// common definitions between vertex shader and fragment shader:\n"
2596 "#ifdef __GLSL_CG_DATA_TYPES\n"
2597 "#define myhalf half\n"
2598 "#define myhvec2 hvec2\n"
2599 "#define myhvec3 hvec3\n"
2600 "#define myhvec4 hvec4\n"
2602 "#define myhalf float\n"
2603 "#define myhvec2 vec2\n"
2604 "#define myhvec3 vec3\n"
2605 "#define myhvec4 vec4\n"
2608 "varying vec2 ScreenTexCoord;\n"
2609 "varying vec2 BloomTexCoord;\n"
2614 "// vertex shader specific:\n"
2615 "#ifdef VERTEX_SHADER\n"
2619 " ScreenTexCoord = vec2(gl_MultiTexCoord0);\n"
2620 " BloomTexCoord = vec2(gl_MultiTexCoord1);\n"
2621 " // transform vertex to camera space, using ftransform to match non-VS\n"
2623 " gl_Position = ftransform();\n"
2626 "#endif // VERTEX_SHADER\n"
2631 "// fragment shader specific:\n"
2632 "#ifdef FRAGMENT_SHADER\n"
2637 " myhvec3 color = myhvec3(texture2D(Texture_Screen, ScreenTexCoord));\n"
2638 " for (x = -BLUR_X;x <= BLUR_X;x++)
2639 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2640 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2641 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2642 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2644 " gl_FragColor = vec4(color);\n"
2647 "#endif // FRAGMENT_SHADER\n"
2650 void R_RenderScene(qboolean addwaterplanes);
2652 static void R_Water_StartFrame(void)
2655 int waterwidth, waterheight, texturewidth, textureheight;
2656 r_waterstate_waterplane_t *p;
2658 // set waterwidth and waterheight to the water resolution that will be
2659 // used (often less than the screen resolution for faster rendering)
2660 waterwidth = (int)bound(1, r_view.width * r_water_resolutionmultiplier.value, r_view.width);
2661 waterheight = (int)bound(1, r_view.height * r_water_resolutionmultiplier.value, r_view.height);
2663 // calculate desired texture sizes
2664 // can't use water if the card does not support the texture size
2665 if (!r_water.integer || !r_glsl.integer || !gl_support_fragment_shader || waterwidth > gl_max_texture_size || waterheight > gl_max_texture_size)
2666 texturewidth = textureheight = waterwidth = waterheight = 0;
2667 else if (gl_support_arb_texture_non_power_of_two)
2669 texturewidth = waterwidth;
2670 textureheight = waterheight;
2674 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
2675 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
2678 // allocate textures as needed
2679 if (r_waterstate.waterwidth != waterwidth || r_waterstate.waterheight != waterheight || r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight)
2681 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
2682 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
2684 if (p->texture_refraction)
2685 R_FreeTexture(p->texture_refraction);
2686 p->texture_refraction = NULL;
2687 if (p->texture_reflection)
2688 R_FreeTexture(p->texture_reflection);
2689 p->texture_reflection = NULL;
2691 memset(&r_waterstate, 0, sizeof(r_waterstate));
2692 r_waterstate.waterwidth = waterwidth;
2693 r_waterstate.waterheight = waterheight;
2694 r_waterstate.texturewidth = texturewidth;
2695 r_waterstate.textureheight = textureheight;
2698 if (r_waterstate.waterwidth)
2700 r_waterstate.enabled = true;
2702 // set up variables that will be used in shader setup
2703 r_waterstate.screenscale[0] = 0.5f * (float)waterwidth / (float)texturewidth;
2704 r_waterstate.screenscale[1] = 0.5f * (float)waterheight / (float)textureheight;
2705 r_waterstate.screencenter[0] = 0.5f * (float)waterwidth / (float)texturewidth;
2706 r_waterstate.screencenter[1] = 0.5f * (float)waterheight / (float)textureheight;
2709 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
2710 r_waterstate.numwaterplanes = 0;
2713 static void R_Water_AddWaterPlane(msurface_t *surface)
2715 int triangleindex, planeindex;
2720 r_waterstate_waterplane_t *p;
2721 // just use the first triangle with a valid normal for any decisions
2722 VectorClear(normal);
2723 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
2725 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
2726 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
2727 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
2728 TriangleNormal(vert[0], vert[1], vert[2], normal);
2729 if (VectorLength2(normal) >= 0.001)
2733 // find a matching plane if there is one
2734 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
2735 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
2737 if (planeindex >= r_waterstate.maxwaterplanes)
2738 return; // nothing we can do, out of planes
2740 // if this triangle does not fit any known plane rendered this frame, add one
2741 if (planeindex >= r_waterstate.numwaterplanes)
2743 // store the new plane
2744 r_waterstate.numwaterplanes++;
2745 VectorCopy(normal, p->plane.normal);
2746 VectorNormalize(p->plane.normal);
2747 p->plane.dist = DotProduct(vert[0], p->plane.normal);
2748 PlaneClassify(&p->plane);
2749 // flip the plane if it does not face the viewer
2750 if (PlaneDiff(r_view.origin, &p->plane) < 0)
2752 VectorNegate(p->plane.normal, p->plane.normal);
2753 p->plane.dist *= -1;
2754 PlaneClassify(&p->plane);
2756 // clear materialflags and pvs
2757 p->materialflags = 0;
2758 p->pvsvalid = false;
2760 // merge this surface's materialflags into the waterplane
2761 p->materialflags |= surface->texture->currentframe->currentmaterialflags;
2762 // merge this surface's PVS into the waterplane
2763 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
2764 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.worldmodel && r_refdef.worldmodel->brush.FatPVS
2765 && r_refdef.worldmodel->brush.PointInLeaf && r_refdef.worldmodel->brush.PointInLeaf(r_refdef.worldmodel, center)->clusterindex >= 0)
2767 r_refdef.worldmodel->brush.FatPVS(r_refdef.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
2772 static void R_Water_ProcessPlanes(void)
2774 r_view_t originalview;
2776 r_waterstate_waterplane_t *p;
2778 originalview = r_view;
2780 // make sure enough textures are allocated
2781 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
2783 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
2785 if (!p->texture_refraction)
2786 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);
2787 if (!p->texture_refraction)
2791 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
2793 if (!p->texture_reflection)
2794 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);
2795 if (!p->texture_reflection)
2801 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
2803 r_view.showdebug = false;
2804 r_view.width = r_waterstate.waterwidth;
2805 r_view.height = r_waterstate.waterheight;
2806 r_view.useclipplane = true;
2807 r_waterstate.renderingscene = true;
2809 // render the normal view scene and copy into texture
2810 // (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)
2811 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
2813 r_view.clipplane = p->plane;
2814 VectorNegate(r_view.clipplane.normal, r_view.clipplane.normal);
2815 r_view.clipplane.dist = -r_view.clipplane.dist;
2816 PlaneClassify(&r_view.clipplane);
2818 R_RenderScene(false);
2820 // copy view into the screen texture
2821 R_Mesh_TexBind(0, R_GetTexture(p->texture_refraction));
2822 GL_ActiveTexture(0);
2824 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
2827 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
2829 // render reflected scene and copy into texture
2830 Matrix4x4_Reflect(&r_view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
2831 r_view.clipplane = p->plane;
2832 // reverse the cullface settings for this render
2833 r_view.cullface_front = GL_FRONT;
2834 r_view.cullface_back = GL_BACK;
2835 if (r_refdef.worldmodel && r_refdef.worldmodel->brush.num_pvsclusterbytes)
2837 r_view.usecustompvs = true;
2839 memcpy(r_viewcache.world_pvsbits, p->pvsbits, r_refdef.worldmodel->brush.num_pvsclusterbytes);
2841 memset(r_viewcache.world_pvsbits, 0xFF, r_refdef.worldmodel->brush.num_pvsclusterbytes);
2844 R_ResetViewRendering3D();
2845 R_ClearScreen(r_refdef.fogenabled);
2846 if (r_timereport_active)
2847 R_TimeReport("viewclear");
2849 R_RenderScene(false);
2851 R_Mesh_TexBind(0, R_GetTexture(p->texture_reflection));
2852 GL_ActiveTexture(0);
2854 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
2856 R_ResetViewRendering3D();
2857 R_ClearScreen(r_refdef.fogenabled);
2858 if (r_timereport_active)
2859 R_TimeReport("viewclear");
2862 r_view = originalview;
2863 r_view.clear = true;
2864 r_waterstate.renderingscene = false;
2868 r_view = originalview;
2869 r_waterstate.renderingscene = false;
2870 Cvar_SetValueQuick(&r_water, 0);
2871 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
2875 void R_Bloom_StartFrame(void)
2877 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
2879 // set bloomwidth and bloomheight to the bloom resolution that will be
2880 // used (often less than the screen resolution for faster rendering)
2881 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_view.width);
2882 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_view.height / r_view.width;
2883 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_view.height);
2885 // calculate desired texture sizes
2886 if (gl_support_arb_texture_non_power_of_two)
2888 screentexturewidth = r_view.width;
2889 screentextureheight = r_view.height;
2890 bloomtexturewidth = r_bloomstate.bloomwidth;
2891 bloomtextureheight = r_bloomstate.bloomheight;
2895 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
2896 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
2897 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
2898 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
2903 screentexturewidth = screentextureheight = 0;
2905 else if (r_bloom.integer)
2910 screentexturewidth = screentextureheight = 0;
2911 bloomtexturewidth = bloomtextureheight = 0;
2914 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)
2916 // can't use bloom if the parameters are too weird
2917 // can't use bloom if the card does not support the texture size
2918 if (r_bloomstate.texture_screen)
2919 R_FreeTexture(r_bloomstate.texture_screen);
2920 if (r_bloomstate.texture_bloom)
2921 R_FreeTexture(r_bloomstate.texture_bloom);
2922 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
2926 r_bloomstate.enabled = true;
2927 r_bloomstate.hdr = r_hdr.integer != 0;
2929 // allocate textures as needed
2930 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
2932 if (r_bloomstate.texture_screen)
2933 R_FreeTexture(r_bloomstate.texture_screen);
2934 r_bloomstate.texture_screen = NULL;
2935 r_bloomstate.screentexturewidth = screentexturewidth;
2936 r_bloomstate.screentextureheight = screentextureheight;
2937 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
2938 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);
2940 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
2942 if (r_bloomstate.texture_bloom)
2943 R_FreeTexture(r_bloomstate.texture_bloom);
2944 r_bloomstate.texture_bloom = NULL;
2945 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
2946 r_bloomstate.bloomtextureheight = bloomtextureheight;
2947 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
2948 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);
2951 // set up a texcoord array for the full resolution screen image
2952 // (we have to keep this around to copy back during final render)
2953 r_bloomstate.screentexcoord2f[0] = 0;
2954 r_bloomstate.screentexcoord2f[1] = (float)r_view.height / (float)r_bloomstate.screentextureheight;
2955 r_bloomstate.screentexcoord2f[2] = (float)r_view.width / (float)r_bloomstate.screentexturewidth;
2956 r_bloomstate.screentexcoord2f[3] = (float)r_view.height / (float)r_bloomstate.screentextureheight;
2957 r_bloomstate.screentexcoord2f[4] = (float)r_view.width / (float)r_bloomstate.screentexturewidth;
2958 r_bloomstate.screentexcoord2f[5] = 0;
2959 r_bloomstate.screentexcoord2f[6] = 0;
2960 r_bloomstate.screentexcoord2f[7] = 0;
2962 // set up a texcoord array for the reduced resolution bloom image
2963 // (which will be additive blended over the screen image)
2964 r_bloomstate.bloomtexcoord2f[0] = 0;
2965 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
2966 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
2967 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
2968 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
2969 r_bloomstate.bloomtexcoord2f[5] = 0;
2970 r_bloomstate.bloomtexcoord2f[6] = 0;
2971 r_bloomstate.bloomtexcoord2f[7] = 0;
2974 void R_Bloom_CopyScreenTexture(float colorscale)
2976 r_refdef.stats.bloom++;
2978 R_ResetViewRendering2D();
2979 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
2980 R_Mesh_ColorPointer(NULL, 0, 0);
2981 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
2982 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
2984 // copy view into the screen texture
2985 GL_ActiveTexture(0);
2987 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
2988 r_refdef.stats.bloom_copypixels += r_view.width * r_view.height;
2990 // now scale it down to the bloom texture size
2992 qglViewport(r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
2993 GL_BlendFunc(GL_ONE, GL_ZERO);
2994 GL_Color(colorscale, colorscale, colorscale, 1);
2995 // TODO: optimize with multitexture or GLSL
2996 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2997 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
2999 // we now have a bloom image in the framebuffer
3000 // copy it into the bloom image texture for later processing
3001 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3002 GL_ActiveTexture(0);
3004 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
3005 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3008 void R_Bloom_CopyHDRTexture(void)
3010 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3011 GL_ActiveTexture(0);
3013 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
3014 r_refdef.stats.bloom_copypixels += r_view.width * r_view.height;
3017 void R_Bloom_MakeTexture(void)
3020 float xoffset, yoffset, r, brighten;
3022 r_refdef.stats.bloom++;
3024 R_ResetViewRendering2D();
3025 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3026 R_Mesh_ColorPointer(NULL, 0, 0);
3028 // we have a bloom image in the framebuffer
3030 qglViewport(r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
3032 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
3035 r = bound(0, r_bloom_colorexponent.value / x, 1);
3036 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
3037 GL_Color(r, r, r, 1);
3038 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3039 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3040 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3041 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3043 // copy the vertically blurred bloom view to a texture
3044 GL_ActiveTexture(0);
3046 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
3047 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3050 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
3051 brighten = r_bloom_brighten.value;
3053 brighten *= r_hdr_range.value;
3054 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3055 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
3057 for (dir = 0;dir < 2;dir++)
3059 // blend on at multiple vertical offsets to achieve a vertical blur
3060 // TODO: do offset blends using GLSL
3061 GL_BlendFunc(GL_ONE, GL_ZERO);
3062 for (x = -range;x <= range;x++)
3064 if (!dir){xoffset = 0;yoffset = x;}
3065 else {xoffset = x;yoffset = 0;}
3066 xoffset /= (float)r_bloomstate.bloomtexturewidth;
3067 yoffset /= (float)r_bloomstate.bloomtextureheight;
3068 // compute a texcoord array with the specified x and y offset
3069 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
3070 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3071 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3072 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3073 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3074 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
3075 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
3076 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
3077 // this r value looks like a 'dot' particle, fading sharply to
3078 // black at the edges
3079 // (probably not realistic but looks good enough)
3080 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
3081 //r = (dir ? 1.0f : brighten)/(range*2+1);
3082 r = (dir ? 1.0f : brighten)/(range*2+1)*(1 - x*x/(float)(range*range));
3083 GL_Color(r, r, r, 1);
3084 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3085 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3086 GL_BlendFunc(GL_ONE, GL_ONE);
3089 // copy the vertically blurred bloom view to a texture
3090 GL_ActiveTexture(0);
3092 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
3093 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3096 // apply subtract last
3097 // (just like it would be in a GLSL shader)
3098 if (r_bloom_colorsubtract.value > 0 && gl_support_ext_blend_subtract)
3100 GL_BlendFunc(GL_ONE, GL_ZERO);
3101 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3102 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3103 GL_Color(1, 1, 1, 1);
3104 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3105 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3107 GL_BlendFunc(GL_ONE, GL_ONE);
3108 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
3109 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
3110 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3111 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
3112 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3113 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3114 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
3116 // copy the darkened bloom view to a texture
3117 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3118 GL_ActiveTexture(0);
3120 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
3121 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3125 void R_HDR_RenderBloomTexture(void)
3127 int oldwidth, oldheight;
3128 float oldcolorscale;
3130 oldcolorscale = r_view.colorscale;
3131 oldwidth = r_view.width;
3132 oldheight = r_view.height;
3133 r_view.width = r_bloomstate.bloomwidth;
3134 r_view.height = r_bloomstate.bloomheight;
3136 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
3137 // TODO: add exposure compensation features
3138 // TODO: add fp16 framebuffer support
3140 r_view.showdebug = false;
3141 r_view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
3143 R_ClearScreen(r_refdef.fogenabled);
3144 if (r_timereport_active)
3145 R_TimeReport("HDRclear");
3147 r_waterstate.numwaterplanes = 0;
3148 R_RenderScene(r_waterstate.enabled);
3149 r_view.showdebug = true;
3151 R_ResetViewRendering2D();
3153 R_Bloom_CopyHDRTexture();
3154 R_Bloom_MakeTexture();
3156 // restore the view settings
3157 r_view.width = oldwidth;
3158 r_view.height = oldheight;
3159 r_view.colorscale = oldcolorscale;
3161 R_ResetViewRendering3D();
3163 R_ClearScreen(r_refdef.fogenabled);
3164 if (r_timereport_active)
3165 R_TimeReport("viewclear");
3168 static void R_BlendView(void)
3170 if (r_bloomstate.enabled && r_bloomstate.hdr)
3172 // render high dynamic range bloom effect
3173 // the bloom texture was made earlier this render, so we just need to
3174 // blend it onto the screen...
3175 R_ResetViewRendering2D();
3176 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3177 R_Mesh_ColorPointer(NULL, 0, 0);
3178 GL_Color(1, 1, 1, 1);
3179 GL_BlendFunc(GL_ONE, GL_ONE);
3180 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3181 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3182 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3183 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
3185 else if (r_bloomstate.enabled)
3187 // render simple bloom effect
3188 // copy the screen and shrink it and darken it for the bloom process
3189 R_Bloom_CopyScreenTexture(r_bloom_colorscale.value);
3190 // make the bloom texture
3191 R_Bloom_MakeTexture();
3192 // put the original screen image back in place and blend the bloom
3194 R_ResetViewRendering2D();
3195 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3196 R_Mesh_ColorPointer(NULL, 0, 0);
3197 GL_Color(1, 1, 1, 1);
3198 GL_BlendFunc(GL_ONE, GL_ZERO);
3199 // do both in one pass if possible
3200 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3201 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3202 if (r_textureunits.integer >= 2 && gl_combine.integer)
3204 R_Mesh_TexCombine(1, GL_ADD, GL_ADD, 1, 1);
3205 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_screen));
3206 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.screentexcoord2f, 0, 0);
3210 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3211 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
3212 // now blend on the bloom texture
3213 GL_BlendFunc(GL_ONE, GL_ONE);
3214 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
3215 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
3217 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3218 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
3220 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
3222 // apply a color tint to the whole view
3223 R_ResetViewRendering2D();
3224 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3225 R_Mesh_ColorPointer(NULL, 0, 0);
3226 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3227 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
3228 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3232 void R_RenderScene(qboolean addwaterplanes);
3234 matrix4x4_t r_waterscrollmatrix;
3236 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
3238 if (r_refdef.fog_density)
3240 r_refdef.fogcolor[0] = r_refdef.fog_red;
3241 r_refdef.fogcolor[1] = r_refdef.fog_green;
3242 r_refdef.fogcolor[2] = r_refdef.fog_blue;
3246 VectorCopy(r_refdef.fogcolor, fogvec);
3247 if(r_glsl.integer && (r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)) // need to support contrast boost
3249 // color.rgb /= ((ContrastBoost - 1) * color.rgb + 1);
3250 fogvec[0] /= ((r_glsl_contrastboost.value - 1) * fogvec[0] + 1);
3251 fogvec[1] /= ((r_glsl_contrastboost.value - 1) * fogvec[1] + 1);
3252 fogvec[2] /= ((r_glsl_contrastboost.value - 1) * fogvec[2] + 1);
3254 // color.rgb *= ContrastBoost * SceneBrightness;
3255 VectorScale(fogvec, r_glsl_contrastboost.value * r_view.colorscale, fogvec);
3256 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
3257 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
3258 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
3263 void R_UpdateVariables(void)
3267 r_refdef.farclip = 4096;
3268 if (r_refdef.worldmodel)
3269 r_refdef.farclip += VectorDistance(r_refdef.worldmodel->normalmins, r_refdef.worldmodel->normalmaxs);
3270 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
3272 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
3273 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
3274 r_refdef.polygonfactor = 0;
3275 r_refdef.polygonoffset = 0;
3276 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
3277 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
3279 r_refdef.rtworld = r_shadow_realtime_world.integer;
3280 r_refdef.rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
3281 r_refdef.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
3282 r_refdef.rtdlightshadows = r_refdef.rtdlight && r_shadow_realtime_dlight_shadows.integer && gl_stencil;
3283 r_refdef.lightmapintensity = r_refdef.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
3284 if (r_showsurfaces.integer)
3286 r_refdef.rtworld = false;
3287 r_refdef.rtworldshadows = false;
3288 r_refdef.rtdlight = false;
3289 r_refdef.rtdlightshadows = false;
3290 r_refdef.lightmapintensity = 0;
3293 if (gamemode == GAME_NEHAHRA)
3295 if (gl_fogenable.integer)
3297 r_refdef.oldgl_fogenable = true;
3298 r_refdef.fog_density = gl_fogdensity.value;
3299 r_refdef.fog_red = gl_fogred.value;
3300 r_refdef.fog_green = gl_foggreen.value;
3301 r_refdef.fog_blue = gl_fogblue.value;
3302 r_refdef.fog_alpha = 1;
3303 r_refdef.fog_start = 0;
3304 r_refdef.fog_end = gl_skyclip.value;
3306 else if (r_refdef.oldgl_fogenable)
3308 r_refdef.oldgl_fogenable = false;
3309 r_refdef.fog_density = 0;
3310 r_refdef.fog_red = 0;
3311 r_refdef.fog_green = 0;
3312 r_refdef.fog_blue = 0;
3313 r_refdef.fog_alpha = 0;
3314 r_refdef.fog_start = 0;
3315 r_refdef.fog_end = 0;
3319 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
3320 r_refdef.fog_start = max(0, r_refdef.fog_start);
3321 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
3323 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
3325 if (r_refdef.fog_density)
3327 r_refdef.fogenabled = true;
3328 // this is the point where the fog reaches 0.9986 alpha, which we
3329 // consider a good enough cutoff point for the texture
3330 // (0.9986 * 256 == 255.6)
3331 if (r_fog_exp2.integer)
3332 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
3334 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
3335 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
3336 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
3337 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
3338 // fog color was already set
3339 // update the fog texture
3340 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)
3341 R_BuildFogTexture();
3344 r_refdef.fogenabled = false;
3352 void R_RenderView(void)
3354 if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
3355 return; //Host_Error ("R_RenderView: NULL worldmodel");
3357 r_view.colorscale = r_hdr_scenebrightness.value;
3359 R_Shadow_UpdateWorldLightSelection();
3361 R_Bloom_StartFrame();
3362 R_Water_StartFrame();
3365 if (r_timereport_active)
3366 R_TimeReport("viewsetup");
3368 R_ResetViewRendering3D();
3370 if (r_view.clear || r_refdef.fogenabled)
3372 R_ClearScreen(r_refdef.fogenabled);
3373 if (r_timereport_active)
3374 R_TimeReport("viewclear");
3376 r_view.clear = true;
3378 r_view.showdebug = true;
3380 // this produces a bloom texture to be used in R_BlendView() later
3382 R_HDR_RenderBloomTexture();
3384 r_waterstate.numwaterplanes = 0;
3385 R_RenderScene(r_waterstate.enabled);
3388 if (r_timereport_active)
3389 R_TimeReport("blendview");
3391 GL_Scissor(0, 0, vid.width, vid.height);
3392 GL_ScissorTest(false);
3396 extern void R_DrawLightningBeams (void);
3397 extern void VM_CL_AddPolygonsToMeshQueue (void);
3398 extern void R_DrawPortals (void);
3399 extern cvar_t cl_locs_show;
3400 static void R_DrawLocs(void);
3401 static void R_DrawEntityBBoxes(void);
3402 void R_RenderScene(qboolean addwaterplanes)
3408 R_ResetViewRendering3D();
3411 if (r_timereport_active)
3412 R_TimeReport("watervis");
3414 if (cl.csqc_vidvars.drawworld && r_refdef.worldmodel && r_refdef.worldmodel->DrawAddWaterPlanes)
3416 r_refdef.worldmodel->DrawAddWaterPlanes(r_refdef.worldentity);
3417 if (r_timereport_active)
3418 R_TimeReport("waterworld");
3421 // don't let sound skip if going slow
3422 if (r_refdef.extraupdate)
3425 R_DrawModelsAddWaterPlanes();
3426 if (r_timereport_active)
3427 R_TimeReport("watermodels");
3429 R_Water_ProcessPlanes();
3430 if (r_timereport_active)
3431 R_TimeReport("waterscenes");
3434 R_ResetViewRendering3D();
3436 // don't let sound skip if going slow
3437 if (r_refdef.extraupdate)
3440 R_MeshQueue_BeginScene();
3445 if (r_timereport_active)
3446 R_TimeReport("visibility");
3448 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);
3450 if (cl.csqc_vidvars.drawworld)
3452 // don't let sound skip if going slow
3453 if (r_refdef.extraupdate)
3456 if (r_refdef.worldmodel && r_refdef.worldmodel->DrawSky)
3458 r_refdef.worldmodel->DrawSky(r_refdef.worldentity);
3459 if (r_timereport_active)
3460 R_TimeReport("worldsky");
3463 if (R_DrawBrushModelsSky() && r_timereport_active)
3464 R_TimeReport("bmodelsky");
3467 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.worldmodel && r_refdef.worldmodel->DrawDepth)
3469 r_refdef.worldmodel->DrawDepth(r_refdef.worldentity);
3470 if (r_timereport_active)
3471 R_TimeReport("worlddepth");
3473 if (r_depthfirst.integer >= 2)
3475 R_DrawModelsDepth();
3476 if (r_timereport_active)
3477 R_TimeReport("modeldepth");
3480 if (cl.csqc_vidvars.drawworld && r_refdef.worldmodel && r_refdef.worldmodel->Draw)
3482 r_refdef.worldmodel->Draw(r_refdef.worldentity);
3483 if (r_timereport_active)
3484 R_TimeReport("world");
3487 // don't let sound skip if going slow
3488 if (r_refdef.extraupdate)
3492 if (r_timereport_active)
3493 R_TimeReport("models");
3495 // don't let sound skip if going slow
3496 if (r_refdef.extraupdate)
3499 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
3501 R_DrawModelShadows();
3503 R_ResetViewRendering3D();
3505 // don't let sound skip if going slow
3506 if (r_refdef.extraupdate)
3510 R_ShadowVolumeLighting(false);
3511 if (r_timereport_active)
3512 R_TimeReport("rtlights");
3514 // don't let sound skip if going slow
3515 if (r_refdef.extraupdate)
3518 if (cl.csqc_vidvars.drawworld)
3520 R_DrawLightningBeams();
3521 if (r_timereport_active)
3522 R_TimeReport("lightning");
3525 if (r_timereport_active)
3526 R_TimeReport("decals");
3529 if (r_timereport_active)
3530 R_TimeReport("particles");
3533 if (r_timereport_active)
3534 R_TimeReport("explosions");
3537 if (gl_support_fragment_shader)
3539 qglUseProgramObjectARB(0);CHECKGLERROR
3541 VM_CL_AddPolygonsToMeshQueue();
3543 if (r_view.showdebug)
3545 if (cl_locs_show.integer)
3548 if (r_timereport_active)
3549 R_TimeReport("showlocs");
3552 if (r_drawportals.integer)
3555 if (r_timereport_active)
3556 R_TimeReport("portals");
3559 if (r_showbboxes.value > 0)
3561 R_DrawEntityBBoxes();
3562 if (r_timereport_active)
3563 R_TimeReport("bboxes");
3567 if (gl_support_fragment_shader)
3569 qglUseProgramObjectARB(0);CHECKGLERROR
3571 R_MeshQueue_RenderTransparent();
3572 if (r_timereport_active)
3573 R_TimeReport("drawtrans");
3575 if (gl_support_fragment_shader)
3577 qglUseProgramObjectARB(0);CHECKGLERROR
3580 if (r_view.showdebug && r_refdef.worldmodel && r_refdef.worldmodel->DrawDebug && (r_showtris.value > 0 || r_shownormals.value > 0 || r_showcollisionbrushes.value > 0))
3582 r_refdef.worldmodel->DrawDebug(r_refdef.worldentity);
3583 if (r_timereport_active)
3584 R_TimeReport("worlddebug");
3585 R_DrawModelsDebug();
3586 if (r_timereport_active)
3587 R_TimeReport("modeldebug");
3590 if (gl_support_fragment_shader)
3592 qglUseProgramObjectARB(0);CHECKGLERROR
3595 if (cl.csqc_vidvars.drawworld)
3598 if (r_timereport_active)
3599 R_TimeReport("coronas");
3602 // don't let sound skip if going slow
3603 if (r_refdef.extraupdate)
3606 R_ResetViewRendering2D();
3609 static const int bboxelements[36] =
3619 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
3622 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
3623 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3624 GL_DepthMask(false);
3625 GL_DepthRange(0, 1);
3626 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3627 R_Mesh_Matrix(&identitymatrix);
3628 R_Mesh_ResetTextureState();
3630 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
3631 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
3632 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
3633 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
3634 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
3635 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
3636 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
3637 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
3638 R_FillColors(color4f, 8, cr, cg, cb, ca);
3639 if (r_refdef.fogenabled)
3641 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
3643 f1 = FogPoint_World(v);
3645 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
3646 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
3647 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
3650 R_Mesh_VertexPointer(vertex3f, 0, 0);
3651 R_Mesh_ColorPointer(color4f, 0, 0);
3652 R_Mesh_ResetTextureState();
3653 R_Mesh_Draw(0, 8, 12, bboxelements, 0, 0);
3656 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
3660 prvm_edict_t *edict;
3661 // this function draws bounding boxes of server entities
3665 for (i = 0;i < numsurfaces;i++)
3667 edict = PRVM_EDICT_NUM(surfacelist[i]);
3668 switch ((int)edict->fields.server->solid)
3670 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
3671 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
3672 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
3673 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
3674 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
3675 default: Vector4Set(color, 0, 0, 0, 0.50);break;
3677 color[3] *= r_showbboxes.value;
3678 color[3] = bound(0, color[3], 1);
3679 GL_DepthTest(!r_showdisabledepthtest.integer);
3680 GL_CullFace(r_view.cullface_front);
3681 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
3686 static void R_DrawEntityBBoxes(void)
3689 prvm_edict_t *edict;
3691 // this function draws bounding boxes of server entities
3695 for (i = 0;i < prog->num_edicts;i++)
3697 edict = PRVM_EDICT_NUM(i);
3698 if (edict->priv.server->free)
3700 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
3701 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
3706 int nomodelelements[24] =
3718 float nomodelvertex3f[6*3] =
3728 float nomodelcolor4f[6*4] =
3730 0.0f, 0.0f, 0.5f, 1.0f,
3731 0.0f, 0.0f, 0.5f, 1.0f,
3732 0.0f, 0.5f, 0.0f, 1.0f,
3733 0.0f, 0.5f, 0.0f, 1.0f,
3734 0.5f, 0.0f, 0.0f, 1.0f,
3735 0.5f, 0.0f, 0.0f, 1.0f
3738 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
3743 // this is only called once per entity so numsurfaces is always 1, and
3744 // surfacelist is always {0}, so this code does not handle batches
3745 R_Mesh_Matrix(&ent->matrix);
3747 if (ent->flags & EF_ADDITIVE)
3749 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
3750 GL_DepthMask(false);
3752 else if (ent->alpha < 1)
3754 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3755 GL_DepthMask(false);
3759 GL_BlendFunc(GL_ONE, GL_ZERO);
3762 GL_DepthRange(0, (ent->flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
3763 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3764 GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
3765 GL_CullFace((ent->effects & EF_DOUBLESIDED) ? GL_NONE : r_view.cullface_back);
3766 R_Mesh_VertexPointer(nomodelvertex3f, 0, 0);
3767 if (r_refdef.fogenabled)
3770 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
3771 R_Mesh_ColorPointer(color4f, 0, 0);
3772 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
3773 f1 = FogPoint_World(org);
3775 for (i = 0, c = color4f;i < 6;i++, c += 4)
3777 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
3778 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
3779 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
3783 else if (ent->alpha != 1)
3785 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
3786 R_Mesh_ColorPointer(color4f, 0, 0);
3787 for (i = 0, c = color4f;i < 6;i++, c += 4)
3791 R_Mesh_ColorPointer(nomodelcolor4f, 0, 0);
3792 R_Mesh_ResetTextureState();
3793 R_Mesh_Draw(0, 6, 8, nomodelelements, 0, 0);
3796 void R_DrawNoModel(entity_render_t *ent)
3799 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
3800 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
3801 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
3803 // R_DrawNoModelCallback(ent, 0);
3806 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
3808 vec3_t right1, right2, diff, normal;
3810 VectorSubtract (org2, org1, normal);
3812 // calculate 'right' vector for start
3813 VectorSubtract (r_view.origin, org1, diff);
3814 CrossProduct (normal, diff, right1);
3815 VectorNormalize (right1);
3817 // calculate 'right' vector for end
3818 VectorSubtract (r_view.origin, org2, diff);
3819 CrossProduct (normal, diff, right2);
3820 VectorNormalize (right2);
3822 vert[ 0] = org1[0] + width * right1[0];
3823 vert[ 1] = org1[1] + width * right1[1];
3824 vert[ 2] = org1[2] + width * right1[2];
3825 vert[ 3] = org1[0] - width * right1[0];
3826 vert[ 4] = org1[1] - width * right1[1];
3827 vert[ 5] = org1[2] - width * right1[2];
3828 vert[ 6] = org2[0] - width * right2[0];
3829 vert[ 7] = org2[1] - width * right2[1];
3830 vert[ 8] = org2[2] - width * right2[2];
3831 vert[ 9] = org2[0] + width * right2[0];
3832 vert[10] = org2[1] + width * right2[1];
3833 vert[11] = org2[2] + width * right2[2];
3836 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
3838 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)
3843 if (r_refdef.fogenabled)
3844 fog = FogPoint_World(origin);
3846 R_Mesh_Matrix(&identitymatrix);
3847 GL_BlendFunc(blendfunc1, blendfunc2);
3853 GL_CullFace(r_view.cullface_front);
3856 GL_CullFace(r_view.cullface_back);
3858 GL_DepthMask(false);
3859 GL_DepthRange(0, depthshort ? 0.0625 : 1);
3860 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3861 GL_DepthTest(!depthdisable);
3863 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
3864 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
3865 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
3866 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
3867 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
3868 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
3869 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
3870 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
3871 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
3872 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
3873 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
3874 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
3876 R_Mesh_VertexPointer(vertex3f, 0, 0);
3877 R_Mesh_ColorPointer(NULL, 0, 0);
3878 R_Mesh_ResetTextureState();
3879 R_Mesh_TexBind(0, R_GetTexture(texture));
3880 R_Mesh_TexCoordPointer(0, 2, spritetexcoord2f, 0, 0);
3881 // FIXME: fixed function path can't properly handle r_view.colorscale > 1
3882 GL_Color(cr * fog * r_view.colorscale, cg * fog * r_view.colorscale, cb * fog * r_view.colorscale, ca);
3883 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3885 if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
3887 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
3888 GL_BlendFunc(blendfunc1, GL_ONE);
3890 GL_Color(r_refdef.fogcolor[0] * fog, r_refdef.fogcolor[1] * fog, r_refdef.fogcolor[2] * fog, ca);
3891 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3895 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
3900 VectorSet(v, x, y, z);
3901 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
3902 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
3904 if (i == mesh->numvertices)
3906 if (mesh->numvertices < mesh->maxvertices)
3908 VectorCopy(v, vertex3f);
3909 mesh->numvertices++;
3911 return mesh->numvertices;
3917 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
3921 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
3922 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
3923 e = mesh->element3i + mesh->numtriangles * 3;
3924 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
3926 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
3927 if (mesh->numtriangles < mesh->maxtriangles)
3932 mesh->numtriangles++;
3934 element[1] = element[2];
3938 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
3942 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
3943 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
3944 e = mesh->element3i + mesh->numtriangles * 3;
3945 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
3947 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
3948 if (mesh->numtriangles < mesh->maxtriangles)
3953 mesh->numtriangles++;
3955 element[1] = element[2];
3959 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
3960 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
3962 int planenum, planenum2;
3965 mplane_t *plane, *plane2;
3967 double temppoints[2][256*3];
3968 // figure out how large a bounding box we need to properly compute this brush
3970 for (w = 0;w < numplanes;w++)
3971 maxdist = max(maxdist, planes[w].dist);
3972 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
3973 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
3974 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
3978 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
3979 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
3981 if (planenum2 == planenum)
3983 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);
3986 if (tempnumpoints < 3)
3988 // generate elements forming a triangle fan for this polygon
3989 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
3993 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)
3995 texturelayer_t *layer;
3996 layer = t->currentlayers + t->currentnumlayers++;
3998 layer->depthmask = depthmask;
3999 layer->blendfunc1 = blendfunc1;
4000 layer->blendfunc2 = blendfunc2;
4001 layer->texture = texture;
4002 layer->texmatrix = *matrix;
4003 layer->color[0] = r * r_view.colorscale;
4004 layer->color[1] = g * r_view.colorscale;
4005 layer->color[2] = b * r_view.colorscale;
4006 layer->color[3] = a;
4009 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
4012 index = parms[2] + r_refdef.time * parms[3];
4013 index -= floor(index);
4017 case Q3WAVEFUNC_NONE:
4018 case Q3WAVEFUNC_NOISE:
4019 case Q3WAVEFUNC_COUNT:
4022 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
4023 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
4024 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
4025 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
4026 case Q3WAVEFUNC_TRIANGLE:
4028 f = index - floor(index);
4039 return (float)(parms[0] + parms[1] * f);
4042 void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
4045 model_t *model = ent->model;
4048 q3shaderinfo_layer_tcmod_t *tcmod;
4050 // switch to an alternate material if this is a q1bsp animated material
4052 texture_t *texture = t;
4053 int s = ent->skinnum;
4054 if ((unsigned int)s >= (unsigned int)model->numskins)
4056 if (model->skinscenes)
4058 if (model->skinscenes[s].framecount > 1)
4059 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
4061 s = model->skinscenes[s].firstframe;
4064 t = t + s * model->num_surfaces;
4067 // use an alternate animation if the entity's frame is not 0,
4068 // and only if the texture has an alternate animation
4069 if (ent->frame2 != 0 && t->anim_total[1])
4070 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.time * 5.0f) % t->anim_total[1]) : 0];
4072 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.time * 5.0f) % t->anim_total[0]) : 0];
4074 texture->currentframe = t;
4077 // update currentskinframe to be a qw skin or animation frame
4078 if ((i = ent->entitynumber - 1) >= 0 && i < cl.maxclients)
4080 if (strcmp(r_qwskincache[i], cl.scores[i].qw_skin))
4082 strlcpy(r_qwskincache[i], cl.scores[i].qw_skin, sizeof(r_qwskincache[i]));
4083 Con_DPrintf("loading skins/%s\n", r_qwskincache[i]);
4084 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);
4086 t->currentskinframe = r_qwskincache_skinframe[i];
4087 if (t->currentskinframe == NULL)
4088 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->frame2time)) % t->numskinframes];
4090 else if (t->numskinframes >= 2)
4091 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->frame2time)) % t->numskinframes];
4092 if (t->backgroundnumskinframes >= 2)
4093 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - ent->frame2time)) % t->backgroundnumskinframes];
4095 t->currentmaterialflags = t->basematerialflags;
4096 t->currentalpha = ent->alpha;
4097 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
4099 t->currentalpha *= r_wateralpha.value;
4101 * FIXME what is this supposed to do?
4102 // if rendering refraction/reflection, disable transparency
4103 if (r_waterstate.enabled && (t->currentalpha < 1 || (t->currentmaterialflags & MATERIALFLAG_ALPHA)))
4104 t->currentmaterialflags |= MATERIALFLAG_WATERSHADER;
4107 if(!r_waterstate.enabled)
4108 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION);
4109 if (!(ent->flags & RENDER_LIGHT))
4110 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
4111 else if (rsurface.modeltexcoordlightmap2f == NULL)
4113 // pick a model lighting mode
4114 if (VectorLength2(ent->modellight_diffuse) >= (1.0f / 256.0f))
4115 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
4117 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
4119 if (ent->effects & EF_ADDITIVE)
4120 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
4121 else if (t->currentalpha < 1)
4122 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
4123 if (ent->effects & EF_DOUBLESIDED)
4124 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
4125 if (ent->effects & EF_NODEPTHTEST)
4126 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
4127 if (ent->flags & RENDER_VIEWMODEL)
4128 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
4129 if (t->backgroundnumskinframes && !(t->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED))
4130 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
4132 // make sure that the waterscroll matrix is used on water surfaces when
4133 // there is no tcmod
4134 if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
4135 t->currenttexmatrix = r_waterscrollmatrix;
4137 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
4140 switch(tcmod->tcmod)
4144 if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
4145 matrix = r_waterscrollmatrix;
4147 matrix = identitymatrix;
4149 case Q3TCMOD_ENTITYTRANSLATE:
4150 // this is used in Q3 to allow the gamecode to control texcoord
4151 // scrolling on the entity, which is not supported in darkplaces yet.
4152 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
4154 case Q3TCMOD_ROTATE:
4155 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
4156 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.time, 0, 0, 1);
4157 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
4160 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
4162 case Q3TCMOD_SCROLL:
4163 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.time, tcmod->parms[1] * r_refdef.time, 0);
4165 case Q3TCMOD_STRETCH:
4166 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
4167 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
4169 case Q3TCMOD_TRANSFORM:
4170 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
4171 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
4172 VectorSet(tcmat + 6, 0 , 0 , 1);
4173 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
4174 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
4176 case Q3TCMOD_TURBULENT:
4177 // this is handled in the RSurf_PrepareVertices function
4178 matrix = identitymatrix;
4181 // either replace or concatenate the transformation
4183 t->currenttexmatrix = matrix;
4186 matrix4x4_t temp = t->currenttexmatrix;
4187 Matrix4x4_Concat(&t->currenttexmatrix, &matrix, &temp);
4191 t->colormapping = VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f);
4192 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
4193 t->glosstexture = r_texture_black;
4194 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
4195 t->backgroundglosstexture = r_texture_black;
4196 t->specularpower = r_shadow_glossexponent.value;
4197 // TODO: store reference values for these in the texture?
4198 t->specularscale = 0;
4199 if (r_shadow_gloss.integer > 0)
4201 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
4203 if (r_shadow_glossintensity.value > 0)
4205 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
4206 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
4207 t->specularscale = r_shadow_glossintensity.value;
4210 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
4212 t->glosstexture = r_texture_white;
4213 t->backgroundglosstexture = r_texture_white;
4214 t->specularscale = r_shadow_gloss2intensity.value;
4218 // lightmaps mode looks bad with dlights using actual texturing, so turn
4219 // off the colormap and glossmap, but leave the normalmap on as it still
4220 // accurately represents the shading involved
4221 if (gl_lightmaps.integer && !(t->currentmaterialflags & MATERIALFLAG_BLENDED))
4223 t->basetexture = r_texture_white;
4224 t->specularscale = 0;
4227 VectorClear(t->dlightcolor);
4228 t->currentnumlayers = 0;
4229 if (!(t->currentmaterialflags & MATERIALFLAG_NODRAW))
4231 if (!(t->currentmaterialflags & MATERIALFLAG_SKY))
4233 int blendfunc1, blendfunc2, depthmask;
4234 if (t->currentmaterialflags & MATERIALFLAG_ADD)
4236 blendfunc1 = GL_SRC_ALPHA;
4237 blendfunc2 = GL_ONE;
4239 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
4241 blendfunc1 = GL_SRC_ALPHA;
4242 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
4244 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
4246 blendfunc1 = t->customblendfunc[0];
4247 blendfunc2 = t->customblendfunc[1];
4251 blendfunc1 = GL_ONE;
4252 blendfunc2 = GL_ZERO;
4254 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
4255 if (t->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL))
4257 rtexture_t *currentbasetexture;
4259 if (r_refdef.fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED))
4260 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
4261 currentbasetexture = (VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) < (1.0f / 1048576.0f) && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
4262 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
4264 // fullbright is not affected by r_refdef.lightmapintensity
4265 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
4266 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
4267 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);
4268 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
4269 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);
4274 // set the color tint used for lights affecting this surface
4275 VectorSet(t->dlightcolor, ent->colormod[0] * t->currentalpha, ent->colormod[1] * t->currentalpha, ent->colormod[2] * t->currentalpha);
4277 // q3bsp has no lightmap updates, so the lightstylevalue that
4278 // would normally be baked into the lightmap must be
4279 // applied to the color
4280 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
4281 if (ent->model->type == mod_brushq3)
4282 colorscale *= r_refdef.rtlightstylevalue[0];
4283 colorscale *= r_refdef.lightmapintensity;
4284 Vector4Set(t->lightmapcolor, ent->colormod[0] * colorscale, ent->colormod[1] * colorscale, ent->colormod[2] * colorscale, t->currentalpha);
4285 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);
4286 if (r_ambient.value >= (1.0f/64.0f))
4287 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);
4288 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
4290 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);
4291 if (r_ambient.value >= (1.0f/64.0f))
4292 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);
4294 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
4296 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);
4297 if (r_ambient.value >= (1.0f/64.0f))
4298 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);
4301 if (t->currentskinframe->glow != NULL)
4302 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);
4303 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
4305 // if this is opaque use alpha blend which will darken the earlier
4308 // if this is an alpha blended material, all the earlier passes
4309 // were darkened by fog already, so we only need to add the fog
4310 // color ontop through the fog mask texture
4312 // if this is an additive blended material, all the earlier passes
4313 // were darkened by fog already, and we should not add fog color
4314 // (because the background was not darkened, there is no fog color
4315 // that was lost behind it).
4316 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);
4323 void R_UpdateAllTextureInfo(entity_render_t *ent)
4327 for (i = 0;i < ent->model->num_texturesperskin;i++)
4328 R_UpdateTextureInfo(ent, ent->model->data_textures + i);
4331 rsurfacestate_t rsurface;
4333 void R_Mesh_ResizeArrays(int newvertices)
4336 if (rsurface.array_size >= newvertices)
4338 if (rsurface.array_modelvertex3f)
4339 Mem_Free(rsurface.array_modelvertex3f);
4340 rsurface.array_size = (newvertices + 1023) & ~1023;
4341 base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
4342 rsurface.array_modelvertex3f = base + rsurface.array_size * 0;
4343 rsurface.array_modelsvector3f = base + rsurface.array_size * 3;
4344 rsurface.array_modeltvector3f = base + rsurface.array_size * 6;
4345 rsurface.array_modelnormal3f = base + rsurface.array_size * 9;
4346 rsurface.array_deformedvertex3f = base + rsurface.array_size * 12;
4347 rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
4348 rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
4349 rsurface.array_deformednormal3f = base + rsurface.array_size * 21;
4350 rsurface.array_texcoord3f = base + rsurface.array_size * 24;
4351 rsurface.array_color4f = base + rsurface.array_size * 27;
4352 rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
4355 void RSurf_CleanUp(void)
4358 if (rsurface.mode == RSURFMODE_GLSL)
4360 qglUseProgramObjectARB(0);CHECKGLERROR
4362 GL_AlphaTest(false);
4363 rsurface.mode = RSURFMODE_NONE;
4364 rsurface.uselightmaptexture = false;
4365 rsurface.texture = NULL;
4368 void RSurf_ActiveWorldEntity(void)
4370 model_t *model = r_refdef.worldmodel;
4372 if (rsurface.array_size < model->surfmesh.num_vertices)
4373 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
4374 rsurface.matrix = identitymatrix;
4375 rsurface.inversematrix = identitymatrix;
4376 R_Mesh_Matrix(&identitymatrix);
4377 VectorCopy(r_view.origin, rsurface.modelorg);
4378 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
4379 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
4380 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
4381 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
4382 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
4383 rsurface.frameblend[0].frame = 0;
4384 rsurface.frameblend[0].lerp = 1;
4385 rsurface.frameblend[1].frame = 0;
4386 rsurface.frameblend[1].lerp = 0;
4387 rsurface.frameblend[2].frame = 0;
4388 rsurface.frameblend[2].lerp = 0;
4389 rsurface.frameblend[3].frame = 0;
4390 rsurface.frameblend[3].lerp = 0;
4391 rsurface.basepolygonfactor = r_refdef.polygonfactor;
4392 rsurface.basepolygonoffset = r_refdef.polygonoffset;
4393 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
4394 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
4395 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
4396 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
4397 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
4398 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
4399 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
4400 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
4401 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
4402 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
4403 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
4404 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
4405 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
4406 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
4407 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
4408 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
4409 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
4410 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
4411 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
4412 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
4413 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
4414 rsurface.modelelement3i = model->surfmesh.data_element3i;
4415 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo;
4416 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
4417 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
4418 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
4419 rsurface.modelsurfaces = model->data_surfaces;
4420 rsurface.generatedvertex = false;
4421 rsurface.vertex3f = rsurface.modelvertex3f;
4422 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
4423 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
4424 rsurface.svector3f = rsurface.modelsvector3f;
4425 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
4426 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
4427 rsurface.tvector3f = rsurface.modeltvector3f;
4428 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
4429 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
4430 rsurface.normal3f = rsurface.modelnormal3f;
4431 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
4432 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
4433 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
4436 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4438 model_t *model = ent->model;
4440 if (rsurface.array_size < model->surfmesh.num_vertices)
4441 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
4442 rsurface.matrix = ent->matrix;
4443 rsurface.inversematrix = ent->inversematrix;
4444 R_Mesh_Matrix(&rsurface.matrix);
4445 Matrix4x4_Transform(&rsurface.inversematrix, r_view.origin, rsurface.modelorg);
4446 rsurface.modellight_ambient[0] = ent->modellight_ambient[0] * ent->colormod[0];
4447 rsurface.modellight_ambient[1] = ent->modellight_ambient[1] * ent->colormod[1];
4448 rsurface.modellight_ambient[2] = ent->modellight_ambient[2] * ent->colormod[2];
4449 rsurface.modellight_diffuse[0] = ent->modellight_diffuse[0] * ent->colormod[0];
4450 rsurface.modellight_diffuse[1] = ent->modellight_diffuse[1] * ent->colormod[1];
4451 rsurface.modellight_diffuse[2] = ent->modellight_diffuse[2] * ent->colormod[2];
4452 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
4453 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
4454 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
4455 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
4456 rsurface.frameblend[0] = ent->frameblend[0];
4457 rsurface.frameblend[1] = ent->frameblend[1];
4458 rsurface.frameblend[2] = ent->frameblend[2];
4459 rsurface.frameblend[3] = ent->frameblend[3];
4460 rsurface.basepolygonfactor = r_refdef.polygonfactor;
4461 rsurface.basepolygonoffset = r_refdef.polygonoffset;
4462 if (ent->model->brush.submodel)
4464 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
4465 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
4467 if (model->surfmesh.isanimated && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].frame != 0))
4471 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
4472 rsurface.modelsvector3f = rsurface.array_modelsvector3f;
4473 rsurface.modeltvector3f = rsurface.array_modeltvector3f;
4474 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
4475 Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
4477 else if (wantnormals)
4479 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
4480 rsurface.modelsvector3f = NULL;
4481 rsurface.modeltvector3f = NULL;
4482 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
4483 Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
4487 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
4488 rsurface.modelsvector3f = NULL;
4489 rsurface.modeltvector3f = NULL;
4490 rsurface.modelnormal3f = NULL;
4491 Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, NULL, NULL, NULL);
4493 rsurface.modelvertex3f_bufferobject = 0;
4494 rsurface.modelvertex3f_bufferoffset = 0;
4495 rsurface.modelsvector3f_bufferobject = 0;
4496 rsurface.modelsvector3f_bufferoffset = 0;
4497 rsurface.modeltvector3f_bufferobject = 0;
4498 rsurface.modeltvector3f_bufferoffset = 0;
4499 rsurface.modelnormal3f_bufferobject = 0;
4500 rsurface.modelnormal3f_bufferoffset = 0;
4501 rsurface.generatedvertex = true;
4505 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
4506 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
4507 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
4508 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
4509 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
4510 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
4511 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
4512 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
4513 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
4514 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
4515 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
4516 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
4517 rsurface.generatedvertex = false;
4519 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
4520 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
4521 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
4522 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
4523 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
4524 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
4525 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
4526 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
4527 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
4528 rsurface.modelelement3i = model->surfmesh.data_element3i;
4529 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo;
4530 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
4531 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
4532 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
4533 rsurface.modelsurfaces = model->data_surfaces;
4534 rsurface.vertex3f = rsurface.modelvertex3f;
4535 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
4536 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
4537 rsurface.svector3f = rsurface.modelsvector3f;
4538 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
4539 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
4540 rsurface.tvector3f = rsurface.modeltvector3f;
4541 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
4542 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
4543 rsurface.normal3f = rsurface.modelnormal3f;
4544 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
4545 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
4546 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
4549 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
4550 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, msurface_t **texturesurfacelist)
4553 int texturesurfaceindex;
4558 const float *v1, *in_tc;
4560 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
4562 q3shaderinfo_deform_t *deform;
4563 // 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
4564 if (rsurface.generatedvertex)
4566 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
4567 generatenormals = true;
4568 for (i = 0;i < Q3MAXDEFORMS;i++)
4570 if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
4572 generatetangents = true;
4573 generatenormals = true;
4575 if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
4576 generatenormals = true;
4578 if (generatenormals && !rsurface.modelnormal3f)
4580 rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
4581 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
4582 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
4583 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer);
4585 if (generatetangents && !rsurface.modelsvector3f)
4587 rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
4588 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
4589 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
4590 rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
4591 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
4592 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
4593 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);
4596 rsurface.vertex3f = rsurface.modelvertex3f;
4597 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
4598 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
4599 rsurface.svector3f = rsurface.modelsvector3f;
4600 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
4601 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
4602 rsurface.tvector3f = rsurface.modeltvector3f;
4603 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
4604 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
4605 rsurface.normal3f = rsurface.modelnormal3f;
4606 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
4607 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
4608 // if vertices are deformed (sprite flares and things in maps, possibly
4609 // water waves, bulges and other deformations), generate them into
4610 // rsurface.deform* arrays from whatever the rsurface.* arrays point to
4611 // (may be static model data or generated data for an animated model, or
4612 // the previous deform pass)
4613 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
4615 switch (deform->deform)
4618 case Q3DEFORM_PROJECTIONSHADOW:
4619 case Q3DEFORM_TEXT0:
4620 case Q3DEFORM_TEXT1:
4621 case Q3DEFORM_TEXT2:
4622 case Q3DEFORM_TEXT3:
4623 case Q3DEFORM_TEXT4:
4624 case Q3DEFORM_TEXT5:
4625 case Q3DEFORM_TEXT6:
4626 case Q3DEFORM_TEXT7:
4629 case Q3DEFORM_AUTOSPRITE:
4630 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.forward, newforward);
4631 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.right, newright);
4632 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.up, newup);
4633 VectorNormalize(newforward);
4634 VectorNormalize(newright);
4635 VectorNormalize(newup);
4636 // make deformed versions of only the model vertices used by the specified surfaces
4637 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4639 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4640 // a single autosprite surface can contain multiple sprites...
4641 for (j = 0;j < surface->num_vertices - 3;j += 4)
4643 VectorClear(center);
4644 for (i = 0;i < 4;i++)
4645 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
4646 VectorScale(center, 0.25f, center);
4647 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, forward);
4648 VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
4649 VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
4650 for (i = 0;i < 4;i++)
4652 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
4653 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
4656 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);
4657 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);
4659 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4660 rsurface.vertex3f_bufferobject = 0;
4661 rsurface.vertex3f_bufferoffset = 0;
4662 rsurface.svector3f = rsurface.array_deformedsvector3f;
4663 rsurface.svector3f_bufferobject = 0;
4664 rsurface.svector3f_bufferoffset = 0;
4665 rsurface.tvector3f = rsurface.array_deformedtvector3f;
4666 rsurface.tvector3f_bufferobject = 0;
4667 rsurface.tvector3f_bufferoffset = 0;
4668 rsurface.normal3f = rsurface.array_deformednormal3f;
4669 rsurface.normal3f_bufferobject = 0;
4670 rsurface.normal3f_bufferoffset = 0;
4672 case Q3DEFORM_AUTOSPRITE2:
4673 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.forward, newforward);
4674 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.right, newright);
4675 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.up, newup);
4676 VectorNormalize(newforward);
4677 VectorNormalize(newright);
4678 VectorNormalize(newup);
4679 // make deformed versions of only the model vertices used by the specified surfaces
4680 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4682 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4683 const float *v1, *v2;
4693 memset(shortest, 0, sizeof(shortest));
4694 // a single autosprite surface can contain multiple sprites...
4695 for (j = 0;j < surface->num_vertices - 3;j += 4)
4697 VectorClear(center);
4698 for (i = 0;i < 4;i++)
4699 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
4700 VectorScale(center, 0.25f, center);
4701 // find the two shortest edges, then use them to define the
4702 // axis vectors for rotating around the central axis
4703 for (i = 0;i < 6;i++)
4705 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
4706 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
4708 Debug_PolygonBegin(NULL, 0, false, 0);
4709 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
4710 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);
4711 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
4714 l = VectorDistance2(v1, v2);
4715 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
4717 l += (1.0f / 1024.0f);
4718 if (shortest[0].length2 > l || i == 0)
4720 shortest[1] = shortest[0];
4721 shortest[0].length2 = l;
4722 shortest[0].v1 = v1;
4723 shortest[0].v2 = v2;
4725 else if (shortest[1].length2 > l || i == 1)
4727 shortest[1].length2 = l;
4728 shortest[1].v1 = v1;
4729 shortest[1].v2 = v2;
4732 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
4733 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
4735 Debug_PolygonBegin(NULL, 0, false, 0);
4736 Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
4737 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);
4738 Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
4741 // this calculates the right vector from the shortest edge
4742 // and the up vector from the edge midpoints
4743 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
4744 VectorNormalize(right);
4745 VectorSubtract(end, start, up);
4746 VectorNormalize(up);
4747 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
4748 //VectorSubtract(rsurface.modelorg, center, forward);
4749 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.forward, forward);
4750 VectorNegate(forward, forward);
4751 VectorReflect(forward, 0, up, forward);
4752 VectorNormalize(forward);
4753 CrossProduct(up, forward, newright);
4754 VectorNormalize(newright);
4756 Debug_PolygonBegin(NULL, 0, false, 0);
4757 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);
4758 Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
4759 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
4763 Debug_PolygonBegin(NULL, 0, false, 0);
4764 Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
4765 Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
4766 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
4769 // rotate the quad around the up axis vector, this is made
4770 // especially easy by the fact we know the quad is flat,
4771 // so we only have to subtract the center position and
4772 // measure distance along the right vector, and then
4773 // multiply that by the newright vector and add back the
4775 // we also need to subtract the old position to undo the
4776 // displacement from the center, which we do with a
4777 // DotProduct, the subtraction/addition of center is also
4778 // optimized into DotProducts here
4779 l = DotProduct(right, center);
4780 for (i = 0;i < 4;i++)
4782 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
4783 f = DotProduct(right, v1) - l;
4784 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
4787 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);
4788 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);
4790 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4791 rsurface.vertex3f_bufferobject = 0;
4792 rsurface.vertex3f_bufferoffset = 0;
4793 rsurface.svector3f = rsurface.array_deformedsvector3f;
4794 rsurface.svector3f_bufferobject = 0;
4795 rsurface.svector3f_bufferoffset = 0;
4796 rsurface.tvector3f = rsurface.array_deformedtvector3f;
4797 rsurface.tvector3f_bufferobject = 0;
4798 rsurface.tvector3f_bufferoffset = 0;
4799 rsurface.normal3f = rsurface.array_deformednormal3f;
4800 rsurface.normal3f_bufferobject = 0;
4801 rsurface.normal3f_bufferoffset = 0;
4803 case Q3DEFORM_NORMAL:
4804 // deform the normals to make reflections wavey
4805 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4807 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4808 for (j = 0;j < surface->num_vertices;j++)
4811 float *normal = (rsurface.array_deformednormal3f + 3 * surface->num_firstvertex) + j*3;
4812 VectorScale((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
4813 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, normal);
4814 normal[0] += deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.time * deform->parms[1]);
4815 normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.time * deform->parms[1]);
4816 normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.time * deform->parms[1]);
4817 VectorNormalize(normal);
4819 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);
4821 rsurface.svector3f = rsurface.array_deformedsvector3f;
4822 rsurface.svector3f_bufferobject = 0;
4823 rsurface.svector3f_bufferoffset = 0;
4824 rsurface.tvector3f = rsurface.array_deformedtvector3f;
4825 rsurface.tvector3f_bufferobject = 0;
4826 rsurface.tvector3f_bufferoffset = 0;
4827 rsurface.normal3f = rsurface.array_deformednormal3f;
4828 rsurface.normal3f_bufferobject = 0;
4829 rsurface.normal3f_bufferoffset = 0;
4832 // deform vertex array to make wavey water and flags and such
4833 waveparms[0] = deform->waveparms[0];
4834 waveparms[1] = deform->waveparms[1];
4835 waveparms[2] = deform->waveparms[2];
4836 waveparms[3] = deform->waveparms[3];
4837 // this is how a divisor of vertex influence on deformation
4838 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
4839 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
4840 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4842 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4843 for (j = 0;j < surface->num_vertices;j++)
4845 float *vertex = (rsurface.array_deformedvertex3f + 3 * surface->num_firstvertex) + j*3;
4846 VectorCopy((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, vertex);
4847 // if the wavefunc depends on time, evaluate it per-vertex
4850 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
4851 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
4853 VectorMA(vertex, scale, (rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, vertex);
4856 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4857 rsurface.vertex3f_bufferobject = 0;
4858 rsurface.vertex3f_bufferoffset = 0;
4860 case Q3DEFORM_BULGE:
4861 // deform vertex array to make the surface have moving bulges
4862 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4864 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4865 for (j = 0;j < surface->num_vertices;j++)
4867 scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.time * deform->parms[2])) * deform->parms[1];
4868 VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
4871 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4872 rsurface.vertex3f_bufferobject = 0;
4873 rsurface.vertex3f_bufferoffset = 0;
4876 // deform vertex array
4877 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
4878 VectorScale(deform->parms, scale, waveparms);
4879 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4881 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4882 for (j = 0;j < surface->num_vertices;j++)
4883 VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
4885 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4886 rsurface.vertex3f_bufferobject = 0;
4887 rsurface.vertex3f_bufferoffset = 0;
4891 // generate texcoords based on the chosen texcoord source
4892 switch(rsurface.texture->tcgen.tcgen)
4895 case Q3TCGEN_TEXTURE:
4896 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
4897 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordtexture2f_bufferobject;
4898 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
4900 case Q3TCGEN_LIGHTMAP:
4901 rsurface.texcoordtexture2f = rsurface.modeltexcoordlightmap2f;
4902 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
4903 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
4905 case Q3TCGEN_VECTOR:
4906 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4908 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4909 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)
4911 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
4912 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
4915 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
4916 rsurface.texcoordtexture2f_bufferobject = 0;
4917 rsurface.texcoordtexture2f_bufferoffset = 0;
4919 case Q3TCGEN_ENVIRONMENT:
4920 // make environment reflections using a spheremap
4921 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4923 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4924 const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
4925 const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
4926 float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
4927 for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
4929 float l, d, eyedir[3];
4930 VectorSubtract(rsurface.modelorg, vertex, eyedir);
4931 l = 0.5f / VectorLength(eyedir);
4932 d = DotProduct(normal, eyedir)*2;
4933 out_tc[0] = 0.5f + (normal[1]*d - eyedir[1])*l;
4934 out_tc[1] = 0.5f - (normal[2]*d - eyedir[2])*l;
4937 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
4938 rsurface.texcoordtexture2f_bufferobject = 0;
4939 rsurface.texcoordtexture2f_bufferoffset = 0;
4942 // the only tcmod that needs software vertex processing is turbulent, so
4943 // check for it here and apply the changes if needed
4944 // and we only support that as the first one
4945 // (handling a mixture of turbulent and other tcmods would be problematic
4946 // without punting it entirely to a software path)
4947 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
4949 amplitude = rsurface.texture->tcmods[0].parms[1];
4950 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.time * rsurface.texture->tcmods[0].parms[3];
4951 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4953 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4954 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)
4956 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
4957 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
4960 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
4961 rsurface.texcoordtexture2f_bufferobject = 0;
4962 rsurface.texcoordtexture2f_bufferoffset = 0;
4964 rsurface.texcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
4965 rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
4966 rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
4967 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
4970 void RSurf_DrawBatch_Simple(int texturenumsurfaces, msurface_t **texturesurfacelist)
4973 const msurface_t *surface = texturesurfacelist[0];
4974 const msurface_t *surface2;
4979 // TODO: lock all array ranges before render, rather than on each surface
4980 if (texturenumsurfaces == 1)
4982 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
4983 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));
4985 else if (r_batchmode.integer == 2)
4987 #define MAXBATCHTRIANGLES 4096
4988 int batchtriangles = 0;
4989 int batchelements[MAXBATCHTRIANGLES*3];
4990 for (i = 0;i < texturenumsurfaces;i = j)
4992 surface = texturesurfacelist[i];
4994 if (surface->num_triangles > MAXBATCHTRIANGLES)
4996 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));
4999 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
5000 batchtriangles = surface->num_triangles;
5001 firstvertex = surface->num_firstvertex;
5002 endvertex = surface->num_firstvertex + surface->num_vertices;
5003 for (;j < texturenumsurfaces;j++)
5005 surface2 = texturesurfacelist[j];
5006 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
5008 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
5009 batchtriangles += surface2->num_triangles;
5010 firstvertex = min(firstvertex, surface2->num_firstvertex);
5011 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
5013 surface2 = texturesurfacelist[j-1];
5014 numvertices = endvertex - firstvertex;
5015 R_Mesh_Draw(firstvertex, numvertices, batchtriangles, batchelements, 0, 0);
5018 else if (r_batchmode.integer == 1)
5020 for (i = 0;i < texturenumsurfaces;i = j)
5022 surface = texturesurfacelist[i];
5023 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
5024 if (texturesurfacelist[j] != surface2)
5026 surface2 = texturesurfacelist[j-1];
5027 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
5028 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
5029 GL_LockArrays(surface->num_firstvertex, numvertices);
5030 R_Mesh_Draw(surface->num_firstvertex, numvertices, numtriangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
5035 for (i = 0;i < texturenumsurfaces;i++)
5037 surface = texturesurfacelist[i];
5038 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5039 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));
5044 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit, int refractiontexunit, int reflectiontexunit)
5046 int i, planeindex, vertexindex;
5050 r_waterstate_waterplane_t *p, *bestp;
5051 msurface_t *surface;
5052 if (r_waterstate.renderingscene)
5054 for (i = 0;i < texturenumsurfaces;i++)
5056 surface = texturesurfacelist[i];
5057 if (lightmaptexunit >= 0)
5058 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5059 if (deluxemaptexunit >= 0)
5060 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5061 // pick the closest matching water plane
5064 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5067 for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
5069 Matrix4x4_Transform(&rsurface.matrix, v, vert);
5070 d += fabs(PlaneDiff(vert, &p->plane));
5072 if (bestd > d || !bestp)
5080 if (refractiontexunit >= 0)
5081 R_Mesh_TexBind(refractiontexunit, R_GetTexture(bestp->texture_refraction));
5082 if (reflectiontexunit >= 0)
5083 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(bestp->texture_reflection));
5087 if (refractiontexunit >= 0)
5088 R_Mesh_TexBind(refractiontexunit, R_GetTexture(r_texture_black));
5089 if (reflectiontexunit >= 0)
5090 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(r_texture_black));
5092 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5093 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));
5097 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit)
5101 const msurface_t *surface = texturesurfacelist[0];
5102 const msurface_t *surface2;
5107 // TODO: lock all array ranges before render, rather than on each surface
5108 if (texturenumsurfaces == 1)
5110 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5111 if (deluxemaptexunit >= 0)
5112 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5113 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5114 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));
5116 else if (r_batchmode.integer == 2)
5118 #define MAXBATCHTRIANGLES 4096
5119 int batchtriangles = 0;
5120 int batchelements[MAXBATCHTRIANGLES*3];
5121 for (i = 0;i < texturenumsurfaces;i = j)
5123 surface = texturesurfacelist[i];
5124 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5125 if (deluxemaptexunit >= 0)
5126 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5128 if (surface->num_triangles > MAXBATCHTRIANGLES)
5130 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));
5133 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
5134 batchtriangles = surface->num_triangles;
5135 firstvertex = surface->num_firstvertex;
5136 endvertex = surface->num_firstvertex + surface->num_vertices;
5137 for (;j < texturenumsurfaces;j++)
5139 surface2 = texturesurfacelist[j];
5140 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
5142 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
5143 batchtriangles += surface2->num_triangles;
5144 firstvertex = min(firstvertex, surface2->num_firstvertex);
5145 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
5147 surface2 = texturesurfacelist[j-1];
5148 numvertices = endvertex - firstvertex;
5149 R_Mesh_Draw(firstvertex, numvertices, batchtriangles, batchelements, 0, 0);
5152 else if (r_batchmode.integer == 1)
5155 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
5156 for (i = 0;i < texturenumsurfaces;i = j)
5158 surface = texturesurfacelist[i];
5159 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
5160 if (texturesurfacelist[j] != surface2)
5162 Con_Printf(" %i", j - i);
5165 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
5167 for (i = 0;i < texturenumsurfaces;i = j)
5169 surface = texturesurfacelist[i];
5170 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5171 if (deluxemaptexunit >= 0)
5172 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5173 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
5174 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
5177 Con_Printf(" %i", j - i);
5179 surface2 = texturesurfacelist[j-1];
5180 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
5181 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
5182 GL_LockArrays(surface->num_firstvertex, numvertices);
5183 R_Mesh_Draw(surface->num_firstvertex, numvertices, numtriangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
5191 for (i = 0;i < texturenumsurfaces;i++)
5193 surface = texturesurfacelist[i];
5194 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5195 if (deluxemaptexunit >= 0)
5196 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5197 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5198 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));
5203 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
5206 int texturesurfaceindex;
5207 if (r_showsurfaces.integer == 2)
5209 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5211 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5212 for (j = 0;j < surface->num_triangles;j++)
5214 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_view.colorscale;
5215 GL_Color(f, f, f, 1);
5216 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)));
5222 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5224 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5225 int k = (int)(((size_t)surface) / sizeof(msurface_t));
5226 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);
5227 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5228 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));
5233 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, msurface_t **texturesurfacelist)
5235 int texturesurfaceindex;
5239 if (rsurface.lightmapcolor4f)
5241 // generate color arrays for the surfaces in this list
5242 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5244 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5245 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)
5247 f = FogPoint_Model(v);
5257 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5259 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5260 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)
5262 f = FogPoint_Model(v);
5270 rsurface.lightmapcolor4f = rsurface.array_color4f;
5271 rsurface.lightmapcolor4f_bufferobject = 0;
5272 rsurface.lightmapcolor4f_bufferoffset = 0;
5275 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a)
5277 int texturesurfaceindex;
5280 if (!rsurface.lightmapcolor4f)
5282 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5284 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5285 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)
5293 rsurface.lightmapcolor4f = rsurface.array_color4f;
5294 rsurface.lightmapcolor4f_bufferobject = 0;
5295 rsurface.lightmapcolor4f_bufferoffset = 0;
5298 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5301 rsurface.lightmapcolor4f = NULL;
5302 rsurface.lightmapcolor4f_bufferobject = 0;
5303 rsurface.lightmapcolor4f_bufferoffset = 0;
5304 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5305 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5306 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5307 GL_Color(r, g, b, a);
5308 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 0, -1);
5311 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5313 // TODO: optimize applyfog && applycolor case
5314 // just apply fog if necessary, and tint the fog color array if necessary
5315 rsurface.lightmapcolor4f = NULL;
5316 rsurface.lightmapcolor4f_bufferobject = 0;
5317 rsurface.lightmapcolor4f_bufferoffset = 0;
5318 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5319 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5320 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5321 GL_Color(r, g, b, a);
5322 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5325 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5327 int texturesurfaceindex;
5331 if (texturesurfacelist[0]->lightmapinfo && texturesurfacelist[0]->lightmapinfo->stainsamples)
5333 // generate color arrays for the surfaces in this list
5334 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5336 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5337 for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
5339 if (surface->lightmapinfo->samples)
5341 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
5342 float scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
5343 VectorScale(lm, scale, c);
5344 if (surface->lightmapinfo->styles[1] != 255)
5346 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
5348 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
5349 VectorMA(c, scale, lm, c);
5350 if (surface->lightmapinfo->styles[2] != 255)
5353 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
5354 VectorMA(c, scale, lm, c);
5355 if (surface->lightmapinfo->styles[3] != 255)
5358 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
5359 VectorMA(c, scale, lm, c);
5369 rsurface.lightmapcolor4f = rsurface.array_color4f;
5370 rsurface.lightmapcolor4f_bufferobject = 0;
5371 rsurface.lightmapcolor4f_bufferoffset = 0;
5375 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
5376 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
5377 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
5379 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5380 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5381 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5382 GL_Color(r, g, b, a);
5383 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5386 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5388 int texturesurfaceindex;
5392 vec3_t ambientcolor;
5393 vec3_t diffusecolor;
5397 VectorCopy(rsurface.modellight_lightdir, lightdir);
5398 f = 0.5f * r_refdef.lightmapintensity;
5399 ambientcolor[0] = rsurface.modellight_ambient[0] * r * f;
5400 ambientcolor[1] = rsurface.modellight_ambient[1] * g * f;
5401 ambientcolor[2] = rsurface.modellight_ambient[2] * b * f;
5402 diffusecolor[0] = rsurface.modellight_diffuse[0] * r * f;
5403 diffusecolor[1] = rsurface.modellight_diffuse[1] * g * f;
5404 diffusecolor[2] = rsurface.modellight_diffuse[2] * b * f;
5405 if (VectorLength2(diffusecolor) > 0)
5407 // generate color arrays for the surfaces in this list
5408 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5410 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5411 int numverts = surface->num_vertices;
5412 v = rsurface.vertex3f + 3 * surface->num_firstvertex;
5413 c2 = rsurface.normal3f + 3 * surface->num_firstvertex;
5414 c = rsurface.array_color4f + 4 * surface->num_firstvertex;
5415 // q3-style directional shading
5416 for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
5418 if ((f = DotProduct(c2, lightdir)) > 0)
5419 VectorMA(ambientcolor, f, diffusecolor, c);
5421 VectorCopy(ambientcolor, c);
5430 rsurface.lightmapcolor4f = rsurface.array_color4f;
5431 rsurface.lightmapcolor4f_bufferobject = 0;
5432 rsurface.lightmapcolor4f_bufferoffset = 0;
5436 r = ambientcolor[0];
5437 g = ambientcolor[1];
5438 b = ambientcolor[2];
5439 rsurface.lightmapcolor4f = NULL;
5440 rsurface.lightmapcolor4f_bufferobject = 0;
5441 rsurface.lightmapcolor4f_bufferoffset = 0;
5443 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5444 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5445 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5446 GL_Color(r, g, b, a);
5447 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5450 void RSurf_SetupDepthAndCulling(void)
5452 // submodels are biased to avoid z-fighting with world surfaces that they
5453 // may be exactly overlapping (avoids z-fighting artifacts on certain
5454 // doors and things in Quake maps)
5455 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5456 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
5457 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
5458 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_view.cullface_back);
5461 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
5463 RSurf_SetupDepthAndCulling();
5464 if (rsurface.mode != RSURFMODE_SHOWSURFACES)
5466 rsurface.mode = RSURFMODE_SHOWSURFACES;
5468 GL_BlendFunc(GL_ONE, GL_ZERO);
5469 R_Mesh_ColorPointer(NULL, 0, 0);
5470 R_Mesh_ResetTextureState();
5472 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
5473 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
5476 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, msurface_t **texturesurfacelist)
5478 // transparent sky would be ridiculous
5479 if ((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED))
5481 if (rsurface.mode != RSURFMODE_SKY)
5483 if (rsurface.mode == RSURFMODE_GLSL)
5485 qglUseProgramObjectARB(0);CHECKGLERROR
5487 rsurface.mode = RSURFMODE_SKY;
5491 skyrendernow = false;
5493 // restore entity matrix
5494 R_Mesh_Matrix(&rsurface.matrix);
5496 RSurf_SetupDepthAndCulling();
5498 // LordHavoc: HalfLife maps have freaky skypolys so don't use
5499 // skymasking on them, and Quake3 never did sky masking (unlike
5500 // software Quake and software Quake2), so disable the sky masking
5501 // in Quake3 maps as it causes problems with q3map2 sky tricks,
5502 // and skymasking also looks very bad when noclipping outside the
5503 // level, so don't use it then either.
5504 if (r_refdef.worldmodel && r_refdef.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_viewcache.world_novis)
5506 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
5507 R_Mesh_ColorPointer(NULL, 0, 0);
5508 R_Mesh_ResetTextureState();
5509 if (skyrendermasked)
5511 // depth-only (masking)
5512 GL_ColorMask(0,0,0,0);
5513 // just to make sure that braindead drivers don't draw
5514 // anything despite that colormask...
5515 GL_BlendFunc(GL_ZERO, GL_ONE);
5520 GL_BlendFunc(GL_ONE, GL_ZERO);
5522 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
5523 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5524 if (skyrendermasked)
5525 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
5529 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, msurface_t **texturesurfacelist)
5531 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION)))
5534 if (rsurface.mode != RSURFMODE_GLSL)
5536 rsurface.mode = RSURFMODE_GLSL;
5537 R_Mesh_ResetTextureState();
5538 GL_Color(1, 1, 1, 1);
5541 R_Mesh_TexMatrix(0, &rsurface.texture->currenttexmatrix);
5542 R_Mesh_TexBind(0, R_GetTexture(rsurface.texture->currentskinframe->nmap));
5543 R_Mesh_TexBind(1, R_GetTexture(rsurface.texture->basetexture));
5544 R_Mesh_TexBind(2, R_GetTexture(rsurface.texture->glosstexture));
5545 R_Mesh_TexBind(4, R_GetTexture(r_texture_fogattenuation));
5546 R_Mesh_TexBind(5, R_GetTexture(rsurface.texture->currentskinframe->pants));
5547 R_Mesh_TexBind(6, R_GetTexture(rsurface.texture->currentskinframe->shirt));
5548 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
5550 R_Mesh_TexBind(7, R_GetTexture(r_texture_grey128));
5551 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
5552 R_Mesh_ColorPointer(NULL, 0, 0);
5554 else if (rsurface.uselightmaptexture)
5556 R_Mesh_TexBind(7, R_GetTexture(texturesurfacelist[0]->lightmaptexture));
5557 R_Mesh_TexBind(8, R_GetTexture(texturesurfacelist[0]->deluxemaptexture));
5558 R_Mesh_ColorPointer(NULL, 0, 0);
5562 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
5563 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
5564 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
5566 R_Mesh_TexBind(9, R_GetTexture(rsurface.texture->currentskinframe->glow));
5567 R_Mesh_TexBind(11, R_GetTexture(r_texture_white)); // changed per surface
5568 R_Mesh_TexBind(12, R_GetTexture(r_texture_white)); // changed per surface
5570 if (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5572 // render background
5573 GL_BlendFunc(GL_ONE, GL_ZERO);
5575 GL_AlphaTest(false);
5577 GL_Color(1, 1, 1, 1);
5578 R_Mesh_ColorPointer(NULL, 0, 0);
5580 R_SetupSurfaceShader(vec3_origin, rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
5581 if (r_glsl_permutation)
5583 RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
5584 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
5585 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
5586 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
5587 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
5588 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
5589 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist, -1, -1, r_glsl_permutation->loc_Texture_Refraction ? 11 : -1, r_glsl_permutation->loc_Texture_Reflection ? 12 : -1);
5592 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5593 GL_DepthMask(false);
5594 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5595 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
5597 R_Mesh_TexBind(7, R_GetTexture(r_texture_grey128));
5598 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
5599 R_Mesh_ColorPointer(NULL, 0, 0);
5601 else if (rsurface.uselightmaptexture)
5603 R_Mesh_TexBind(7, R_GetTexture(texturesurfacelist[0]->lightmaptexture));
5604 R_Mesh_TexBind(8, R_GetTexture(texturesurfacelist[0]->deluxemaptexture));
5605 R_Mesh_ColorPointer(NULL, 0, 0);
5609 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
5610 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
5611 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
5613 R_Mesh_TexBind(11, R_GetTexture(r_texture_white)); // changed per surface
5614 R_Mesh_TexBind(12, R_GetTexture(r_texture_white)); // changed per surface
5617 R_SetupSurfaceShader(vec3_origin, rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE);
5618 if (!r_glsl_permutation)
5621 RSurf_PrepareVerticesForBatch(r_glsl_permutation->loc_Texture_Normal >= 0 || r_glsl_permutation->loc_LightDir >= 0, r_glsl_permutation->loc_Texture_Normal >= 0, texturenumsurfaces, texturesurfacelist);
5622 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
5623 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
5624 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
5625 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
5626 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
5628 if (r_glsl_permutation->loc_Texture_Refraction >= 0)
5630 GL_BlendFunc(GL_ONE, GL_ZERO);
5632 GL_AlphaTest(false);
5635 if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
5637 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
5638 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);
5640 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 7, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? 8 : -1);
5644 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
5645 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);
5647 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5649 if (rsurface.texture->backgroundnumskinframes && !(rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED))
5654 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, msurface_t **texturesurfacelist)
5656 // OpenGL 1.3 path - anything not completely ancient
5657 int texturesurfaceindex;
5658 qboolean applycolor;
5662 const texturelayer_t *layer;
5663 if (rsurface.mode != RSURFMODE_MULTIPASS)
5664 rsurface.mode = RSURFMODE_MULTIPASS;
5665 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
5667 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
5670 int layertexrgbscale;
5671 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5673 if (layerindex == 0)
5677 GL_AlphaTest(false);
5678 qglDepthFunc(GL_EQUAL);CHECKGLERROR
5681 GL_DepthMask(layer->depthmask);
5682 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
5683 if ((layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2) && (gl_combine.integer || layer->depthmask))
5685 layertexrgbscale = 4;
5686 VectorScale(layer->color, 0.25f, layercolor);
5688 else if ((layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1) && (gl_combine.integer || layer->depthmask))
5690 layertexrgbscale = 2;
5691 VectorScale(layer->color, 0.5f, layercolor);
5695 layertexrgbscale = 1;
5696 VectorScale(layer->color, 1.0f, layercolor);
5698 layercolor[3] = layer->color[3];
5699 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
5700 R_Mesh_ColorPointer(NULL, 0, 0);
5701 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
5702 switch (layer->type)
5704 case TEXTURELAYERTYPE_LITTEXTURE:
5705 memset(&m, 0, sizeof(m));
5706 m.tex[0] = R_GetTexture(r_texture_white);
5707 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
5708 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
5709 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
5710 m.tex[1] = R_GetTexture(layer->texture);
5711 m.texmatrix[1] = layer->texmatrix;
5712 m.texrgbscale[1] = layertexrgbscale;
5713 m.pointer_texcoord[1] = rsurface.texcoordtexture2f;
5714 m.pointer_texcoord_bufferobject[1] = rsurface.texcoordtexture2f_bufferobject;
5715 m.pointer_texcoord_bufferoffset[1] = rsurface.texcoordtexture2f_bufferoffset;
5716 R_Mesh_TextureState(&m);
5717 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
5718 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
5719 else if (rsurface.uselightmaptexture)
5720 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
5722 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
5724 case TEXTURELAYERTYPE_TEXTURE:
5725 memset(&m, 0, sizeof(m));
5726 m.tex[0] = R_GetTexture(layer->texture);
5727 m.texmatrix[0] = layer->texmatrix;
5728 m.texrgbscale[0] = layertexrgbscale;
5729 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5730 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5731 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5732 R_Mesh_TextureState(&m);
5733 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
5735 case TEXTURELAYERTYPE_FOG:
5736 memset(&m, 0, sizeof(m));
5737 m.texrgbscale[0] = layertexrgbscale;
5740 m.tex[0] = R_GetTexture(layer->texture);
5741 m.texmatrix[0] = layer->texmatrix;
5742 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5743 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5744 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5746 R_Mesh_TextureState(&m);
5747 // generate a color array for the fog pass
5748 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
5749 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5753 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5754 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)
5756 f = 1 - FogPoint_Model(v);
5757 c[0] = layercolor[0];
5758 c[1] = layercolor[1];
5759 c[2] = layercolor[2];
5760 c[3] = f * layercolor[3];
5763 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5766 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
5768 GL_LockArrays(0, 0);
5771 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5773 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
5774 GL_AlphaTest(false);
5778 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, msurface_t **texturesurfacelist)
5780 // OpenGL 1.1 - crusty old voodoo path
5781 int texturesurfaceindex;
5785 const texturelayer_t *layer;
5786 if (rsurface.mode != RSURFMODE_MULTIPASS)
5787 rsurface.mode = RSURFMODE_MULTIPASS;
5788 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
5790 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
5792 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5794 if (layerindex == 0)
5798 GL_AlphaTest(false);
5799 qglDepthFunc(GL_EQUAL);CHECKGLERROR
5802 GL_DepthMask(layer->depthmask);
5803 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
5804 R_Mesh_ColorPointer(NULL, 0, 0);
5805 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
5806 switch (layer->type)
5808 case TEXTURELAYERTYPE_LITTEXTURE:
5809 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
5811 // two-pass lit texture with 2x rgbscale
5812 // first the lightmap pass
5813 memset(&m, 0, sizeof(m));
5814 m.tex[0] = R_GetTexture(r_texture_white);
5815 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
5816 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
5817 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
5818 R_Mesh_TextureState(&m);
5819 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
5820 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5821 else if (rsurface.uselightmaptexture)
5822 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5824 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5825 GL_LockArrays(0, 0);
5826 // then apply the texture to it
5827 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
5828 memset(&m, 0, sizeof(m));
5829 m.tex[0] = R_GetTexture(layer->texture);
5830 m.texmatrix[0] = layer->texmatrix;
5831 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5832 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5833 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5834 R_Mesh_TextureState(&m);
5835 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);
5839 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
5840 memset(&m, 0, sizeof(m));
5841 m.tex[0] = R_GetTexture(layer->texture);
5842 m.texmatrix[0] = layer->texmatrix;
5843 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5844 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5845 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5846 R_Mesh_TextureState(&m);
5847 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
5848 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);
5850 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);
5853 case TEXTURELAYERTYPE_TEXTURE:
5854 // singletexture unlit texture with transparency support
5855 memset(&m, 0, sizeof(m));
5856 m.tex[0] = R_GetTexture(layer->texture);
5857 m.texmatrix[0] = layer->texmatrix;
5858 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5859 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5860 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5861 R_Mesh_TextureState(&m);
5862 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);
5864 case TEXTURELAYERTYPE_FOG:
5865 // singletexture fogging
5866 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
5869 memset(&m, 0, sizeof(m));
5870 m.tex[0] = R_GetTexture(layer->texture);
5871 m.texmatrix[0] = layer->texmatrix;
5872 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5873 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5874 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5875 R_Mesh_TextureState(&m);
5878 R_Mesh_ResetTextureState();
5879 // generate a color array for the fog pass
5880 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5884 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5885 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)
5887 f = 1 - FogPoint_Model(v);
5888 c[0] = layer->color[0];
5889 c[1] = layer->color[1];
5890 c[2] = layer->color[2];
5891 c[3] = f * layer->color[3];
5894 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5897 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
5899 GL_LockArrays(0, 0);
5902 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5904 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
5905 GL_AlphaTest(false);
5909 static void R_DrawTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly)
5911 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW)
5913 rsurface.rtlight = NULL;
5917 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
5919 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
5921 if (rsurface.mode != RSURFMODE_MULTIPASS)
5922 rsurface.mode = RSURFMODE_MULTIPASS;
5923 if (r_depthfirst.integer == 3)
5925 int i = (int)(texturesurfacelist[0] - rsurface.modelsurfaces);
5926 if (!r_view.showdebug)
5927 GL_Color(0, 0, 0, 1);
5929 GL_Color(((i >> 6) & 7) / 7.0f, ((i >> 3) & 7) / 7.0f, (i & 7) / 7.0f,1);
5933 GL_ColorMask(0,0,0,0);
5936 RSurf_SetupDepthAndCulling();
5938 GL_BlendFunc(GL_ONE, GL_ZERO);
5940 GL_AlphaTest(false);
5941 R_Mesh_ColorPointer(NULL, 0, 0);
5942 R_Mesh_ResetTextureState();
5943 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
5944 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5945 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
5947 else if (r_depthfirst.integer == 3)
5949 else if (!r_view.showdebug && (r_showsurfaces.integer || gl_lightmaps.integer))
5951 GL_Color(0, 0, 0, 1);
5952 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5954 else if (r_showsurfaces.integer)
5956 if (rsurface.mode != RSURFMODE_MULTIPASS)
5957 rsurface.mode = RSURFMODE_MULTIPASS;
5958 RSurf_SetupDepthAndCulling();
5960 GL_BlendFunc(GL_ONE, GL_ZERO);
5961 GL_DepthMask(writedepth);
5963 GL_AlphaTest(false);
5964 R_Mesh_ColorPointer(NULL, 0, 0);
5965 R_Mesh_ResetTextureState();
5966 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
5967 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
5969 else if (gl_lightmaps.integer)
5972 if (rsurface.mode != RSURFMODE_MULTIPASS)
5973 rsurface.mode = RSURFMODE_MULTIPASS;
5974 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5976 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_view.cullface_back);
5977 GL_BlendFunc(GL_ONE, GL_ZERO);
5978 GL_DepthMask(writedepth);
5980 GL_AlphaTest(false);
5981 R_Mesh_ColorPointer(NULL, 0, 0);
5982 memset(&m, 0, sizeof(m));
5983 m.tex[0] = R_GetTexture(r_texture_white);
5984 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
5985 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
5986 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
5987 R_Mesh_TextureState(&m);
5988 RSurf_PrepareVerticesForBatch(rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT, false, texturenumsurfaces, texturesurfacelist);
5989 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
5990 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5991 else if (rsurface.uselightmaptexture)
5992 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5994 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5996 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
5997 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
5998 else if (rsurface.texture->currentnumlayers)
6000 // write depth for anything we skipped on the depth-only pass earlier
6001 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
6003 RSurf_SetupDepthAndCulling();
6004 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
6005 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
6006 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
6007 if (r_glsl.integer && gl_support_fragment_shader)
6008 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist);
6009 else if (gl_combine.integer && r_textureunits.integer >= 2)
6010 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist);
6012 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist);
6015 GL_LockArrays(0, 0);
6018 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6021 int texturenumsurfaces, endsurface;
6023 msurface_t *surface;
6024 msurface_t *texturesurfacelist[1024];
6026 // if the model is static it doesn't matter what value we give for
6027 // wantnormals and wanttangents, so this logic uses only rules applicable
6028 // to a model, knowing that they are meaningless otherwise
6029 if (ent == r_refdef.worldentity)
6030 RSurf_ActiveWorldEntity();
6031 else if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
6032 RSurf_ActiveModelEntity(ent, false, false);
6034 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
6036 for (i = 0;i < numsurfaces;i = j)
6039 surface = rsurface.modelsurfaces + surfacelist[i];
6040 texture = surface->texture;
6041 R_UpdateTextureInfo(ent, texture);
6042 rsurface.texture = texture->currentframe;
6043 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
6044 // scan ahead until we find a different texture
6045 endsurface = min(i + 1024, numsurfaces);
6046 texturenumsurfaces = 0;
6047 texturesurfacelist[texturenumsurfaces++] = surface;
6048 for (;j < endsurface;j++)
6050 surface = rsurface.modelsurfaces + surfacelist[j];
6051 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
6053 texturesurfacelist[texturenumsurfaces++] = surface;
6055 // render the range of surfaces
6056 R_DrawTextureSurfaceList(texturenumsurfaces, texturesurfacelist, true, false);
6062 void R_QueueSurfaceList(entity_render_t *ent, int numsurfaces, msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes)
6065 vec3_t tempcenter, center;
6067 // if we're rendering water textures (extra scene renders), use a separate loop to avoid burdening the main one
6070 for (i = 0;i < numsurfaces;i++)
6071 if (surfacelist[i]->texture->currentframe->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION))
6072 R_Water_AddWaterPlane(surfacelist[i]);
6075 // break the surface list down into batches by texture and use of lightmapping
6076 for (i = 0;i < numsurfaces;i = j)
6079 // texture is the base texture pointer, rsurface.texture is the
6080 // current frame/skin the texture is directing us to use (for example
6081 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
6082 // use skin 1 instead)
6083 texture = surfacelist[i]->texture;
6084 rsurface.texture = texture->currentframe;
6085 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
6086 if (!(rsurface.texture->currentmaterialflags & flagsmask))
6088 // if this texture is not the kind we want, skip ahead to the next one
6089 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
6093 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
6095 // transparent surfaces get pushed off into the transparent queue
6096 const msurface_t *surface = surfacelist[i];
6099 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
6100 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
6101 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
6102 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
6103 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_view.origin : center, R_DrawSurface_TransparentCallback, ent, surface - rsurface.modelsurfaces, rsurface.rtlight);
6107 // simply scan ahead until we find a different texture or lightmap state
6108 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
6110 // render the range of surfaces
6111 R_DrawTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly);
6116 float locboxvertex3f[6*4*3] =
6118 1,0,1, 1,0,0, 1,1,0, 1,1,1,
6119 0,1,1, 0,1,0, 0,0,0, 0,0,1,
6120 1,1,1, 1,1,0, 0,1,0, 0,1,1,
6121 0,0,1, 0,0,0, 1,0,0, 1,0,1,
6122 0,0,1, 1,0,1, 1,1,1, 0,1,1,
6123 1,0,0, 0,0,0, 0,1,0, 1,1,0
6126 int locboxelement3i[6*2*3] =
6136 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6139 cl_locnode_t *loc = (cl_locnode_t *)ent;
6141 float vertex3f[6*4*3];
6143 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6144 GL_DepthMask(false);
6145 GL_DepthRange(0, 1);
6146 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6148 GL_CullFace(GL_NONE);
6149 R_Mesh_Matrix(&identitymatrix);
6151 R_Mesh_VertexPointer(vertex3f, 0, 0);
6152 R_Mesh_ColorPointer(NULL, 0, 0);
6153 R_Mesh_ResetTextureState();
6156 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_view.colorscale,
6157 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_view.colorscale,
6158 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_view.colorscale,
6159 surfacelist[0] < 0 ? 0.5f : 0.125f);
6161 if (VectorCompare(loc->mins, loc->maxs))
6163 VectorSet(size, 2, 2, 2);
6164 VectorMA(loc->mins, -0.5f, size, mins);
6168 VectorCopy(loc->mins, mins);
6169 VectorSubtract(loc->maxs, loc->mins, size);
6172 for (i = 0;i < 6*4*3;)
6173 for (j = 0;j < 3;j++, i++)
6174 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
6176 R_Mesh_Draw(0, 6*4, 6*2, locboxelement3i, 0, 0);
6179 void R_DrawLocs(void)
6182 cl_locnode_t *loc, *nearestloc;
6184 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
6185 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
6187 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
6188 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
6192 void R_DrawDebugModel(entity_render_t *ent)
6194 int i, j, k, l, flagsmask;
6195 const int *elements;
6197 msurface_t *surface;
6198 model_t *model = ent->model;
6201 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WATER | MATERIALFLAG_WALL;
6203 R_Mesh_ColorPointer(NULL, 0, 0);
6204 R_Mesh_ResetTextureState();
6205 GL_DepthRange(0, 1);
6206 GL_DepthTest(!r_showdisabledepthtest.integer);
6207 GL_DepthMask(false);
6208 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6210 if (r_showcollisionbrushes.value > 0 && model->brush.num_brushes)
6212 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
6213 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
6215 if (brush->colbrushf && brush->colbrushf->numtriangles)
6217 R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
6218 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);
6219 R_Mesh_Draw(0, brush->colbrushf->numpoints, brush->colbrushf->numtriangles, brush->colbrushf->elements, 0, 0);
6222 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
6224 if (surface->num_collisiontriangles)
6226 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
6227 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);
6228 R_Mesh_Draw(0, surface->num_collisionvertices, surface->num_collisiontriangles, surface->data_collisionelement3i, 0, 0);
6233 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6235 if (r_showtris.integer || r_shownormals.integer)
6237 if (r_showdisabledepthtest.integer)
6239 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6240 GL_DepthMask(false);
6244 GL_BlendFunc(GL_ONE, GL_ZERO);
6247 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
6249 if (ent == r_refdef.worldentity && !r_viewcache.world_surfacevisible[j])
6251 rsurface.texture = surface->texture->currentframe;
6252 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
6254 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
6255 if (r_showtris.value > 0)
6257 if (!rsurface.texture->currentlayers->depthmask)
6258 GL_Color(r_view.colorscale, 0, 0, r_showtris.value);
6259 else if (ent == r_refdef.worldentity)
6260 GL_Color(r_view.colorscale, r_view.colorscale, r_view.colorscale, r_showtris.value);
6262 GL_Color(0, r_view.colorscale, 0, r_showtris.value);
6263 elements = (ent->model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
6266 for (k = 0;k < surface->num_triangles;k++, elements += 3)
6268 #define GLVERTEXELEMENT(n) qglVertex3f(rsurface.vertex3f[elements[n]*3+0], rsurface.vertex3f[elements[n]*3+1], rsurface.vertex3f[elements[n]*3+2])
6269 GLVERTEXELEMENT(0);GLVERTEXELEMENT(1);
6270 GLVERTEXELEMENT(1);GLVERTEXELEMENT(2);
6271 GLVERTEXELEMENT(2);GLVERTEXELEMENT(0);
6276 if (r_shownormals.value > 0)
6279 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
6281 VectorCopy(rsurface.vertex3f + l * 3, v);
6282 GL_Color(r_view.colorscale, 0, 0, 1);
6283 qglVertex3f(v[0], v[1], v[2]);
6284 VectorMA(v, r_shownormals.value, rsurface.svector3f + l * 3, v);
6285 GL_Color(r_view.colorscale, 1, 1, 1);
6286 qglVertex3f(v[0], v[1], v[2]);
6291 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
6293 VectorCopy(rsurface.vertex3f + l * 3, v);
6294 GL_Color(0, r_view.colorscale, 0, 1);
6295 qglVertex3f(v[0], v[1], v[2]);
6296 VectorMA(v, r_shownormals.value, rsurface.tvector3f + l * 3, v);
6297 GL_Color(r_view.colorscale, 1, 1, 1);
6298 qglVertex3f(v[0], v[1], v[2]);
6303 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
6305 VectorCopy(rsurface.vertex3f + l * 3, v);
6306 GL_Color(0, 0, r_view.colorscale, 1);
6307 qglVertex3f(v[0], v[1], v[2]);
6308 VectorMA(v, r_shownormals.value, rsurface.normal3f + l * 3, v);
6309 GL_Color(r_view.colorscale, 1, 1, 1);
6310 qglVertex3f(v[0], v[1], v[2]);
6317 rsurface.texture = NULL;
6321 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
6322 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes, qboolean debug)
6324 int i, j, endj, f, flagsmask;
6325 msurface_t *surface;
6327 model_t *model = r_refdef.worldmodel;
6328 const int maxsurfacelist = 1024;
6329 int numsurfacelist = 0;
6330 msurface_t *surfacelist[1024];
6334 RSurf_ActiveWorldEntity();
6336 // update light styles on this submodel
6337 if (!skysurfaces && !depthonly && !addwaterplanes && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
6339 model_brush_lightstyleinfo_t *style;
6340 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
6342 if (style->value != r_refdef.lightstylevalue[style->style])
6344 msurface_t *surfaces = model->data_surfaces;
6345 int *list = style->surfacelist;
6346 style->value = r_refdef.lightstylevalue[style->style];
6347 for (j = 0;j < style->numsurfaces;j++)
6348 surfaces[list[j]].cached_dlight = true;
6353 R_UpdateAllTextureInfo(r_refdef.worldentity);
6354 flagsmask = addwaterplanes ? (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) : (skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL));
6358 R_DrawDebugModel(r_refdef.worldentity);
6364 rsurface.uselightmaptexture = false;
6365 rsurface.texture = NULL;
6367 j = model->firstmodelsurface;
6368 endj = j + model->nummodelsurfaces;
6371 // quickly skip over non-visible surfaces
6372 for (;j < endj && !r_viewcache.world_surfacevisible[j];j++)
6374 // quickly iterate over visible surfaces
6375 for (;j < endj && r_viewcache.world_surfacevisible[j];j++)
6377 // process this surface
6378 surface = model->data_surfaces + j;
6379 // if this surface fits the criteria, add it to the list
6380 if (surface->num_triangles)
6382 // if lightmap parameters changed, rebuild lightmap texture
6383 if (surface->cached_dlight)
6384 R_BuildLightMap(r_refdef.worldentity, surface);
6385 // add face to draw list
6386 surfacelist[numsurfacelist++] = surface;
6387 r_refdef.stats.world_triangles += surface->num_triangles;
6388 if (numsurfacelist >= maxsurfacelist)
6390 r_refdef.stats.world_surfaces += numsurfacelist;
6391 R_QueueSurfaceList(r_refdef.worldentity, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
6397 r_refdef.stats.world_surfaces += numsurfacelist;
6399 R_QueueSurfaceList(r_refdef.worldentity, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
6403 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes, qboolean debug)
6405 int i, j, f, flagsmask;
6406 msurface_t *surface, *endsurface;
6408 model_t *model = ent->model;
6409 const int maxsurfacelist = 1024;
6410 int numsurfacelist = 0;
6411 msurface_t *surfacelist[1024];
6415 // if the model is static it doesn't matter what value we give for
6416 // wantnormals and wanttangents, so this logic uses only rules applicable
6417 // to a model, knowing that they are meaningless otherwise
6418 if (ent == r_refdef.worldentity)
6419 RSurf_ActiveWorldEntity();
6420 else if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
6421 RSurf_ActiveModelEntity(ent, false, false);
6423 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader && !depthonly);
6425 // update light styles
6426 if (!skysurfaces && !depthonly && !addwaterplanes && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
6428 model_brush_lightstyleinfo_t *style;
6429 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
6431 if (style->value != r_refdef.lightstylevalue[style->style])
6433 msurface_t *surfaces = model->data_surfaces;
6434 int *list = style->surfacelist;
6435 style->value = r_refdef.lightstylevalue[style->style];
6436 for (j = 0;j < style->numsurfaces;j++)
6437 surfaces[list[j]].cached_dlight = true;
6442 R_UpdateAllTextureInfo(ent);
6443 flagsmask = addwaterplanes ? (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) : (skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL));
6447 R_DrawDebugModel(ent);
6453 rsurface.uselightmaptexture = false;
6454 rsurface.texture = NULL;
6456 surface = model->data_surfaces + model->firstmodelsurface;
6457 endsurface = surface + model->nummodelsurfaces;
6458 for (;surface < endsurface;surface++)
6460 // if this surface fits the criteria, add it to the list
6461 if (surface->num_triangles)
6463 // if lightmap parameters changed, rebuild lightmap texture
6464 if (surface->cached_dlight)
6465 R_BuildLightMap(ent, surface);
6466 // add face to draw list
6467 surfacelist[numsurfacelist++] = surface;
6468 r_refdef.stats.entities_triangles += surface->num_triangles;
6469 if (numsurfacelist >= maxsurfacelist)
6471 r_refdef.stats.entities_surfaces += numsurfacelist;
6472 R_QueueSurfaceList(ent, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
6477 r_refdef.stats.entities_surfaces += numsurfacelist;
6479 R_QueueSurfaceList(ent, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);