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 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"};
37 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
38 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%, 10 = 100%)"};
39 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)"};
40 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
41 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
42 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"};
43 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"};
44 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
45 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"};
46 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"};
47 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"};
48 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
49 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
50 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
51 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
52 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling"};
53 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
54 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
55 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
56 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
57 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
58 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
59 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
60 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this)"};
61 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
62 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
63 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"};
64 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"};
65 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
67 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
68 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
69 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
70 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
71 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
72 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
73 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
74 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
76 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)"};
78 cvar_t r_glsl = {CVAR_SAVE, "r_glsl", "1", "enables use of OpenGL 2.0 pixel shaders for lighting"};
79 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)"};
80 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)"};
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_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
85 cvar_t r_glsl_postprocess_contrastboost = {CVAR_SAVE, "r_glsl_postprocess_contrastboost", "1", "brightening effect (1 is no change, higher values brighten the view)"};
86 cvar_t r_glsl_postprocess_gamma = {CVAR_SAVE, "r_glsl_postprocess_gamma", "1", "inverse gamma correction value, a brightness effect that does not affect white or black, and tends to make the image grey and dull"};
87 cvar_t r_glsl_postprocess_uservec1 = {CVAR_SAVE, "r_glsl_postprocess_uservec1", "0 0 0 0", "a 4-component vector to pass as uservec1 to the postprocessing shader (only useful if default.glsl has been customized)"};
88 cvar_t r_glsl_postprocess_uservec2 = {CVAR_SAVE, "r_glsl_postprocess_uservec2", "0 0 0 0", "a 4-component vector to pass as uservec2 to the postprocessing shader (only useful if default.glsl has been customized)"};
89 cvar_t r_glsl_postprocess_uservec3 = {CVAR_SAVE, "r_glsl_postprocess_uservec3", "0 0 0 0", "a 4-component vector to pass as uservec3 to the postprocessing shader (only useful if default.glsl has been customized)"};
90 cvar_t r_glsl_postprocess_uservec4 = {CVAR_SAVE, "r_glsl_postprocess_uservec4", "0 0 0 0", "a 4-component vector to pass as uservec4 to the postprocessing shader (only useful if default.glsl has been customized)"};
91 cvar_t r_glsl_usegeneric = {CVAR_SAVE, "r_glsl_usegeneric", "1", "use shaders for rendering simple geometry (rather than conventional fixed-function rendering for this purpose)"};
93 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)"};
94 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
95 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"};
96 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
97 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
99 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1", "enables animation smoothing on sprites (requires r_lerpmodels 1)"};
100 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
101 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
102 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
104 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
105 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
106 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
107 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
108 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
109 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
110 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
112 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
113 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
114 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
115 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)"};
117 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"};
119 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"};
121 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
123 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
124 cvar_t r_batchmode = {0, "r_batchmode", "1", "selects method of rendering multiple surfaces with one driver call (values are 0, 1, 2, etc...)"};
125 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"};
126 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accodringly, 2: Make it a continuous rotation"};
127 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
128 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
130 extern qboolean v_flipped_state;
132 static struct r_bloomstate_s
137 int bloomwidth, bloomheight;
139 int screentexturewidth, screentextureheight;
140 rtexture_t *texture_screen;
142 int bloomtexturewidth, bloomtextureheight;
143 rtexture_t *texture_bloom;
145 // arrays for rendering the screen passes
146 float screentexcoord2f[8];
147 float bloomtexcoord2f[8];
148 float offsettexcoord2f[8];
152 typedef struct r_waterstate_waterplane_s
154 rtexture_t *texture_refraction;
155 rtexture_t *texture_reflection;
157 int materialflags; // combined flags of all water surfaces on this plane
158 unsigned char pvsbits[(32768+7)>>3]; // FIXME: buffer overflow on huge maps
161 r_waterstate_waterplane_t;
163 #define MAX_WATERPLANES 16
165 static struct r_waterstate_s
169 qboolean renderingscene; // true while rendering a refraction or reflection texture, disables water surfaces
171 int waterwidth, waterheight;
172 int texturewidth, textureheight;
174 int maxwaterplanes; // same as MAX_WATERPLANES
176 r_waterstate_waterplane_t waterplanes[MAX_WATERPLANES];
178 float screenscale[2];
179 float screencenter[2];
183 // shadow volume bsp struct with automatically growing nodes buffer
186 rtexture_t *r_texture_blanknormalmap;
187 rtexture_t *r_texture_white;
188 rtexture_t *r_texture_grey128;
189 rtexture_t *r_texture_black;
190 rtexture_t *r_texture_notexture;
191 rtexture_t *r_texture_whitecube;
192 rtexture_t *r_texture_normalizationcube;
193 rtexture_t *r_texture_fogattenuation;
194 //rtexture_t *r_texture_fogintensity;
196 char r_qwskincache[MAX_SCOREBOARD][MAX_QPATH];
197 skinframe_t *r_qwskincache_skinframe[MAX_SCOREBOARD];
199 // vertex coordinates for a quad that covers the screen exactly
200 const static float r_screenvertex3f[12] =
208 extern void R_DrawModelShadows(void);
210 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
213 for (i = 0;i < verts;i++)
224 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
227 for (i = 0;i < verts;i++)
237 // FIXME: move this to client?
240 if (gamemode == GAME_NEHAHRA)
242 Cvar_Set("gl_fogenable", "0");
243 Cvar_Set("gl_fogdensity", "0.2");
244 Cvar_Set("gl_fogred", "0.3");
245 Cvar_Set("gl_foggreen", "0.3");
246 Cvar_Set("gl_fogblue", "0.3");
248 r_refdef.fog_density = 0;
249 r_refdef.fog_red = 0;
250 r_refdef.fog_green = 0;
251 r_refdef.fog_blue = 0;
252 r_refdef.fog_alpha = 1;
253 r_refdef.fog_start = 0;
254 r_refdef.fog_end = 0;
257 float FogForDistance(vec_t dist)
259 unsigned int fogmasktableindex = (unsigned int)(dist * r_refdef.fogmasktabledistmultiplier);
260 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
263 float FogPoint_World(const vec3_t p)
265 return FogForDistance(VectorDistance((p), r_refdef.view.origin));
268 float FogPoint_Model(const vec3_t p)
270 return FogForDistance(VectorDistance((p), rsurface.modelorg));
273 static void R_BuildBlankTextures(void)
275 unsigned char data[4];
276 data[2] = 128; // normal X
277 data[1] = 128; // normal Y
278 data[0] = 255; // normal Z
279 data[3] = 128; // height
280 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
285 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
290 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
295 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
298 static void R_BuildNoTexture(void)
301 unsigned char pix[16][16][4];
302 // this makes a light grey/dark grey checkerboard texture
303 for (y = 0;y < 16;y++)
305 for (x = 0;x < 16;x++)
307 if ((y < 8) ^ (x < 8))
323 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, NULL);
326 static void R_BuildWhiteCube(void)
328 unsigned char data[6*1*1*4];
329 memset(data, 255, sizeof(data));
330 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_CLAMP | TEXF_PERSISTENT, NULL);
333 static void R_BuildNormalizationCube(void)
337 vec_t s, t, intensity;
339 unsigned char data[6][NORMSIZE][NORMSIZE][4];
340 for (side = 0;side < 6;side++)
342 for (y = 0;y < NORMSIZE;y++)
344 for (x = 0;x < NORMSIZE;x++)
346 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
347 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
382 intensity = 127.0f / sqrt(DotProduct(v, v));
383 data[side][y][x][2] = (unsigned char)(128.0f + intensity * v[0]);
384 data[side][y][x][1] = (unsigned char)(128.0f + intensity * v[1]);
385 data[side][y][x][0] = (unsigned char)(128.0f + intensity * v[2]);
386 data[side][y][x][3] = 255;
390 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, &data[0][0][0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_CLAMP | TEXF_PERSISTENT, NULL);
393 static void R_BuildFogTexture(void)
397 unsigned char data1[FOGWIDTH][4];
398 //unsigned char data2[FOGWIDTH][4];
401 r_refdef.fogmasktable_start = r_refdef.fog_start;
402 r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
403 r_refdef.fogmasktable_range = r_refdef.fogrange;
404 r_refdef.fogmasktable_density = r_refdef.fog_density;
406 r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
407 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
409 d = (x * r - r_refdef.fogmasktable_start);
410 if(developer.integer >= 100)
411 Con_Printf("%f ", d);
413 if (r_fog_exp2.integer)
414 alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
416 alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
417 if(developer.integer >= 100)
418 Con_Printf(" : %f ", alpha);
419 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
420 if(developer.integer >= 100)
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 myhalf2 half2\n"
458 "//# define myhalf3 half3\n"
459 "//# define myhalf4 half4\n"
461 "# define myhalf float\n"
462 "# define myhalf2 vec2\n"
463 "# define myhalf3 vec3\n"
464 "# define myhalf4 vec4\n"
467 "#ifdef MODE_DEPTH_OR_SHADOW\n"
469 "# ifdef VERTEX_SHADER\n"
472 " gl_Position = ftransform();\n"
478 "#ifdef MODE_POSTPROCESS\n"
479 "# ifdef VERTEX_SHADER\n"
482 " gl_FrontColor = gl_Color;\n"
483 " gl_Position = ftransform();\n"
484 " gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;\n"
486 " gl_TexCoord[1] = gl_TextureMatrix[1] * gl_MultiTexCoord1;\n"
490 "# ifdef FRAGMENT_SHADER\n"
492 "uniform sampler2D Texture_First;\n"
494 "uniform sampler2D Texture_Second;\n"
496 "#ifdef USEVERTEXTEXTUREBLEND\n"
497 "uniform vec4 TintColor;\n"
499 "#ifdef USECOLORMOD\n"
500 "uniform vec3 Gamma;\n"
502 "#ifdef USECONTRASTBOOST\n"
503 "uniform float ContrastBoostCoeff;\n"
506 "uniform float GammaCoeff;\n"
508 "//uncomment these if you want to use them:\n"
509 "// uniform vec4 UserVec1;\n"
510 "// uniform vec4 UserVec2;\n"
511 "// uniform vec4 UserVec3;\n"
512 "// uniform vec4 UserVec4;\n"
513 "// uniform float ClientTime;\n"
516 " gl_FragColor = texture2D(Texture_First, gl_TexCoord[0].xy);\n"
518 " gl_FragColor += texture2D(Texture_Second, gl_TexCoord[1].xy);\n"
520 "#ifdef USECONTRASTBOOST\n"
521 " gl_FragColor.rgb /= (ContrastBoostCoeff * gl_FragColor.rgb + vec3(1.0, 1.0, 1.0));\n"
522 " gl_FragColor.rgb *= (ContrastBoostCoeff + 1.0);\n"
525 " gl_FragColor.rgb = pow(gl_FragColor.rgb, GammaCoeff);\n"
527 "#ifdef USEVERTEXTEXTUREBLEND\n"
528 " gl_FragColor = mix(TintColor, gl_FragColor, TintColor.a);\n"
536 "#ifdef MODE_GENERIC\n"
537 "# ifdef VERTEX_SHADER\n"
540 " gl_FrontColor = gl_Color;\n"
541 "# ifdef USEDIFFUSE\n"
542 " gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;\n"
544 "# ifdef USESPECULAR\n"
545 " gl_TexCoord[1] = gl_TextureMatrix[1] * gl_MultiTexCoord1;\n"
547 " gl_Position = ftransform();\n"
550 "# ifdef FRAGMENT_SHADER\n"
552 "# ifdef USEDIFFUSE\n"
553 "uniform sampler2D Texture_First;\n"
555 "# ifdef USESPECULAR\n"
556 "uniform sampler2D Texture_Second;\n"
561 " gl_FragColor = gl_Color;\n"
562 "# ifdef USEDIFFUSE\n"
563 " gl_FragColor *= texture2D(Texture_First, gl_TexCoord[0].xy);\n"
566 "# ifdef USESPECULAR\n"
567 " vec4 tex2 = texture2D(Texture_Second, gl_TexCoord[1].xy);\n"
569 "# ifdef USECOLORMAPPING\n"
570 " gl_FragColor *= tex2;\n"
573 " gl_FragColor += tex2;\n"
575 "# ifdef USEVERTEXTEXTUREBLEND\n"
576 " gl_FragColor = mix(tex2, gl_FragColor, tex2.a);\n"
581 "#else // !MODE_GENERIC\n"
583 "varying vec2 TexCoord;\n"
584 "varying vec2 TexCoordLightmap;\n"
586 "#ifdef MODE_LIGHTSOURCE\n"
587 "varying vec3 CubeVector;\n"
590 "#ifdef MODE_LIGHTSOURCE\n"
591 "varying vec3 LightVector;\n"
593 "#ifdef MODE_LIGHTDIRECTION\n"
594 "varying vec3 LightVector;\n"
597 "varying vec3 EyeVector;\n"
599 "varying vec3 EyeVectorModelSpace;\n"
602 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
603 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
604 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
606 "#ifdef MODE_WATER\n"
607 "varying vec4 ModelViewProjectionPosition;\n"
608 "#ifdef MODE_REFRACTION\n"
609 "varying vec4 ModelViewProjectionPosition;\n"
611 "# ifdef USEREFLECTION\n"
612 "varying vec4 ModelViewProjectionPosition;\n"
621 "// vertex shader specific:\n"
622 "#ifdef VERTEX_SHADER\n"
624 "uniform vec3 LightPosition;\n"
625 "uniform vec3 EyePosition;\n"
626 "uniform vec3 LightDir;\n"
628 "// TODO: get rid of tangentt (texcoord2) and use a crossproduct to regenerate it from tangents (texcoord1) and normal (texcoord3), this would require sending a 4 component texcoord1 with W as 1 or -1 according to which side the texcoord2 should be on\n"
632 " gl_FrontColor = gl_Color;\n"
633 " // copy the surface texcoord\n"
634 " TexCoord = vec2(gl_TextureMatrix[0] * gl_MultiTexCoord0);\n"
635 "#ifndef MODE_LIGHTSOURCE\n"
636 "# ifndef MODE_LIGHTDIRECTION\n"
637 " TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
641 "#ifdef MODE_LIGHTSOURCE\n"
642 " // transform vertex position into light attenuation/cubemap space\n"
643 " // (-1 to +1 across the light box)\n"
644 " CubeVector = vec3(gl_TextureMatrix[3] * gl_Vertex);\n"
646 " // transform unnormalized light direction into tangent space\n"
647 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
648 " // normalize it per pixel)\n"
649 " vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
650 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
651 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
652 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
655 "#ifdef MODE_LIGHTDIRECTION\n"
656 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
657 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
658 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
661 " // transform unnormalized eye direction into tangent space\n"
663 " vec3 EyeVectorModelSpace;\n"
665 " EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
666 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
667 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
668 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
670 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
671 " VectorS = gl_MultiTexCoord1.xyz;\n"
672 " VectorT = gl_MultiTexCoord2.xyz;\n"
673 " VectorR = gl_MultiTexCoord3.xyz;\n"
676 "//#if defined(MODE_WATER) || defined(MODE_REFRACTION) || defined(USEREFLECTION)\n"
677 "// ModelViewProjectionPosition = gl_Vertex * gl_ModelViewProjectionMatrix;\n"
678 "// //ModelViewProjectionPosition_svector = (gl_Vertex + vec4(gl_MultiTexCoord1.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
679 "// //ModelViewProjectionPosition_tvector = (gl_Vertex + vec4(gl_MultiTexCoord2.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
682 "// transform vertex to camera space, using ftransform to match non-VS\n"
684 " gl_Position = ftransform();\n"
686 "#ifdef MODE_WATER\n"
687 " ModelViewProjectionPosition = gl_Position;\n"
689 "#ifdef MODE_REFRACTION\n"
690 " ModelViewProjectionPosition = gl_Position;\n"
692 "#ifdef USEREFLECTION\n"
693 " ModelViewProjectionPosition = gl_Position;\n"
697 "#endif // VERTEX_SHADER\n"
702 "// fragment shader specific:\n"
703 "#ifdef FRAGMENT_SHADER\n"
705 "// 13 textures, we can only use up to 16 on DX9-class hardware\n"
706 "uniform sampler2D Texture_Normal;\n"
707 "uniform sampler2D Texture_Color;\n"
708 "uniform sampler2D Texture_Gloss;\n"
709 "uniform sampler2D Texture_Glow;\n"
710 "uniform sampler2D Texture_SecondaryNormal;\n"
711 "uniform sampler2D Texture_SecondaryColor;\n"
712 "uniform sampler2D Texture_SecondaryGloss;\n"
713 "uniform sampler2D Texture_SecondaryGlow;\n"
714 "uniform sampler2D Texture_Pants;\n"
715 "uniform sampler2D Texture_Shirt;\n"
716 "uniform sampler2D Texture_FogMask;\n"
717 "uniform sampler2D Texture_Lightmap;\n"
718 "uniform sampler2D Texture_Deluxemap;\n"
719 "uniform sampler2D Texture_Refraction;\n"
720 "uniform sampler2D Texture_Reflection;\n"
721 "uniform sampler2D Texture_Attenuation;\n"
722 "uniform samplerCube Texture_Cube;\n"
724 "uniform myhalf3 LightColor;\n"
725 "uniform myhalf3 AmbientColor;\n"
726 "uniform myhalf3 DiffuseColor;\n"
727 "uniform myhalf3 SpecularColor;\n"
728 "uniform myhalf3 Color_Pants;\n"
729 "uniform myhalf3 Color_Shirt;\n"
730 "uniform myhalf3 FogColor;\n"
732 "uniform myhalf4 TintColor;\n"
735 "//#ifdef MODE_WATER\n"
736 "uniform vec4 DistortScaleRefractReflect;\n"
737 "uniform vec4 ScreenScaleRefractReflect;\n"
738 "uniform vec4 ScreenCenterRefractReflect;\n"
739 "uniform myhalf4 RefractColor;\n"
740 "uniform myhalf4 ReflectColor;\n"
741 "uniform myhalf ReflectFactor;\n"
742 "uniform myhalf ReflectOffset;\n"
744 "//# ifdef MODE_REFRACTION\n"
745 "//uniform vec4 DistortScaleRefractReflect;\n"
746 "//uniform vec4 ScreenScaleRefractReflect;\n"
747 "//uniform vec4 ScreenCenterRefractReflect;\n"
748 "//uniform myhalf4 RefractColor;\n"
749 "//# ifdef USEREFLECTION\n"
750 "//uniform myhalf4 ReflectColor;\n"
753 "//# ifdef USEREFLECTION\n"
754 "//uniform vec4 DistortScaleRefractReflect;\n"
755 "//uniform vec4 ScreenScaleRefractReflect;\n"
756 "//uniform vec4 ScreenCenterRefractReflect;\n"
757 "//uniform myhalf4 ReflectColor;\n"
762 "uniform myhalf GlowScale;\n"
763 "uniform myhalf SceneBrightness;\n"
764 "#ifdef USECONTRASTBOOST\n"
765 "uniform myhalf ContrastBoostCoeff;\n"
768 "uniform float OffsetMapping_Scale;\n"
769 "uniform float OffsetMapping_Bias;\n"
770 "uniform float FogRangeRecip;\n"
772 "uniform myhalf AmbientScale;\n"
773 "uniform myhalf DiffuseScale;\n"
774 "uniform myhalf SpecularScale;\n"
775 "uniform myhalf SpecularPower;\n"
777 "#ifdef USEOFFSETMAPPING\n"
778 "vec2 OffsetMapping(vec2 TexCoord)\n"
780 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
781 " // 14 sample relief mapping: linear search and then binary search\n"
782 " // this basically steps forward a small amount repeatedly until it finds\n"
783 " // itself inside solid, then jitters forward and back using decreasing\n"
784 " // amounts to find the impact\n"
785 " //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
786 " //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
787 " vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
788 " vec3 RT = vec3(TexCoord, 1);\n"
789 " OffsetVector *= 0.1;\n"
790 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
791 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
792 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
793 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
794 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
795 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
796 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
797 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
798 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
799 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) - 0.5);\n"
800 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5 - 0.25);\n"
801 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25 - 0.125);\n"
802 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125 - 0.0625);\n"
803 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
806 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
807 " // this basically moves forward the full distance, and then backs up based\n"
808 " // on height of samples\n"
809 " //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
810 " //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
811 " vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
812 " TexCoord += OffsetVector;\n"
813 " OffsetVector *= 0.333;\n"
814 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
815 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
816 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
817 " return TexCoord;\n"
820 "#endif // USEOFFSETMAPPING\n"
822 "#ifdef MODE_WATER\n"
827 "#ifdef USEOFFSETMAPPING\n"
828 " // apply offsetmapping\n"
829 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
830 "#define TexCoord TexCoordOffset\n"
833 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
834 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
835 " vec4 ScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect + vec2(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xyxy * DistortScaleRefractReflect;\n"
836 " float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
837 " gl_FragColor = mix(texture2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, texture2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
840 "#else // !MODE_WATER\n"
841 "#ifdef MODE_REFRACTION\n"
843 "// refraction pass\n"
846 "#ifdef USEOFFSETMAPPING\n"
847 " // apply offsetmapping\n"
848 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
849 "#define TexCoord TexCoordOffset\n"
852 " vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
853 " //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
854 " vec2 ScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy + vec2(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
855 " gl_FragColor = texture2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
858 "#else // !MODE_REFRACTION\n"
861 "#ifdef USEOFFSETMAPPING\n"
862 " // apply offsetmapping\n"
863 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
864 "#define TexCoord TexCoordOffset\n"
867 " // combine the diffuse textures (base, pants, shirt)\n"
868 " myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
869 "#ifdef USECOLORMAPPING\n"
870 " color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
872 "#ifdef USEVERTEXTEXTUREBLEND\n"
873 " myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
874 " //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
875 " //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
876 " color = mix(myhalf4(texture2D(Texture_SecondaryColor, TexCoord)), color, terrainblend);\n"
877 " //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
880 "#ifdef USEDIFFUSE\n"
881 " // get the surface normal and the gloss color\n"
882 "# ifdef USEVERTEXTEXTUREBLEND\n"
883 " myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
884 "# ifdef USESPECULAR\n"
885 " myhalf3 glosscolor = mix(myhalf3(texture2D(Texture_SecondaryGloss, TexCoord)), myhalf3(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
888 " myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5));\n"
889 "# ifdef USESPECULAR\n"
890 " myhalf3 glosscolor = myhalf3(texture2D(Texture_Gloss, TexCoord));\n"
897 "#ifdef MODE_LIGHTSOURCE\n"
900 " // calculate surface normal, light normal, and specular normal\n"
901 " // compute color intensity for the two textures (colormap and glossmap)\n"
902 " // scale by light color and attenuation as efficiently as possible\n"
903 " // (do as much scalar math as possible rather than vector math)\n"
904 "# ifdef USEDIFFUSE\n"
905 " // get the light normal\n"
906 " myhalf3 diffusenormal = myhalf3(normalize(LightVector));\n"
908 "# ifdef USESPECULAR\n"
909 " myhalf3 specularnormal = normalize(diffusenormal + myhalf3(normalize(EyeVector)));\n"
911 " // calculate directional shading\n"
912 " color.rgb = 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)) * glosscolor);\n"
914 "# ifdef USEDIFFUSE\n"
915 " // calculate directional shading\n"
916 " color.rgb = color.rgb * (myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0))) * (AmbientScale + DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0))));\n"
918 " // calculate directionless shading\n"
919 " color.rgb = color.rgb * myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
923 "# ifdef USECUBEFILTER\n"
924 " // apply light cubemap filter\n"
925 " //color.rgb *= normalize(CubeVector) * 0.5 + 0.5;//vec3(textureCube(Texture_Cube, CubeVector));\n"
926 " color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
928 "#endif // MODE_LIGHTSOURCE\n"
933 "#ifdef MODE_LIGHTDIRECTION\n"
934 " // directional model lighting\n"
935 "# ifdef USEDIFFUSE\n"
936 " // get the light normal\n"
937 " myhalf3 diffusenormal = myhalf3(LightVector);\n"
939 "# ifdef USESPECULAR\n"
940 " // calculate directional shading\n"
941 " color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
942 " myhalf3 specularnormal = normalize(diffusenormal + myhalf3(normalize(EyeVector)));\n"
943 " color.rgb += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
945 "# ifdef USEDIFFUSE\n"
947 " // calculate directional shading\n"
948 " color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
950 " color.rgb *= AmbientColor;\n"
953 "#endif // MODE_LIGHTDIRECTION\n"
958 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
959 " // deluxemap lightmapping using light vectors in modelspace (evil q3map2)\n"
961 " // get the light normal\n"
962 " myhalf3 diffusenormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - myhalf3(0.5);\n"
963 " myhalf3 diffusenormal = normalize(myhalf3(dot(diffusenormal_modelspace, myhalf3(VectorS)), dot(diffusenormal_modelspace, myhalf3(VectorT)), dot(diffusenormal_modelspace, myhalf3(VectorR))));\n"
964 " // calculate directional shading\n"
965 " myhalf3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0)));\n"
966 "# ifdef USESPECULAR\n"
967 " myhalf3 specularnormal = myhalf3(normalize(diffusenormal + myhalf3(normalize(EyeVector))));\n"
968 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
971 " // apply lightmap color\n"
972 " color.rgb = color.rgb * AmbientScale + tempcolor * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
973 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
978 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
979 " // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
981 " // get the light normal\n"
982 " myhalf3 diffusenormal = normalize(myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - myhalf3(0.5));\n"
983 " // calculate directional shading\n"
984 " myhalf3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0)));\n"
985 "# ifdef USESPECULAR\n"
986 " myhalf3 specularnormal = myhalf3(normalize(diffusenormal + myhalf3(normalize(EyeVector))));\n"
987 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
990 " // apply lightmap color\n"
991 " color.rgb = color.rgb * AmbientScale + tempcolor * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
992 "#endif // MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
997 "#ifdef MODE_LIGHTMAP\n"
998 " // apply lightmap color\n"
999 " color.rgb = color.rgb * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * DiffuseScale + color.rgb * AmbientScale;\n"
1000 "#endif // MODE_LIGHTMAP\n"
1005 "#ifdef MODE_VERTEXCOLOR\n"
1006 " // apply lightmap color\n"
1007 " color.rgb = color.rgb * myhalf3(gl_Color.rgb) * DiffuseScale + color.rgb * AmbientScale;\n"
1008 "#endif // MODE_VERTEXCOLOR\n"
1013 "#ifdef MODE_FLATCOLOR\n"
1014 "#endif // MODE_FLATCOLOR\n"
1022 " color *= TintColor;\n"
1025 " color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * GlowScale;\n"
1028 "#ifdef USECONTRASTBOOST\n"
1029 " color.rgb = color.rgb / (ContrastBoostCoeff * color.rgb + myhalf3(1, 1, 1));\n"
1032 " color.rgb *= SceneBrightness;\n"
1034 " // apply fog after Contrastboost/SceneBrightness because its color is already modified appropriately\n"
1036 " color.rgb = mix(FogColor, color.rgb, myhalf(texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*FogRangeRecip, 0.0))));\n"
1039 " // 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"
1040 "#ifdef USEREFLECTION\n"
1041 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1042 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1043 " vec4 ScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xyxy * DistortScaleRefractReflect;\n"
1044 " color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord.zw)) * ReflectColor.rgb, ReflectColor.a);\n"
1047 " gl_FragColor = vec4(color);\n"
1049 "#endif // !MODE_REFRACTION\n"
1050 "#endif // !MODE_WATER\n"
1052 "#endif // FRAGMENT_SHADER\n"
1054 "#endif // !MODE_GENERIC\n"
1055 "#endif // !MODE_POSTPROCESS\n"
1056 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1059 typedef struct shaderpermutationinfo_s
1061 const char *pretext;
1064 shaderpermutationinfo_t;
1066 typedef struct shadermodeinfo_s
1068 const char *vertexfilename;
1069 const char *geometryfilename;
1070 const char *fragmentfilename;
1071 const char *pretext;
1076 typedef enum shaderpermutation_e
1078 SHADERPERMUTATION_DIFFUSE = 1<<0, // (lightsource) whether to use directional shading
1079 SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, // indicates this is a two-layer material blend based on vertex alpha (q3bsp)
1080 SHADERPERMUTATION_COLORMAPPING = 1<<2, // indicates this is a colormapped skin
1081 SHADERPERMUTATION_CONTRASTBOOST = 1<<3, // r_glsl_contrastboost boosts the contrast at low color levels (similar to gamma)
1082 SHADERPERMUTATION_FOG = 1<<4, // tint the color by fog color or black if using additive blend mode
1083 SHADERPERMUTATION_CUBEFILTER = 1<<5, // (lightsource) use cubemap light filter
1084 SHADERPERMUTATION_GLOW = 1<<6, // (lightmap) blend in an additive glow texture
1085 SHADERPERMUTATION_SPECULAR = 1<<7, // (lightsource or deluxemapping) render specular effects
1086 SHADERPERMUTATION_REFLECTION = 1<<8, // normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
1087 SHADERPERMUTATION_OFFSETMAPPING = 1<<9, // adjust texcoords to roughly simulate a displacement mapped surface
1088 SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<10, // adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
1089 SHADERPERMUTATION_GAMMA = 1<<11, // gamma (postprocessing only)
1090 SHADERPERMUTATION_LIMIT = 1<<12, // size of permutations array
1091 SHADERPERMUTATION_COUNT = 12 // size of shaderpermutationinfo array
1093 shaderpermutation_t;
1095 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
1096 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
1098 {"#define USEDIFFUSE\n", " diffuse"},
1099 {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
1100 {"#define USECOLORMAPPING\n", " colormapping"},
1101 {"#define USECONTRASTBOOST\n", " contrastboost"},
1102 {"#define USEFOG\n", " fog"},
1103 {"#define USECUBEFILTER\n", " cubefilter"},
1104 {"#define USEGLOW\n", " glow"},
1105 {"#define USESPECULAR\n", " specular"},
1106 {"#define USEREFLECTION\n", " reflection"},
1107 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
1108 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
1109 {"#define USEGAMMA\n", " gamma"},
1112 // this enum is multiplied by SHADERPERMUTATION_MODEBASE
1113 typedef enum shadermode_e
1115 SHADERMODE_GENERIC, // (particles/HUD/etc) vertex color, optionally multiplied by one texture
1116 SHADERMODE_POSTPROCESS, // postprocessing shader (r_glsl_postprocess)
1117 SHADERMODE_DEPTH_OR_SHADOW, // (depthfirst/shadows) vertex shader only
1118 SHADERMODE_FLATCOLOR, // (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
1119 SHADERMODE_VERTEXCOLOR, // (lightmap) modulate texture by vertex colors (q3bsp)
1120 SHADERMODE_LIGHTMAP, // (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
1121 SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, // (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
1122 SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, // (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
1123 SHADERMODE_LIGHTDIRECTION, // (lightmap) use directional pixel shading from fixed light direction (q3bsp)
1124 SHADERMODE_LIGHTSOURCE, // (lightsource) use directional pixel shading from light source (rtlight)
1125 SHADERMODE_REFRACTION, // refract background (the material is rendered normally after this pass)
1126 SHADERMODE_WATER, // refract background and reflection (the material is rendered normally after this pass)
1131 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
1132 shadermodeinfo_t shadermodeinfo[SHADERMODE_COUNT] =
1134 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
1135 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
1136 {"glsl/default.glsl", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
1137 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
1138 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
1139 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
1140 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
1141 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
1142 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
1143 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
1144 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
1145 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
1148 typedef struct r_glsl_permutation_s
1150 // indicates if we have tried compiling this permutation already
1152 // 0 if compilation failed
1154 // locations of detected uniforms in program object, or -1 if not found
1155 int loc_Texture_First;
1156 int loc_Texture_Second;
1157 int loc_Texture_Normal;
1158 int loc_Texture_Color;
1159 int loc_Texture_Gloss;
1160 int loc_Texture_Glow;
1161 int loc_Texture_SecondaryNormal;
1162 int loc_Texture_SecondaryColor;
1163 int loc_Texture_SecondaryGloss;
1164 int loc_Texture_SecondaryGlow;
1165 int loc_Texture_Pants;
1166 int loc_Texture_Shirt;
1167 int loc_Texture_FogMask;
1168 int loc_Texture_Lightmap;
1169 int loc_Texture_Deluxemap;
1170 int loc_Texture_Attenuation;
1171 int loc_Texture_Cube;
1172 int loc_Texture_Refraction;
1173 int loc_Texture_Reflection;
1175 int loc_LightPosition;
1176 int loc_EyePosition;
1177 int loc_Color_Pants;
1178 int loc_Color_Shirt;
1179 int loc_FogRangeRecip;
1180 int loc_AmbientScale;
1181 int loc_DiffuseScale;
1182 int loc_SpecularScale;
1183 int loc_SpecularPower;
1185 int loc_SceneBrightness; // or: Scenebrightness * ContrastBoost
1186 int loc_OffsetMapping_Scale;
1188 int loc_AmbientColor;
1189 int loc_DiffuseColor;
1190 int loc_SpecularColor;
1192 int loc_ContrastBoostCoeff; // 1 - 1/ContrastBoost
1193 int loc_GammaCoeff; // 1 / gamma
1194 int loc_DistortScaleRefractReflect;
1195 int loc_ScreenScaleRefractReflect;
1196 int loc_ScreenCenterRefractReflect;
1197 int loc_RefractColor;
1198 int loc_ReflectColor;
1199 int loc_ReflectFactor;
1200 int loc_ReflectOffset;
1207 r_glsl_permutation_t;
1209 // information about each possible shader permutation
1210 r_glsl_permutation_t r_glsl_permutations[SHADERMODE_COUNT][SHADERPERMUTATION_LIMIT];
1211 // currently selected permutation
1212 r_glsl_permutation_t *r_glsl_permutation;
1214 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
1217 if (!filename || !filename[0])
1219 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1222 if (printfromdisknotice)
1223 Con_DPrint("from disk... ");
1224 return shaderstring;
1226 else if (!strcmp(filename, "glsl/default.glsl"))
1228 shaderstring = Mem_Alloc(r_main_mempool, strlen(builtinshaderstring) + 1);
1229 memcpy(shaderstring, builtinshaderstring, strlen(builtinshaderstring) + 1);
1231 return shaderstring;
1234 static void R_GLSL_CompilePermutation(shadermode_t mode, shaderpermutation_t permutation)
1237 shadermodeinfo_t *modeinfo = shadermodeinfo + mode;
1238 r_glsl_permutation_t *p = &r_glsl_permutations[mode][permutation];
1239 int vertstrings_count = 0;
1240 int geomstrings_count = 0;
1241 int fragstrings_count = 0;
1242 char *vertexstring, *geometrystring, *fragmentstring;
1243 const char *vertstrings_list[32+3];
1244 const char *geomstrings_list[32+3];
1245 const char *fragstrings_list[32+3];
1246 char permutationname[256];
1253 permutationname[0] = 0;
1254 vertexstring = R_GLSL_GetText(modeinfo->vertexfilename, true);
1255 geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1256 fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1258 strlcat(permutationname, shadermodeinfo[mode].vertexfilename, sizeof(permutationname));
1260 // the first pretext is which type of shader to compile as
1261 // (later these will all be bound together as a program object)
1262 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1263 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1264 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1266 // the second pretext is the mode (for example a light source)
1267 vertstrings_list[vertstrings_count++] = shadermodeinfo[mode].pretext;
1268 geomstrings_list[geomstrings_count++] = shadermodeinfo[mode].pretext;
1269 fragstrings_list[fragstrings_count++] = shadermodeinfo[mode].pretext;
1270 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1272 // now add all the permutation pretexts
1273 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1275 if (permutation & (1<<i))
1277 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1278 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1279 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1280 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1284 // keep line numbers correct
1285 vertstrings_list[vertstrings_count++] = "\n";
1286 geomstrings_list[geomstrings_count++] = "\n";
1287 fragstrings_list[fragstrings_count++] = "\n";
1291 // now append the shader text itself
1292 vertstrings_list[vertstrings_count++] = vertexstring;
1293 geomstrings_list[geomstrings_count++] = geometrystring;
1294 fragstrings_list[fragstrings_count++] = fragmentstring;
1296 // if any sources were NULL, clear the respective list
1298 vertstrings_count = 0;
1299 if (!geometrystring)
1300 geomstrings_count = 0;
1301 if (!fragmentstring)
1302 fragstrings_count = 0;
1304 // compile the shader program
1305 if (vertstrings_count + geomstrings_count + fragstrings_count)
1306 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1310 qglUseProgramObjectARB(p->program);CHECKGLERROR
1311 // look up all the uniform variable names we care about, so we don't
1312 // have to look them up every time we set them
1313 p->loc_Texture_First = qglGetUniformLocationARB(p->program, "Texture_First");
1314 p->loc_Texture_Second = qglGetUniformLocationARB(p->program, "Texture_Second");
1315 p->loc_Texture_Normal = qglGetUniformLocationARB(p->program, "Texture_Normal");
1316 p->loc_Texture_Color = qglGetUniformLocationARB(p->program, "Texture_Color");
1317 p->loc_Texture_Gloss = qglGetUniformLocationARB(p->program, "Texture_Gloss");
1318 p->loc_Texture_Glow = qglGetUniformLocationARB(p->program, "Texture_Glow");
1319 p->loc_Texture_SecondaryNormal = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
1320 p->loc_Texture_SecondaryColor = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
1321 p->loc_Texture_SecondaryGloss = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
1322 p->loc_Texture_SecondaryGlow = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
1323 p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
1324 p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
1325 p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
1326 p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
1327 p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
1328 p->loc_Texture_Refraction = qglGetUniformLocationARB(p->program, "Texture_Refraction");
1329 p->loc_Texture_Reflection = qglGetUniformLocationARB(p->program, "Texture_Reflection");
1330 p->loc_Texture_Attenuation = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
1331 p->loc_Texture_Cube = qglGetUniformLocationARB(p->program, "Texture_Cube");
1332 p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
1333 p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
1334 p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
1335 p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants");
1336 p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt");
1337 p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip");
1338 p->loc_AmbientScale = qglGetUniformLocationARB(p->program, "AmbientScale");
1339 p->loc_DiffuseScale = qglGetUniformLocationARB(p->program, "DiffuseScale");
1340 p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
1341 p->loc_SpecularScale = qglGetUniformLocationARB(p->program, "SpecularScale");
1342 p->loc_GlowScale = qglGetUniformLocationARB(p->program, "GlowScale");
1343 p->loc_SceneBrightness = qglGetUniformLocationARB(p->program, "SceneBrightness");
1344 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
1345 p->loc_TintColor = qglGetUniformLocationARB(p->program, "TintColor");
1346 p->loc_AmbientColor = qglGetUniformLocationARB(p->program, "AmbientColor");
1347 p->loc_DiffuseColor = qglGetUniformLocationARB(p->program, "DiffuseColor");
1348 p->loc_SpecularColor = qglGetUniformLocationARB(p->program, "SpecularColor");
1349 p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
1350 p->loc_ContrastBoostCoeff = qglGetUniformLocationARB(p->program, "ContrastBoostCoeff");
1351 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
1352 p->loc_ScreenScaleRefractReflect = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
1353 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
1354 p->loc_RefractColor = qglGetUniformLocationARB(p->program, "RefractColor");
1355 p->loc_ReflectColor = qglGetUniformLocationARB(p->program, "ReflectColor");
1356 p->loc_ReflectFactor = qglGetUniformLocationARB(p->program, "ReflectFactor");
1357 p->loc_ReflectOffset = qglGetUniformLocationARB(p->program, "ReflectOffset");
1358 p->loc_GammaCoeff = qglGetUniformLocationARB(p->program, "GammaCoeff");
1359 p->loc_UserVec1 = qglGetUniformLocationARB(p->program, "UserVec1");
1360 p->loc_UserVec2 = qglGetUniformLocationARB(p->program, "UserVec2");
1361 p->loc_UserVec3 = qglGetUniformLocationARB(p->program, "UserVec3");
1362 p->loc_UserVec4 = qglGetUniformLocationARB(p->program, "UserVec4");
1363 p->loc_ClientTime = qglGetUniformLocationARB(p->program, "ClientTime");
1364 // initialize the samplers to refer to the texture units we use
1365 if (p->loc_Texture_First >= 0) qglUniform1iARB(p->loc_Texture_First , GL20TU_FIRST);
1366 if (p->loc_Texture_Second >= 0) qglUniform1iARB(p->loc_Texture_Second , GL20TU_SECOND);
1367 if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal , GL20TU_NORMAL);
1368 if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color , GL20TU_COLOR);
1369 if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss , GL20TU_GLOSS);
1370 if (p->loc_Texture_Glow >= 0) qglUniform1iARB(p->loc_Texture_Glow , GL20TU_GLOW);
1371 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
1372 if (p->loc_Texture_SecondaryColor >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
1373 if (p->loc_Texture_SecondaryGloss >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
1374 if (p->loc_Texture_SecondaryGlow >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow , GL20TU_SECONDARY_GLOW);
1375 if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants , GL20TU_PANTS);
1376 if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt , GL20TU_SHIRT);
1377 if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask , GL20TU_FOGMASK);
1378 if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap , GL20TU_LIGHTMAP);
1379 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap , GL20TU_DELUXEMAP);
1380 if (p->loc_Texture_Attenuation >= 0) qglUniform1iARB(p->loc_Texture_Attenuation , GL20TU_ATTENUATION);
1381 if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube , GL20TU_CUBE);
1382 if (p->loc_Texture_Refraction >= 0) qglUniform1iARB(p->loc_Texture_Refraction , GL20TU_REFRACTION);
1383 if (p->loc_Texture_Reflection >= 0) qglUniform1iARB(p->loc_Texture_Reflection , GL20TU_REFLECTION);
1385 if (developer.integer)
1386 Con_Printf("GLSL shader %s compiled.\n", permutationname);
1389 Con_Printf("GLSL shader %s failed! some features may not work properly.\n", permutationname);
1393 Mem_Free(vertexstring);
1395 Mem_Free(geometrystring);
1397 Mem_Free(fragmentstring);
1400 void R_GLSL_Restart_f(void)
1403 shaderpermutation_t permutation;
1404 for (mode = 0;mode < SHADERMODE_COUNT;mode++)
1405 for (permutation = 0;permutation < SHADERPERMUTATION_LIMIT;permutation++)
1406 if (r_glsl_permutations[mode][permutation].program)
1407 GL_Backend_FreeProgram(r_glsl_permutations[mode][permutation].program);
1408 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
1411 void R_GLSL_DumpShader_f(void)
1415 qfile_t *file = FS_Open("glsl/default.glsl", "w", false, false);
1418 Con_Printf("failed to write to glsl/default.glsl\n");
1422 FS_Print(file, "// The engine may define the following macros:\n");
1423 FS_Print(file, "// #define VERTEX_SHADER\n// #define GEOMETRY_SHADER\n// #define FRAGMENT_SHADER\n");
1424 for (i = 0;i < SHADERMODE_COUNT;i++)
1425 FS_Printf(file, "// %s", shadermodeinfo[i].pretext);
1426 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1427 FS_Printf(file, "// %s", shaderpermutationinfo[i].pretext);
1428 FS_Print(file, "\n");
1429 FS_Print(file, builtinshaderstring);
1432 Con_Printf("glsl/default.glsl written\n");
1435 void R_SetupShader_SetPermutation(shadermode_t mode, unsigned int permutation)
1437 r_glsl_permutation_t *perm = &r_glsl_permutations[mode][permutation];
1438 if (r_glsl_permutation != perm)
1440 r_glsl_permutation = perm;
1441 if (!r_glsl_permutation->program)
1443 if (!r_glsl_permutation->compiled)
1444 R_GLSL_CompilePermutation(mode, permutation);
1445 if (!r_glsl_permutation->program)
1447 // remove features until we find a valid permutation
1449 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1451 // reduce i more quickly whenever it would not remove any bits
1452 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1453 if (!(permutation & j))
1456 r_glsl_permutation = &r_glsl_permutations[mode][permutation];
1457 if (!r_glsl_permutation->compiled)
1458 R_GLSL_CompilePermutation(mode, permutation);
1459 if (r_glsl_permutation->program)
1462 if (i >= SHADERPERMUTATION_COUNT)
1464 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");
1465 Cvar_SetValueQuick(&r_glsl, 0);
1466 R_GLSL_Restart_f(); // unload shaders
1467 return; // no bit left to clear
1472 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
1476 void R_SetupGenericShader(qboolean usetexture)
1478 if (gl_support_fragment_shader)
1480 if (r_glsl.integer && r_glsl_usegeneric.integer)
1481 R_SetupShader_SetPermutation(SHADERMODE_GENERIC, usetexture ? SHADERPERMUTATION_DIFFUSE : 0);
1482 else if (r_glsl_permutation)
1484 r_glsl_permutation = NULL;
1485 qglUseProgramObjectARB(0);CHECKGLERROR
1490 void R_SetupGenericTwoTextureShader(int texturemode)
1492 if (gl_support_fragment_shader)
1494 if (r_glsl.integer && r_glsl_usegeneric.integer)
1495 R_SetupShader_SetPermutation(SHADERMODE_GENERIC, SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
1496 else if (r_glsl_permutation)
1498 r_glsl_permutation = NULL;
1499 qglUseProgramObjectARB(0);CHECKGLERROR
1502 if (!r_glsl_permutation)
1504 if (texturemode == GL_DECAL && gl_combine.integer)
1505 texturemode = GL_INTERPOLATE_ARB;
1506 R_Mesh_TexCombine(1, texturemode, texturemode, 1, 1);
1510 void R_SetupDepthOrShadowShader(void)
1512 if (gl_support_fragment_shader)
1514 if (r_glsl.integer && r_glsl_usegeneric.integer)
1515 R_SetupShader_SetPermutation(SHADERMODE_DEPTH_OR_SHADOW, 0);
1516 else if (r_glsl_permutation)
1518 r_glsl_permutation = NULL;
1519 qglUseProgramObjectARB(0);CHECKGLERROR
1524 extern rtexture_t *r_shadow_attenuationgradienttexture;
1525 extern rtexture_t *r_shadow_attenuation2dtexture;
1526 extern rtexture_t *r_shadow_attenuation3dtexture;
1527 void R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass)
1529 // select a permutation of the lighting shader appropriate to this
1530 // combination of texture, entity, light source, and fogging, only use the
1531 // minimum features necessary to avoid wasting rendering time in the
1532 // fragment shader on features that are not being used
1533 unsigned int permutation = 0;
1534 shadermode_t mode = 0;
1535 // TODO: implement geometry-shader based shadow volumes someday
1536 if (r_glsl_offsetmapping.integer)
1538 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
1539 if (r_glsl_offsetmapping_reliefmapping.integer)
1540 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
1542 if (rsurfacepass == RSURFPASS_BACKGROUND)
1544 // distorted background
1545 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
1546 mode = SHADERMODE_WATER;
1548 mode = SHADERMODE_REFRACTION;
1550 else if (rsurfacepass == RSURFPASS_RTLIGHT)
1553 mode = SHADERMODE_LIGHTSOURCE;
1554 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1555 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1556 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
1557 permutation |= SHADERPERMUTATION_CUBEFILTER;
1558 if (diffusescale > 0)
1559 permutation |= SHADERPERMUTATION_DIFFUSE;
1560 if (specularscale > 0)
1561 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
1562 if (r_refdef.fogenabled)
1563 permutation |= SHADERPERMUTATION_FOG;
1564 if (rsurface.texture->colormapping)
1565 permutation |= SHADERPERMUTATION_COLORMAPPING;
1566 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1567 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1569 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
1571 // unshaded geometry (fullbright or ambient model lighting)
1572 mode = SHADERMODE_FLATCOLOR;
1573 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1574 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1575 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
1576 permutation |= SHADERPERMUTATION_GLOW;
1577 if (r_refdef.fogenabled)
1578 permutation |= SHADERPERMUTATION_FOG;
1579 if (rsurface.texture->colormapping)
1580 permutation |= SHADERPERMUTATION_COLORMAPPING;
1581 if (r_glsl_offsetmapping.integer)
1583 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
1584 if (r_glsl_offsetmapping_reliefmapping.integer)
1585 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
1587 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1588 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1589 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1590 permutation |= SHADERPERMUTATION_REFLECTION;
1592 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
1594 // directional model lighting
1595 mode = SHADERMODE_LIGHTDIRECTION;
1596 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1597 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1598 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
1599 permutation |= SHADERPERMUTATION_GLOW;
1600 permutation |= SHADERPERMUTATION_DIFFUSE;
1601 if (specularscale > 0)
1602 permutation |= SHADERPERMUTATION_SPECULAR;
1603 if (r_refdef.fogenabled)
1604 permutation |= SHADERPERMUTATION_FOG;
1605 if (rsurface.texture->colormapping)
1606 permutation |= SHADERPERMUTATION_COLORMAPPING;
1607 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1608 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1609 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1610 permutation |= SHADERPERMUTATION_REFLECTION;
1612 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
1614 // ambient model lighting
1615 mode = SHADERMODE_LIGHTDIRECTION;
1616 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1617 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1618 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
1619 permutation |= SHADERPERMUTATION_GLOW;
1620 if (r_refdef.fogenabled)
1621 permutation |= SHADERPERMUTATION_FOG;
1622 if (rsurface.texture->colormapping)
1623 permutation |= SHADERPERMUTATION_COLORMAPPING;
1624 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1625 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1626 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1627 permutation |= SHADERPERMUTATION_REFLECTION;
1632 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
1634 // deluxemapping (light direction texture)
1635 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
1636 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
1638 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
1639 permutation |= SHADERPERMUTATION_DIFFUSE;
1640 if (specularscale > 0)
1641 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
1643 else if (r_glsl_deluxemapping.integer >= 2)
1645 // fake deluxemapping (uniform light direction in tangentspace)
1646 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
1647 permutation |= SHADERPERMUTATION_DIFFUSE;
1648 if (specularscale > 0)
1649 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
1651 else if (rsurface.uselightmaptexture)
1653 // ordinary lightmapping (q1bsp, q3bsp)
1654 mode = SHADERMODE_LIGHTMAP;
1658 // ordinary vertex coloring (q3bsp)
1659 mode = SHADERMODE_VERTEXCOLOR;
1661 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1662 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1663 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
1664 permutation |= SHADERPERMUTATION_GLOW;
1665 if (r_refdef.fogenabled)
1666 permutation |= SHADERPERMUTATION_FOG;
1667 if (rsurface.texture->colormapping)
1668 permutation |= SHADERPERMUTATION_COLORMAPPING;
1669 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1670 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1671 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1672 permutation |= SHADERPERMUTATION_REFLECTION;
1674 R_SetupShader_SetPermutation(mode, permutation);
1675 if (mode == SHADERMODE_LIGHTSOURCE)
1677 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
1678 if (permutation & SHADERPERMUTATION_DIFFUSE)
1680 if (r_glsl_permutation->loc_TintColor >= 0) qglUniform4fARB(r_glsl_permutation->loc_TintColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2], rsurface.texture->lightmapcolor[3]);
1681 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, ambientscale);
1682 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, diffusescale);
1683 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, specularscale);
1687 // ambient only is simpler
1688 if (r_glsl_permutation->loc_TintColor >= 0) qglUniform4fARB(r_glsl_permutation->loc_TintColor, lightcolorbase[0] * ambientscale, lightcolorbase[1] * ambientscale, lightcolorbase[2] * ambientscale, rsurface.texture->lightmapcolor[3]);
1689 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, 1);
1690 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, 0);
1691 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, 0);
1693 // additive passes are only darkened by fog, not tinted
1694 if (r_glsl_permutation->loc_FogColor >= 0)
1695 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
1699 if (mode == SHADERMODE_LIGHTDIRECTION)
1701 if (r_glsl_permutation->loc_AmbientColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_AmbientColor , rsurface.modellight_ambient[0] * ambientscale * 0.5f, rsurface.modellight_ambient[1] * ambientscale * 0.5f, rsurface.modellight_ambient[2] * ambientscale * 0.5f);
1702 if (r_glsl_permutation->loc_DiffuseColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_DiffuseColor , rsurface.modellight_diffuse[0] * diffusescale * 0.5f, rsurface.modellight_diffuse[1] * diffusescale * 0.5f, rsurface.modellight_diffuse[2] * diffusescale * 0.5f);
1703 if (r_glsl_permutation->loc_SpecularColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_SpecularColor, rsurface.modellight_diffuse[0] * specularscale * 0.5f, rsurface.modellight_diffuse[1] * specularscale * 0.5f, rsurface.modellight_diffuse[2] * specularscale * 0.5f);
1704 if (r_glsl_permutation->loc_LightDir >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
1708 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_ambient.value * 1.0f / 128.0f);
1709 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_refdef.lightmapintensity);
1710 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, r_refdef.lightmapintensity * specularscale);
1712 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]);
1713 if (r_glsl_permutation->loc_GlowScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_GlowScale, r_hdr_glowintensity.value);
1714 // additive passes are only darkened by fog, not tinted
1715 if (r_glsl_permutation->loc_FogColor >= 0)
1717 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
1718 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
1720 qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
1722 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);
1723 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]);
1724 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]);
1725 if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f);
1726 if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f);
1727 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
1728 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
1730 if (r_glsl_permutation->loc_ContrastBoostCoeff >= 0)
1732 // The formula used is actually:
1733 // color.rgb *= ContrastBoost / ((ContrastBoost - 1) * color.rgb + 1);
1734 // color.rgb *= SceneBrightness;
1736 // color.rgb = [[SceneBrightness * ContrastBoost]] * color.rgb / ([[ContrastBoost - 1]] * color.rgb + 1);
1737 // and do [[calculations]] here in the engine
1738 qglUniform1fARB(r_glsl_permutation->loc_ContrastBoostCoeff, r_glsl_contrastboost.value - 1);
1739 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_refdef.view.colorscale * r_glsl_contrastboost.value);
1742 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_refdef.view.colorscale);
1743 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.modelorg[0], rsurface.modelorg[1], rsurface.modelorg[2]);
1744 if (r_glsl_permutation->loc_Color_Pants >= 0)
1746 if (rsurface.texture->currentskinframe->pants)
1747 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
1749 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
1751 if (r_glsl_permutation->loc_Color_Shirt >= 0)
1753 if (rsurface.texture->currentskinframe->shirt)
1754 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
1756 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
1758 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, r_refdef.fograngerecip);
1759 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower);
1760 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
1764 #define SKINFRAME_HASH 1024
1768 int loadsequence; // incremented each level change
1769 memexpandablearray_t array;
1770 skinframe_t *hash[SKINFRAME_HASH];
1774 void R_SkinFrame_PrepareForPurge(void)
1776 r_skinframe.loadsequence++;
1777 // wrap it without hitting zero
1778 if (r_skinframe.loadsequence >= 200)
1779 r_skinframe.loadsequence = 1;
1782 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
1786 // mark the skinframe as used for the purging code
1787 skinframe->loadsequence = r_skinframe.loadsequence;
1790 void R_SkinFrame_Purge(void)
1794 for (i = 0;i < SKINFRAME_HASH;i++)
1796 for (s = r_skinframe.hash[i];s;s = s->next)
1798 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
1800 if (s->merged == s->base)
1802 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
1803 R_PurgeTexture(s->stain );s->stain = NULL;
1804 R_PurgeTexture(s->merged);s->merged = NULL;
1805 R_PurgeTexture(s->base );s->base = NULL;
1806 R_PurgeTexture(s->pants );s->pants = NULL;
1807 R_PurgeTexture(s->shirt );s->shirt = NULL;
1808 R_PurgeTexture(s->nmap );s->nmap = NULL;
1809 R_PurgeTexture(s->gloss );s->gloss = NULL;
1810 R_PurgeTexture(s->glow );s->glow = NULL;
1811 R_PurgeTexture(s->fog );s->fog = NULL;
1812 s->loadsequence = 0;
1818 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
1820 char basename[MAX_QPATH];
1822 Image_StripImageExtension(name, basename, sizeof(basename));
1824 if( last == NULL ) {
1826 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
1827 item = r_skinframe.hash[hashindex];
1832 // linearly search through the hash bucket
1833 for( ; item ; item = item->next ) {
1834 if( !strcmp( item->basename, basename ) ) {
1841 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
1845 char basename[MAX_QPATH];
1847 Image_StripImageExtension(name, basename, sizeof(basename));
1849 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
1850 for (item = r_skinframe.hash[hashindex];item;item = item->next)
1851 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
1855 rtexture_t *dyntexture;
1856 // check whether its a dynamic texture
1857 dyntexture = CL_GetDynTexture( basename );
1858 if (!add && !dyntexture)
1860 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
1861 memset(item, 0, sizeof(*item));
1862 strlcpy(item->basename, basename, sizeof(item->basename));
1863 item->base = dyntexture; // either NULL or dyntexture handle
1864 item->textureflags = textureflags;
1865 item->comparewidth = comparewidth;
1866 item->compareheight = compareheight;
1867 item->comparecrc = comparecrc;
1868 item->next = r_skinframe.hash[hashindex];
1869 r_skinframe.hash[hashindex] = item;
1871 else if( item->base == NULL )
1873 rtexture_t *dyntexture;
1874 // check whether its a dynamic texture
1875 // 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]
1876 dyntexture = CL_GetDynTexture( basename );
1877 item->base = dyntexture; // either NULL or dyntexture handle
1880 R_SkinFrame_MarkUsed(item);
1884 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
1886 // FIXME: it should be possible to disable loading various layers using
1887 // cvars, to prevent wasted loading time and memory usage if the user does
1889 qboolean loadnormalmap = true;
1890 qboolean loadgloss = true;
1891 qboolean loadpantsandshirt = true;
1892 qboolean loadglow = true;
1894 unsigned char *pixels;
1895 unsigned char *bumppixels;
1896 unsigned char *basepixels = NULL;
1897 int basepixels_width;
1898 int basepixels_height;
1899 skinframe_t *skinframe;
1901 if (cls.state == ca_dedicated)
1904 // return an existing skinframe if already loaded
1905 // if loading of the first image fails, don't make a new skinframe as it
1906 // would cause all future lookups of this to be missing
1907 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
1908 if (skinframe && skinframe->base)
1911 basepixels = loadimagepixelsbgra(name, complain, true);
1912 if (basepixels == NULL)
1915 // we've got some pixels to store, so really allocate this new texture now
1917 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
1918 skinframe->stain = NULL;
1919 skinframe->merged = NULL;
1920 skinframe->base = r_texture_notexture;
1921 skinframe->pants = NULL;
1922 skinframe->shirt = NULL;
1923 skinframe->nmap = r_texture_blanknormalmap;
1924 skinframe->gloss = NULL;
1925 skinframe->glow = NULL;
1926 skinframe->fog = NULL;
1928 basepixels_width = image_width;
1929 basepixels_height = image_height;
1930 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);
1932 if (textureflags & TEXF_ALPHA)
1934 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
1935 if (basepixels[j] < 255)
1937 if (j < basepixels_width * basepixels_height * 4)
1939 // has transparent pixels
1940 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
1941 for (j = 0;j < image_width * image_height * 4;j += 4)
1946 pixels[j+3] = basepixels[j+3];
1948 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);
1953 // _norm is the name used by tenebrae and has been adopted as standard
1956 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false)) != NULL)
1958 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);
1962 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false)) != NULL)
1964 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
1965 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
1966 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);
1968 Mem_Free(bumppixels);
1970 else if (r_shadow_bumpscale_basetexture.value > 0)
1972 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
1973 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
1974 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);
1978 // _luma is supported for tenebrae compatibility
1979 // (I think it's a very stupid name, but oh well)
1980 // _glow is the preferred name
1981 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;}
1982 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;}
1983 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;}
1984 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;}
1987 Mem_Free(basepixels);
1992 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)
1997 for (i = 0;i < width*height;i++)
1998 if (((unsigned char *)&palette[in[i]])[3] > 0)
2000 if (i == width*height)
2003 return R_LoadTexture2D (r_main_texturepool, name, width, height, in, TEXTYPE_PALETTE, textureflags, palette);
2006 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
2007 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
2010 unsigned char *temp1, *temp2;
2011 skinframe_t *skinframe;
2013 if (cls.state == ca_dedicated)
2016 // if already loaded just return it, otherwise make a new skinframe
2017 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
2018 if (skinframe && skinframe->base)
2021 skinframe->stain = NULL;
2022 skinframe->merged = NULL;
2023 skinframe->base = r_texture_notexture;
2024 skinframe->pants = NULL;
2025 skinframe->shirt = NULL;
2026 skinframe->nmap = r_texture_blanknormalmap;
2027 skinframe->gloss = NULL;
2028 skinframe->glow = NULL;
2029 skinframe->fog = NULL;
2031 // if no data was provided, then clearly the caller wanted to get a blank skinframe
2035 if (r_shadow_bumpscale_basetexture.value > 0)
2037 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
2038 temp2 = temp1 + width * height * 4;
2039 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
2040 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
2043 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, skinframe->textureflags, NULL);
2044 if (textureflags & TEXF_ALPHA)
2046 for (i = 3;i < width * height * 4;i += 4)
2047 if (skindata[i] < 255)
2049 if (i < width * height * 4)
2051 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
2052 memcpy(fogpixels, skindata, width * height * 4);
2053 for (i = 0;i < width * height * 4;i += 4)
2054 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
2055 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, skinframe->textureflags, NULL);
2056 Mem_Free(fogpixels);
2063 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
2066 unsigned char *temp1, *temp2;
2067 skinframe_t *skinframe;
2069 if (cls.state == ca_dedicated)
2072 // if already loaded just return it, otherwise make a new skinframe
2073 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
2074 if (skinframe && skinframe->base)
2077 skinframe->stain = NULL;
2078 skinframe->merged = NULL;
2079 skinframe->base = r_texture_notexture;
2080 skinframe->pants = NULL;
2081 skinframe->shirt = NULL;
2082 skinframe->nmap = r_texture_blanknormalmap;
2083 skinframe->gloss = NULL;
2084 skinframe->glow = NULL;
2085 skinframe->fog = NULL;
2087 // if no data was provided, then clearly the caller wanted to get a blank skinframe
2091 if (r_shadow_bumpscale_basetexture.value > 0)
2093 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
2094 temp2 = temp1 + width * height * 4;
2095 // use either a custom palette or the quake palette
2096 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
2097 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
2098 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
2101 // use either a custom palette, or the quake palette
2102 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
2103 if (loadglowtexture)
2104 skinframe->glow = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_glow", skinframe->basename), palette_bgra_onlyfullbrights, skinframe->textureflags, false); // glow
2105 if (loadpantsandshirt)
2107 skinframe->pants = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_pants", skinframe->basename), palette_bgra_pantsaswhite, skinframe->textureflags, false); // pants
2108 skinframe->shirt = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_shirt", skinframe->basename), palette_bgra_shirtaswhite, skinframe->textureflags, false); // shirt
2110 if (skinframe->pants || skinframe->shirt)
2111 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
2112 if (textureflags & TEXF_ALPHA)
2114 for (i = 0;i < width * height;i++)
2115 if (((unsigned char *)palette_bgra_alpha)[skindata[i]*4+3] < 255)
2117 if (i < width * height)
2118 skinframe->fog = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_fog", skinframe->basename), palette_bgra_alpha, skinframe->textureflags, true); // fog mask
2124 skinframe_t *R_SkinFrame_LoadMissing(void)
2126 skinframe_t *skinframe;
2128 if (cls.state == ca_dedicated)
2131 skinframe = R_SkinFrame_Find("missing", TEXF_PRECACHE, 0, 0, 0, true);
2132 skinframe->stain = NULL;
2133 skinframe->merged = NULL;
2134 skinframe->base = r_texture_notexture;
2135 skinframe->pants = NULL;
2136 skinframe->shirt = NULL;
2137 skinframe->nmap = r_texture_blanknormalmap;
2138 skinframe->gloss = NULL;
2139 skinframe->glow = NULL;
2140 skinframe->fog = NULL;
2145 void gl_main_start(void)
2147 memset(r_qwskincache, 0, sizeof(r_qwskincache));
2148 memset(r_qwskincache_skinframe, 0, sizeof(r_qwskincache_skinframe));
2150 // set up r_skinframe loading system for textures
2151 memset(&r_skinframe, 0, sizeof(r_skinframe));
2152 r_skinframe.loadsequence = 1;
2153 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
2155 r_main_texturepool = R_AllocTexturePool();
2156 R_BuildBlankTextures();
2158 if (gl_texturecubemap)
2161 R_BuildNormalizationCube();
2163 r_texture_fogattenuation = NULL;
2164 //r_texture_fogintensity = NULL;
2165 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
2166 memset(&r_waterstate, 0, sizeof(r_waterstate));
2167 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
2168 memset(&r_svbsp, 0, sizeof (r_svbsp));
2170 r_refdef.fogmasktable_density = 0;
2173 void gl_main_shutdown(void)
2175 memset(r_qwskincache, 0, sizeof(r_qwskincache));
2176 memset(r_qwskincache_skinframe, 0, sizeof(r_qwskincache_skinframe));
2178 // clear out the r_skinframe state
2179 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
2180 memset(&r_skinframe, 0, sizeof(r_skinframe));
2183 Mem_Free(r_svbsp.nodes);
2184 memset(&r_svbsp, 0, sizeof (r_svbsp));
2185 R_FreeTexturePool(&r_main_texturepool);
2186 r_texture_blanknormalmap = NULL;
2187 r_texture_white = NULL;
2188 r_texture_grey128 = NULL;
2189 r_texture_black = NULL;
2190 r_texture_whitecube = NULL;
2191 r_texture_normalizationcube = NULL;
2192 r_texture_fogattenuation = NULL;
2193 //r_texture_fogintensity = NULL;
2194 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
2195 memset(&r_waterstate, 0, sizeof(r_waterstate));
2199 extern void CL_ParseEntityLump(char *entitystring);
2200 void gl_main_newmap(void)
2202 // FIXME: move this code to client
2204 char *entities, entname[MAX_QPATH];
2207 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
2208 l = (int)strlen(entname) - 4;
2209 if (l >= 0 && !strcmp(entname + l, ".bsp"))
2211 memcpy(entname + l, ".ent", 5);
2212 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
2214 CL_ParseEntityLump(entities);
2219 if (cl.worldmodel->brush.entities)
2220 CL_ParseEntityLump(cl.worldmodel->brush.entities);
2224 void GL_Main_Init(void)
2226 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
2228 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
2229 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
2230 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
2231 if (gamemode == GAME_NEHAHRA)
2233 Cvar_RegisterVariable (&gl_fogenable);
2234 Cvar_RegisterVariable (&gl_fogdensity);
2235 Cvar_RegisterVariable (&gl_fogred);
2236 Cvar_RegisterVariable (&gl_foggreen);
2237 Cvar_RegisterVariable (&gl_fogblue);
2238 Cvar_RegisterVariable (&gl_fogstart);
2239 Cvar_RegisterVariable (&gl_fogend);
2240 Cvar_RegisterVariable (&gl_skyclip);
2242 Cvar_RegisterVariable(&r_depthfirst);
2243 Cvar_RegisterVariable(&r_nearclip);
2244 Cvar_RegisterVariable(&r_showbboxes);
2245 Cvar_RegisterVariable(&r_showsurfaces);
2246 Cvar_RegisterVariable(&r_showtris);
2247 Cvar_RegisterVariable(&r_shownormals);
2248 Cvar_RegisterVariable(&r_showlighting);
2249 Cvar_RegisterVariable(&r_showshadowvolumes);
2250 Cvar_RegisterVariable(&r_showcollisionbrushes);
2251 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
2252 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
2253 Cvar_RegisterVariable(&r_showdisabledepthtest);
2254 Cvar_RegisterVariable(&r_drawportals);
2255 Cvar_RegisterVariable(&r_drawentities);
2256 Cvar_RegisterVariable(&r_cullentities_trace);
2257 Cvar_RegisterVariable(&r_cullentities_trace_samples);
2258 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
2259 Cvar_RegisterVariable(&r_cullentities_trace_delay);
2260 Cvar_RegisterVariable(&r_drawviewmodel);
2261 Cvar_RegisterVariable(&r_speeds);
2262 Cvar_RegisterVariable(&r_fullbrights);
2263 Cvar_RegisterVariable(&r_wateralpha);
2264 Cvar_RegisterVariable(&r_dynamic);
2265 Cvar_RegisterVariable(&r_fullbright);
2266 Cvar_RegisterVariable(&r_shadows);
2267 Cvar_RegisterVariable(&r_shadows_throwdistance);
2268 Cvar_RegisterVariable(&r_q1bsp_skymasking);
2269 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
2270 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
2271 Cvar_RegisterVariable(&r_fog_exp2);
2272 Cvar_RegisterVariable(&r_textureunits);
2273 Cvar_RegisterVariable(&r_glsl);
2274 Cvar_RegisterVariable(&r_glsl_contrastboost);
2275 Cvar_RegisterVariable(&r_glsl_deluxemapping);
2276 Cvar_RegisterVariable(&r_glsl_offsetmapping);
2277 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
2278 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
2279 Cvar_RegisterVariable(&r_glsl_postprocess);
2280 Cvar_RegisterVariable(&r_glsl_postprocess_contrastboost);
2281 Cvar_RegisterVariable(&r_glsl_postprocess_gamma);
2282 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
2283 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
2284 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
2285 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
2286 Cvar_RegisterVariable(&r_glsl_usegeneric);
2287 Cvar_RegisterVariable(&r_water);
2288 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
2289 Cvar_RegisterVariable(&r_water_clippingplanebias);
2290 Cvar_RegisterVariable(&r_water_refractdistort);
2291 Cvar_RegisterVariable(&r_water_reflectdistort);
2292 Cvar_RegisterVariable(&r_lerpsprites);
2293 Cvar_RegisterVariable(&r_lerpmodels);
2294 Cvar_RegisterVariable(&r_lerplightstyles);
2295 Cvar_RegisterVariable(&r_waterscroll);
2296 Cvar_RegisterVariable(&r_bloom);
2297 Cvar_RegisterVariable(&r_bloom_colorscale);
2298 Cvar_RegisterVariable(&r_bloom_brighten);
2299 Cvar_RegisterVariable(&r_bloom_blur);
2300 Cvar_RegisterVariable(&r_bloom_resolution);
2301 Cvar_RegisterVariable(&r_bloom_colorexponent);
2302 Cvar_RegisterVariable(&r_bloom_colorsubtract);
2303 Cvar_RegisterVariable(&r_hdr);
2304 Cvar_RegisterVariable(&r_hdr_scenebrightness);
2305 Cvar_RegisterVariable(&r_hdr_glowintensity);
2306 Cvar_RegisterVariable(&r_hdr_range);
2307 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
2308 Cvar_RegisterVariable(&developer_texturelogging);
2309 Cvar_RegisterVariable(&gl_lightmaps);
2310 Cvar_RegisterVariable(&r_test);
2311 Cvar_RegisterVariable(&r_batchmode);
2312 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
2313 Cvar_SetValue("r_fullbrights", 0);
2314 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
2316 Cvar_RegisterVariable(&r_track_sprites);
2317 Cvar_RegisterVariable(&r_track_sprites_flags);
2318 Cvar_RegisterVariable(&r_track_sprites_scalew);
2319 Cvar_RegisterVariable(&r_track_sprites_scaleh);
2322 extern void R_Textures_Init(void);
2323 extern void GL_Draw_Init(void);
2324 extern void GL_Main_Init(void);
2325 extern void R_Shadow_Init(void);
2326 extern void R_Sky_Init(void);
2327 extern void GL_Surf_Init(void);
2328 extern void R_Particles_Init(void);
2329 extern void R_Explosion_Init(void);
2330 extern void gl_backend_init(void);
2331 extern void Sbar_Init(void);
2332 extern void R_LightningBeams_Init(void);
2333 extern void Mod_RenderInit(void);
2335 void Render_Init(void)
2347 R_LightningBeams_Init();
2356 extern char *ENGINE_EXTENSIONS;
2359 VID_CheckExtensions();
2361 // LordHavoc: report supported extensions
2362 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
2364 // clear to black (loading plaque will be seen over this)
2366 qglClearColor(0,0,0,1);CHECKGLERROR
2367 qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
2370 int R_CullBox(const vec3_t mins, const vec3_t maxs)
2374 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
2376 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
2379 p = r_refdef.view.frustum + i;
2384 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2388 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2392 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2396 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2400 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2404 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2408 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2412 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2420 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
2424 for (i = 0;i < numplanes;i++)
2431 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2435 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2439 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2443 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2447 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2451 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2455 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2459 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2467 //==================================================================================
2469 static void R_View_UpdateEntityVisible (void)
2472 entity_render_t *ent;
2474 if (!r_drawentities.integer)
2477 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : ((chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL : RENDER_EXTERIORMODEL);
2478 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
2480 // worldmodel can check visibility
2481 for (i = 0;i < r_refdef.scene.numentities;i++)
2483 ent = r_refdef.scene.entities[i];
2484 r_refdef.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.scene.worldmodel->brush.BoxTouchingVisibleLeafs(r_refdef.scene.worldmodel, r_refdef.viewcache.world_leafvisible, ent->mins, ent->maxs));
2487 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight)
2489 for (i = 0;i < r_refdef.scene.numentities;i++)
2491 ent = r_refdef.scene.entities[i];
2492 if(r_refdef.viewcache.entityvisible[i] && !(ent->effects & EF_NODEPTHTEST) && !(ent->flags & RENDER_VIEWMODEL) && !(ent->model && (ent->model->name[0] == '*')))
2494 if(Mod_CanSeeBox_Trace(r_cullentities_trace_samples.integer, r_cullentities_trace_enlarge.value, r_refdef.scene.worldmodel, r_refdef.view.origin, ent->mins, ent->maxs))
2495 ent->last_trace_visibility = realtime;
2496 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
2497 r_refdef.viewcache.entityvisible[i] = 0;
2504 // no worldmodel or it can't check visibility
2505 for (i = 0;i < r_refdef.scene.numentities;i++)
2507 ent = r_refdef.scene.entities[i];
2508 r_refdef.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));
2513 // only used if skyrendermasked, and normally returns false
2514 int R_DrawBrushModelsSky (void)
2517 entity_render_t *ent;
2519 if (!r_drawentities.integer)
2523 for (i = 0;i < r_refdef.scene.numentities;i++)
2525 if (!r_refdef.viewcache.entityvisible[i])
2527 ent = r_refdef.scene.entities[i];
2528 if (!ent->model || !ent->model->DrawSky)
2530 ent->model->DrawSky(ent);
2536 static void R_DrawNoModel(entity_render_t *ent);
2537 static void R_DrawModels(void)
2540 entity_render_t *ent;
2542 if (!r_drawentities.integer)
2545 for (i = 0;i < r_refdef.scene.numentities;i++)
2547 if (!r_refdef.viewcache.entityvisible[i])
2549 ent = r_refdef.scene.entities[i];
2550 r_refdef.stats.entities++;
2551 if (ent->model && ent->model->Draw != NULL)
2552 ent->model->Draw(ent);
2558 static void R_DrawModelsDepth(void)
2561 entity_render_t *ent;
2563 if (!r_drawentities.integer)
2566 for (i = 0;i < r_refdef.scene.numentities;i++)
2568 if (!r_refdef.viewcache.entityvisible[i])
2570 ent = r_refdef.scene.entities[i];
2571 if (ent->model && ent->model->DrawDepth != NULL)
2572 ent->model->DrawDepth(ent);
2576 static void R_DrawModelsDebug(void)
2579 entity_render_t *ent;
2581 if (!r_drawentities.integer)
2584 for (i = 0;i < r_refdef.scene.numentities;i++)
2586 if (!r_refdef.viewcache.entityvisible[i])
2588 ent = r_refdef.scene.entities[i];
2589 if (ent->model && ent->model->DrawDebug != NULL)
2590 ent->model->DrawDebug(ent);
2594 static void R_DrawModelsAddWaterPlanes(void)
2597 entity_render_t *ent;
2599 if (!r_drawentities.integer)
2602 for (i = 0;i < r_refdef.scene.numentities;i++)
2604 if (!r_refdef.viewcache.entityvisible[i])
2606 ent = r_refdef.scene.entities[i];
2607 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
2608 ent->model->DrawAddWaterPlanes(ent);
2612 static void R_View_SetFrustum(void)
2615 double slopex, slopey;
2616 vec3_t forward, left, up, origin;
2618 // we can't trust r_refdef.view.forward and friends in reflected scenes
2619 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
2622 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
2623 r_refdef.view.frustum[0].normal[1] = 0 - 0;
2624 r_refdef.view.frustum[0].normal[2] = -1 - 0;
2625 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
2626 r_refdef.view.frustum[1].normal[1] = 0 + 0;
2627 r_refdef.view.frustum[1].normal[2] = -1 + 0;
2628 r_refdef.view.frustum[2].normal[0] = 0 - 0;
2629 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
2630 r_refdef.view.frustum[2].normal[2] = -1 - 0;
2631 r_refdef.view.frustum[3].normal[0] = 0 + 0;
2632 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
2633 r_refdef.view.frustum[3].normal[2] = -1 + 0;
2637 zNear = r_refdef.nearclip;
2638 nudge = 1.0 - 1.0 / (1<<23);
2639 r_refdef.view.frustum[4].normal[0] = 0 - 0;
2640 r_refdef.view.frustum[4].normal[1] = 0 - 0;
2641 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
2642 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
2643 r_refdef.view.frustum[5].normal[0] = 0 + 0;
2644 r_refdef.view.frustum[5].normal[1] = 0 + 0;
2645 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
2646 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
2652 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
2653 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
2654 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
2655 r_refdef.view.frustum[0].dist = m[15] - m[12];
2657 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
2658 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
2659 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
2660 r_refdef.view.frustum[1].dist = m[15] + m[12];
2662 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
2663 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
2664 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
2665 r_refdef.view.frustum[2].dist = m[15] - m[13];
2667 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
2668 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
2669 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
2670 r_refdef.view.frustum[3].dist = m[15] + m[13];
2672 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
2673 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
2674 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
2675 r_refdef.view.frustum[4].dist = m[15] - m[14];
2677 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
2678 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
2679 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
2680 r_refdef.view.frustum[5].dist = m[15] + m[14];
2683 if (r_refdef.view.useperspective)
2685 slopex = 1.0 / r_refdef.view.frustum_x;
2686 slopey = 1.0 / r_refdef.view.frustum_y;
2687 VectorMA(forward, -slopex, left, r_refdef.view.frustum[0].normal);
2688 VectorMA(forward, slopex, left, r_refdef.view.frustum[1].normal);
2689 VectorMA(forward, -slopey, up , r_refdef.view.frustum[2].normal);
2690 VectorMA(forward, slopey, up , r_refdef.view.frustum[3].normal);
2691 VectorCopy(forward, r_refdef.view.frustum[4].normal);
2693 // Leaving those out was a mistake, those were in the old code, and they
2694 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
2695 // I couldn't reproduce it after adding those normalizations. --blub
2696 VectorNormalize(r_refdef.view.frustum[0].normal);
2697 VectorNormalize(r_refdef.view.frustum[1].normal);
2698 VectorNormalize(r_refdef.view.frustum[2].normal);
2699 VectorNormalize(r_refdef.view.frustum[3].normal);
2701 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
2702 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, -1024 * slopex, left, -1024 * slopey, up, r_refdef.view.frustumcorner[0]);
2703 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, 1024 * slopex, left, -1024 * slopey, up, r_refdef.view.frustumcorner[1]);
2704 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, -1024 * slopex, left, 1024 * slopey, up, r_refdef.view.frustumcorner[2]);
2705 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, 1024 * slopex, left, 1024 * slopey, up, r_refdef.view.frustumcorner[3]);
2707 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
2708 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
2709 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
2710 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
2711 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
2715 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
2716 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
2717 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
2718 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
2719 VectorCopy(forward, r_refdef.view.frustum[4].normal);
2720 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
2721 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
2722 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
2723 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
2724 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
2726 r_refdef.view.numfrustumplanes = 5;
2728 if (r_refdef.view.useclipplane)
2730 r_refdef.view.numfrustumplanes = 6;
2731 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
2734 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
2735 PlaneClassify(r_refdef.view.frustum + i);
2737 // LordHavoc: note to all quake engine coders, Quake had a special case
2738 // for 90 degrees which assumed a square view (wrong), so I removed it,
2739 // Quake2 has it disabled as well.
2741 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
2742 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
2743 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
2744 //PlaneClassify(&frustum[0]);
2746 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
2747 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
2748 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
2749 //PlaneClassify(&frustum[1]);
2751 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
2752 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
2753 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
2754 //PlaneClassify(&frustum[2]);
2756 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
2757 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
2758 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
2759 //PlaneClassify(&frustum[3]);
2762 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
2763 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
2764 //PlaneClassify(&frustum[4]);
2767 void R_View_Update(void)
2769 R_View_SetFrustum();
2770 R_View_WorldVisibility(r_refdef.view.useclipplane);
2771 R_View_UpdateEntityVisible();
2774 void R_SetupView(qboolean allowwaterclippingplane)
2776 if (!r_refdef.view.useperspective)
2777 GL_SetupView_Mode_Ortho(-r_refdef.view.ortho_x, -r_refdef.view.ortho_y, r_refdef.view.ortho_x, r_refdef.view.ortho_y, -r_refdef.farclip, r_refdef.farclip);
2778 else if (r_refdef.rtworldshadows || r_refdef.rtdlightshadows)
2779 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip);
2781 GL_SetupView_Mode_Perspective(r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, r_refdef.farclip);
2783 GL_SetupView_Orientation_FromEntity(&r_refdef.view.matrix);
2785 if (r_refdef.view.useclipplane && allowwaterclippingplane)
2787 // LordHavoc: couldn't figure out how to make this approach the
2788 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
2789 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
2790 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
2791 dist = r_refdef.view.clipplane.dist;
2792 GL_SetupView_ApplyCustomNearClipPlane(r_refdef.view.clipplane.normal[0], r_refdef.view.clipplane.normal[1], r_refdef.view.clipplane.normal[2], dist);
2796 void R_ResetViewRendering2D(void)
2800 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
2801 qglViewport(r_refdef.view.x, vid.height - (r_refdef.view.y + r_refdef.view.height), r_refdef.view.width, r_refdef.view.height);CHECKGLERROR
2802 GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
2803 GL_Scissor(r_refdef.view.x, r_refdef.view.y, r_refdef.view.width, r_refdef.view.height);
2804 GL_Color(1, 1, 1, 1);
2805 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
2806 GL_BlendFunc(GL_ONE, GL_ZERO);
2807 GL_AlphaTest(false);
2808 GL_ScissorTest(false);
2809 GL_DepthMask(false);
2810 GL_DepthRange(0, 1);
2811 GL_DepthTest(false);
2812 R_Mesh_Matrix(&identitymatrix);
2813 R_Mesh_ResetTextureState();
2814 GL_PolygonOffset(0, 0);
2815 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
2816 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
2817 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
2818 qglStencilMask(~0);CHECKGLERROR
2819 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
2820 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
2821 GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
2822 R_SetupGenericShader(true);
2825 void R_ResetViewRendering3D(void)
2829 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
2830 qglViewport(r_refdef.view.x, vid.height - (r_refdef.view.y + r_refdef.view.height), r_refdef.view.width, r_refdef.view.height);CHECKGLERROR
2832 GL_Scissor(r_refdef.view.x, r_refdef.view.y, r_refdef.view.width, r_refdef.view.height);
2833 GL_Color(1, 1, 1, 1);
2834 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
2835 GL_BlendFunc(GL_ONE, GL_ZERO);
2836 GL_AlphaTest(false);
2837 GL_ScissorTest(true);
2839 GL_DepthRange(0, 1);
2841 R_Mesh_Matrix(&identitymatrix);
2842 R_Mesh_ResetTextureState();
2843 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
2844 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
2845 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
2846 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
2847 qglStencilMask(~0);CHECKGLERROR
2848 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
2849 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
2850 GL_CullFace(r_refdef.view.cullface_back);
2851 R_SetupGenericShader(true);
2854 void R_RenderScene(qboolean addwaterplanes);
2856 static void R_Water_StartFrame(void)
2859 int waterwidth, waterheight, texturewidth, textureheight;
2860 r_waterstate_waterplane_t *p;
2862 // set waterwidth and waterheight to the water resolution that will be
2863 // used (often less than the screen resolution for faster rendering)
2864 waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
2865 waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
2867 // calculate desired texture sizes
2868 // can't use water if the card does not support the texture size
2869 if (!r_water.integer || !r_glsl.integer || !gl_support_fragment_shader || waterwidth > gl_max_texture_size || waterheight > gl_max_texture_size)
2870 texturewidth = textureheight = waterwidth = waterheight = 0;
2871 else if (gl_support_arb_texture_non_power_of_two)
2873 texturewidth = waterwidth;
2874 textureheight = waterheight;
2878 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
2879 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
2882 // allocate textures as needed
2883 if (r_waterstate.waterwidth != waterwidth || r_waterstate.waterheight != waterheight || r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight)
2885 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
2886 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
2888 if (p->texture_refraction)
2889 R_FreeTexture(p->texture_refraction);
2890 p->texture_refraction = NULL;
2891 if (p->texture_reflection)
2892 R_FreeTexture(p->texture_reflection);
2893 p->texture_reflection = NULL;
2895 memset(&r_waterstate, 0, sizeof(r_waterstate));
2896 r_waterstate.waterwidth = waterwidth;
2897 r_waterstate.waterheight = waterheight;
2898 r_waterstate.texturewidth = texturewidth;
2899 r_waterstate.textureheight = textureheight;
2902 if (r_waterstate.waterwidth)
2904 r_waterstate.enabled = true;
2906 // set up variables that will be used in shader setup
2907 r_waterstate.screenscale[0] = 0.5f * (float)waterwidth / (float)texturewidth;
2908 r_waterstate.screenscale[1] = 0.5f * (float)waterheight / (float)textureheight;
2909 r_waterstate.screencenter[0] = 0.5f * (float)waterwidth / (float)texturewidth;
2910 r_waterstate.screencenter[1] = 0.5f * (float)waterheight / (float)textureheight;
2913 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
2914 r_waterstate.numwaterplanes = 0;
2917 static void R_Water_AddWaterPlane(msurface_t *surface)
2919 int triangleindex, planeindex;
2924 r_waterstate_waterplane_t *p;
2925 // just use the first triangle with a valid normal for any decisions
2926 VectorClear(normal);
2927 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
2929 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
2930 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
2931 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
2932 TriangleNormal(vert[0], vert[1], vert[2], normal);
2933 if (VectorLength2(normal) >= 0.001)
2937 // find a matching plane if there is one
2938 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
2939 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
2941 if (planeindex >= r_waterstate.maxwaterplanes)
2942 return; // nothing we can do, out of planes
2944 // if this triangle does not fit any known plane rendered this frame, add one
2945 if (planeindex >= r_waterstate.numwaterplanes)
2947 // store the new plane
2948 r_waterstate.numwaterplanes++;
2949 VectorCopy(normal, p->plane.normal);
2950 VectorNormalize(p->plane.normal);
2951 p->plane.dist = DotProduct(vert[0], p->plane.normal);
2952 PlaneClassify(&p->plane);
2953 // flip the plane if it does not face the viewer
2954 if (PlaneDiff(r_refdef.view.origin, &p->plane) < 0)
2956 VectorNegate(p->plane.normal, p->plane.normal);
2957 p->plane.dist *= -1;
2958 PlaneClassify(&p->plane);
2960 // clear materialflags and pvs
2961 p->materialflags = 0;
2962 p->pvsvalid = false;
2964 // merge this surface's materialflags into the waterplane
2965 p->materialflags |= surface->texture->currentframe->currentmaterialflags;
2966 // merge this surface's PVS into the waterplane
2967 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
2968 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
2969 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
2971 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
2976 static void R_Water_ProcessPlanes(void)
2978 r_refdef_view_t originalview;
2980 r_waterstate_waterplane_t *p;
2982 originalview = r_refdef.view;
2984 // make sure enough textures are allocated
2985 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
2987 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
2989 if (!p->texture_refraction)
2990 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);
2991 if (!p->texture_refraction)
2995 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
2997 if (!p->texture_reflection)
2998 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);
2999 if (!p->texture_reflection)
3005 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
3007 r_refdef.view.showdebug = false;
3008 r_refdef.view.width = r_waterstate.waterwidth;
3009 r_refdef.view.height = r_waterstate.waterheight;
3010 r_refdef.view.useclipplane = true;
3011 r_waterstate.renderingscene = true;
3013 // render the normal view scene and copy into texture
3014 // (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)
3015 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
3017 r_refdef.view.clipplane = p->plane;
3018 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
3019 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
3020 PlaneClassify(&r_refdef.view.clipplane);
3022 R_RenderScene(false);
3024 // copy view into the screen texture
3025 R_Mesh_TexBind(0, R_GetTexture(p->texture_refraction));
3026 GL_ActiveTexture(0);
3028 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_refdef.view.x, vid.height - (r_refdef.view.y + r_refdef.view.height), r_refdef.view.width, r_refdef.view.height);CHECKGLERROR
3031 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
3033 // render reflected scene and copy into texture
3034 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
3035 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
3036 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
3037 r_refdef.view.clipplane = p->plane;
3038 // reverse the cullface settings for this render
3039 r_refdef.view.cullface_front = GL_FRONT;
3040 r_refdef.view.cullface_back = GL_BACK;
3041 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
3043 r_refdef.view.usecustompvs = true;
3045 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
3047 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
3050 R_ResetViewRendering3D();
3051 R_ClearScreen(r_refdef.fogenabled);
3052 if (r_timereport_active)
3053 R_TimeReport("viewclear");
3055 R_RenderScene(false);
3057 R_Mesh_TexBind(0, R_GetTexture(p->texture_reflection));
3058 GL_ActiveTexture(0);
3060 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_refdef.view.x, vid.height - (r_refdef.view.y + r_refdef.view.height), r_refdef.view.width, r_refdef.view.height);CHECKGLERROR
3062 R_ResetViewRendering3D();
3063 R_ClearScreen(r_refdef.fogenabled);
3064 if (r_timereport_active)
3065 R_TimeReport("viewclear");
3068 r_refdef.view = originalview;
3069 r_refdef.view.clear = true;
3070 r_waterstate.renderingscene = false;
3074 r_refdef.view = originalview;
3075 r_waterstate.renderingscene = false;
3076 Cvar_SetValueQuick(&r_water, 0);
3077 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
3081 void R_Bloom_StartFrame(void)
3083 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
3085 // set bloomwidth and bloomheight to the bloom resolution that will be
3086 // used (often less than the screen resolution for faster rendering)
3087 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.width);
3088 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
3089 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
3090 r_bloomstate.bloomwidth = min(r_bloomstate.bloomwidth, gl_max_texture_size);
3091 r_bloomstate.bloomheight = min(r_bloomstate.bloomheight, gl_max_texture_size);
3093 // calculate desired texture sizes
3094 if (gl_support_arb_texture_non_power_of_two)
3096 screentexturewidth = r_refdef.view.width;
3097 screentextureheight = r_refdef.view.height;
3098 bloomtexturewidth = r_bloomstate.bloomwidth;
3099 bloomtextureheight = r_bloomstate.bloomheight;
3103 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
3104 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
3105 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
3106 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
3109 if ((r_hdr.integer || r_bloom.integer) && ((r_bloom_resolution.integer < 4 || r_bloom_blur.value < 1 || r_bloom_blur.value >= 512) || r_refdef.view.width > gl_max_texture_size || r_refdef.view.height > gl_max_texture_size))
3111 Cvar_SetValueQuick(&r_hdr, 0);
3112 Cvar_SetValueQuick(&r_bloom, 0);
3115 if (!(r_glsl.integer && (r_glsl_postprocess.integer || r_bloom.integer || r_hdr.integer)) && !r_bloom.integer)
3116 screentexturewidth = screentextureheight = 0;
3117 if (!r_hdr.integer && !r_bloom.integer)
3118 bloomtexturewidth = bloomtextureheight = 0;
3120 // allocate textures as needed
3121 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
3123 if (r_bloomstate.texture_screen)
3124 R_FreeTexture(r_bloomstate.texture_screen);
3125 r_bloomstate.texture_screen = NULL;
3126 r_bloomstate.screentexturewidth = screentexturewidth;
3127 r_bloomstate.screentextureheight = screentextureheight;
3128 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
3129 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);
3131 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
3133 if (r_bloomstate.texture_bloom)
3134 R_FreeTexture(r_bloomstate.texture_bloom);
3135 r_bloomstate.texture_bloom = NULL;
3136 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
3137 r_bloomstate.bloomtextureheight = bloomtextureheight;
3138 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
3139 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);
3142 // set up a texcoord array for the full resolution screen image
3143 // (we have to keep this around to copy back during final render)
3144 r_bloomstate.screentexcoord2f[0] = 0;
3145 r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
3146 r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
3147 r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
3148 r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
3149 r_bloomstate.screentexcoord2f[5] = 0;
3150 r_bloomstate.screentexcoord2f[6] = 0;
3151 r_bloomstate.screentexcoord2f[7] = 0;
3153 // set up a texcoord array for the reduced resolution bloom image
3154 // (which will be additive blended over the screen image)
3155 r_bloomstate.bloomtexcoord2f[0] = 0;
3156 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3157 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3158 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3159 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3160 r_bloomstate.bloomtexcoord2f[5] = 0;
3161 r_bloomstate.bloomtexcoord2f[6] = 0;
3162 r_bloomstate.bloomtexcoord2f[7] = 0;
3164 if (r_hdr.integer || r_bloom.integer)
3166 r_bloomstate.enabled = true;
3167 r_bloomstate.hdr = r_hdr.integer != 0;
3171 void R_Bloom_CopyBloomTexture(float colorscale)
3173 r_refdef.stats.bloom++;
3175 // scale down screen texture to the bloom texture size
3177 qglViewport(r_refdef.view.x, vid.height - (r_refdef.view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
3178 GL_BlendFunc(GL_ONE, GL_ZERO);
3179 GL_Color(colorscale, colorscale, colorscale, 1);
3180 // TODO: optimize with multitexture or GLSL
3181 R_SetupGenericShader(true);
3182 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
3183 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
3184 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3185 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3187 // we now have a bloom image in the framebuffer
3188 // copy it into the bloom image texture for later processing
3189 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3190 GL_ActiveTexture(0);
3192 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_refdef.view.x, vid.height - (r_refdef.view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
3193 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3196 void R_Bloom_CopyHDRTexture(void)
3198 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3199 GL_ActiveTexture(0);
3201 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_refdef.view.x, vid.height - (r_refdef.view.y + r_refdef.view.height), r_refdef.view.width, r_refdef.view.height);CHECKGLERROR
3202 r_refdef.stats.bloom_copypixels += r_refdef.view.width * r_refdef.view.height;
3205 void R_Bloom_MakeTexture(void)
3208 float xoffset, yoffset, r, brighten;
3210 r_refdef.stats.bloom++;
3212 R_ResetViewRendering2D();
3213 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3214 R_Mesh_ColorPointer(NULL, 0, 0);
3215 R_SetupGenericShader(true);
3217 // we have a bloom image in the framebuffer
3219 qglViewport(r_refdef.view.x, vid.height - (r_refdef.view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
3221 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
3224 r = bound(0, r_bloom_colorexponent.value / x, 1);
3225 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
3226 GL_Color(r, r, r, 1);
3227 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3228 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3229 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3230 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3232 // copy the vertically blurred bloom view to a texture
3233 GL_ActiveTexture(0);
3235 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_refdef.view.x, vid.height - (r_refdef.view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
3236 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3239 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
3240 brighten = r_bloom_brighten.value;
3242 brighten *= r_hdr_range.value;
3243 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3244 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
3246 for (dir = 0;dir < 2;dir++)
3248 // blend on at multiple vertical offsets to achieve a vertical blur
3249 // TODO: do offset blends using GLSL
3250 GL_BlendFunc(GL_ONE, GL_ZERO);
3251 for (x = -range;x <= range;x++)
3253 if (!dir){xoffset = 0;yoffset = x;}
3254 else {xoffset = x;yoffset = 0;}
3255 xoffset /= (float)r_bloomstate.bloomtexturewidth;
3256 yoffset /= (float)r_bloomstate.bloomtextureheight;
3257 // compute a texcoord array with the specified x and y offset
3258 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
3259 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3260 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3261 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3262 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3263 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
3264 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
3265 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
3266 // this r value looks like a 'dot' particle, fading sharply to
3267 // black at the edges
3268 // (probably not realistic but looks good enough)
3269 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
3270 //r = (dir ? 1.0f : brighten)/(range*2+1);
3271 r = (dir ? 1.0f : brighten)/(range*2+1)*(1 - x*x/(float)(range*range));
3272 GL_Color(r, r, r, 1);
3273 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3274 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3275 GL_BlendFunc(GL_ONE, GL_ONE);
3278 // copy the vertically blurred bloom view to a texture
3279 GL_ActiveTexture(0);
3281 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_refdef.view.x, vid.height - (r_refdef.view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
3282 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3285 // apply subtract last
3286 // (just like it would be in a GLSL shader)
3287 if (r_bloom_colorsubtract.value > 0 && gl_support_ext_blend_subtract)
3289 GL_BlendFunc(GL_ONE, GL_ZERO);
3290 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3291 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3292 GL_Color(1, 1, 1, 1);
3293 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3294 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3296 GL_BlendFunc(GL_ONE, GL_ONE);
3297 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
3298 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
3299 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3300 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
3301 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3302 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3303 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
3305 // copy the darkened bloom view to a texture
3306 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3307 GL_ActiveTexture(0);
3309 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_refdef.view.x, vid.height - (r_refdef.view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
3310 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3314 void R_HDR_RenderBloomTexture(void)
3316 int oldwidth, oldheight;
3317 float oldcolorscale;
3319 oldcolorscale = r_refdef.view.colorscale;
3320 oldwidth = r_refdef.view.width;
3321 oldheight = r_refdef.view.height;
3322 r_refdef.view.width = r_bloomstate.bloomwidth;
3323 r_refdef.view.height = r_bloomstate.bloomheight;
3325 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
3326 // TODO: add exposure compensation features
3327 // TODO: add fp16 framebuffer support
3329 r_refdef.view.showdebug = false;
3330 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
3332 R_ClearScreen(r_refdef.fogenabled);
3333 if (r_timereport_active)
3334 R_TimeReport("HDRclear");
3336 r_waterstate.numwaterplanes = 0;
3337 R_RenderScene(r_waterstate.enabled);
3338 r_refdef.view.showdebug = true;
3340 R_ResetViewRendering2D();
3342 R_Bloom_CopyHDRTexture();
3343 R_Bloom_MakeTexture();
3345 // restore the view settings
3346 r_refdef.view.width = oldwidth;
3347 r_refdef.view.height = oldheight;
3348 r_refdef.view.colorscale = oldcolorscale;
3350 R_ResetViewRendering3D();
3352 R_ClearScreen(r_refdef.fogenabled);
3353 if (r_timereport_active)
3354 R_TimeReport("viewclear");
3357 static void R_BlendView(void)
3359 if (r_bloomstate.texture_screen)
3361 // copy view into the screen texture
3362 R_ResetViewRendering2D();
3363 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3364 R_Mesh_ColorPointer(NULL, 0, 0);
3365 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
3366 GL_ActiveTexture(0);CHECKGLERROR
3367 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_refdef.view.x, vid.height - (r_refdef.view.y + r_refdef.view.height), r_refdef.view.width, r_refdef.view.height);CHECKGLERROR
3368 r_refdef.stats.bloom_copypixels += r_refdef.view.width * r_refdef.view.height;
3371 if (r_glsl.integer && gl_support_fragment_shader && (r_bloomstate.texture_screen || r_bloomstate.texture_bloom))
3373 unsigned int permutation =
3374 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_GLOW : 0)
3375 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0);
3376 if(r_glsl_postprocess.value)
3378 (r_glsl_postprocess_contrastboost.value != 1 ? SHADERPERMUTATION_CONTRASTBOOST : 0)
3379 | (r_glsl_postprocess_gamma.value != 1 ? SHADERPERMUTATION_GAMMA : 0);
3381 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
3383 // render simple bloom effect
3384 // copy the screen and shrink it and darken it for the bloom process
3385 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
3386 // make the bloom texture
3387 R_Bloom_MakeTexture();
3390 R_ResetViewRendering2D();
3391 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3392 R_Mesh_ColorPointer(NULL, 0, 0);
3393 GL_Color(1, 1, 1, 1);
3394 GL_BlendFunc(GL_ONE, GL_ZERO);
3395 R_SetupShader_SetPermutation(SHADERMODE_POSTPROCESS, permutation);
3396 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
3397 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
3398 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_bloom));
3399 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3400 if (r_glsl_permutation->loc_TintColor >= 0)
3401 qglUniform4fARB(r_glsl_permutation->loc_TintColor, r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
3402 if (r_glsl_permutation->loc_ContrastBoostCoeff >= 0)
3403 qglUniform1fARB(r_glsl_permutation->loc_ContrastBoostCoeff, r_glsl_postprocess_contrastboost.value - 1);
3404 if (r_glsl_permutation->loc_GammaCoeff >= 0)
3405 qglUniform1fARB(r_glsl_permutation->loc_GammaCoeff, 1 / r_glsl_postprocess_gamma.value);
3406 if (r_glsl_permutation->loc_ClientTime >= 0)
3407 qglUniform1fARB(r_glsl_permutation->loc_ClientTime, cl.time);
3408 if (r_glsl_permutation->loc_UserVec1 >= 0)
3410 float a=0, b=0, c=0, d=0;
3411 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &a, &b, &c, &d);
3412 qglUniform4fARB(r_glsl_permutation->loc_UserVec1, a, b, c, d);
3414 if (r_glsl_permutation->loc_UserVec2 >= 0)
3416 float a=0, b=0, c=0, d=0;
3417 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &a, &b, &c, &d);
3418 qglUniform4fARB(r_glsl_permutation->loc_UserVec2, a, b, c, d);
3420 if (r_glsl_permutation->loc_UserVec3 >= 0)
3422 float a=0, b=0, c=0, d=0;
3423 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &a, &b, &c, &d);
3424 qglUniform4fARB(r_glsl_permutation->loc_UserVec3, a, b, c, d);
3426 if (r_glsl_permutation->loc_UserVec4 >= 0)
3428 float a=0, b=0, c=0, d=0;
3429 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &a, &b, &c, &d);
3430 qglUniform4fARB(r_glsl_permutation->loc_UserVec4, a, b, c, d);
3432 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3433 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
3439 if (r_bloomstate.texture_bloom && r_bloomstate.hdr)
3441 // render high dynamic range bloom effect
3442 // the bloom texture was made earlier this render, so we just need to
3443 // blend it onto the screen...
3444 R_ResetViewRendering2D();
3445 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3446 R_Mesh_ColorPointer(NULL, 0, 0);
3447 R_SetupGenericShader(true);
3448 GL_Color(1, 1, 1, 1);
3449 GL_BlendFunc(GL_ONE, GL_ONE);
3450 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3451 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3452 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3453 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
3455 else if (r_bloomstate.texture_bloom)
3457 // render simple bloom effect
3458 // copy the screen and shrink it and darken it for the bloom process
3459 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
3460 // make the bloom texture
3461 R_Bloom_MakeTexture();
3462 // put the original screen image back in place and blend the bloom
3464 R_ResetViewRendering2D();
3465 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3466 R_Mesh_ColorPointer(NULL, 0, 0);
3467 GL_Color(1, 1, 1, 1);
3468 GL_BlendFunc(GL_ONE, GL_ZERO);
3469 // do both in one pass if possible
3470 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3471 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3472 if (r_textureunits.integer >= 2 && gl_combine.integer)
3474 R_SetupGenericTwoTextureShader(GL_ADD);
3475 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_screen));
3476 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.screentexcoord2f, 0, 0);
3480 R_SetupGenericShader(true);
3481 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3482 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
3483 // now blend on the bloom texture
3484 GL_BlendFunc(GL_ONE, GL_ONE);
3485 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
3486 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
3488 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3489 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
3491 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
3493 // apply a color tint to the whole view
3494 R_ResetViewRendering2D();
3495 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3496 R_Mesh_ColorPointer(NULL, 0, 0);
3497 R_SetupGenericShader(false);
3498 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3499 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
3500 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3504 void R_RenderScene(qboolean addwaterplanes);
3506 matrix4x4_t r_waterscrollmatrix;
3508 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
3510 if (r_refdef.fog_density)
3512 r_refdef.fogcolor[0] = r_refdef.fog_red;
3513 r_refdef.fogcolor[1] = r_refdef.fog_green;
3514 r_refdef.fogcolor[2] = r_refdef.fog_blue;
3518 VectorCopy(r_refdef.fogcolor, fogvec);
3519 if(r_glsl.integer && (r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)) // need to support contrast boost
3521 // color.rgb /= ((ContrastBoost - 1) * color.rgb + 1);
3522 fogvec[0] *= r_glsl_contrastboost.value / ((r_glsl_contrastboost.value - 1) * fogvec[0] + 1);
3523 fogvec[1] *= r_glsl_contrastboost.value / ((r_glsl_contrastboost.value - 1) * fogvec[1] + 1);
3524 fogvec[2] *= r_glsl_contrastboost.value / ((r_glsl_contrastboost.value - 1) * fogvec[2] + 1);
3526 // color.rgb *= ContrastBoost * SceneBrightness;
3527 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
3528 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
3529 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
3530 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
3535 void R_UpdateVariables(void)
3539 r_refdef.farclip = 4096;
3540 if (r_refdef.scene.worldmodel)
3541 r_refdef.farclip += VectorDistance(r_refdef.scene.worldmodel->normalmins, r_refdef.scene.worldmodel->normalmaxs);
3542 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
3544 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
3545 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
3546 r_refdef.polygonfactor = 0;
3547 r_refdef.polygonoffset = 0;
3548 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
3549 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
3551 r_refdef.rtworld = r_shadow_realtime_world.integer;
3552 r_refdef.rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
3553 r_refdef.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
3554 r_refdef.rtdlightshadows = r_refdef.rtdlight && r_shadow_realtime_dlight_shadows.integer && gl_stencil;
3555 r_refdef.lightmapintensity = r_refdef.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
3556 if (r_showsurfaces.integer)
3558 r_refdef.rtworld = false;
3559 r_refdef.rtworldshadows = false;
3560 r_refdef.rtdlight = false;
3561 r_refdef.rtdlightshadows = false;
3562 r_refdef.lightmapintensity = 0;
3565 if (gamemode == GAME_NEHAHRA)
3567 if (gl_fogenable.integer)
3569 r_refdef.oldgl_fogenable = true;
3570 r_refdef.fog_density = gl_fogdensity.value;
3571 r_refdef.fog_red = gl_fogred.value;
3572 r_refdef.fog_green = gl_foggreen.value;
3573 r_refdef.fog_blue = gl_fogblue.value;
3574 r_refdef.fog_alpha = 1;
3575 r_refdef.fog_start = 0;
3576 r_refdef.fog_end = gl_skyclip.value;
3578 else if (r_refdef.oldgl_fogenable)
3580 r_refdef.oldgl_fogenable = false;
3581 r_refdef.fog_density = 0;
3582 r_refdef.fog_red = 0;
3583 r_refdef.fog_green = 0;
3584 r_refdef.fog_blue = 0;
3585 r_refdef.fog_alpha = 0;
3586 r_refdef.fog_start = 0;
3587 r_refdef.fog_end = 0;
3591 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
3592 r_refdef.fog_start = max(0, r_refdef.fog_start);
3593 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
3595 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
3597 if (r_refdef.fog_density)
3599 r_refdef.fogenabled = true;
3600 // this is the point where the fog reaches 0.9986 alpha, which we
3601 // consider a good enough cutoff point for the texture
3602 // (0.9986 * 256 == 255.6)
3603 if (r_fog_exp2.integer)
3604 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
3606 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
3607 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
3608 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
3609 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
3610 // fog color was already set
3611 // update the fog texture
3612 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)
3613 R_BuildFogTexture();
3616 r_refdef.fogenabled = false;
3619 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
3620 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
3626 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
3627 if( scenetype != r_currentscenetype ) {
3628 // store the old scenetype
3629 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
3630 r_currentscenetype = scenetype;
3631 // move in the new scene
3632 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
3641 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
3643 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
3644 if( scenetype == r_currentscenetype ) {
3645 return &r_refdef.scene;
3647 return &r_scenes_store[ scenetype ];
3656 void R_RenderView(void)
3658 if (!r_refdef.scene.entities/* || !r_refdef.scene.worldmodel*/)
3659 return; //Host_Error ("R_RenderView: NULL worldmodel");
3661 r_refdef.view.colorscale = r_hdr_scenebrightness.value;
3663 // break apart the view matrix into vectors for various purposes
3664 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
3665 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
3666 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
3667 VectorNegate(r_refdef.view.left, r_refdef.view.right);
3668 // make an inverted copy of the view matrix for tracking sprites
3669 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
3671 R_Shadow_UpdateWorldLightSelection();
3673 R_Bloom_StartFrame();
3674 R_Water_StartFrame();
3677 if (r_timereport_active)
3678 R_TimeReport("viewsetup");
3680 R_ResetViewRendering3D();
3682 if (r_refdef.view.clear || r_refdef.fogenabled)
3684 R_ClearScreen(r_refdef.fogenabled);
3685 if (r_timereport_active)
3686 R_TimeReport("viewclear");
3688 r_refdef.view.clear = true;
3690 r_refdef.view.showdebug = true;
3692 // this produces a bloom texture to be used in R_BlendView() later
3694 R_HDR_RenderBloomTexture();
3696 r_waterstate.numwaterplanes = 0;
3697 R_RenderScene(r_waterstate.enabled);
3700 if (r_timereport_active)
3701 R_TimeReport("blendview");
3703 GL_Scissor(0, 0, vid.width, vid.height);
3704 GL_ScissorTest(false);
3708 extern void R_DrawLightningBeams (void);
3709 extern void VM_CL_AddPolygonsToMeshQueue (void);
3710 extern void R_DrawPortals (void);
3711 extern cvar_t cl_locs_show;
3712 static void R_DrawLocs(void);
3713 static void R_DrawEntityBBoxes(void);
3714 void R_RenderScene(qboolean addwaterplanes)
3716 r_refdef.stats.renders++;
3722 R_ResetViewRendering3D();
3725 if (r_timereport_active)
3726 R_TimeReport("watervis");
3728 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
3730 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
3731 if (r_timereport_active)
3732 R_TimeReport("waterworld");
3735 // don't let sound skip if going slow
3736 if (r_refdef.scene.extraupdate)
3739 R_DrawModelsAddWaterPlanes();
3740 if (r_timereport_active)
3741 R_TimeReport("watermodels");
3743 R_Water_ProcessPlanes();
3744 if (r_timereport_active)
3745 R_TimeReport("waterscenes");
3748 R_ResetViewRendering3D();
3750 // don't let sound skip if going slow
3751 if (r_refdef.scene.extraupdate)
3754 R_MeshQueue_BeginScene();
3759 if (r_timereport_active)
3760 R_TimeReport("visibility");
3762 Matrix4x4_CreateTranslate(&r_waterscrollmatrix, sin(r_refdef.scene.time) * 0.025 * r_waterscroll.value, sin(r_refdef.scene.time * 0.8f) * 0.025 * r_waterscroll.value, 0);
3764 if (cl.csqc_vidvars.drawworld)
3766 // don't let sound skip if going slow
3767 if (r_refdef.scene.extraupdate)
3770 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
3772 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
3773 if (r_timereport_active)
3774 R_TimeReport("worldsky");
3777 if (R_DrawBrushModelsSky() && r_timereport_active)
3778 R_TimeReport("bmodelsky");
3781 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
3783 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
3784 if (r_timereport_active)
3785 R_TimeReport("worlddepth");
3787 if (r_depthfirst.integer >= 2)
3789 R_DrawModelsDepth();
3790 if (r_timereport_active)
3791 R_TimeReport("modeldepth");
3794 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
3796 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
3797 if (r_timereport_active)
3798 R_TimeReport("world");
3801 // don't let sound skip if going slow
3802 if (r_refdef.scene.extraupdate)
3806 if (r_timereport_active)
3807 R_TimeReport("models");
3809 // don't let sound skip if going slow
3810 if (r_refdef.scene.extraupdate)
3813 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
3815 R_DrawModelShadows();
3817 R_ResetViewRendering3D();
3819 // don't let sound skip if going slow
3820 if (r_refdef.scene.extraupdate)
3824 R_ShadowVolumeLighting(false);
3825 if (r_timereport_active)
3826 R_TimeReport("rtlights");
3828 // don't let sound skip if going slow
3829 if (r_refdef.scene.extraupdate)
3832 if (cl.csqc_vidvars.drawworld)
3834 R_DrawLightningBeams();
3835 if (r_timereport_active)
3836 R_TimeReport("lightning");
3839 if (r_timereport_active)
3840 R_TimeReport("decals");
3843 if (r_timereport_active)
3844 R_TimeReport("particles");
3847 if (r_timereport_active)
3848 R_TimeReport("explosions");
3851 R_SetupGenericShader(true);
3852 VM_CL_AddPolygonsToMeshQueue();
3854 if (r_refdef.view.showdebug)
3856 if (cl_locs_show.integer)
3859 if (r_timereport_active)
3860 R_TimeReport("showlocs");
3863 if (r_drawportals.integer)
3866 if (r_timereport_active)
3867 R_TimeReport("portals");
3870 if (r_showbboxes.value > 0)
3872 R_DrawEntityBBoxes();
3873 if (r_timereport_active)
3874 R_TimeReport("bboxes");
3878 R_SetupGenericShader(true);
3879 R_MeshQueue_RenderTransparent();
3880 if (r_timereport_active)
3881 R_TimeReport("drawtrans");
3883 R_SetupGenericShader(true);
3885 if (r_refdef.view.showdebug && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDebug && (r_showtris.value > 0 || r_shownormals.value > 0 || r_showcollisionbrushes.value > 0))
3887 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
3888 if (r_timereport_active)
3889 R_TimeReport("worlddebug");
3890 R_DrawModelsDebug();
3891 if (r_timereport_active)
3892 R_TimeReport("modeldebug");
3895 R_SetupGenericShader(true);
3897 if (cl.csqc_vidvars.drawworld)
3900 if (r_timereport_active)
3901 R_TimeReport("coronas");
3904 // don't let sound skip if going slow
3905 if (r_refdef.scene.extraupdate)
3908 R_ResetViewRendering2D();
3911 static const int bboxelements[36] =
3921 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
3924 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
3925 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3926 GL_DepthMask(false);
3927 GL_DepthRange(0, 1);
3928 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3929 R_Mesh_Matrix(&identitymatrix);
3930 R_Mesh_ResetTextureState();
3932 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
3933 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
3934 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
3935 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
3936 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
3937 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
3938 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
3939 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
3940 R_FillColors(color4f, 8, cr, cg, cb, ca);
3941 if (r_refdef.fogenabled)
3943 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
3945 f1 = FogPoint_World(v);
3947 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
3948 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
3949 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
3952 R_Mesh_VertexPointer(vertex3f, 0, 0);
3953 R_Mesh_ColorPointer(color4f, 0, 0);
3954 R_Mesh_ResetTextureState();
3955 R_SetupGenericShader(false);
3956 R_Mesh_Draw(0, 8, 12, bboxelements, 0, 0);
3959 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
3963 prvm_edict_t *edict;
3964 // this function draws bounding boxes of server entities
3967 R_SetupGenericShader(false);
3969 for (i = 0;i < numsurfaces;i++)
3971 edict = PRVM_EDICT_NUM(surfacelist[i]);
3972 switch ((int)edict->fields.server->solid)
3974 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
3975 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
3976 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
3977 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
3978 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
3979 default: Vector4Set(color, 0, 0, 0, 0.50);break;
3981 color[3] *= r_showbboxes.value;
3982 color[3] = bound(0, color[3], 1);
3983 GL_DepthTest(!r_showdisabledepthtest.integer);
3984 GL_CullFace(r_refdef.view.cullface_front);
3985 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
3990 static void R_DrawEntityBBoxes(void)
3993 prvm_edict_t *edict;
3995 // this function draws bounding boxes of server entities
3999 for (i = 0;i < prog->num_edicts;i++)
4001 edict = PRVM_EDICT_NUM(i);
4002 if (edict->priv.server->free)
4004 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
4005 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
4010 int nomodelelements[24] =
4022 float nomodelvertex3f[6*3] =
4032 float nomodelcolor4f[6*4] =
4034 0.0f, 0.0f, 0.5f, 1.0f,
4035 0.0f, 0.0f, 0.5f, 1.0f,
4036 0.0f, 0.5f, 0.0f, 1.0f,
4037 0.0f, 0.5f, 0.0f, 1.0f,
4038 0.5f, 0.0f, 0.0f, 1.0f,
4039 0.5f, 0.0f, 0.0f, 1.0f
4042 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
4047 // this is only called once per entity so numsurfaces is always 1, and
4048 // surfacelist is always {0}, so this code does not handle batches
4049 R_Mesh_Matrix(&ent->matrix);
4051 if (ent->flags & EF_ADDITIVE)
4053 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
4054 GL_DepthMask(false);
4056 else if (ent->alpha < 1)
4058 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4059 GL_DepthMask(false);
4063 GL_BlendFunc(GL_ONE, GL_ZERO);
4066 GL_DepthRange(0, (ent->flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
4067 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
4068 GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
4069 GL_CullFace((ent->effects & EF_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
4070 R_SetupGenericShader(false);
4071 R_Mesh_VertexPointer(nomodelvertex3f, 0, 0);
4072 if (r_refdef.fogenabled)
4075 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
4076 R_Mesh_ColorPointer(color4f, 0, 0);
4077 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4078 f1 = FogPoint_World(org);
4080 for (i = 0, c = color4f;i < 6;i++, c += 4)
4082 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
4083 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
4084 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
4088 else if (ent->alpha != 1)
4090 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
4091 R_Mesh_ColorPointer(color4f, 0, 0);
4092 for (i = 0, c = color4f;i < 6;i++, c += 4)
4096 R_Mesh_ColorPointer(nomodelcolor4f, 0, 0);
4097 R_Mesh_ResetTextureState();
4098 R_Mesh_Draw(0, 6, 8, nomodelelements, 0, 0);
4101 void R_DrawNoModel(entity_render_t *ent)
4104 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4105 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
4106 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
4108 // R_DrawNoModelCallback(ent, 0);
4111 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
4113 vec3_t right1, right2, diff, normal;
4115 VectorSubtract (org2, org1, normal);
4117 // calculate 'right' vector for start
4118 VectorSubtract (r_refdef.view.origin, org1, diff);
4119 CrossProduct (normal, diff, right1);
4120 VectorNormalize (right1);
4122 // calculate 'right' vector for end
4123 VectorSubtract (r_refdef.view.origin, org2, diff);
4124 CrossProduct (normal, diff, right2);
4125 VectorNormalize (right2);
4127 vert[ 0] = org1[0] + width * right1[0];
4128 vert[ 1] = org1[1] + width * right1[1];
4129 vert[ 2] = org1[2] + width * right1[2];
4130 vert[ 3] = org1[0] - width * right1[0];
4131 vert[ 4] = org1[1] - width * right1[1];
4132 vert[ 5] = org1[2] - width * right1[2];
4133 vert[ 6] = org2[0] - width * right2[0];
4134 vert[ 7] = org2[1] - width * right2[1];
4135 vert[ 8] = org2[2] - width * right2[2];
4136 vert[ 9] = org2[0] + width * right2[0];
4137 vert[10] = org2[1] + width * right2[1];
4138 vert[11] = org2[2] + width * right2[2];
4141 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
4143 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)
4148 if (r_refdef.fogenabled && !depthdisable) // TODO maybe make the unfog effect a separate flag?
4149 fog = FogPoint_World(origin);
4151 R_Mesh_Matrix(&identitymatrix);
4152 GL_BlendFunc(blendfunc1, blendfunc2);
4158 GL_CullFace(r_refdef.view.cullface_front);
4161 GL_CullFace(r_refdef.view.cullface_back);
4162 GL_CullFace(GL_NONE);
4164 GL_DepthMask(false);
4165 GL_DepthRange(0, depthshort ? 0.0625 : 1);
4166 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
4167 GL_DepthTest(!depthdisable);
4169 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
4170 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
4171 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
4172 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
4173 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
4174 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
4175 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
4176 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
4177 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
4178 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
4179 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
4180 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
4182 R_Mesh_VertexPointer(vertex3f, 0, 0);
4183 R_Mesh_ColorPointer(NULL, 0, 0);
4184 R_Mesh_ResetTextureState();
4185 R_SetupGenericShader(true);
4186 R_Mesh_TexBind(0, R_GetTexture(texture));
4187 R_Mesh_TexCoordPointer(0, 2, spritetexcoord2f, 0, 0);
4188 // FIXME: fixed function path can't properly handle r_refdef.view.colorscale > 1
4189 GL_Color(cr * fog * r_refdef.view.colorscale, cg * fog * r_refdef.view.colorscale, cb * fog * r_refdef.view.colorscale, ca);
4190 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
4192 if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
4194 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
4195 GL_BlendFunc(blendfunc1, GL_ONE);
4197 GL_Color(r_refdef.fogcolor[0] * fog, r_refdef.fogcolor[1] * fog, r_refdef.fogcolor[2] * fog, ca);
4198 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
4202 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
4207 VectorSet(v, x, y, z);
4208 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
4209 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
4211 if (i == mesh->numvertices)
4213 if (mesh->numvertices < mesh->maxvertices)
4215 VectorCopy(v, vertex3f);
4216 mesh->numvertices++;
4218 return mesh->numvertices;
4224 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
4228 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
4229 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
4230 e = mesh->element3i + mesh->numtriangles * 3;
4231 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
4233 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
4234 if (mesh->numtriangles < mesh->maxtriangles)
4239 mesh->numtriangles++;
4241 element[1] = element[2];
4245 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
4249 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
4250 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
4251 e = mesh->element3i + mesh->numtriangles * 3;
4252 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
4254 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
4255 if (mesh->numtriangles < mesh->maxtriangles)
4260 mesh->numtriangles++;
4262 element[1] = element[2];
4266 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
4267 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
4269 int planenum, planenum2;
4272 mplane_t *plane, *plane2;
4274 double temppoints[2][256*3];
4275 // figure out how large a bounding box we need to properly compute this brush
4277 for (w = 0;w < numplanes;w++)
4278 maxdist = max(maxdist, planes[w].dist);
4279 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
4280 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
4281 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
4285 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
4286 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
4288 if (planenum2 == planenum)
4290 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);
4293 if (tempnumpoints < 3)
4295 // generate elements forming a triangle fan for this polygon
4296 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
4300 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)
4302 texturelayer_t *layer;
4303 layer = t->currentlayers + t->currentnumlayers++;
4305 layer->depthmask = depthmask;
4306 layer->blendfunc1 = blendfunc1;
4307 layer->blendfunc2 = blendfunc2;
4308 layer->texture = texture;
4309 layer->texmatrix = *matrix;
4310 layer->color[0] = r * r_refdef.view.colorscale;
4311 layer->color[1] = g * r_refdef.view.colorscale;
4312 layer->color[2] = b * r_refdef.view.colorscale;
4313 layer->color[3] = a;
4316 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
4319 index = parms[2] + r_refdef.scene.time * parms[3];
4320 index -= floor(index);
4324 case Q3WAVEFUNC_NONE:
4325 case Q3WAVEFUNC_NOISE:
4326 case Q3WAVEFUNC_COUNT:
4329 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
4330 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
4331 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
4332 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
4333 case Q3WAVEFUNC_TRIANGLE:
4335 f = index - floor(index);
4346 return (float)(parms[0] + parms[1] * f);
4349 void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
4352 model_t *model = ent->model;
4355 q3shaderinfo_layer_tcmod_t *tcmod;
4357 // switch to an alternate material if this is a q1bsp animated material
4359 texture_t *texture = t;
4360 int s = ent->skinnum;
4361 if ((unsigned int)s >= (unsigned int)model->numskins)
4363 if (model->skinscenes)
4365 if (model->skinscenes[s].framecount > 1)
4366 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
4368 s = model->skinscenes[s].firstframe;
4371 t = t + s * model->num_surfaces;
4374 // use an alternate animation if the entity's frame is not 0,
4375 // and only if the texture has an alternate animation
4376 if (ent->frame2 != 0 && t->anim_total[1])
4377 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
4379 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
4381 texture->currentframe = t;
4384 // update currentskinframe to be a qw skin or animation frame
4385 if ((i = ent->entitynumber - 1) >= 0 && i < cl.maxclients)
4387 if (strcmp(r_qwskincache[i], cl.scores[i].qw_skin))
4389 strlcpy(r_qwskincache[i], cl.scores[i].qw_skin, sizeof(r_qwskincache[i]));
4390 Con_DPrintf("loading skins/%s\n", r_qwskincache[i]);
4391 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);
4393 t->currentskinframe = r_qwskincache_skinframe[i];
4394 if (t->currentskinframe == NULL)
4395 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->frame2time)) % t->numskinframes];
4397 else if (t->numskinframes >= 2)
4398 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->frame2time)) % t->numskinframes];
4399 if (t->backgroundnumskinframes >= 2)
4400 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - ent->frame2time)) % t->backgroundnumskinframes];
4402 t->currentmaterialflags = t->basematerialflags;
4403 t->currentalpha = ent->alpha;
4404 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
4406 t->currentalpha *= r_wateralpha.value;
4408 * FIXME what is this supposed to do?
4409 // if rendering refraction/reflection, disable transparency
4410 if (r_waterstate.enabled && (t->currentalpha < 1 || (t->currentmaterialflags & MATERIALFLAG_ALPHA)))
4411 t->currentmaterialflags |= MATERIALFLAG_WATERSHADER;
4414 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled)
4415 t->currentalpha *= t->r_water_wateralpha;
4416 if(!r_waterstate.enabled)
4417 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION);
4418 if (!(ent->flags & RENDER_LIGHT))
4419 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
4420 else if (rsurface.modeltexcoordlightmap2f == NULL)
4422 // pick a model lighting mode
4423 if (VectorLength2(ent->modellight_diffuse) >= (1.0f / 256.0f))
4424 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
4426 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
4428 if (ent->effects & EF_ADDITIVE)
4429 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
4430 else if (t->currentalpha < 1)
4431 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
4432 if (ent->effects & EF_DOUBLESIDED)
4433 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
4434 if (ent->effects & EF_NODEPTHTEST)
4435 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
4436 if (ent->flags & RENDER_VIEWMODEL)
4437 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
4438 if (t->backgroundnumskinframes)
4439 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
4440 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
4442 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER))
4443 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
4446 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER);
4448 // there is no tcmod
4449 if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
4450 t->currenttexmatrix = r_waterscrollmatrix;
4452 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
4455 switch(tcmod->tcmod)
4459 if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
4460 matrix = r_waterscrollmatrix;
4462 matrix = identitymatrix;
4464 case Q3TCMOD_ENTITYTRANSLATE:
4465 // this is used in Q3 to allow the gamecode to control texcoord
4466 // scrolling on the entity, which is not supported in darkplaces yet.
4467 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
4469 case Q3TCMOD_ROTATE:
4470 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
4471 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
4472 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
4475 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
4477 case Q3TCMOD_SCROLL:
4478 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
4480 case Q3TCMOD_STRETCH:
4481 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
4482 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
4484 case Q3TCMOD_TRANSFORM:
4485 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
4486 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
4487 VectorSet(tcmat + 6, 0 , 0 , 1);
4488 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
4489 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
4491 case Q3TCMOD_TURBULENT:
4492 // this is handled in the RSurf_PrepareVertices function
4493 matrix = identitymatrix;
4496 // either replace or concatenate the transformation
4498 t->currenttexmatrix = matrix;
4501 matrix4x4_t temp = t->currenttexmatrix;
4502 Matrix4x4_Concat(&t->currenttexmatrix, &matrix, &temp);
4506 t->colormapping = VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f);
4507 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
4508 t->glosstexture = r_texture_black;
4509 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
4510 t->backgroundglosstexture = r_texture_black;
4511 t->specularpower = r_shadow_glossexponent.value;
4512 // TODO: store reference values for these in the texture?
4513 t->specularscale = 0;
4514 if (r_shadow_gloss.integer > 0)
4516 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
4518 if (r_shadow_glossintensity.value > 0)
4520 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
4521 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
4522 t->specularscale = r_shadow_glossintensity.value;
4525 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
4527 t->glosstexture = r_texture_white;
4528 t->backgroundglosstexture = r_texture_white;
4529 t->specularscale = r_shadow_gloss2intensity.value;
4533 // lightmaps mode looks bad with dlights using actual texturing, so turn
4534 // off the colormap and glossmap, but leave the normalmap on as it still
4535 // accurately represents the shading involved
4536 if (gl_lightmaps.integer)
4538 t->basetexture = r_texture_grey128;
4539 t->backgroundbasetexture = NULL;
4540 t->specularscale = 0;
4541 t->currentmaterialflags &= ~(MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_WATERALPHA | MATERIALFLAG_WATER | MATERIALFLAG_SKY | MATERIALFLAG_ALPHATEST | MATERIALFLAG_BLENDED | MATERIALFLAG_CUSTOMBLEND | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION);
4542 t->currentmaterialflags |= MATERIALFLAG_WALL;
4545 Vector4Set(t->lightmapcolor, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
4546 VectorClear(t->dlightcolor);
4547 t->currentnumlayers = 0;
4548 if (!(t->currentmaterialflags & MATERIALFLAG_NODRAW))
4550 if (!(t->currentmaterialflags & MATERIALFLAG_SKY))
4552 int blendfunc1, blendfunc2, depthmask;
4553 if (t->currentmaterialflags & MATERIALFLAG_ADD)
4555 blendfunc1 = GL_SRC_ALPHA;
4556 blendfunc2 = GL_ONE;
4558 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
4560 blendfunc1 = GL_SRC_ALPHA;
4561 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
4563 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
4565 blendfunc1 = t->customblendfunc[0];
4566 blendfunc2 = t->customblendfunc[1];
4570 blendfunc1 = GL_ONE;
4571 blendfunc2 = GL_ZERO;
4573 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
4574 if (t->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL))
4577 if (r_refdef.fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED))
4578 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
4579 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
4581 // fullbright is not affected by r_refdef.lightmapintensity
4582 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, t->basetexture, &t->currenttexmatrix, t->lightmapcolor[0], t->lightmapcolor[1], t->lightmapcolor[2], t->lightmapcolor[3]);
4583 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
4584 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->pants, &t->currenttexmatrix, ent->colormap_pantscolor[0] * t->lightmapcolor[0], ent->colormap_pantscolor[1] * t->lightmapcolor[1], ent->colormap_pantscolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
4585 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
4586 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->shirt, &t->currenttexmatrix, ent->colormap_shirtcolor[0] * t->lightmapcolor[0], ent->colormap_shirtcolor[1] * t->lightmapcolor[1], ent->colormap_shirtcolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
4590 vec3_t ambientcolor;
4592 // set the color tint used for lights affecting this surface
4593 VectorSet(t->dlightcolor, ent->colormod[0] * t->lightmapcolor[3], ent->colormod[1] * t->lightmapcolor[3], ent->colormod[2] * t->lightmapcolor[3]);
4595 // q3bsp has no lightmap updates, so the lightstylevalue that
4596 // would normally be baked into the lightmap must be
4597 // applied to the color
4598 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
4599 if (ent->model->type == mod_brushq3)
4600 colorscale *= r_refdef.scene.rtlightstylevalue[0];
4601 colorscale *= r_refdef.lightmapintensity;
4602 VectorScale(t->lightmapcolor, r_ambient.value * (1.0f / 64.0f), ambientcolor);
4603 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
4604 // basic lit geometry
4605 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_LITTEXTURE, t->basetexture, &t->currenttexmatrix, t->lightmapcolor[0], t->lightmapcolor[1], t->lightmapcolor[2], t->lightmapcolor[3]);
4606 // add pants/shirt if needed
4607 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
4608 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->currentskinframe->pants, &t->currenttexmatrix, ent->colormap_pantscolor[0] * t->lightmapcolor[0], ent->colormap_pantscolor[1] * t->lightmapcolor[1], ent->colormap_pantscolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
4609 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
4610 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->currentskinframe->shirt, &t->currenttexmatrix, ent->colormap_shirtcolor[0] * t->lightmapcolor[0], ent->colormap_shirtcolor[1] * t->lightmapcolor[1], ent->colormap_shirtcolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
4611 // now add ambient passes if needed
4612 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
4614 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->basetexture, &t->currenttexmatrix, ambientcolor[0], ambientcolor[1], ambientcolor[2], t->lightmapcolor[3]);
4615 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
4616 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->pants, &t->currenttexmatrix, ent->colormap_pantscolor[0] * ambientcolor[0], ent->colormap_pantscolor[1] * ambientcolor[1], ent->colormap_pantscolor[2] * ambientcolor[2], t->lightmapcolor[3]);
4617 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
4618 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->shirt, &t->currenttexmatrix, ent->colormap_shirtcolor[0] * ambientcolor[0], ent->colormap_shirtcolor[1] * ambientcolor[1], ent->colormap_shirtcolor[2] * ambientcolor[2], t->lightmapcolor[3]);
4621 if (t->currentskinframe->glow != NULL && !gl_lightmaps.integer)
4622 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->glow, &t->currenttexmatrix, r_hdr_glowintensity.value, r_hdr_glowintensity.value, r_hdr_glowintensity.value, t->lightmapcolor[3]);
4623 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
4625 // if this is opaque use alpha blend which will darken the earlier
4628 // if this is an alpha blended material, all the earlier passes
4629 // were darkened by fog already, so we only need to add the fog
4630 // color ontop through the fog mask texture
4632 // if this is an additive blended material, all the earlier passes
4633 // were darkened by fog already, and we should not add fog color
4634 // (because the background was not darkened, there is no fog color
4635 // that was lost behind it).
4636 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_refdef.view.colorscale, r_refdef.fogcolor[1] / r_refdef.view.colorscale, r_refdef.fogcolor[2] / r_refdef.view.colorscale, t->lightmapcolor[3]);
4643 void R_UpdateAllTextureInfo(entity_render_t *ent)
4647 for (i = 0;i < ent->model->num_texturesperskin;i++)
4648 R_UpdateTextureInfo(ent, ent->model->data_textures + i);
4651 rsurfacestate_t rsurface;
4653 void R_Mesh_ResizeArrays(int newvertices)
4656 if (rsurface.array_size >= newvertices)
4658 if (rsurface.array_modelvertex3f)
4659 Mem_Free(rsurface.array_modelvertex3f);
4660 rsurface.array_size = (newvertices + 1023) & ~1023;
4661 base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
4662 rsurface.array_modelvertex3f = base + rsurface.array_size * 0;
4663 rsurface.array_modelsvector3f = base + rsurface.array_size * 3;
4664 rsurface.array_modeltvector3f = base + rsurface.array_size * 6;
4665 rsurface.array_modelnormal3f = base + rsurface.array_size * 9;
4666 rsurface.array_deformedvertex3f = base + rsurface.array_size * 12;
4667 rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
4668 rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
4669 rsurface.array_deformednormal3f = base + rsurface.array_size * 21;
4670 rsurface.array_texcoord3f = base + rsurface.array_size * 24;
4671 rsurface.array_color4f = base + rsurface.array_size * 27;
4672 rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
4675 void RSurf_ActiveWorldEntity(void)
4677 model_t *model = r_refdef.scene.worldmodel;
4678 if (rsurface.array_size < model->surfmesh.num_vertices)
4679 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
4680 rsurface.matrix = identitymatrix;
4681 rsurface.inversematrix = identitymatrix;
4682 R_Mesh_Matrix(&identitymatrix);
4683 VectorCopy(r_refdef.view.origin, rsurface.modelorg);
4684 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
4685 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
4686 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
4687 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
4688 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
4689 rsurface.frameblend[0].frame = 0;
4690 rsurface.frameblend[0].lerp = 1;
4691 rsurface.frameblend[1].frame = 0;
4692 rsurface.frameblend[1].lerp = 0;
4693 rsurface.frameblend[2].frame = 0;
4694 rsurface.frameblend[2].lerp = 0;
4695 rsurface.frameblend[3].frame = 0;
4696 rsurface.frameblend[3].lerp = 0;
4697 rsurface.basepolygonfactor = r_refdef.polygonfactor;
4698 rsurface.basepolygonoffset = r_refdef.polygonoffset;
4699 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
4700 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
4701 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
4702 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
4703 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
4704 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
4705 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
4706 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
4707 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
4708 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
4709 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
4710 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
4711 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
4712 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
4713 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
4714 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
4715 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
4716 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
4717 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
4718 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
4719 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
4720 rsurface.modelelement3i = model->surfmesh.data_element3i;
4721 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo;
4722 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
4723 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
4724 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
4725 rsurface.modelsurfaces = model->data_surfaces;
4726 rsurface.generatedvertex = false;
4727 rsurface.vertex3f = rsurface.modelvertex3f;
4728 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
4729 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
4730 rsurface.svector3f = rsurface.modelsvector3f;
4731 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
4732 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
4733 rsurface.tvector3f = rsurface.modeltvector3f;
4734 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
4735 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
4736 rsurface.normal3f = rsurface.modelnormal3f;
4737 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
4738 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
4739 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
4742 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4744 model_t *model = ent->model;
4745 if (rsurface.array_size < model->surfmesh.num_vertices)
4746 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
4747 rsurface.matrix = ent->matrix;
4748 rsurface.inversematrix = ent->inversematrix;
4749 R_Mesh_Matrix(&rsurface.matrix);
4750 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.modelorg);
4751 rsurface.modellight_ambient[0] = ent->modellight_ambient[0] * ent->colormod[0];
4752 rsurface.modellight_ambient[1] = ent->modellight_ambient[1] * ent->colormod[1];
4753 rsurface.modellight_ambient[2] = ent->modellight_ambient[2] * ent->colormod[2];
4754 rsurface.modellight_diffuse[0] = ent->modellight_diffuse[0] * ent->colormod[0];
4755 rsurface.modellight_diffuse[1] = ent->modellight_diffuse[1] * ent->colormod[1];
4756 rsurface.modellight_diffuse[2] = ent->modellight_diffuse[2] * ent->colormod[2];
4757 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
4758 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
4759 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
4760 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
4761 rsurface.frameblend[0] = ent->frameblend[0];
4762 rsurface.frameblend[1] = ent->frameblend[1];
4763 rsurface.frameblend[2] = ent->frameblend[2];
4764 rsurface.frameblend[3] = ent->frameblend[3];
4765 rsurface.basepolygonfactor = r_refdef.polygonfactor;
4766 rsurface.basepolygonoffset = r_refdef.polygonoffset;
4767 if (ent->model->brush.submodel)
4769 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
4770 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
4772 if (model->surfmesh.isanimated && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].frame != 0))
4776 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
4777 rsurface.modelsvector3f = rsurface.array_modelsvector3f;
4778 rsurface.modeltvector3f = rsurface.array_modeltvector3f;
4779 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
4780 Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
4782 else if (wantnormals)
4784 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
4785 rsurface.modelsvector3f = NULL;
4786 rsurface.modeltvector3f = NULL;
4787 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
4788 Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
4792 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
4793 rsurface.modelsvector3f = NULL;
4794 rsurface.modeltvector3f = NULL;
4795 rsurface.modelnormal3f = NULL;
4796 Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, NULL, NULL, NULL);
4798 rsurface.modelvertex3f_bufferobject = 0;
4799 rsurface.modelvertex3f_bufferoffset = 0;
4800 rsurface.modelsvector3f_bufferobject = 0;
4801 rsurface.modelsvector3f_bufferoffset = 0;
4802 rsurface.modeltvector3f_bufferobject = 0;
4803 rsurface.modeltvector3f_bufferoffset = 0;
4804 rsurface.modelnormal3f_bufferobject = 0;
4805 rsurface.modelnormal3f_bufferoffset = 0;
4806 rsurface.generatedvertex = true;
4810 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
4811 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
4812 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
4813 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
4814 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
4815 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
4816 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
4817 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
4818 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
4819 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
4820 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
4821 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
4822 rsurface.generatedvertex = false;
4824 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
4825 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
4826 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
4827 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
4828 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
4829 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
4830 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
4831 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
4832 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
4833 rsurface.modelelement3i = model->surfmesh.data_element3i;
4834 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo;
4835 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
4836 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
4837 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
4838 rsurface.modelsurfaces = model->data_surfaces;
4839 rsurface.vertex3f = rsurface.modelvertex3f;
4840 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
4841 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
4842 rsurface.svector3f = rsurface.modelsvector3f;
4843 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
4844 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
4845 rsurface.tvector3f = rsurface.modeltvector3f;
4846 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
4847 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
4848 rsurface.normal3f = rsurface.modelnormal3f;
4849 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
4850 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
4851 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
4854 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
4855 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, msurface_t **texturesurfacelist)
4858 int texturesurfaceindex;
4863 const float *v1, *in_tc;
4865 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
4867 q3shaderinfo_deform_t *deform;
4868 // 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
4869 if (rsurface.generatedvertex)
4871 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
4872 generatenormals = true;
4873 for (i = 0;i < Q3MAXDEFORMS;i++)
4875 if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
4877 generatetangents = true;
4878 generatenormals = true;
4880 if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
4881 generatenormals = true;
4883 if (generatenormals && !rsurface.modelnormal3f)
4885 rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
4886 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
4887 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
4888 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer);
4890 if (generatetangents && !rsurface.modelsvector3f)
4892 rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
4893 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
4894 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
4895 rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
4896 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
4897 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
4898 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);
4901 rsurface.vertex3f = rsurface.modelvertex3f;
4902 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
4903 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
4904 rsurface.svector3f = rsurface.modelsvector3f;
4905 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
4906 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
4907 rsurface.tvector3f = rsurface.modeltvector3f;
4908 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
4909 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
4910 rsurface.normal3f = rsurface.modelnormal3f;
4911 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
4912 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
4913 // if vertices are deformed (sprite flares and things in maps, possibly
4914 // water waves, bulges and other deformations), generate them into
4915 // rsurface.deform* arrays from whatever the rsurface.* arrays point to
4916 // (may be static model data or generated data for an animated model, or
4917 // the previous deform pass)
4918 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
4920 switch (deform->deform)
4923 case Q3DEFORM_PROJECTIONSHADOW:
4924 case Q3DEFORM_TEXT0:
4925 case Q3DEFORM_TEXT1:
4926 case Q3DEFORM_TEXT2:
4927 case Q3DEFORM_TEXT3:
4928 case Q3DEFORM_TEXT4:
4929 case Q3DEFORM_TEXT5:
4930 case Q3DEFORM_TEXT6:
4931 case Q3DEFORM_TEXT7:
4934 case Q3DEFORM_AUTOSPRITE:
4935 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
4936 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
4937 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
4938 VectorNormalize(newforward);
4939 VectorNormalize(newright);
4940 VectorNormalize(newup);
4941 // make deformed versions of only the model vertices used by the specified surfaces
4942 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4944 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4945 // a single autosprite surface can contain multiple sprites...
4946 for (j = 0;j < surface->num_vertices - 3;j += 4)
4948 VectorClear(center);
4949 for (i = 0;i < 4;i++)
4950 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
4951 VectorScale(center, 0.25f, center);
4952 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, forward);
4953 VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
4954 VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
4955 for (i = 0;i < 4;i++)
4957 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
4958 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
4961 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);
4962 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);
4964 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4965 rsurface.vertex3f_bufferobject = 0;
4966 rsurface.vertex3f_bufferoffset = 0;
4967 rsurface.svector3f = rsurface.array_deformedsvector3f;
4968 rsurface.svector3f_bufferobject = 0;
4969 rsurface.svector3f_bufferoffset = 0;
4970 rsurface.tvector3f = rsurface.array_deformedtvector3f;
4971 rsurface.tvector3f_bufferobject = 0;
4972 rsurface.tvector3f_bufferoffset = 0;
4973 rsurface.normal3f = rsurface.array_deformednormal3f;
4974 rsurface.normal3f_bufferobject = 0;
4975 rsurface.normal3f_bufferoffset = 0;
4977 case Q3DEFORM_AUTOSPRITE2:
4978 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
4979 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
4980 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
4981 VectorNormalize(newforward);
4982 VectorNormalize(newright);
4983 VectorNormalize(newup);
4984 // make deformed versions of only the model vertices used by the specified surfaces
4985 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4987 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4988 const float *v1, *v2;
4998 memset(shortest, 0, sizeof(shortest));
4999 // a single autosprite surface can contain multiple sprites...
5000 for (j = 0;j < surface->num_vertices - 3;j += 4)
5002 VectorClear(center);
5003 for (i = 0;i < 4;i++)
5004 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
5005 VectorScale(center, 0.25f, center);
5006 // find the two shortest edges, then use them to define the
5007 // axis vectors for rotating around the central axis
5008 for (i = 0;i < 6;i++)
5010 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
5011 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
5013 Debug_PolygonBegin(NULL, 0);
5014 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
5015 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);
5016 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
5019 l = VectorDistance2(v1, v2);
5020 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
5022 l += (1.0f / 1024.0f);
5023 if (shortest[0].length2 > l || i == 0)
5025 shortest[1] = shortest[0];
5026 shortest[0].length2 = l;
5027 shortest[0].v1 = v1;
5028 shortest[0].v2 = v2;
5030 else if (shortest[1].length2 > l || i == 1)
5032 shortest[1].length2 = l;
5033 shortest[1].v1 = v1;
5034 shortest[1].v2 = v2;
5037 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
5038 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
5040 Debug_PolygonBegin(NULL, 0);
5041 Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
5042 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);
5043 Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
5046 // this calculates the right vector from the shortest edge
5047 // and the up vector from the edge midpoints
5048 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
5049 VectorNormalize(right);
5050 VectorSubtract(end, start, up);
5051 VectorNormalize(up);
5052 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
5053 //VectorSubtract(rsurface.modelorg, center, forward);
5054 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
5055 VectorNegate(forward, forward);
5056 VectorReflect(forward, 0, up, forward);
5057 VectorNormalize(forward);
5058 CrossProduct(up, forward, newright);
5059 VectorNormalize(newright);
5061 Debug_PolygonBegin(NULL, 0);
5062 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);
5063 Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
5064 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
5068 Debug_PolygonBegin(NULL, 0);
5069 Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
5070 Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
5071 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
5074 // rotate the quad around the up axis vector, this is made
5075 // especially easy by the fact we know the quad is flat,
5076 // so we only have to subtract the center position and
5077 // measure distance along the right vector, and then
5078 // multiply that by the newright vector and add back the
5080 // we also need to subtract the old position to undo the
5081 // displacement from the center, which we do with a
5082 // DotProduct, the subtraction/addition of center is also
5083 // optimized into DotProducts here
5084 l = DotProduct(right, center);
5085 for (i = 0;i < 4;i++)
5087 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
5088 f = DotProduct(right, v1) - l;
5089 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
5092 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);
5093 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);
5095 rsurface.vertex3f = rsurface.array_deformedvertex3f;
5096 rsurface.vertex3f_bufferobject = 0;
5097 rsurface.vertex3f_bufferoffset = 0;
5098 rsurface.svector3f = rsurface.array_deformedsvector3f;
5099 rsurface.svector3f_bufferobject = 0;
5100 rsurface.svector3f_bufferoffset = 0;
5101 rsurface.tvector3f = rsurface.array_deformedtvector3f;
5102 rsurface.tvector3f_bufferobject = 0;
5103 rsurface.tvector3f_bufferoffset = 0;
5104 rsurface.normal3f = rsurface.array_deformednormal3f;
5105 rsurface.normal3f_bufferobject = 0;
5106 rsurface.normal3f_bufferoffset = 0;
5108 case Q3DEFORM_NORMAL:
5109 // deform the normals to make reflections wavey
5110 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5112 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5113 for (j = 0;j < surface->num_vertices;j++)
5116 float *normal = (rsurface.array_deformednormal3f + 3 * surface->num_firstvertex) + j*3;
5117 VectorScale((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
5118 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, normal);
5119 normal[0] += deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
5120 normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
5121 normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
5122 VectorNormalize(normal);
5124 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);
5126 rsurface.svector3f = rsurface.array_deformedsvector3f;
5127 rsurface.svector3f_bufferobject = 0;
5128 rsurface.svector3f_bufferoffset = 0;
5129 rsurface.tvector3f = rsurface.array_deformedtvector3f;
5130 rsurface.tvector3f_bufferobject = 0;
5131 rsurface.tvector3f_bufferoffset = 0;
5132 rsurface.normal3f = rsurface.array_deformednormal3f;
5133 rsurface.normal3f_bufferobject = 0;
5134 rsurface.normal3f_bufferoffset = 0;
5137 // deform vertex array to make wavey water and flags and such
5138 waveparms[0] = deform->waveparms[0];
5139 waveparms[1] = deform->waveparms[1];
5140 waveparms[2] = deform->waveparms[2];
5141 waveparms[3] = deform->waveparms[3];
5142 // this is how a divisor of vertex influence on deformation
5143 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
5144 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
5145 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5147 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5148 for (j = 0;j < surface->num_vertices;j++)
5150 float *vertex = (rsurface.array_deformedvertex3f + 3 * surface->num_firstvertex) + j*3;
5151 VectorCopy((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, vertex);
5152 // if the wavefunc depends on time, evaluate it per-vertex
5155 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
5156 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
5158 VectorMA(vertex, scale, (rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, vertex);
5161 rsurface.vertex3f = rsurface.array_deformedvertex3f;
5162 rsurface.vertex3f_bufferobject = 0;
5163 rsurface.vertex3f_bufferoffset = 0;
5165 case Q3DEFORM_BULGE:
5166 // deform vertex array to make the surface have moving bulges
5167 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5169 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5170 for (j = 0;j < surface->num_vertices;j++)
5172 scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.scene.time * deform->parms[2])) * deform->parms[1];
5173 VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
5176 rsurface.vertex3f = rsurface.array_deformedvertex3f;
5177 rsurface.vertex3f_bufferobject = 0;
5178 rsurface.vertex3f_bufferoffset = 0;
5181 // deform vertex array
5182 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
5183 VectorScale(deform->parms, scale, waveparms);
5184 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5186 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5187 for (j = 0;j < surface->num_vertices;j++)
5188 VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
5190 rsurface.vertex3f = rsurface.array_deformedvertex3f;
5191 rsurface.vertex3f_bufferobject = 0;
5192 rsurface.vertex3f_bufferoffset = 0;
5196 // generate texcoords based on the chosen texcoord source
5197 switch(rsurface.texture->tcgen.tcgen)
5200 case Q3TCGEN_TEXTURE:
5201 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
5202 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordtexture2f_bufferobject;
5203 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
5205 case Q3TCGEN_LIGHTMAP:
5206 rsurface.texcoordtexture2f = rsurface.modeltexcoordlightmap2f;
5207 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
5208 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
5210 case Q3TCGEN_VECTOR:
5211 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5213 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5214 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)
5216 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
5217 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
5220 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
5221 rsurface.texcoordtexture2f_bufferobject = 0;
5222 rsurface.texcoordtexture2f_bufferoffset = 0;
5224 case Q3TCGEN_ENVIRONMENT:
5225 // make environment reflections using a spheremap
5226 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5228 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5229 const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
5230 const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
5231 float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
5232 for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
5234 float l, d, eyedir[3];
5235 VectorSubtract(rsurface.modelorg, vertex, eyedir);
5236 l = 0.5f / VectorLength(eyedir);
5237 d = DotProduct(normal, eyedir)*2;
5238 out_tc[0] = 0.5f + (normal[1]*d - eyedir[1])*l;
5239 out_tc[1] = 0.5f - (normal[2]*d - eyedir[2])*l;
5242 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
5243 rsurface.texcoordtexture2f_bufferobject = 0;
5244 rsurface.texcoordtexture2f_bufferoffset = 0;
5247 // the only tcmod that needs software vertex processing is turbulent, so
5248 // check for it here and apply the changes if needed
5249 // and we only support that as the first one
5250 // (handling a mixture of turbulent and other tcmods would be problematic
5251 // without punting it entirely to a software path)
5252 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
5254 amplitude = rsurface.texture->tcmods[0].parms[1];
5255 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
5256 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5258 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5259 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)
5261 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
5262 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
5265 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
5266 rsurface.texcoordtexture2f_bufferobject = 0;
5267 rsurface.texcoordtexture2f_bufferoffset = 0;
5269 rsurface.texcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
5270 rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
5271 rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
5272 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
5275 void RSurf_DrawBatch_Simple(int texturenumsurfaces, msurface_t **texturesurfacelist)
5278 const msurface_t *surface = texturesurfacelist[0];
5279 const msurface_t *surface2;
5284 // TODO: lock all array ranges before render, rather than on each surface
5285 if (texturenumsurfaces == 1)
5287 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5288 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));
5290 else if (r_batchmode.integer == 2)
5292 #define MAXBATCHTRIANGLES 4096
5293 int batchtriangles = 0;
5294 int batchelements[MAXBATCHTRIANGLES*3];
5295 for (i = 0;i < texturenumsurfaces;i = j)
5297 surface = texturesurfacelist[i];
5299 if (surface->num_triangles > MAXBATCHTRIANGLES)
5301 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));
5304 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
5305 batchtriangles = surface->num_triangles;
5306 firstvertex = surface->num_firstvertex;
5307 endvertex = surface->num_firstvertex + surface->num_vertices;
5308 for (;j < texturenumsurfaces;j++)
5310 surface2 = texturesurfacelist[j];
5311 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
5313 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
5314 batchtriangles += surface2->num_triangles;
5315 firstvertex = min(firstvertex, surface2->num_firstvertex);
5316 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
5318 surface2 = texturesurfacelist[j-1];
5319 numvertices = endvertex - firstvertex;
5320 R_Mesh_Draw(firstvertex, numvertices, batchtriangles, batchelements, 0, 0);
5323 else if (r_batchmode.integer == 1)
5325 for (i = 0;i < texturenumsurfaces;i = j)
5327 surface = texturesurfacelist[i];
5328 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
5329 if (texturesurfacelist[j] != surface2)
5331 surface2 = texturesurfacelist[j-1];
5332 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
5333 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
5334 GL_LockArrays(surface->num_firstvertex, numvertices);
5335 R_Mesh_Draw(surface->num_firstvertex, numvertices, numtriangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
5340 for (i = 0;i < texturenumsurfaces;i++)
5342 surface = texturesurfacelist[i];
5343 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5344 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));
5349 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit, int refractiontexunit, int reflectiontexunit)
5351 int i, planeindex, vertexindex;
5355 r_waterstate_waterplane_t *p, *bestp;
5356 msurface_t *surface;
5357 if (r_waterstate.renderingscene)
5359 for (i = 0;i < texturenumsurfaces;i++)
5361 surface = texturesurfacelist[i];
5362 if (lightmaptexunit >= 0)
5363 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5364 if (deluxemaptexunit >= 0)
5365 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5366 // pick the closest matching water plane
5369 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5372 for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
5374 Matrix4x4_Transform(&rsurface.matrix, v, vert);
5375 d += fabs(PlaneDiff(vert, &p->plane));
5377 if (bestd > d || !bestp)
5385 if (refractiontexunit >= 0)
5386 R_Mesh_TexBind(refractiontexunit, R_GetTexture(bestp->texture_refraction));
5387 if (reflectiontexunit >= 0)
5388 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(bestp->texture_reflection));
5392 if (refractiontexunit >= 0)
5393 R_Mesh_TexBind(refractiontexunit, R_GetTexture(r_texture_black));
5394 if (reflectiontexunit >= 0)
5395 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(r_texture_black));
5397 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5398 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));
5402 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit)
5406 const msurface_t *surface = texturesurfacelist[0];
5407 const msurface_t *surface2;
5412 // TODO: lock all array ranges before render, rather than on each surface
5413 if (texturenumsurfaces == 1)
5415 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5416 if (deluxemaptexunit >= 0)
5417 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5418 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5419 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));
5421 else if (r_batchmode.integer == 2)
5423 #define MAXBATCHTRIANGLES 4096
5424 int batchtriangles = 0;
5425 int batchelements[MAXBATCHTRIANGLES*3];
5426 for (i = 0;i < texturenumsurfaces;i = j)
5428 surface = texturesurfacelist[i];
5429 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5430 if (deluxemaptexunit >= 0)
5431 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5433 if (surface->num_triangles > MAXBATCHTRIANGLES)
5435 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));
5438 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
5439 batchtriangles = surface->num_triangles;
5440 firstvertex = surface->num_firstvertex;
5441 endvertex = surface->num_firstvertex + surface->num_vertices;
5442 for (;j < texturenumsurfaces;j++)
5444 surface2 = texturesurfacelist[j];
5445 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
5447 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
5448 batchtriangles += surface2->num_triangles;
5449 firstvertex = min(firstvertex, surface2->num_firstvertex);
5450 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
5452 surface2 = texturesurfacelist[j-1];
5453 numvertices = endvertex - firstvertex;
5454 R_Mesh_Draw(firstvertex, numvertices, batchtriangles, batchelements, 0, 0);
5457 else if (r_batchmode.integer == 1)
5460 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
5461 for (i = 0;i < texturenumsurfaces;i = j)
5463 surface = texturesurfacelist[i];
5464 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
5465 if (texturesurfacelist[j] != surface2)
5467 Con_Printf(" %i", j - i);
5470 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
5472 for (i = 0;i < texturenumsurfaces;i = j)
5474 surface = texturesurfacelist[i];
5475 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5476 if (deluxemaptexunit >= 0)
5477 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5478 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
5479 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
5482 Con_Printf(" %i", j - i);
5484 surface2 = texturesurfacelist[j-1];
5485 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
5486 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
5487 GL_LockArrays(surface->num_firstvertex, numvertices);
5488 R_Mesh_Draw(surface->num_firstvertex, numvertices, numtriangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
5496 for (i = 0;i < texturenumsurfaces;i++)
5498 surface = texturesurfacelist[i];
5499 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5500 if (deluxemaptexunit >= 0)
5501 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5502 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5503 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));
5508 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
5511 int texturesurfaceindex;
5512 if (r_showsurfaces.integer == 2)
5514 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5516 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5517 for (j = 0;j < surface->num_triangles;j++)
5519 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_refdef.view.colorscale;
5520 GL_Color(f, f, f, 1);
5521 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)));
5527 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5529 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5530 int k = (int)(((size_t)surface) / sizeof(msurface_t));
5531 GL_Color((k & 15) * (1.0f / 16.0f) * r_refdef.view.colorscale, ((k >> 4) & 15) * (1.0f / 16.0f) * r_refdef.view.colorscale, ((k >> 8) & 15) * (1.0f / 16.0f) * r_refdef.view.colorscale, 1);
5532 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5533 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));
5538 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, msurface_t **texturesurfacelist)
5540 int texturesurfaceindex;
5544 if (rsurface.lightmapcolor4f)
5546 // generate color arrays for the surfaces in this list
5547 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5549 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5550 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)
5552 f = FogPoint_Model(v);
5562 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5564 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5565 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)
5567 f = FogPoint_Model(v);
5575 rsurface.lightmapcolor4f = rsurface.array_color4f;
5576 rsurface.lightmapcolor4f_bufferobject = 0;
5577 rsurface.lightmapcolor4f_bufferoffset = 0;
5580 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a)
5582 int texturesurfaceindex;
5585 if (!rsurface.lightmapcolor4f)
5587 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5589 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5590 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)
5598 rsurface.lightmapcolor4f = rsurface.array_color4f;
5599 rsurface.lightmapcolor4f_bufferobject = 0;
5600 rsurface.lightmapcolor4f_bufferoffset = 0;
5603 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5606 rsurface.lightmapcolor4f = NULL;
5607 rsurface.lightmapcolor4f_bufferobject = 0;
5608 rsurface.lightmapcolor4f_bufferoffset = 0;
5609 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5610 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5611 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5612 GL_Color(r, g, b, a);
5613 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 0, -1);
5616 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5618 // TODO: optimize applyfog && applycolor case
5619 // just apply fog if necessary, and tint the fog color array if necessary
5620 rsurface.lightmapcolor4f = NULL;
5621 rsurface.lightmapcolor4f_bufferobject = 0;
5622 rsurface.lightmapcolor4f_bufferoffset = 0;
5623 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5624 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5625 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5626 GL_Color(r, g, b, a);
5627 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5630 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5632 int texturesurfaceindex;
5636 if (texturesurfacelist[0]->lightmapinfo && texturesurfacelist[0]->lightmapinfo->stainsamples)
5638 // generate color arrays for the surfaces in this list
5639 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5641 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5642 for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
5644 if (surface->lightmapinfo->samples)
5646 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
5647 float scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
5648 VectorScale(lm, scale, c);
5649 if (surface->lightmapinfo->styles[1] != 255)
5651 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
5653 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
5654 VectorMA(c, scale, lm, c);
5655 if (surface->lightmapinfo->styles[2] != 255)
5658 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
5659 VectorMA(c, scale, lm, c);
5660 if (surface->lightmapinfo->styles[3] != 255)
5663 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
5664 VectorMA(c, scale, lm, c);
5674 rsurface.lightmapcolor4f = rsurface.array_color4f;
5675 rsurface.lightmapcolor4f_bufferobject = 0;
5676 rsurface.lightmapcolor4f_bufferoffset = 0;
5680 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
5681 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
5682 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
5684 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5685 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5686 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5687 GL_Color(r, g, b, a);
5688 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5691 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5693 int texturesurfaceindex;
5697 vec3_t ambientcolor;
5698 vec3_t diffusecolor;
5702 VectorCopy(rsurface.modellight_lightdir, lightdir);
5703 f = 0.5f * r_refdef.lightmapintensity;
5704 ambientcolor[0] = rsurface.modellight_ambient[0] * r * f;
5705 ambientcolor[1] = rsurface.modellight_ambient[1] * g * f;
5706 ambientcolor[2] = rsurface.modellight_ambient[2] * b * f;
5707 diffusecolor[0] = rsurface.modellight_diffuse[0] * r * f;
5708 diffusecolor[1] = rsurface.modellight_diffuse[1] * g * f;
5709 diffusecolor[2] = rsurface.modellight_diffuse[2] * b * f;
5710 if (VectorLength2(diffusecolor) > 0)
5712 // generate color arrays for the surfaces in this list
5713 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5715 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5716 int numverts = surface->num_vertices;
5717 v = rsurface.vertex3f + 3 * surface->num_firstvertex;
5718 c2 = rsurface.normal3f + 3 * surface->num_firstvertex;
5719 c = rsurface.array_color4f + 4 * surface->num_firstvertex;
5720 // q3-style directional shading
5721 for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
5723 if ((f = DotProduct(c2, lightdir)) > 0)
5724 VectorMA(ambientcolor, f, diffusecolor, c);
5726 VectorCopy(ambientcolor, c);
5735 rsurface.lightmapcolor4f = rsurface.array_color4f;
5736 rsurface.lightmapcolor4f_bufferobject = 0;
5737 rsurface.lightmapcolor4f_bufferoffset = 0;
5741 r = ambientcolor[0];
5742 g = ambientcolor[1];
5743 b = ambientcolor[2];
5744 rsurface.lightmapcolor4f = NULL;
5745 rsurface.lightmapcolor4f_bufferobject = 0;
5746 rsurface.lightmapcolor4f_bufferoffset = 0;
5748 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5749 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5750 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5751 GL_Color(r, g, b, a);
5752 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5755 void RSurf_SetupDepthAndCulling(void)
5757 // submodels are biased to avoid z-fighting with world surfaces that they
5758 // may be exactly overlapping (avoids z-fighting artifacts on certain
5759 // doors and things in Quake maps)
5760 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5761 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
5762 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
5763 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
5766 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, msurface_t **texturesurfacelist)
5768 // transparent sky would be ridiculous
5769 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
5771 R_SetupGenericShader(false);
5774 skyrendernow = false;
5775 // we have to force off the water clipping plane while rendering sky
5779 // restore entity matrix
5780 R_Mesh_Matrix(&rsurface.matrix);
5782 RSurf_SetupDepthAndCulling();
5784 // LordHavoc: HalfLife maps have freaky skypolys so don't use
5785 // skymasking on them, and Quake3 never did sky masking (unlike
5786 // software Quake and software Quake2), so disable the sky masking
5787 // in Quake3 maps as it causes problems with q3map2 sky tricks,
5788 // and skymasking also looks very bad when noclipping outside the
5789 // level, so don't use it then either.
5790 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
5792 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
5793 R_Mesh_ColorPointer(NULL, 0, 0);
5794 R_Mesh_ResetTextureState();
5795 if (skyrendermasked)
5797 R_SetupDepthOrShadowShader();
5798 // depth-only (masking)
5799 GL_ColorMask(0,0,0,0);
5800 // just to make sure that braindead drivers don't draw
5801 // anything despite that colormask...
5802 GL_BlendFunc(GL_ZERO, GL_ONE);
5806 R_SetupGenericShader(false);
5808 GL_BlendFunc(GL_ONE, GL_ZERO);
5810 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
5811 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5812 if (skyrendermasked)
5813 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5815 R_Mesh_ResetTextureState();
5816 GL_Color(1, 1, 1, 1);
5819 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
5821 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION)))
5824 R_Mesh_TexMatrix(0, &rsurface.texture->currenttexmatrix);
5825 R_Mesh_TexBind(GL20TU_NORMAL, R_GetTexture(rsurface.texture->currentskinframe->nmap));
5826 R_Mesh_TexBind(GL20TU_COLOR, R_GetTexture(rsurface.texture->basetexture));
5827 R_Mesh_TexBind(GL20TU_GLOSS, R_GetTexture(rsurface.texture->glosstexture));
5828 R_Mesh_TexBind(GL20TU_GLOW, R_GetTexture(rsurface.texture->currentskinframe->glow));
5829 if (rsurface.texture->backgroundcurrentskinframe)
5831 R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->nmap));
5832 R_Mesh_TexBind(GL20TU_SECONDARY_COLOR, R_GetTexture(rsurface.texture->backgroundbasetexture));
5833 R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS, R_GetTexture(rsurface.texture->backgroundglosstexture));
5834 R_Mesh_TexBind(GL20TU_SECONDARY_GLOW, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->glow));
5836 R_Mesh_TexBind(GL20TU_PANTS, R_GetTexture(rsurface.texture->currentskinframe->pants));
5837 R_Mesh_TexBind(GL20TU_SHIRT, R_GetTexture(rsurface.texture->currentskinframe->shirt));
5838 R_Mesh_TexBind(GL20TU_FOGMASK, R_GetTexture(r_texture_fogattenuation));
5839 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
5840 R_Mesh_ColorPointer(NULL, 0, 0);
5842 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
5844 if (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5846 // render background
5847 GL_BlendFunc(GL_ONE, GL_ZERO);
5849 GL_AlphaTest(false);
5851 GL_Color(1, 1, 1, 1);
5852 R_Mesh_ColorPointer(NULL, 0, 0);
5854 R_SetupSurfaceShader(vec3_origin, rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
5855 if (r_glsl_permutation)
5857 RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
5858 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
5859 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
5860 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
5861 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
5862 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
5863 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist, -1, -1, r_glsl_permutation->loc_Texture_Refraction >= 0 ? GL20TU_REFRACTION : -1, r_glsl_permutation->loc_Texture_Reflection >= 0 ? GL20TU_REFLECTION : -1);
5865 GL_LockArrays(0, 0);
5867 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5868 GL_DepthMask(false);
5869 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
5870 R_Mesh_ColorPointer(NULL, 0, 0);
5872 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
5873 R_Mesh_TexBind(GL20TU_REFRACTION, R_GetTexture(r_texture_white)); // changed per surface
5874 R_Mesh_TexBind(GL20TU_REFLECTION, R_GetTexture(r_texture_white)); // changed per surface
5877 R_SetupSurfaceShader(vec3_origin, rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE);
5878 if (!r_glsl_permutation)
5881 RSurf_PrepareVerticesForBatch(r_glsl_permutation->loc_Texture_Normal >= 0 || r_glsl_permutation->loc_LightDir >= 0, r_glsl_permutation->loc_Texture_Normal >= 0, texturenumsurfaces, texturesurfacelist);
5882 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
5883 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
5884 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
5885 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
5886 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
5888 if (r_glsl_permutation->loc_Texture_Refraction >= 0)
5890 GL_BlendFunc(GL_ONE, GL_ZERO);
5892 GL_AlphaTest(false);
5896 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5897 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
5898 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5901 if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
5903 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
5904 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist, GL20TU_LIGHTMAP, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? GL20TU_DELUXEMAP : -1, r_glsl_permutation->loc_Texture_Refraction >= 0 ? GL20TU_REFRACTION : -1, r_glsl_permutation->loc_Texture_Reflection >= 0 ? GL20TU_REFLECTION : -1);
5906 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, GL20TU_LIGHTMAP, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? GL20TU_DELUXEMAP : -1);
5910 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
5911 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist, -1, -1, r_glsl_permutation->loc_Texture_Refraction >= 0 ? GL20TU_REFRACTION : -1, r_glsl_permutation->loc_Texture_Reflection >= 0 ? GL20TU_REFLECTION : -1);
5913 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5915 GL_LockArrays(0, 0);
5918 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
5920 // OpenGL 1.3 path - anything not completely ancient
5921 int texturesurfaceindex;
5922 qboolean applycolor;
5926 const texturelayer_t *layer;
5927 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
5929 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
5932 int layertexrgbscale;
5933 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5935 if (layerindex == 0)
5939 GL_AlphaTest(false);
5940 qglDepthFunc(GL_EQUAL);CHECKGLERROR
5943 GL_DepthMask(layer->depthmask && writedepth);
5944 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
5945 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
5947 layertexrgbscale = 4;
5948 VectorScale(layer->color, 0.25f, layercolor);
5950 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
5952 layertexrgbscale = 2;
5953 VectorScale(layer->color, 0.5f, layercolor);
5957 layertexrgbscale = 1;
5958 VectorScale(layer->color, 1.0f, layercolor);
5960 layercolor[3] = layer->color[3];
5961 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
5962 R_Mesh_ColorPointer(NULL, 0, 0);
5963 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
5964 switch (layer->type)
5966 case TEXTURELAYERTYPE_LITTEXTURE:
5967 memset(&m, 0, sizeof(m));
5968 m.tex[0] = R_GetTexture(r_texture_white);
5969 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
5970 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
5971 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
5972 m.tex[1] = R_GetTexture(layer->texture);
5973 m.texmatrix[1] = layer->texmatrix;
5974 m.texrgbscale[1] = layertexrgbscale;
5975 m.pointer_texcoord[1] = rsurface.texcoordtexture2f;
5976 m.pointer_texcoord_bufferobject[1] = rsurface.texcoordtexture2f_bufferobject;
5977 m.pointer_texcoord_bufferoffset[1] = rsurface.texcoordtexture2f_bufferoffset;
5978 R_Mesh_TextureState(&m);
5979 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
5980 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
5981 else if (rsurface.uselightmaptexture)
5982 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
5984 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
5986 case TEXTURELAYERTYPE_TEXTURE:
5987 memset(&m, 0, sizeof(m));
5988 m.tex[0] = R_GetTexture(layer->texture);
5989 m.texmatrix[0] = layer->texmatrix;
5990 m.texrgbscale[0] = layertexrgbscale;
5991 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5992 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5993 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5994 R_Mesh_TextureState(&m);
5995 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
5997 case TEXTURELAYERTYPE_FOG:
5998 memset(&m, 0, sizeof(m));
5999 m.texrgbscale[0] = layertexrgbscale;
6002 m.tex[0] = R_GetTexture(layer->texture);
6003 m.texmatrix[0] = layer->texmatrix;
6004 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6005 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6006 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6008 R_Mesh_TextureState(&m);
6009 // generate a color array for the fog pass
6010 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
6011 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6015 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6016 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)
6018 f = 1 - FogPoint_Model(v);
6019 c[0] = layercolor[0];
6020 c[1] = layercolor[1];
6021 c[2] = layercolor[2];
6022 c[3] = f * layercolor[3];
6025 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6028 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
6030 GL_LockArrays(0, 0);
6033 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
6035 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
6036 GL_AlphaTest(false);
6040 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6042 // OpenGL 1.1 - crusty old voodoo path
6043 int texturesurfaceindex;
6047 const texturelayer_t *layer;
6048 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
6050 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
6052 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
6054 if (layerindex == 0)
6058 GL_AlphaTest(false);
6059 qglDepthFunc(GL_EQUAL);CHECKGLERROR
6062 GL_DepthMask(layer->depthmask && writedepth);
6063 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
6064 R_Mesh_ColorPointer(NULL, 0, 0);
6065 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
6066 switch (layer->type)
6068 case TEXTURELAYERTYPE_LITTEXTURE:
6069 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
6071 // two-pass lit texture with 2x rgbscale
6072 // first the lightmap pass
6073 memset(&m, 0, sizeof(m));
6074 m.tex[0] = R_GetTexture(r_texture_white);
6075 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
6076 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
6077 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
6078 R_Mesh_TextureState(&m);
6079 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
6080 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
6081 else if (rsurface.uselightmaptexture)
6082 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
6084 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
6085 GL_LockArrays(0, 0);
6086 // then apply the texture to it
6087 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
6088 memset(&m, 0, sizeof(m));
6089 m.tex[0] = R_GetTexture(layer->texture);
6090 m.texmatrix[0] = layer->texmatrix;
6091 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6092 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6093 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6094 R_Mesh_TextureState(&m);
6095 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);
6099 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
6100 memset(&m, 0, sizeof(m));
6101 m.tex[0] = R_GetTexture(layer->texture);
6102 m.texmatrix[0] = layer->texmatrix;
6103 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6104 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6105 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6106 R_Mesh_TextureState(&m);
6107 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
6108 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);
6110 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);
6113 case TEXTURELAYERTYPE_TEXTURE:
6114 // singletexture unlit texture with transparency support
6115 memset(&m, 0, sizeof(m));
6116 m.tex[0] = R_GetTexture(layer->texture);
6117 m.texmatrix[0] = layer->texmatrix;
6118 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6119 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6120 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6121 R_Mesh_TextureState(&m);
6122 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);
6124 case TEXTURELAYERTYPE_FOG:
6125 // singletexture fogging
6126 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
6129 memset(&m, 0, sizeof(m));
6130 m.tex[0] = R_GetTexture(layer->texture);
6131 m.texmatrix[0] = layer->texmatrix;
6132 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6133 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6134 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6135 R_Mesh_TextureState(&m);
6138 R_Mesh_ResetTextureState();
6139 // generate a color array for the fog pass
6140 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6144 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6145 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)
6147 f = 1 - FogPoint_Model(v);
6148 c[0] = layer->color[0];
6149 c[1] = layer->color[1];
6150 c[2] = layer->color[2];
6151 c[3] = f * layer->color[3];
6154 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6157 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
6159 GL_LockArrays(0, 0);
6162 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
6164 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
6165 GL_AlphaTest(false);
6169 static void R_DrawTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6172 RSurf_SetupDepthAndCulling();
6173 if (r_glsl.integer && gl_support_fragment_shader)
6174 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth);
6175 else if (gl_combine.integer && r_textureunits.integer >= 2)
6176 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
6178 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
6182 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6185 int texturenumsurfaces, endsurface;
6187 msurface_t *surface;
6188 msurface_t *texturesurfacelist[1024];
6190 // if the model is static it doesn't matter what value we give for
6191 // wantnormals and wanttangents, so this logic uses only rules applicable
6192 // to a model, knowing that they are meaningless otherwise
6193 if (ent == r_refdef.scene.worldentity)
6194 RSurf_ActiveWorldEntity();
6195 else if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
6196 RSurf_ActiveModelEntity(ent, false, false);
6198 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
6200 for (i = 0;i < numsurfaces;i = j)
6203 surface = rsurface.modelsurfaces + surfacelist[i];
6204 texture = surface->texture;
6205 R_UpdateTextureInfo(ent, texture);
6206 rsurface.texture = texture->currentframe;
6207 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
6208 // scan ahead until we find a different texture
6209 endsurface = min(i + 1024, numsurfaces);
6210 texturenumsurfaces = 0;
6211 texturesurfacelist[texturenumsurfaces++] = surface;
6212 for (;j < endsurface;j++)
6214 surface = rsurface.modelsurfaces + surfacelist[j];
6215 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
6217 texturesurfacelist[texturenumsurfaces++] = surface;
6219 // render the range of surfaces
6220 R_DrawTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false);
6222 GL_AlphaTest(false);
6225 static void R_ProcessTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity)
6230 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
6232 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
6234 RSurf_SetupDepthAndCulling();
6235 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6236 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6238 else if (r_showsurfaces.integer)
6240 RSurf_SetupDepthAndCulling();
6242 GL_BlendFunc(GL_ONE, GL_ZERO);
6244 GL_AlphaTest(false);
6245 R_Mesh_ColorPointer(NULL, 0, 0);
6246 R_Mesh_ResetTextureState();
6247 R_SetupGenericShader(false);
6248 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6249 if (!r_refdef.view.showdebug)
6251 GL_Color(0, 0, 0, 1);
6252 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6255 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
6257 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
6258 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
6259 else if (!rsurface.texture->currentnumlayers)
6261 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) && queueentity)
6263 // transparent surfaces get pushed off into the transparent queue
6264 int surfacelistindex;
6265 const msurface_t *surface;
6266 vec3_t tempcenter, center;
6267 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
6269 surface = texturesurfacelist[surfacelistindex];
6270 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
6271 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
6272 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
6273 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
6274 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
6279 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
6280 R_DrawTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST));
6285 void R_QueueSurfaceList(entity_render_t *ent, int numsurfaces, msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes)
6289 // if we're rendering water textures (extra scene renders), use a separate loop to avoid burdening the main one
6292 for (i = 0;i < numsurfaces;i++)
6293 if (surfacelist[i]->texture->currentframe->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION))
6294 R_Water_AddWaterPlane(surfacelist[i]);
6297 // break the surface list down into batches by texture and use of lightmapping
6298 for (i = 0;i < numsurfaces;i = j)
6301 // texture is the base texture pointer, rsurface.texture is the
6302 // current frame/skin the texture is directing us to use (for example
6303 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
6304 // use skin 1 instead)
6305 texture = surfacelist[i]->texture;
6306 rsurface.texture = texture->currentframe;
6307 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
6308 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
6310 // if this texture is not the kind we want, skip ahead to the next one
6311 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
6315 // simply scan ahead until we find a different texture or lightmap state
6316 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
6318 // render the range of surfaces
6319 R_ProcessTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent);
6323 float locboxvertex3f[6*4*3] =
6325 1,0,1, 1,0,0, 1,1,0, 1,1,1,
6326 0,1,1, 0,1,0, 0,0,0, 0,0,1,
6327 1,1,1, 1,1,0, 0,1,0, 0,1,1,
6328 0,0,1, 0,0,0, 1,0,0, 1,0,1,
6329 0,0,1, 1,0,1, 1,1,1, 0,1,1,
6330 1,0,0, 0,0,0, 0,1,0, 1,1,0
6333 int locboxelement3i[6*2*3] =
6343 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6346 cl_locnode_t *loc = (cl_locnode_t *)ent;
6348 float vertex3f[6*4*3];
6350 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6351 GL_DepthMask(false);
6352 GL_DepthRange(0, 1);
6353 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6355 GL_CullFace(GL_NONE);
6356 R_Mesh_Matrix(&identitymatrix);
6358 R_Mesh_VertexPointer(vertex3f, 0, 0);
6359 R_Mesh_ColorPointer(NULL, 0, 0);
6360 R_Mesh_ResetTextureState();
6361 R_SetupGenericShader(false);
6364 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
6365 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
6366 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
6367 surfacelist[0] < 0 ? 0.5f : 0.125f);
6369 if (VectorCompare(loc->mins, loc->maxs))
6371 VectorSet(size, 2, 2, 2);
6372 VectorMA(loc->mins, -0.5f, size, mins);
6376 VectorCopy(loc->mins, mins);
6377 VectorSubtract(loc->maxs, loc->mins, size);
6380 for (i = 0;i < 6*4*3;)
6381 for (j = 0;j < 3;j++, i++)
6382 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
6384 R_Mesh_Draw(0, 6*4, 6*2, locboxelement3i, 0, 0);
6387 void R_DrawLocs(void)
6390 cl_locnode_t *loc, *nearestloc;
6392 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
6393 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
6395 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
6396 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
6400 void R_DrawDebugModel(entity_render_t *ent)
6402 int i, j, k, l, flagsmask;
6403 const int *elements;
6405 msurface_t *surface;
6406 model_t *model = ent->model;
6409 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WATER | MATERIALFLAG_WALL;
6411 R_Mesh_ColorPointer(NULL, 0, 0);
6412 R_Mesh_ResetTextureState();
6413 R_SetupGenericShader(false);
6414 GL_DepthRange(0, 1);
6415 GL_DepthTest(!r_showdisabledepthtest.integer);
6416 GL_DepthMask(false);
6417 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6419 if (r_showcollisionbrushes.value > 0 && model->brush.num_brushes)
6421 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
6422 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
6424 if (brush->colbrushf && brush->colbrushf->numtriangles)
6426 R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
6427 GL_Color((i & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((i >> 5) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((i >> 10) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, r_showcollisionbrushes.value);
6428 R_Mesh_Draw(0, brush->colbrushf->numpoints, brush->colbrushf->numtriangles, brush->colbrushf->elements, 0, 0);
6431 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
6433 if (surface->num_collisiontriangles)
6435 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
6436 GL_Color((i & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((i >> 5) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((i >> 10) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, r_showcollisionbrushes.value);
6437 R_Mesh_Draw(0, surface->num_collisionvertices, surface->num_collisiontriangles, surface->data_collisionelement3i, 0, 0);
6442 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6444 if (r_showtris.integer || r_shownormals.integer)
6446 if (r_showdisabledepthtest.integer)
6448 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6449 GL_DepthMask(false);
6453 GL_BlendFunc(GL_ONE, GL_ZERO);
6456 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
6458 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
6460 rsurface.texture = surface->texture->currentframe;
6461 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
6463 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
6464 if (r_showtris.value > 0)
6466 if (!rsurface.texture->currentlayers->depthmask)
6467 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
6468 else if (ent == r_refdef.scene.worldentity)
6469 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
6471 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
6472 elements = (ent->model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
6475 for (k = 0;k < surface->num_triangles;k++, elements += 3)
6477 #define GLVERTEXELEMENT(n) qglVertex3f(rsurface.vertex3f[elements[n]*3+0], rsurface.vertex3f[elements[n]*3+1], rsurface.vertex3f[elements[n]*3+2])
6478 GLVERTEXELEMENT(0);GLVERTEXELEMENT(1);
6479 GLVERTEXELEMENT(1);GLVERTEXELEMENT(2);
6480 GLVERTEXELEMENT(2);GLVERTEXELEMENT(0);
6485 if (r_shownormals.value > 0)
6488 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
6490 VectorCopy(rsurface.vertex3f + l * 3, v);
6491 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
6492 qglVertex3f(v[0], v[1], v[2]);
6493 VectorMA(v, r_shownormals.value, rsurface.svector3f + l * 3, v);
6494 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
6495 qglVertex3f(v[0], v[1], v[2]);
6500 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
6502 VectorCopy(rsurface.vertex3f + l * 3, v);
6503 GL_Color(0, r_refdef.view.colorscale, 0, 1);
6504 qglVertex3f(v[0], v[1], v[2]);
6505 VectorMA(v, r_shownormals.value, rsurface.tvector3f + l * 3, v);
6506 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
6507 qglVertex3f(v[0], v[1], v[2]);
6512 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
6514 VectorCopy(rsurface.vertex3f + l * 3, v);
6515 GL_Color(0, 0, r_refdef.view.colorscale, 1);
6516 qglVertex3f(v[0], v[1], v[2]);
6517 VectorMA(v, r_shownormals.value, rsurface.normal3f + l * 3, v);
6518 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
6519 qglVertex3f(v[0], v[1], v[2]);
6526 rsurface.texture = NULL;
6530 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
6531 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes, qboolean debug)
6533 int i, j, endj, f, flagsmask;
6534 msurface_t *surface;
6536 model_t *model = r_refdef.scene.worldmodel;
6537 const int maxsurfacelist = 1024;
6538 int numsurfacelist = 0;
6539 msurface_t *surfacelist[1024];
6543 RSurf_ActiveWorldEntity();
6545 // update light styles on this submodel
6546 if (!skysurfaces && !depthonly && !addwaterplanes && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
6548 model_brush_lightstyleinfo_t *style;
6549 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
6551 if (style->value != r_refdef.scene.lightstylevalue[style->style])
6553 msurface_t *surfaces = model->data_surfaces;
6554 int *list = style->surfacelist;
6555 style->value = r_refdef.scene.lightstylevalue[style->style];
6556 for (j = 0;j < style->numsurfaces;j++)
6557 surfaces[list[j]].cached_dlight = true;
6562 R_UpdateAllTextureInfo(r_refdef.scene.worldentity);
6563 flagsmask = addwaterplanes ? (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) : (skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL));
6567 R_DrawDebugModel(r_refdef.scene.worldentity);
6573 rsurface.uselightmaptexture = false;
6574 rsurface.texture = NULL;
6575 rsurface.rtlight = NULL;
6577 j = model->firstmodelsurface;
6578 endj = j + model->nummodelsurfaces;
6581 // quickly skip over non-visible surfaces
6582 for (;j < endj && !r_refdef.viewcache.world_surfacevisible[j];j++)
6584 // quickly iterate over visible surfaces
6585 for (;j < endj && r_refdef.viewcache.world_surfacevisible[j];j++)
6587 // process this surface
6588 surface = model->data_surfaces + j;
6589 // if this surface fits the criteria, add it to the list
6590 if (surface->num_triangles)
6592 // if lightmap parameters changed, rebuild lightmap texture
6593 if (surface->cached_dlight)
6594 R_BuildLightMap(r_refdef.scene.worldentity, surface);
6595 // add face to draw list
6596 surfacelist[numsurfacelist++] = surface;
6597 r_refdef.stats.world_triangles += surface->num_triangles;
6598 if (numsurfacelist >= maxsurfacelist)
6600 r_refdef.stats.world_surfaces += numsurfacelist;
6601 R_QueueSurfaceList(r_refdef.scene.worldentity, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
6607 r_refdef.stats.world_surfaces += numsurfacelist;
6609 R_QueueSurfaceList(r_refdef.scene.worldentity, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
6610 GL_AlphaTest(false);
6613 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes, qboolean debug)
6615 int i, j, f, flagsmask;
6616 msurface_t *surface, *endsurface;
6618 model_t *model = ent->model;
6619 const int maxsurfacelist = 1024;
6620 int numsurfacelist = 0;
6621 msurface_t *surfacelist[1024];
6625 // if the model is static it doesn't matter what value we give for
6626 // wantnormals and wanttangents, so this logic uses only rules applicable
6627 // to a model, knowing that they are meaningless otherwise
6628 if (ent == r_refdef.scene.worldentity)
6629 RSurf_ActiveWorldEntity();
6630 else if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
6631 RSurf_ActiveModelEntity(ent, false, false);
6633 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader && !depthonly);
6635 // update light styles
6636 if (!skysurfaces && !depthonly && !addwaterplanes && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
6638 model_brush_lightstyleinfo_t *style;
6639 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
6641 if (style->value != r_refdef.scene.lightstylevalue[style->style])
6643 msurface_t *surfaces = model->data_surfaces;
6644 int *list = style->surfacelist;
6645 style->value = r_refdef.scene.lightstylevalue[style->style];
6646 for (j = 0;j < style->numsurfaces;j++)
6647 surfaces[list[j]].cached_dlight = true;
6652 R_UpdateAllTextureInfo(ent);
6653 flagsmask = addwaterplanes ? (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) : (skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL));
6657 R_DrawDebugModel(ent);
6663 rsurface.uselightmaptexture = false;
6664 rsurface.texture = NULL;
6665 rsurface.rtlight = NULL;
6667 surface = model->data_surfaces + model->firstmodelsurface;
6668 endsurface = surface + model->nummodelsurfaces;
6669 for (;surface < endsurface;surface++)
6671 // if this surface fits the criteria, add it to the list
6672 if (surface->num_triangles)
6674 // if lightmap parameters changed, rebuild lightmap texture
6675 if (surface->cached_dlight)
6676 R_BuildLightMap(ent, surface);
6677 // add face to draw list
6678 surfacelist[numsurfacelist++] = surface;
6679 r_refdef.stats.entities_triangles += surface->num_triangles;
6680 if (numsurfacelist >= maxsurfacelist)
6682 r_refdef.stats.entities_surfaces += numsurfacelist;
6683 R_QueueSurfaceList(ent, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
6688 r_refdef.stats.entities_surfaces += numsurfacelist;
6690 R_QueueSurfaceList(ent, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
6691 GL_AlphaTest(false);