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 Vector4Set(t->lightmapcolor, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
4228 VectorClear(t->dlightcolor);
4229 t->currentnumlayers = 0;
4230 if (!(t->currentmaterialflags & MATERIALFLAG_NODRAW))
4232 if (!(t->currentmaterialflags & MATERIALFLAG_SKY))
4234 int blendfunc1, blendfunc2, depthmask;
4235 if (t->currentmaterialflags & MATERIALFLAG_ADD)
4237 blendfunc1 = GL_SRC_ALPHA;
4238 blendfunc2 = GL_ONE;
4240 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
4242 blendfunc1 = GL_SRC_ALPHA;
4243 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
4245 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
4247 blendfunc1 = t->customblendfunc[0];
4248 blendfunc2 = t->customblendfunc[1];
4252 blendfunc1 = GL_ONE;
4253 blendfunc2 = GL_ZERO;
4255 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
4256 if (t->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL))
4258 rtexture_t *currentbasetexture;
4260 if (r_refdef.fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED))
4261 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
4262 currentbasetexture = (VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) < (1.0f / 1048576.0f) && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
4263 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
4265 // fullbright is not affected by r_refdef.lightmapintensity
4266 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
4267 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
4268 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);
4269 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
4270 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);
4275 // set the color tint used for lights affecting this surface
4276 VectorSet(t->dlightcolor, ent->colormod[0] * t->currentalpha, ent->colormod[1] * t->currentalpha, ent->colormod[2] * t->currentalpha);
4278 // q3bsp has no lightmap updates, so the lightstylevalue that
4279 // would normally be baked into the lightmap must be
4280 // applied to the color
4281 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
4282 if (ent->model->type == mod_brushq3)
4283 colorscale *= r_refdef.rtlightstylevalue[0];
4284 colorscale *= r_refdef.lightmapintensity;
4285 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
4286 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);
4287 if (r_ambient.value >= (1.0f/64.0f))
4288 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);
4289 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
4291 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);
4292 if (r_ambient.value >= (1.0f/64.0f))
4293 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);
4295 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
4297 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->currentskinframe->shirt, &t->currenttexmatrix, ent->colormap_shirtcolor[0] * ent->colormod[0] * colorscale, ent->colormap_shirtcolor[1] * ent->colormod[1] * colorscale, ent->colormap_shirtcolor[2] * ent->colormod[2] * colorscale, t->currentalpha);
4298 if (r_ambient.value >= (1.0f/64.0f))
4299 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);
4302 if (t->currentskinframe->glow != NULL)
4303 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);
4304 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
4306 // if this is opaque use alpha blend which will darken the earlier
4309 // if this is an alpha blended material, all the earlier passes
4310 // were darkened by fog already, so we only need to add the fog
4311 // color ontop through the fog mask texture
4313 // if this is an additive blended material, all the earlier passes
4314 // were darkened by fog already, and we should not add fog color
4315 // (because the background was not darkened, there is no fog color
4316 // that was lost behind it).
4317 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);
4324 void R_UpdateAllTextureInfo(entity_render_t *ent)
4328 for (i = 0;i < ent->model->num_texturesperskin;i++)
4329 R_UpdateTextureInfo(ent, ent->model->data_textures + i);
4332 rsurfacestate_t rsurface;
4334 void R_Mesh_ResizeArrays(int newvertices)
4337 if (rsurface.array_size >= newvertices)
4339 if (rsurface.array_modelvertex3f)
4340 Mem_Free(rsurface.array_modelvertex3f);
4341 rsurface.array_size = (newvertices + 1023) & ~1023;
4342 base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
4343 rsurface.array_modelvertex3f = base + rsurface.array_size * 0;
4344 rsurface.array_modelsvector3f = base + rsurface.array_size * 3;
4345 rsurface.array_modeltvector3f = base + rsurface.array_size * 6;
4346 rsurface.array_modelnormal3f = base + rsurface.array_size * 9;
4347 rsurface.array_deformedvertex3f = base + rsurface.array_size * 12;
4348 rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
4349 rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
4350 rsurface.array_deformednormal3f = base + rsurface.array_size * 21;
4351 rsurface.array_texcoord3f = base + rsurface.array_size * 24;
4352 rsurface.array_color4f = base + rsurface.array_size * 27;
4353 rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
4356 void RSurf_CleanUp(void)
4359 if (rsurface.mode == RSURFMODE_GLSL)
4361 qglUseProgramObjectARB(0);CHECKGLERROR
4363 GL_AlphaTest(false);
4364 rsurface.mode = RSURFMODE_NONE;
4365 rsurface.uselightmaptexture = false;
4366 rsurface.texture = NULL;
4369 void RSurf_ActiveWorldEntity(void)
4371 model_t *model = r_refdef.worldmodel;
4373 if (rsurface.array_size < model->surfmesh.num_vertices)
4374 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
4375 rsurface.matrix = identitymatrix;
4376 rsurface.inversematrix = identitymatrix;
4377 R_Mesh_Matrix(&identitymatrix);
4378 VectorCopy(r_view.origin, rsurface.modelorg);
4379 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
4380 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
4381 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
4382 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
4383 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
4384 rsurface.frameblend[0].frame = 0;
4385 rsurface.frameblend[0].lerp = 1;
4386 rsurface.frameblend[1].frame = 0;
4387 rsurface.frameblend[1].lerp = 0;
4388 rsurface.frameblend[2].frame = 0;
4389 rsurface.frameblend[2].lerp = 0;
4390 rsurface.frameblend[3].frame = 0;
4391 rsurface.frameblend[3].lerp = 0;
4392 rsurface.basepolygonfactor = r_refdef.polygonfactor;
4393 rsurface.basepolygonoffset = r_refdef.polygonoffset;
4394 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
4395 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
4396 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
4397 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
4398 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
4399 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
4400 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
4401 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
4402 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
4403 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
4404 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
4405 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
4406 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
4407 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
4408 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
4409 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
4410 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
4411 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
4412 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
4413 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
4414 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
4415 rsurface.modelelement3i = model->surfmesh.data_element3i;
4416 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo;
4417 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
4418 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
4419 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
4420 rsurface.modelsurfaces = model->data_surfaces;
4421 rsurface.generatedvertex = false;
4422 rsurface.vertex3f = rsurface.modelvertex3f;
4423 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
4424 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
4425 rsurface.svector3f = rsurface.modelsvector3f;
4426 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
4427 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
4428 rsurface.tvector3f = rsurface.modeltvector3f;
4429 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
4430 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
4431 rsurface.normal3f = rsurface.modelnormal3f;
4432 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
4433 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
4434 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
4437 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4439 model_t *model = ent->model;
4441 if (rsurface.array_size < model->surfmesh.num_vertices)
4442 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
4443 rsurface.matrix = ent->matrix;
4444 rsurface.inversematrix = ent->inversematrix;
4445 R_Mesh_Matrix(&rsurface.matrix);
4446 Matrix4x4_Transform(&rsurface.inversematrix, r_view.origin, rsurface.modelorg);
4447 rsurface.modellight_ambient[0] = ent->modellight_ambient[0] * ent->colormod[0];
4448 rsurface.modellight_ambient[1] = ent->modellight_ambient[1] * ent->colormod[1];
4449 rsurface.modellight_ambient[2] = ent->modellight_ambient[2] * ent->colormod[2];
4450 rsurface.modellight_diffuse[0] = ent->modellight_diffuse[0] * ent->colormod[0];
4451 rsurface.modellight_diffuse[1] = ent->modellight_diffuse[1] * ent->colormod[1];
4452 rsurface.modellight_diffuse[2] = ent->modellight_diffuse[2] * ent->colormod[2];
4453 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
4454 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
4455 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
4456 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
4457 rsurface.frameblend[0] = ent->frameblend[0];
4458 rsurface.frameblend[1] = ent->frameblend[1];
4459 rsurface.frameblend[2] = ent->frameblend[2];
4460 rsurface.frameblend[3] = ent->frameblend[3];
4461 rsurface.basepolygonfactor = r_refdef.polygonfactor;
4462 rsurface.basepolygonoffset = r_refdef.polygonoffset;
4463 if (ent->model->brush.submodel)
4465 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
4466 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
4468 if (model->surfmesh.isanimated && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].frame != 0))
4472 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
4473 rsurface.modelsvector3f = rsurface.array_modelsvector3f;
4474 rsurface.modeltvector3f = rsurface.array_modeltvector3f;
4475 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
4476 Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
4478 else if (wantnormals)
4480 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
4481 rsurface.modelsvector3f = NULL;
4482 rsurface.modeltvector3f = NULL;
4483 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
4484 Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
4488 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
4489 rsurface.modelsvector3f = NULL;
4490 rsurface.modeltvector3f = NULL;
4491 rsurface.modelnormal3f = NULL;
4492 Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, NULL, NULL, NULL);
4494 rsurface.modelvertex3f_bufferobject = 0;
4495 rsurface.modelvertex3f_bufferoffset = 0;
4496 rsurface.modelsvector3f_bufferobject = 0;
4497 rsurface.modelsvector3f_bufferoffset = 0;
4498 rsurface.modeltvector3f_bufferobject = 0;
4499 rsurface.modeltvector3f_bufferoffset = 0;
4500 rsurface.modelnormal3f_bufferobject = 0;
4501 rsurface.modelnormal3f_bufferoffset = 0;
4502 rsurface.generatedvertex = true;
4506 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
4507 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
4508 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
4509 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
4510 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
4511 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
4512 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
4513 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
4514 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
4515 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
4516 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
4517 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
4518 rsurface.generatedvertex = false;
4520 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
4521 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
4522 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
4523 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
4524 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
4525 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
4526 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
4527 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
4528 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
4529 rsurface.modelelement3i = model->surfmesh.data_element3i;
4530 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo;
4531 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
4532 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
4533 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
4534 rsurface.modelsurfaces = model->data_surfaces;
4535 rsurface.vertex3f = rsurface.modelvertex3f;
4536 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
4537 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
4538 rsurface.svector3f = rsurface.modelsvector3f;
4539 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
4540 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
4541 rsurface.tvector3f = rsurface.modeltvector3f;
4542 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
4543 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
4544 rsurface.normal3f = rsurface.modelnormal3f;
4545 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
4546 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
4547 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
4550 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
4551 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, msurface_t **texturesurfacelist)
4554 int texturesurfaceindex;
4559 const float *v1, *in_tc;
4561 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
4563 q3shaderinfo_deform_t *deform;
4564 // 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
4565 if (rsurface.generatedvertex)
4567 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
4568 generatenormals = true;
4569 for (i = 0;i < Q3MAXDEFORMS;i++)
4571 if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
4573 generatetangents = true;
4574 generatenormals = true;
4576 if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
4577 generatenormals = true;
4579 if (generatenormals && !rsurface.modelnormal3f)
4581 rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
4582 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
4583 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
4584 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer);
4586 if (generatetangents && !rsurface.modelsvector3f)
4588 rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
4589 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
4590 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
4591 rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
4592 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
4593 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
4594 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);
4597 rsurface.vertex3f = rsurface.modelvertex3f;
4598 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
4599 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
4600 rsurface.svector3f = rsurface.modelsvector3f;
4601 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
4602 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
4603 rsurface.tvector3f = rsurface.modeltvector3f;
4604 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
4605 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
4606 rsurface.normal3f = rsurface.modelnormal3f;
4607 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
4608 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
4609 // if vertices are deformed (sprite flares and things in maps, possibly
4610 // water waves, bulges and other deformations), generate them into
4611 // rsurface.deform* arrays from whatever the rsurface.* arrays point to
4612 // (may be static model data or generated data for an animated model, or
4613 // the previous deform pass)
4614 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
4616 switch (deform->deform)
4619 case Q3DEFORM_PROJECTIONSHADOW:
4620 case Q3DEFORM_TEXT0:
4621 case Q3DEFORM_TEXT1:
4622 case Q3DEFORM_TEXT2:
4623 case Q3DEFORM_TEXT3:
4624 case Q3DEFORM_TEXT4:
4625 case Q3DEFORM_TEXT5:
4626 case Q3DEFORM_TEXT6:
4627 case Q3DEFORM_TEXT7:
4630 case Q3DEFORM_AUTOSPRITE:
4631 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.forward, newforward);
4632 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.right, newright);
4633 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.up, newup);
4634 VectorNormalize(newforward);
4635 VectorNormalize(newright);
4636 VectorNormalize(newup);
4637 // make deformed versions of only the model vertices used by the specified surfaces
4638 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4640 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4641 // a single autosprite surface can contain multiple sprites...
4642 for (j = 0;j < surface->num_vertices - 3;j += 4)
4644 VectorClear(center);
4645 for (i = 0;i < 4;i++)
4646 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
4647 VectorScale(center, 0.25f, center);
4648 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, forward);
4649 VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
4650 VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
4651 for (i = 0;i < 4;i++)
4653 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
4654 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
4657 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);
4658 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);
4660 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4661 rsurface.vertex3f_bufferobject = 0;
4662 rsurface.vertex3f_bufferoffset = 0;
4663 rsurface.svector3f = rsurface.array_deformedsvector3f;
4664 rsurface.svector3f_bufferobject = 0;
4665 rsurface.svector3f_bufferoffset = 0;
4666 rsurface.tvector3f = rsurface.array_deformedtvector3f;
4667 rsurface.tvector3f_bufferobject = 0;
4668 rsurface.tvector3f_bufferoffset = 0;
4669 rsurface.normal3f = rsurface.array_deformednormal3f;
4670 rsurface.normal3f_bufferobject = 0;
4671 rsurface.normal3f_bufferoffset = 0;
4673 case Q3DEFORM_AUTOSPRITE2:
4674 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.forward, newforward);
4675 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.right, newright);
4676 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.up, newup);
4677 VectorNormalize(newforward);
4678 VectorNormalize(newright);
4679 VectorNormalize(newup);
4680 // make deformed versions of only the model vertices used by the specified surfaces
4681 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4683 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4684 const float *v1, *v2;
4694 memset(shortest, 0, sizeof(shortest));
4695 // a single autosprite surface can contain multiple sprites...
4696 for (j = 0;j < surface->num_vertices - 3;j += 4)
4698 VectorClear(center);
4699 for (i = 0;i < 4;i++)
4700 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
4701 VectorScale(center, 0.25f, center);
4702 // find the two shortest edges, then use them to define the
4703 // axis vectors for rotating around the central axis
4704 for (i = 0;i < 6;i++)
4706 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
4707 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
4709 Debug_PolygonBegin(NULL, 0, false, 0);
4710 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
4711 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);
4712 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
4715 l = VectorDistance2(v1, v2);
4716 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
4718 l += (1.0f / 1024.0f);
4719 if (shortest[0].length2 > l || i == 0)
4721 shortest[1] = shortest[0];
4722 shortest[0].length2 = l;
4723 shortest[0].v1 = v1;
4724 shortest[0].v2 = v2;
4726 else if (shortest[1].length2 > l || i == 1)
4728 shortest[1].length2 = l;
4729 shortest[1].v1 = v1;
4730 shortest[1].v2 = v2;
4733 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
4734 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
4736 Debug_PolygonBegin(NULL, 0, false, 0);
4737 Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
4738 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);
4739 Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
4742 // this calculates the right vector from the shortest edge
4743 // and the up vector from the edge midpoints
4744 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
4745 VectorNormalize(right);
4746 VectorSubtract(end, start, up);
4747 VectorNormalize(up);
4748 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
4749 //VectorSubtract(rsurface.modelorg, center, forward);
4750 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.forward, forward);
4751 VectorNegate(forward, forward);
4752 VectorReflect(forward, 0, up, forward);
4753 VectorNormalize(forward);
4754 CrossProduct(up, forward, newright);
4755 VectorNormalize(newright);
4757 Debug_PolygonBegin(NULL, 0, false, 0);
4758 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);
4759 Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
4760 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
4764 Debug_PolygonBegin(NULL, 0, false, 0);
4765 Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
4766 Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
4767 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
4770 // rotate the quad around the up axis vector, this is made
4771 // especially easy by the fact we know the quad is flat,
4772 // so we only have to subtract the center position and
4773 // measure distance along the right vector, and then
4774 // multiply that by the newright vector and add back the
4776 // we also need to subtract the old position to undo the
4777 // displacement from the center, which we do with a
4778 // DotProduct, the subtraction/addition of center is also
4779 // optimized into DotProducts here
4780 l = DotProduct(right, center);
4781 for (i = 0;i < 4;i++)
4783 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
4784 f = DotProduct(right, v1) - l;
4785 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
4788 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);
4789 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);
4791 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4792 rsurface.vertex3f_bufferobject = 0;
4793 rsurface.vertex3f_bufferoffset = 0;
4794 rsurface.svector3f = rsurface.array_deformedsvector3f;
4795 rsurface.svector3f_bufferobject = 0;
4796 rsurface.svector3f_bufferoffset = 0;
4797 rsurface.tvector3f = rsurface.array_deformedtvector3f;
4798 rsurface.tvector3f_bufferobject = 0;
4799 rsurface.tvector3f_bufferoffset = 0;
4800 rsurface.normal3f = rsurface.array_deformednormal3f;
4801 rsurface.normal3f_bufferobject = 0;
4802 rsurface.normal3f_bufferoffset = 0;
4804 case Q3DEFORM_NORMAL:
4805 // deform the normals to make reflections wavey
4806 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4808 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4809 for (j = 0;j < surface->num_vertices;j++)
4812 float *normal = (rsurface.array_deformednormal3f + 3 * surface->num_firstvertex) + j*3;
4813 VectorScale((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
4814 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, normal);
4815 normal[0] += deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.time * deform->parms[1]);
4816 normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.time * deform->parms[1]);
4817 normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.time * deform->parms[1]);
4818 VectorNormalize(normal);
4820 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);
4822 rsurface.svector3f = rsurface.array_deformedsvector3f;
4823 rsurface.svector3f_bufferobject = 0;
4824 rsurface.svector3f_bufferoffset = 0;
4825 rsurface.tvector3f = rsurface.array_deformedtvector3f;
4826 rsurface.tvector3f_bufferobject = 0;
4827 rsurface.tvector3f_bufferoffset = 0;
4828 rsurface.normal3f = rsurface.array_deformednormal3f;
4829 rsurface.normal3f_bufferobject = 0;
4830 rsurface.normal3f_bufferoffset = 0;
4833 // deform vertex array to make wavey water and flags and such
4834 waveparms[0] = deform->waveparms[0];
4835 waveparms[1] = deform->waveparms[1];
4836 waveparms[2] = deform->waveparms[2];
4837 waveparms[3] = deform->waveparms[3];
4838 // this is how a divisor of vertex influence on deformation
4839 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
4840 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
4841 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4843 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4844 for (j = 0;j < surface->num_vertices;j++)
4846 float *vertex = (rsurface.array_deformedvertex3f + 3 * surface->num_firstvertex) + j*3;
4847 VectorCopy((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, vertex);
4848 // if the wavefunc depends on time, evaluate it per-vertex
4851 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
4852 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
4854 VectorMA(vertex, scale, (rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, vertex);
4857 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4858 rsurface.vertex3f_bufferobject = 0;
4859 rsurface.vertex3f_bufferoffset = 0;
4861 case Q3DEFORM_BULGE:
4862 // deform vertex array to make the surface have moving bulges
4863 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4865 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4866 for (j = 0;j < surface->num_vertices;j++)
4868 scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.time * deform->parms[2])) * deform->parms[1];
4869 VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
4872 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4873 rsurface.vertex3f_bufferobject = 0;
4874 rsurface.vertex3f_bufferoffset = 0;
4877 // deform vertex array
4878 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
4879 VectorScale(deform->parms, scale, waveparms);
4880 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4882 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4883 for (j = 0;j < surface->num_vertices;j++)
4884 VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
4886 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4887 rsurface.vertex3f_bufferobject = 0;
4888 rsurface.vertex3f_bufferoffset = 0;
4892 // generate texcoords based on the chosen texcoord source
4893 switch(rsurface.texture->tcgen.tcgen)
4896 case Q3TCGEN_TEXTURE:
4897 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
4898 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordtexture2f_bufferobject;
4899 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
4901 case Q3TCGEN_LIGHTMAP:
4902 rsurface.texcoordtexture2f = rsurface.modeltexcoordlightmap2f;
4903 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
4904 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
4906 case Q3TCGEN_VECTOR:
4907 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4909 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4910 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)
4912 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
4913 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
4916 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
4917 rsurface.texcoordtexture2f_bufferobject = 0;
4918 rsurface.texcoordtexture2f_bufferoffset = 0;
4920 case Q3TCGEN_ENVIRONMENT:
4921 // make environment reflections using a spheremap
4922 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4924 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4925 const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
4926 const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
4927 float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
4928 for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
4930 float l, d, eyedir[3];
4931 VectorSubtract(rsurface.modelorg, vertex, eyedir);
4932 l = 0.5f / VectorLength(eyedir);
4933 d = DotProduct(normal, eyedir)*2;
4934 out_tc[0] = 0.5f + (normal[1]*d - eyedir[1])*l;
4935 out_tc[1] = 0.5f - (normal[2]*d - eyedir[2])*l;
4938 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
4939 rsurface.texcoordtexture2f_bufferobject = 0;
4940 rsurface.texcoordtexture2f_bufferoffset = 0;
4943 // the only tcmod that needs software vertex processing is turbulent, so
4944 // check for it here and apply the changes if needed
4945 // and we only support that as the first one
4946 // (handling a mixture of turbulent and other tcmods would be problematic
4947 // without punting it entirely to a software path)
4948 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
4950 amplitude = rsurface.texture->tcmods[0].parms[1];
4951 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.time * rsurface.texture->tcmods[0].parms[3];
4952 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4954 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4955 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)
4957 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
4958 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
4961 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
4962 rsurface.texcoordtexture2f_bufferobject = 0;
4963 rsurface.texcoordtexture2f_bufferoffset = 0;
4965 rsurface.texcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
4966 rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
4967 rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
4968 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
4971 void RSurf_DrawBatch_Simple(int texturenumsurfaces, msurface_t **texturesurfacelist)
4974 const msurface_t *surface = texturesurfacelist[0];
4975 const msurface_t *surface2;
4980 // TODO: lock all array ranges before render, rather than on each surface
4981 if (texturenumsurfaces == 1)
4983 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
4984 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));
4986 else if (r_batchmode.integer == 2)
4988 #define MAXBATCHTRIANGLES 4096
4989 int batchtriangles = 0;
4990 int batchelements[MAXBATCHTRIANGLES*3];
4991 for (i = 0;i < texturenumsurfaces;i = j)
4993 surface = texturesurfacelist[i];
4995 if (surface->num_triangles > MAXBATCHTRIANGLES)
4997 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));
5000 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
5001 batchtriangles = surface->num_triangles;
5002 firstvertex = surface->num_firstvertex;
5003 endvertex = surface->num_firstvertex + surface->num_vertices;
5004 for (;j < texturenumsurfaces;j++)
5006 surface2 = texturesurfacelist[j];
5007 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
5009 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
5010 batchtriangles += surface2->num_triangles;
5011 firstvertex = min(firstvertex, surface2->num_firstvertex);
5012 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
5014 surface2 = texturesurfacelist[j-1];
5015 numvertices = endvertex - firstvertex;
5016 R_Mesh_Draw(firstvertex, numvertices, batchtriangles, batchelements, 0, 0);
5019 else if (r_batchmode.integer == 1)
5021 for (i = 0;i < texturenumsurfaces;i = j)
5023 surface = texturesurfacelist[i];
5024 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
5025 if (texturesurfacelist[j] != surface2)
5027 surface2 = texturesurfacelist[j-1];
5028 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
5029 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
5030 GL_LockArrays(surface->num_firstvertex, numvertices);
5031 R_Mesh_Draw(surface->num_firstvertex, numvertices, numtriangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
5036 for (i = 0;i < texturenumsurfaces;i++)
5038 surface = texturesurfacelist[i];
5039 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5040 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));
5045 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit, int refractiontexunit, int reflectiontexunit)
5047 int i, planeindex, vertexindex;
5051 r_waterstate_waterplane_t *p, *bestp;
5052 msurface_t *surface;
5053 if (r_waterstate.renderingscene)
5055 for (i = 0;i < texturenumsurfaces;i++)
5057 surface = texturesurfacelist[i];
5058 if (lightmaptexunit >= 0)
5059 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5060 if (deluxemaptexunit >= 0)
5061 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5062 // pick the closest matching water plane
5065 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5068 for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
5070 Matrix4x4_Transform(&rsurface.matrix, v, vert);
5071 d += fabs(PlaneDiff(vert, &p->plane));
5073 if (bestd > d || !bestp)
5081 if (refractiontexunit >= 0)
5082 R_Mesh_TexBind(refractiontexunit, R_GetTexture(bestp->texture_refraction));
5083 if (reflectiontexunit >= 0)
5084 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(bestp->texture_reflection));
5088 if (refractiontexunit >= 0)
5089 R_Mesh_TexBind(refractiontexunit, R_GetTexture(r_texture_black));
5090 if (reflectiontexunit >= 0)
5091 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(r_texture_black));
5093 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5094 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));
5098 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit)
5102 const msurface_t *surface = texturesurfacelist[0];
5103 const msurface_t *surface2;
5108 // TODO: lock all array ranges before render, rather than on each surface
5109 if (texturenumsurfaces == 1)
5111 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5112 if (deluxemaptexunit >= 0)
5113 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5114 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5115 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));
5117 else if (r_batchmode.integer == 2)
5119 #define MAXBATCHTRIANGLES 4096
5120 int batchtriangles = 0;
5121 int batchelements[MAXBATCHTRIANGLES*3];
5122 for (i = 0;i < texturenumsurfaces;i = j)
5124 surface = texturesurfacelist[i];
5125 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5126 if (deluxemaptexunit >= 0)
5127 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5129 if (surface->num_triangles > MAXBATCHTRIANGLES)
5131 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));
5134 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
5135 batchtriangles = surface->num_triangles;
5136 firstvertex = surface->num_firstvertex;
5137 endvertex = surface->num_firstvertex + surface->num_vertices;
5138 for (;j < texturenumsurfaces;j++)
5140 surface2 = texturesurfacelist[j];
5141 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
5143 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
5144 batchtriangles += surface2->num_triangles;
5145 firstvertex = min(firstvertex, surface2->num_firstvertex);
5146 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
5148 surface2 = texturesurfacelist[j-1];
5149 numvertices = endvertex - firstvertex;
5150 R_Mesh_Draw(firstvertex, numvertices, batchtriangles, batchelements, 0, 0);
5153 else if (r_batchmode.integer == 1)
5156 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
5157 for (i = 0;i < texturenumsurfaces;i = j)
5159 surface = texturesurfacelist[i];
5160 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
5161 if (texturesurfacelist[j] != surface2)
5163 Con_Printf(" %i", j - i);
5166 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
5168 for (i = 0;i < texturenumsurfaces;i = j)
5170 surface = texturesurfacelist[i];
5171 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5172 if (deluxemaptexunit >= 0)
5173 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5174 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
5175 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
5178 Con_Printf(" %i", j - i);
5180 surface2 = texturesurfacelist[j-1];
5181 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
5182 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
5183 GL_LockArrays(surface->num_firstvertex, numvertices);
5184 R_Mesh_Draw(surface->num_firstvertex, numvertices, numtriangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
5192 for (i = 0;i < texturenumsurfaces;i++)
5194 surface = texturesurfacelist[i];
5195 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5196 if (deluxemaptexunit >= 0)
5197 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5198 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5199 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));
5204 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
5207 int texturesurfaceindex;
5208 if (r_showsurfaces.integer == 2)
5210 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5212 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5213 for (j = 0;j < surface->num_triangles;j++)
5215 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_view.colorscale;
5216 GL_Color(f, f, f, 1);
5217 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)));
5223 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5225 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5226 int k = (int)(((size_t)surface) / sizeof(msurface_t));
5227 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);
5228 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5229 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));
5234 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, msurface_t **texturesurfacelist)
5236 int texturesurfaceindex;
5240 if (rsurface.lightmapcolor4f)
5242 // generate color arrays for the surfaces in this list
5243 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5245 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5246 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)
5248 f = FogPoint_Model(v);
5258 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5260 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5261 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)
5263 f = FogPoint_Model(v);
5271 rsurface.lightmapcolor4f = rsurface.array_color4f;
5272 rsurface.lightmapcolor4f_bufferobject = 0;
5273 rsurface.lightmapcolor4f_bufferoffset = 0;
5276 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a)
5278 int texturesurfaceindex;
5281 if (!rsurface.lightmapcolor4f)
5283 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5285 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5286 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)
5294 rsurface.lightmapcolor4f = rsurface.array_color4f;
5295 rsurface.lightmapcolor4f_bufferobject = 0;
5296 rsurface.lightmapcolor4f_bufferoffset = 0;
5299 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5302 rsurface.lightmapcolor4f = NULL;
5303 rsurface.lightmapcolor4f_bufferobject = 0;
5304 rsurface.lightmapcolor4f_bufferoffset = 0;
5305 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5306 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5307 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5308 GL_Color(r, g, b, a);
5309 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 0, -1);
5312 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5314 // TODO: optimize applyfog && applycolor case
5315 // just apply fog if necessary, and tint the fog color array if necessary
5316 rsurface.lightmapcolor4f = NULL;
5317 rsurface.lightmapcolor4f_bufferobject = 0;
5318 rsurface.lightmapcolor4f_bufferoffset = 0;
5319 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5320 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5321 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5322 GL_Color(r, g, b, a);
5323 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5326 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5328 int texturesurfaceindex;
5332 if (texturesurfacelist[0]->lightmapinfo && texturesurfacelist[0]->lightmapinfo->stainsamples)
5334 // generate color arrays for the surfaces in this list
5335 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5337 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5338 for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
5340 if (surface->lightmapinfo->samples)
5342 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
5343 float scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
5344 VectorScale(lm, scale, c);
5345 if (surface->lightmapinfo->styles[1] != 255)
5347 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
5349 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
5350 VectorMA(c, scale, lm, c);
5351 if (surface->lightmapinfo->styles[2] != 255)
5354 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
5355 VectorMA(c, scale, lm, c);
5356 if (surface->lightmapinfo->styles[3] != 255)
5359 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
5360 VectorMA(c, scale, lm, c);
5370 rsurface.lightmapcolor4f = rsurface.array_color4f;
5371 rsurface.lightmapcolor4f_bufferobject = 0;
5372 rsurface.lightmapcolor4f_bufferoffset = 0;
5376 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
5377 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
5378 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
5380 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5381 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5382 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5383 GL_Color(r, g, b, a);
5384 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5387 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5389 int texturesurfaceindex;
5393 vec3_t ambientcolor;
5394 vec3_t diffusecolor;
5398 VectorCopy(rsurface.modellight_lightdir, lightdir);
5399 f = 0.5f * r_refdef.lightmapintensity;
5400 ambientcolor[0] = rsurface.modellight_ambient[0] * r * f;
5401 ambientcolor[1] = rsurface.modellight_ambient[1] * g * f;
5402 ambientcolor[2] = rsurface.modellight_ambient[2] * b * f;
5403 diffusecolor[0] = rsurface.modellight_diffuse[0] * r * f;
5404 diffusecolor[1] = rsurface.modellight_diffuse[1] * g * f;
5405 diffusecolor[2] = rsurface.modellight_diffuse[2] * b * f;
5406 if (VectorLength2(diffusecolor) > 0)
5408 // generate color arrays for the surfaces in this list
5409 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5411 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5412 int numverts = surface->num_vertices;
5413 v = rsurface.vertex3f + 3 * surface->num_firstvertex;
5414 c2 = rsurface.normal3f + 3 * surface->num_firstvertex;
5415 c = rsurface.array_color4f + 4 * surface->num_firstvertex;
5416 // q3-style directional shading
5417 for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
5419 if ((f = DotProduct(c2, lightdir)) > 0)
5420 VectorMA(ambientcolor, f, diffusecolor, c);
5422 VectorCopy(ambientcolor, c);
5431 rsurface.lightmapcolor4f = rsurface.array_color4f;
5432 rsurface.lightmapcolor4f_bufferobject = 0;
5433 rsurface.lightmapcolor4f_bufferoffset = 0;
5437 r = ambientcolor[0];
5438 g = ambientcolor[1];
5439 b = ambientcolor[2];
5440 rsurface.lightmapcolor4f = NULL;
5441 rsurface.lightmapcolor4f_bufferobject = 0;
5442 rsurface.lightmapcolor4f_bufferoffset = 0;
5444 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5445 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5446 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5447 GL_Color(r, g, b, a);
5448 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5451 void RSurf_SetupDepthAndCulling(void)
5453 // submodels are biased to avoid z-fighting with world surfaces that they
5454 // may be exactly overlapping (avoids z-fighting artifacts on certain
5455 // doors and things in Quake maps)
5456 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5457 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
5458 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
5459 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_view.cullface_back);
5462 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
5464 RSurf_SetupDepthAndCulling();
5465 if (rsurface.mode != RSURFMODE_SHOWSURFACES)
5467 rsurface.mode = RSURFMODE_SHOWSURFACES;
5469 GL_BlendFunc(GL_ONE, GL_ZERO);
5470 R_Mesh_ColorPointer(NULL, 0, 0);
5471 R_Mesh_ResetTextureState();
5473 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
5474 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
5477 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, msurface_t **texturesurfacelist)
5479 // transparent sky would be ridiculous
5480 if ((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED))
5482 if (rsurface.mode != RSURFMODE_SKY)
5484 if (rsurface.mode == RSURFMODE_GLSL)
5486 qglUseProgramObjectARB(0);CHECKGLERROR
5488 rsurface.mode = RSURFMODE_SKY;
5492 skyrendernow = false;
5494 // restore entity matrix
5495 R_Mesh_Matrix(&rsurface.matrix);
5497 RSurf_SetupDepthAndCulling();
5499 // LordHavoc: HalfLife maps have freaky skypolys so don't use
5500 // skymasking on them, and Quake3 never did sky masking (unlike
5501 // software Quake and software Quake2), so disable the sky masking
5502 // in Quake3 maps as it causes problems with q3map2 sky tricks,
5503 // and skymasking also looks very bad when noclipping outside the
5504 // level, so don't use it then either.
5505 if (r_refdef.worldmodel && r_refdef.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_viewcache.world_novis)
5507 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
5508 R_Mesh_ColorPointer(NULL, 0, 0);
5509 R_Mesh_ResetTextureState();
5510 if (skyrendermasked)
5512 // depth-only (masking)
5513 GL_ColorMask(0,0,0,0);
5514 // just to make sure that braindead drivers don't draw
5515 // anything despite that colormask...
5516 GL_BlendFunc(GL_ZERO, GL_ONE);
5521 GL_BlendFunc(GL_ONE, GL_ZERO);
5523 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
5524 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5525 if (skyrendermasked)
5526 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
5530 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, msurface_t **texturesurfacelist)
5532 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION)))
5535 if (rsurface.mode != RSURFMODE_GLSL)
5537 rsurface.mode = RSURFMODE_GLSL;
5538 R_Mesh_ResetTextureState();
5539 GL_Color(1, 1, 1, 1);
5542 R_Mesh_TexMatrix(0, &rsurface.texture->currenttexmatrix);
5543 R_Mesh_TexBind(0, R_GetTexture(rsurface.texture->currentskinframe->nmap));
5544 R_Mesh_TexBind(1, R_GetTexture(rsurface.texture->basetexture));
5545 R_Mesh_TexBind(2, R_GetTexture(rsurface.texture->glosstexture));
5546 R_Mesh_TexBind(4, R_GetTexture(r_texture_fogattenuation));
5547 R_Mesh_TexBind(5, R_GetTexture(rsurface.texture->currentskinframe->pants));
5548 R_Mesh_TexBind(6, R_GetTexture(rsurface.texture->currentskinframe->shirt));
5549 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
5551 R_Mesh_TexBind(7, R_GetTexture(r_texture_grey128));
5552 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
5553 R_Mesh_ColorPointer(NULL, 0, 0);
5555 else if (rsurface.uselightmaptexture)
5557 R_Mesh_TexBind(7, R_GetTexture(texturesurfacelist[0]->lightmaptexture));
5558 R_Mesh_TexBind(8, R_GetTexture(texturesurfacelist[0]->deluxemaptexture));
5559 R_Mesh_ColorPointer(NULL, 0, 0);
5563 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
5564 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
5565 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
5567 R_Mesh_TexBind(9, R_GetTexture(rsurface.texture->currentskinframe->glow));
5568 R_Mesh_TexBind(11, R_GetTexture(r_texture_white)); // changed per surface
5569 R_Mesh_TexBind(12, R_GetTexture(r_texture_white)); // changed per surface
5571 if (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5573 // render background
5574 GL_BlendFunc(GL_ONE, GL_ZERO);
5576 GL_AlphaTest(false);
5578 GL_Color(1, 1, 1, 1);
5579 R_Mesh_ColorPointer(NULL, 0, 0);
5581 R_SetupSurfaceShader(vec3_origin, rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
5582 if (r_glsl_permutation)
5584 RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
5585 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
5586 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
5587 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
5588 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
5589 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
5590 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist, -1, -1, r_glsl_permutation->loc_Texture_Refraction ? 11 : -1, r_glsl_permutation->loc_Texture_Reflection ? 12 : -1);
5593 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5594 GL_DepthMask(false);
5595 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5596 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
5598 R_Mesh_TexBind(7, R_GetTexture(r_texture_grey128));
5599 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
5600 R_Mesh_ColorPointer(NULL, 0, 0);
5602 else if (rsurface.uselightmaptexture)
5604 R_Mesh_TexBind(7, R_GetTexture(texturesurfacelist[0]->lightmaptexture));
5605 R_Mesh_TexBind(8, R_GetTexture(texturesurfacelist[0]->deluxemaptexture));
5606 R_Mesh_ColorPointer(NULL, 0, 0);
5610 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
5611 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
5612 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
5614 R_Mesh_TexBind(11, R_GetTexture(r_texture_white)); // changed per surface
5615 R_Mesh_TexBind(12, R_GetTexture(r_texture_white)); // changed per surface
5618 R_SetupSurfaceShader(vec3_origin, rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE);
5619 if (!r_glsl_permutation)
5622 RSurf_PrepareVerticesForBatch(r_glsl_permutation->loc_Texture_Normal >= 0 || r_glsl_permutation->loc_LightDir >= 0, r_glsl_permutation->loc_Texture_Normal >= 0, texturenumsurfaces, texturesurfacelist);
5623 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
5624 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
5625 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
5626 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
5627 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
5629 if (r_glsl_permutation->loc_Texture_Refraction >= 0)
5631 GL_BlendFunc(GL_ONE, GL_ZERO);
5633 GL_AlphaTest(false);
5636 if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
5638 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
5639 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);
5641 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 7, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? 8 : -1);
5645 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
5646 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);
5648 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5650 if (rsurface.texture->backgroundnumskinframes && !(rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED))
5655 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, msurface_t **texturesurfacelist)
5657 // OpenGL 1.3 path - anything not completely ancient
5658 int texturesurfaceindex;
5659 qboolean applycolor;
5663 const texturelayer_t *layer;
5664 if (rsurface.mode != RSURFMODE_MULTIPASS)
5665 rsurface.mode = RSURFMODE_MULTIPASS;
5666 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
5668 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
5671 int layertexrgbscale;
5672 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5674 if (layerindex == 0)
5678 GL_AlphaTest(false);
5679 qglDepthFunc(GL_EQUAL);CHECKGLERROR
5682 GL_DepthMask(layer->depthmask);
5683 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
5684 if ((layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2) && (gl_combine.integer || layer->depthmask))
5686 layertexrgbscale = 4;
5687 VectorScale(layer->color, 0.25f, layercolor);
5689 else if ((layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1) && (gl_combine.integer || layer->depthmask))
5691 layertexrgbscale = 2;
5692 VectorScale(layer->color, 0.5f, layercolor);
5696 layertexrgbscale = 1;
5697 VectorScale(layer->color, 1.0f, layercolor);
5699 layercolor[3] = layer->color[3];
5700 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
5701 R_Mesh_ColorPointer(NULL, 0, 0);
5702 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
5703 switch (layer->type)
5705 case TEXTURELAYERTYPE_LITTEXTURE:
5706 memset(&m, 0, sizeof(m));
5707 m.tex[0] = R_GetTexture(r_texture_white);
5708 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
5709 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
5710 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
5711 m.tex[1] = R_GetTexture(layer->texture);
5712 m.texmatrix[1] = layer->texmatrix;
5713 m.texrgbscale[1] = layertexrgbscale;
5714 m.pointer_texcoord[1] = rsurface.texcoordtexture2f;
5715 m.pointer_texcoord_bufferobject[1] = rsurface.texcoordtexture2f_bufferobject;
5716 m.pointer_texcoord_bufferoffset[1] = rsurface.texcoordtexture2f_bufferoffset;
5717 R_Mesh_TextureState(&m);
5718 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
5719 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
5720 else if (rsurface.uselightmaptexture)
5721 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
5723 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
5725 case TEXTURELAYERTYPE_TEXTURE:
5726 memset(&m, 0, sizeof(m));
5727 m.tex[0] = R_GetTexture(layer->texture);
5728 m.texmatrix[0] = layer->texmatrix;
5729 m.texrgbscale[0] = layertexrgbscale;
5730 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5731 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5732 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5733 R_Mesh_TextureState(&m);
5734 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
5736 case TEXTURELAYERTYPE_FOG:
5737 memset(&m, 0, sizeof(m));
5738 m.texrgbscale[0] = layertexrgbscale;
5741 m.tex[0] = R_GetTexture(layer->texture);
5742 m.texmatrix[0] = layer->texmatrix;
5743 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5744 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5745 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5747 R_Mesh_TextureState(&m);
5748 // generate a color array for the fog pass
5749 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
5750 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5754 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5755 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)
5757 f = 1 - FogPoint_Model(v);
5758 c[0] = layercolor[0];
5759 c[1] = layercolor[1];
5760 c[2] = layercolor[2];
5761 c[3] = f * layercolor[3];
5764 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5767 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
5769 GL_LockArrays(0, 0);
5772 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5774 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
5775 GL_AlphaTest(false);
5779 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, msurface_t **texturesurfacelist)
5781 // OpenGL 1.1 - crusty old voodoo path
5782 int texturesurfaceindex;
5786 const texturelayer_t *layer;
5787 if (rsurface.mode != RSURFMODE_MULTIPASS)
5788 rsurface.mode = RSURFMODE_MULTIPASS;
5789 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
5791 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
5793 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5795 if (layerindex == 0)
5799 GL_AlphaTest(false);
5800 qglDepthFunc(GL_EQUAL);CHECKGLERROR
5803 GL_DepthMask(layer->depthmask);
5804 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
5805 R_Mesh_ColorPointer(NULL, 0, 0);
5806 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
5807 switch (layer->type)
5809 case TEXTURELAYERTYPE_LITTEXTURE:
5810 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
5812 // two-pass lit texture with 2x rgbscale
5813 // first the lightmap pass
5814 memset(&m, 0, sizeof(m));
5815 m.tex[0] = R_GetTexture(r_texture_white);
5816 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
5817 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
5818 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
5819 R_Mesh_TextureState(&m);
5820 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
5821 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5822 else if (rsurface.uselightmaptexture)
5823 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5825 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5826 GL_LockArrays(0, 0);
5827 // then apply the texture to it
5828 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
5829 memset(&m, 0, sizeof(m));
5830 m.tex[0] = R_GetTexture(layer->texture);
5831 m.texmatrix[0] = layer->texmatrix;
5832 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5833 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5834 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5835 R_Mesh_TextureState(&m);
5836 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);
5840 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
5841 memset(&m, 0, sizeof(m));
5842 m.tex[0] = R_GetTexture(layer->texture);
5843 m.texmatrix[0] = layer->texmatrix;
5844 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5845 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5846 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5847 R_Mesh_TextureState(&m);
5848 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
5849 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);
5851 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);
5854 case TEXTURELAYERTYPE_TEXTURE:
5855 // singletexture unlit texture with transparency support
5856 memset(&m, 0, sizeof(m));
5857 m.tex[0] = R_GetTexture(layer->texture);
5858 m.texmatrix[0] = layer->texmatrix;
5859 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5860 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5861 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5862 R_Mesh_TextureState(&m);
5863 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);
5865 case TEXTURELAYERTYPE_FOG:
5866 // singletexture fogging
5867 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
5870 memset(&m, 0, sizeof(m));
5871 m.tex[0] = R_GetTexture(layer->texture);
5872 m.texmatrix[0] = layer->texmatrix;
5873 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5874 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5875 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5876 R_Mesh_TextureState(&m);
5879 R_Mesh_ResetTextureState();
5880 // generate a color array for the fog pass
5881 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5885 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5886 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)
5888 f = 1 - FogPoint_Model(v);
5889 c[0] = layer->color[0];
5890 c[1] = layer->color[1];
5891 c[2] = layer->color[2];
5892 c[3] = f * layer->color[3];
5895 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5898 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
5900 GL_LockArrays(0, 0);
5903 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5905 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
5906 GL_AlphaTest(false);
5910 static void R_DrawTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly)
5912 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW)
5914 rsurface.rtlight = NULL;
5918 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
5920 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
5922 if (rsurface.mode != RSURFMODE_MULTIPASS)
5923 rsurface.mode = RSURFMODE_MULTIPASS;
5924 if (r_depthfirst.integer == 3)
5926 int i = (int)(texturesurfacelist[0] - rsurface.modelsurfaces);
5927 if (!r_view.showdebug)
5928 GL_Color(0, 0, 0, 1);
5930 GL_Color(((i >> 6) & 7) / 7.0f, ((i >> 3) & 7) / 7.0f, (i & 7) / 7.0f,1);
5934 GL_ColorMask(0,0,0,0);
5937 RSurf_SetupDepthAndCulling();
5939 GL_BlendFunc(GL_ONE, GL_ZERO);
5941 GL_AlphaTest(false);
5942 R_Mesh_ColorPointer(NULL, 0, 0);
5943 R_Mesh_ResetTextureState();
5944 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
5945 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5946 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
5948 else if (r_depthfirst.integer == 3)
5950 else if (!r_view.showdebug && (r_showsurfaces.integer || gl_lightmaps.integer))
5952 GL_Color(0, 0, 0, 1);
5953 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5955 else if (r_showsurfaces.integer)
5957 if (rsurface.mode != RSURFMODE_MULTIPASS)
5958 rsurface.mode = RSURFMODE_MULTIPASS;
5959 RSurf_SetupDepthAndCulling();
5961 GL_BlendFunc(GL_ONE, GL_ZERO);
5962 GL_DepthMask(writedepth);
5964 GL_AlphaTest(false);
5965 R_Mesh_ColorPointer(NULL, 0, 0);
5966 R_Mesh_ResetTextureState();
5967 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
5968 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
5970 else if (gl_lightmaps.integer)
5973 if (rsurface.mode != RSURFMODE_MULTIPASS)
5974 rsurface.mode = RSURFMODE_MULTIPASS;
5975 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5977 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_view.cullface_back);
5978 GL_BlendFunc(GL_ONE, GL_ZERO);
5979 GL_DepthMask(writedepth);
5981 GL_AlphaTest(false);
5982 R_Mesh_ColorPointer(NULL, 0, 0);
5983 memset(&m, 0, sizeof(m));
5984 m.tex[0] = R_GetTexture(r_texture_white);
5985 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
5986 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
5987 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
5988 R_Mesh_TextureState(&m);
5989 RSurf_PrepareVerticesForBatch(rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT, false, texturenumsurfaces, texturesurfacelist);
5990 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
5991 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5992 else if (rsurface.uselightmaptexture)
5993 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5995 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5997 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
5998 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
5999 else if (rsurface.texture->currentnumlayers)
6001 // write depth for anything we skipped on the depth-only pass earlier
6002 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
6004 RSurf_SetupDepthAndCulling();
6005 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
6006 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
6007 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
6008 if (r_glsl.integer && gl_support_fragment_shader)
6009 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist);
6010 else if (gl_combine.integer && r_textureunits.integer >= 2)
6011 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist);
6013 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist);
6016 GL_LockArrays(0, 0);
6019 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6022 int texturenumsurfaces, endsurface;
6024 msurface_t *surface;
6025 msurface_t *texturesurfacelist[1024];
6027 // if the model is static it doesn't matter what value we give for
6028 // wantnormals and wanttangents, so this logic uses only rules applicable
6029 // to a model, knowing that they are meaningless otherwise
6030 if (ent == r_refdef.worldentity)
6031 RSurf_ActiveWorldEntity();
6032 else if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
6033 RSurf_ActiveModelEntity(ent, false, false);
6035 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
6037 for (i = 0;i < numsurfaces;i = j)
6040 surface = rsurface.modelsurfaces + surfacelist[i];
6041 texture = surface->texture;
6042 R_UpdateTextureInfo(ent, texture);
6043 rsurface.texture = texture->currentframe;
6044 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
6045 // scan ahead until we find a different texture
6046 endsurface = min(i + 1024, numsurfaces);
6047 texturenumsurfaces = 0;
6048 texturesurfacelist[texturenumsurfaces++] = surface;
6049 for (;j < endsurface;j++)
6051 surface = rsurface.modelsurfaces + surfacelist[j];
6052 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
6054 texturesurfacelist[texturenumsurfaces++] = surface;
6056 // render the range of surfaces
6057 R_DrawTextureSurfaceList(texturenumsurfaces, texturesurfacelist, true, false);
6063 void R_QueueSurfaceList(entity_render_t *ent, int numsurfaces, msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes)
6066 vec3_t tempcenter, center;
6068 // if we're rendering water textures (extra scene renders), use a separate loop to avoid burdening the main one
6071 for (i = 0;i < numsurfaces;i++)
6072 if (surfacelist[i]->texture->currentframe->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION))
6073 R_Water_AddWaterPlane(surfacelist[i]);
6076 // break the surface list down into batches by texture and use of lightmapping
6077 for (i = 0;i < numsurfaces;i = j)
6080 // texture is the base texture pointer, rsurface.texture is the
6081 // current frame/skin the texture is directing us to use (for example
6082 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
6083 // use skin 1 instead)
6084 texture = surfacelist[i]->texture;
6085 rsurface.texture = texture->currentframe;
6086 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
6087 if (!(rsurface.texture->currentmaterialflags & flagsmask))
6089 // if this texture is not the kind we want, skip ahead to the next one
6090 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
6094 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
6096 // transparent surfaces get pushed off into the transparent queue
6097 const msurface_t *surface = surfacelist[i];
6100 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
6101 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
6102 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
6103 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
6104 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_view.origin : center, R_DrawSurface_TransparentCallback, ent, surface - rsurface.modelsurfaces, rsurface.rtlight);
6108 // simply scan ahead until we find a different texture or lightmap state
6109 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
6111 // render the range of surfaces
6112 R_DrawTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly);
6117 float locboxvertex3f[6*4*3] =
6119 1,0,1, 1,0,0, 1,1,0, 1,1,1,
6120 0,1,1, 0,1,0, 0,0,0, 0,0,1,
6121 1,1,1, 1,1,0, 0,1,0, 0,1,1,
6122 0,0,1, 0,0,0, 1,0,0, 1,0,1,
6123 0,0,1, 1,0,1, 1,1,1, 0,1,1,
6124 1,0,0, 0,0,0, 0,1,0, 1,1,0
6127 int locboxelement3i[6*2*3] =
6137 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6140 cl_locnode_t *loc = (cl_locnode_t *)ent;
6142 float vertex3f[6*4*3];
6144 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6145 GL_DepthMask(false);
6146 GL_DepthRange(0, 1);
6147 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6149 GL_CullFace(GL_NONE);
6150 R_Mesh_Matrix(&identitymatrix);
6152 R_Mesh_VertexPointer(vertex3f, 0, 0);
6153 R_Mesh_ColorPointer(NULL, 0, 0);
6154 R_Mesh_ResetTextureState();
6157 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_view.colorscale,
6158 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_view.colorscale,
6159 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_view.colorscale,
6160 surfacelist[0] < 0 ? 0.5f : 0.125f);
6162 if (VectorCompare(loc->mins, loc->maxs))
6164 VectorSet(size, 2, 2, 2);
6165 VectorMA(loc->mins, -0.5f, size, mins);
6169 VectorCopy(loc->mins, mins);
6170 VectorSubtract(loc->maxs, loc->mins, size);
6173 for (i = 0;i < 6*4*3;)
6174 for (j = 0;j < 3;j++, i++)
6175 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
6177 R_Mesh_Draw(0, 6*4, 6*2, locboxelement3i, 0, 0);
6180 void R_DrawLocs(void)
6183 cl_locnode_t *loc, *nearestloc;
6185 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
6186 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
6188 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
6189 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
6193 void R_DrawDebugModel(entity_render_t *ent)
6195 int i, j, k, l, flagsmask;
6196 const int *elements;
6198 msurface_t *surface;
6199 model_t *model = ent->model;
6202 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WATER | MATERIALFLAG_WALL;
6204 R_Mesh_ColorPointer(NULL, 0, 0);
6205 R_Mesh_ResetTextureState();
6206 GL_DepthRange(0, 1);
6207 GL_DepthTest(!r_showdisabledepthtest.integer);
6208 GL_DepthMask(false);
6209 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6211 if (r_showcollisionbrushes.value > 0 && model->brush.num_brushes)
6213 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
6214 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
6216 if (brush->colbrushf && brush->colbrushf->numtriangles)
6218 R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
6219 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);
6220 R_Mesh_Draw(0, brush->colbrushf->numpoints, brush->colbrushf->numtriangles, brush->colbrushf->elements, 0, 0);
6223 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
6225 if (surface->num_collisiontriangles)
6227 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
6228 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);
6229 R_Mesh_Draw(0, surface->num_collisionvertices, surface->num_collisiontriangles, surface->data_collisionelement3i, 0, 0);
6234 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6236 if (r_showtris.integer || r_shownormals.integer)
6238 if (r_showdisabledepthtest.integer)
6240 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6241 GL_DepthMask(false);
6245 GL_BlendFunc(GL_ONE, GL_ZERO);
6248 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
6250 if (ent == r_refdef.worldentity && !r_viewcache.world_surfacevisible[j])
6252 rsurface.texture = surface->texture->currentframe;
6253 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
6255 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
6256 if (r_showtris.value > 0)
6258 if (!rsurface.texture->currentlayers->depthmask)
6259 GL_Color(r_view.colorscale, 0, 0, r_showtris.value);
6260 else if (ent == r_refdef.worldentity)
6261 GL_Color(r_view.colorscale, r_view.colorscale, r_view.colorscale, r_showtris.value);
6263 GL_Color(0, r_view.colorscale, 0, r_showtris.value);
6264 elements = (ent->model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
6267 for (k = 0;k < surface->num_triangles;k++, elements += 3)
6269 #define GLVERTEXELEMENT(n) qglVertex3f(rsurface.vertex3f[elements[n]*3+0], rsurface.vertex3f[elements[n]*3+1], rsurface.vertex3f[elements[n]*3+2])
6270 GLVERTEXELEMENT(0);GLVERTEXELEMENT(1);
6271 GLVERTEXELEMENT(1);GLVERTEXELEMENT(2);
6272 GLVERTEXELEMENT(2);GLVERTEXELEMENT(0);
6277 if (r_shownormals.value > 0)
6280 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
6282 VectorCopy(rsurface.vertex3f + l * 3, v);
6283 GL_Color(r_view.colorscale, 0, 0, 1);
6284 qglVertex3f(v[0], v[1], v[2]);
6285 VectorMA(v, r_shownormals.value, rsurface.svector3f + l * 3, v);
6286 GL_Color(r_view.colorscale, 1, 1, 1);
6287 qglVertex3f(v[0], v[1], v[2]);
6292 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
6294 VectorCopy(rsurface.vertex3f + l * 3, v);
6295 GL_Color(0, r_view.colorscale, 0, 1);
6296 qglVertex3f(v[0], v[1], v[2]);
6297 VectorMA(v, r_shownormals.value, rsurface.tvector3f + l * 3, v);
6298 GL_Color(r_view.colorscale, 1, 1, 1);
6299 qglVertex3f(v[0], v[1], v[2]);
6304 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
6306 VectorCopy(rsurface.vertex3f + l * 3, v);
6307 GL_Color(0, 0, r_view.colorscale, 1);
6308 qglVertex3f(v[0], v[1], v[2]);
6309 VectorMA(v, r_shownormals.value, rsurface.normal3f + l * 3, v);
6310 GL_Color(r_view.colorscale, 1, 1, 1);
6311 qglVertex3f(v[0], v[1], v[2]);
6318 rsurface.texture = NULL;
6322 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
6323 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes, qboolean debug)
6325 int i, j, endj, f, flagsmask;
6326 msurface_t *surface;
6328 model_t *model = r_refdef.worldmodel;
6329 const int maxsurfacelist = 1024;
6330 int numsurfacelist = 0;
6331 msurface_t *surfacelist[1024];
6335 RSurf_ActiveWorldEntity();
6337 // update light styles on this submodel
6338 if (!skysurfaces && !depthonly && !addwaterplanes && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
6340 model_brush_lightstyleinfo_t *style;
6341 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
6343 if (style->value != r_refdef.lightstylevalue[style->style])
6345 msurface_t *surfaces = model->data_surfaces;
6346 int *list = style->surfacelist;
6347 style->value = r_refdef.lightstylevalue[style->style];
6348 for (j = 0;j < style->numsurfaces;j++)
6349 surfaces[list[j]].cached_dlight = true;
6354 R_UpdateAllTextureInfo(r_refdef.worldentity);
6355 flagsmask = addwaterplanes ? (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) : (skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL));
6359 R_DrawDebugModel(r_refdef.worldentity);
6365 rsurface.uselightmaptexture = false;
6366 rsurface.texture = NULL;
6368 j = model->firstmodelsurface;
6369 endj = j + model->nummodelsurfaces;
6372 // quickly skip over non-visible surfaces
6373 for (;j < endj && !r_viewcache.world_surfacevisible[j];j++)
6375 // quickly iterate over visible surfaces
6376 for (;j < endj && r_viewcache.world_surfacevisible[j];j++)
6378 // process this surface
6379 surface = model->data_surfaces + j;
6380 // if this surface fits the criteria, add it to the list
6381 if (surface->num_triangles)
6383 // if lightmap parameters changed, rebuild lightmap texture
6384 if (surface->cached_dlight)
6385 R_BuildLightMap(r_refdef.worldentity, surface);
6386 // add face to draw list
6387 surfacelist[numsurfacelist++] = surface;
6388 r_refdef.stats.world_triangles += surface->num_triangles;
6389 if (numsurfacelist >= maxsurfacelist)
6391 r_refdef.stats.world_surfaces += numsurfacelist;
6392 R_QueueSurfaceList(r_refdef.worldentity, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
6398 r_refdef.stats.world_surfaces += numsurfacelist;
6400 R_QueueSurfaceList(r_refdef.worldentity, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
6404 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes, qboolean debug)
6406 int i, j, f, flagsmask;
6407 msurface_t *surface, *endsurface;
6409 model_t *model = ent->model;
6410 const int maxsurfacelist = 1024;
6411 int numsurfacelist = 0;
6412 msurface_t *surfacelist[1024];
6416 // if the model is static it doesn't matter what value we give for
6417 // wantnormals and wanttangents, so this logic uses only rules applicable
6418 // to a model, knowing that they are meaningless otherwise
6419 if (ent == r_refdef.worldentity)
6420 RSurf_ActiveWorldEntity();
6421 else if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
6422 RSurf_ActiveModelEntity(ent, false, false);
6424 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader && !depthonly);
6426 // update light styles
6427 if (!skysurfaces && !depthonly && !addwaterplanes && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
6429 model_brush_lightstyleinfo_t *style;
6430 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
6432 if (style->value != r_refdef.lightstylevalue[style->style])
6434 msurface_t *surfaces = model->data_surfaces;
6435 int *list = style->surfacelist;
6436 style->value = r_refdef.lightstylevalue[style->style];
6437 for (j = 0;j < style->numsurfaces;j++)
6438 surfaces[list[j]].cached_dlight = true;
6443 R_UpdateAllTextureInfo(ent);
6444 flagsmask = addwaterplanes ? (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) : (skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL));
6448 R_DrawDebugModel(ent);
6454 rsurface.uselightmaptexture = false;
6455 rsurface.texture = NULL;
6457 surface = model->data_surfaces + model->firstmodelsurface;
6458 endsurface = surface + model->nummodelsurfaces;
6459 for (;surface < endsurface;surface++)
6461 // if this surface fits the criteria, add it to the list
6462 if (surface->num_triangles)
6464 // if lightmap parameters changed, rebuild lightmap texture
6465 if (surface->cached_dlight)
6466 R_BuildLightMap(ent, surface);
6467 // add face to draw list
6468 surfacelist[numsurfacelist++] = surface;
6469 r_refdef.stats.entities_triangles += surface->num_triangles;
6470 if (numsurfacelist >= maxsurfacelist)
6472 r_refdef.stats.entities_surfaces += numsurfacelist;
6473 R_QueueSurfaceList(ent, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
6478 r_refdef.stats.entities_surfaces += numsurfacelist;
6480 R_QueueSurfaceList(ent, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);