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;
31 static int r_frame = 0; ///< used only by R_GetCurrentTexture
38 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "motionblur value scale - 0.5 recommended"};
39 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "motionblur based on damage"};
40 cvar_t r_motionblur_vmin = {CVAR_SAVE, "r_motionblur_vmin", "300", "minimum influence from velocity"};
41 cvar_t r_motionblur_vmax = {CVAR_SAVE, "r_motionblur_vmax", "600", "maximum influence from velocity"};
42 cvar_t r_motionblur_bmin = {CVAR_SAVE, "r_motionblur_bmin", "0.5", "velocity at which there is no blur yet (may be negative to always have some blur)"};
43 cvar_t r_motionblur_vcoeff = {CVAR_SAVE, "r_motionblur_vcoeff", "0.05", "sliding average reaction time for velocity"};
44 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.88", "cap for motionblur alpha value"};
45 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
47 cvar_t r_animcache = {CVAR_SAVE, "r_animcache", "1", "cache animation frames to save CPU usage, primarily optimizes shadows and reflections"};
49 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "0", "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"};
50 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
51 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
52 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%, 10 = 100%)"};
53 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)"};
54 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
55 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
56 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"};
57 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"};
58 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
59 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"};
60 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"};
61 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"};
62 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
63 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
64 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
65 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
66 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling"};
67 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
68 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
69 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
70 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
71 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
72 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
73 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
74 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this); when set to 2, always cast the shadows in the direction set by r_shadows_throwdirection, otherwise use the model lighting."};
75 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
76 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
77 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
78 cvar_t r_shadows_drawafterrtlightning = {CVAR_SAVE, "r_shadows_drawafterrtlightning", "0", "draw fake shadows AFTER realtime lightning is drawn. May be useful for simulating fast sunlight on large outdoor maps with only one noshadow rtlight. The price is less realistic appearance of dynamic light shadows."};
79 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
80 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
81 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"};
82 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"};
83 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
84 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
86 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
87 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
88 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
89 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
90 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
91 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
92 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
93 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
95 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)"};
97 cvar_t r_glsl = {CVAR_SAVE, "r_glsl", "1", "enables use of OpenGL 2.0 pixel shaders for lighting"};
98 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)"};
99 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
100 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
101 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
102 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
103 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)"};
104 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)"};
105 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)"};
106 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)"};
107 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)"};
109 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)"};
110 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
111 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"};
112 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
113 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
115 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1", "enables animation smoothing on sprites"};
116 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
117 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
118 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
120 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
121 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
122 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
123 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
124 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
125 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
126 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
128 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
129 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
130 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
131 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)"};
133 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"};
135 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"};
137 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
139 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
140 cvar_t r_batchmode = {0, "r_batchmode", "1", "selects method of rendering multiple surfaces with one driver call (values are 0, 1, 2, etc...)"};
141 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"};
142 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accodringly, 2: Make it a continuous rotation"};
143 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
144 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
145 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
147 extern cvar_t v_glslgamma;
149 extern qboolean v_flipped_state;
151 static struct r_bloomstate_s
156 int bloomwidth, bloomheight;
158 int screentexturewidth, screentextureheight;
159 rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
161 int bloomtexturewidth, bloomtextureheight;
162 rtexture_t *texture_bloom;
164 // arrays for rendering the screen passes
165 float screentexcoord2f[8];
166 float bloomtexcoord2f[8];
167 float offsettexcoord2f[8];
171 r_waterstate_t r_waterstate;
173 /// shadow volume bsp struct with automatically growing nodes buffer
176 rtexture_t *r_texture_blanknormalmap;
177 rtexture_t *r_texture_white;
178 rtexture_t *r_texture_grey128;
179 rtexture_t *r_texture_black;
180 rtexture_t *r_texture_notexture;
181 rtexture_t *r_texture_whitecube;
182 rtexture_t *r_texture_normalizationcube;
183 rtexture_t *r_texture_fogattenuation;
184 rtexture_t *r_texture_gammaramps;
185 unsigned int r_texture_gammaramps_serial;
186 //rtexture_t *r_texture_fogintensity;
188 unsigned int r_queries[R_MAX_OCCLUSION_QUERIES];
189 unsigned int r_numqueries;
190 unsigned int r_maxqueries;
192 char r_qwskincache[MAX_SCOREBOARD][MAX_QPATH];
193 skinframe_t *r_qwskincache_skinframe[MAX_SCOREBOARD];
195 /// vertex coordinates for a quad that covers the screen exactly
196 const static float r_screenvertex3f[12] =
204 extern void R_DrawModelShadows(void);
206 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
209 for (i = 0;i < verts;i++)
220 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
223 for (i = 0;i < verts;i++)
233 // FIXME: move this to client?
236 if (gamemode == GAME_NEHAHRA)
238 Cvar_Set("gl_fogenable", "0");
239 Cvar_Set("gl_fogdensity", "0.2");
240 Cvar_Set("gl_fogred", "0.3");
241 Cvar_Set("gl_foggreen", "0.3");
242 Cvar_Set("gl_fogblue", "0.3");
244 r_refdef.fog_density = 0;
245 r_refdef.fog_red = 0;
246 r_refdef.fog_green = 0;
247 r_refdef.fog_blue = 0;
248 r_refdef.fog_alpha = 1;
249 r_refdef.fog_start = 0;
250 r_refdef.fog_end = 0;
253 float FogForDistance(vec_t dist)
255 unsigned int fogmasktableindex = (unsigned int)(dist * r_refdef.fogmasktabledistmultiplier);
256 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
259 float FogPoint_World(const vec3_t p)
261 return FogForDistance(VectorDistance((p), r_refdef.view.origin));
264 float FogPoint_Model(const vec3_t p)
266 return FogForDistance(VectorDistance((p), rsurface.modelorg) * Matrix4x4_ScaleFromMatrix(&rsurface.matrix));
269 static void R_BuildBlankTextures(void)
271 unsigned char data[4];
272 data[2] = 128; // normal X
273 data[1] = 128; // normal Y
274 data[0] = 255; // normal Z
275 data[3] = 128; // height
276 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
281 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
286 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
291 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
294 static void R_BuildNoTexture(void)
297 unsigned char pix[16][16][4];
298 // this makes a light grey/dark grey checkerboard texture
299 for (y = 0;y < 16;y++)
301 for (x = 0;x < 16;x++)
303 if ((y < 8) ^ (x < 8))
319 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, NULL);
322 static void R_BuildWhiteCube(void)
324 unsigned char data[6*1*1*4];
325 memset(data, 255, sizeof(data));
326 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_CLAMP | TEXF_PERSISTENT, NULL);
329 static void R_BuildNormalizationCube(void)
333 vec_t s, t, intensity;
335 unsigned char data[6][NORMSIZE][NORMSIZE][4];
336 for (side = 0;side < 6;side++)
338 for (y = 0;y < NORMSIZE;y++)
340 for (x = 0;x < NORMSIZE;x++)
342 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
343 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
378 intensity = 127.0f / sqrt(DotProduct(v, v));
379 data[side][y][x][2] = (unsigned char)(128.0f + intensity * v[0]);
380 data[side][y][x][1] = (unsigned char)(128.0f + intensity * v[1]);
381 data[side][y][x][0] = (unsigned char)(128.0f + intensity * v[2]);
382 data[side][y][x][3] = 255;
386 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, &data[0][0][0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_CLAMP | TEXF_PERSISTENT, NULL);
389 static void R_BuildFogTexture(void)
393 unsigned char data1[FOGWIDTH][4];
394 //unsigned char data2[FOGWIDTH][4];
397 r_refdef.fogmasktable_start = r_refdef.fog_start;
398 r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
399 r_refdef.fogmasktable_range = r_refdef.fogrange;
400 r_refdef.fogmasktable_density = r_refdef.fog_density;
402 r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
403 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
405 d = (x * r - r_refdef.fogmasktable_start);
406 if(developer.integer >= 100)
407 Con_Printf("%f ", d);
409 if (r_fog_exp2.integer)
410 alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
412 alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
413 if(developer.integer >= 100)
414 Con_Printf(" : %f ", alpha);
415 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
416 if(developer.integer >= 100)
417 Con_Printf(" = %f\n", alpha);
418 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
421 for (x = 0;x < FOGWIDTH;x++)
423 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
428 //data2[x][0] = 255 - b;
429 //data2[x][1] = 255 - b;
430 //data2[x][2] = 255 - b;
433 if (r_texture_fogattenuation)
435 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, FOGWIDTH, 1);
436 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, FOGWIDTH, 1);
440 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);
441 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
445 static const char *builtinshaderstring =
446 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
447 "// written by Forest 'LordHavoc' Hale\n"
448 "#ifdef USESHADOWMAPRECT\n"
449 "#extension GL_ARB_texture_rectangle : enable\n"
451 "#ifdef USESHADOWMAPCUBE\n"
452 "#extension GL_EXT_gpu_shader4 : enable\n"
455 "// common definitions between vertex shader and fragment shader:\n"
457 "//#ifdef __GLSL_CG_DATA_TYPES\n"
458 "//# define myhalf half\n"
459 "//# define myhalf2 half2\n"
460 "//# define myhalf3 half3\n"
461 "//# define myhalf4 half4\n"
463 "# define myhalf float\n"
464 "# define myhalf2 vec2\n"
465 "# define myhalf3 vec3\n"
466 "# define myhalf4 vec4\n"
469 "#ifdef MODE_DEPTH_OR_SHADOW\n"
471 "# ifdef VERTEX_SHADER\n"
474 " gl_Position = ftransform();\n"
479 "#ifdef MODE_SHOWDEPTH\n"
480 "# ifdef VERTEX_SHADER\n"
483 " gl_Position = ftransform();\n"
484 " gl_FrontColor = vec4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
487 "# ifdef FRAGMENT_SHADER\n"
490 " gl_FragColor = gl_Color;\n"
494 "#else // !MODE_SHOWDEPTH\n"
496 "#ifdef MODE_POSTPROCESS\n"
497 "# ifdef VERTEX_SHADER\n"
500 " gl_FrontColor = gl_Color;\n"
501 " gl_Position = ftransform();\n"
502 " gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;\n"
504 " gl_TexCoord[1] = gl_TextureMatrix[1] * gl_MultiTexCoord1;\n"
508 "# ifdef FRAGMENT_SHADER\n"
510 "uniform sampler2D Texture_First;\n"
512 "uniform sampler2D Texture_Second;\n"
514 "#ifdef USEGAMMARAMPS\n"
515 "uniform sampler2D Texture_GammaRamps;\n"
517 "#ifdef USESATURATION\n"
518 "uniform float Saturation;\n"
520 "#ifdef USEVIEWTINT\n"
521 "uniform vec4 TintColor;\n"
523 "//uncomment these if you want to use them:\n"
524 "uniform vec4 UserVec1;\n"
525 "// uniform vec4 UserVec2;\n"
526 "// uniform vec4 UserVec3;\n"
527 "// uniform vec4 UserVec4;\n"
528 "// uniform float ClientTime;\n"
529 "uniform vec2 PixelSize;\n"
532 " gl_FragColor = texture2D(Texture_First, gl_TexCoord[0].xy);\n"
534 " gl_FragColor += texture2D(Texture_Second, gl_TexCoord[1].xy);\n"
536 "#ifdef USEVIEWTINT\n"
537 " gl_FragColor = mix(gl_FragColor, TintColor, TintColor.a);\n"
540 "#ifdef USEPOSTPROCESSING\n"
541 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
542 "// this code does a blur with the radius specified in the first component of r_glsl_postprocess_uservec1 and blends it using the second component\n"
543 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2(-0.987688, -0.156434)) * UserVec1.y;\n"
544 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2(-0.156434, -0.891007)) * UserVec1.y;\n"
545 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2( 0.891007, -0.453990)) * UserVec1.y;\n"
546 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2( 0.707107, 0.707107)) * UserVec1.y;\n"
547 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2(-0.453990, 0.891007)) * UserVec1.y;\n"
548 " gl_FragColor /= (1 + 5 * UserVec1.y);\n"
551 "#ifdef USESATURATION\n"
552 " //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
553 " myhalf y = dot(gl_FragColor.rgb, vec3(0.299, 0.587, 0.114));\n"
554 " //gl_FragColor = vec3(y) + (gl_FragColor.rgb - vec3(y)) * Saturation;\n"
555 " gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n" // TODO: test this on ATI
558 "#ifdef USEGAMMARAMPS\n"
559 " gl_FragColor.r = texture2D(Texture_GammaRamps, vec2(gl_FragColor.r, 0)).r;\n"
560 " gl_FragColor.g = texture2D(Texture_GammaRamps, vec2(gl_FragColor.g, 0)).g;\n"
561 " gl_FragColor.b = texture2D(Texture_GammaRamps, vec2(gl_FragColor.b, 0)).b;\n"
568 "#ifdef MODE_GENERIC\n"
569 "# ifdef VERTEX_SHADER\n"
572 " gl_FrontColor = gl_Color;\n"
573 "# ifdef USEDIFFUSE\n"
574 " gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;\n"
576 "# ifdef USESPECULAR\n"
577 " gl_TexCoord[1] = gl_TextureMatrix[1] * gl_MultiTexCoord1;\n"
579 " gl_Position = ftransform();\n"
582 "# ifdef FRAGMENT_SHADER\n"
584 "# ifdef USEDIFFUSE\n"
585 "uniform sampler2D Texture_First;\n"
587 "# ifdef USESPECULAR\n"
588 "uniform sampler2D Texture_Second;\n"
593 " gl_FragColor = gl_Color;\n"
594 "# ifdef USEDIFFUSE\n"
595 " gl_FragColor *= texture2D(Texture_First, gl_TexCoord[0].xy);\n"
598 "# ifdef USESPECULAR\n"
599 " vec4 tex2 = texture2D(Texture_Second, gl_TexCoord[1].xy);\n"
601 "# ifdef USECOLORMAPPING\n"
602 " gl_FragColor *= tex2;\n"
605 " gl_FragColor += tex2;\n"
607 "# ifdef USEVERTEXTEXTUREBLEND\n"
608 " gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
613 "#else // !MODE_GENERIC\n"
615 "varying vec2 TexCoord;\n"
616 "#ifdef USEVERTEXTEXTUREBLEND\n"
617 "varying vec2 TexCoord2;\n"
619 "varying vec2 TexCoordLightmap;\n"
621 "#ifdef MODE_LIGHTSOURCE\n"
622 "varying vec3 CubeVector;\n"
625 "#ifdef MODE_LIGHTSOURCE\n"
626 "varying vec3 LightVector;\n"
628 "#ifdef MODE_LIGHTDIRECTION\n"
629 "varying vec3 LightVector;\n"
632 "varying vec3 EyeVector;\n"
634 "varying vec3 EyeVectorModelSpace;\n"
637 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
638 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
639 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
641 "#ifdef MODE_WATER\n"
642 "varying vec4 ModelViewProjectionPosition;\n"
644 "#ifdef MODE_REFRACTION\n"
645 "varying vec4 ModelViewProjectionPosition;\n"
647 "#ifdef USEREFLECTION\n"
648 "varying vec4 ModelViewProjectionPosition;\n"
655 "// vertex shader specific:\n"
656 "#ifdef VERTEX_SHADER\n"
658 "uniform vec3 LightPosition;\n"
659 "uniform vec3 EyePosition;\n"
660 "uniform vec3 LightDir;\n"
662 "// 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"
666 " gl_FrontColor = gl_Color;\n"
667 " // copy the surface texcoord\n"
668 " TexCoord = vec2(gl_TextureMatrix[0] * gl_MultiTexCoord0);\n"
669 "#ifdef USEVERTEXTEXTUREBLEND\n"
670 " TexCoord2 = vec2(gl_TextureMatrix[1] * gl_MultiTexCoord0);\n"
672 "#ifndef MODE_LIGHTSOURCE\n"
673 "# ifndef MODE_LIGHTDIRECTION\n"
674 " TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
678 "#ifdef MODE_LIGHTSOURCE\n"
679 " // transform vertex position into light attenuation/cubemap space\n"
680 " // (-1 to +1 across the light box)\n"
681 " CubeVector = vec3(gl_TextureMatrix[3] * gl_Vertex);\n"
683 " // transform unnormalized light direction into tangent space\n"
684 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
685 " // normalize it per pixel)\n"
686 " vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
687 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
688 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
689 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
692 "#ifdef MODE_LIGHTDIRECTION\n"
693 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
694 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
695 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
698 " // transform unnormalized eye direction into tangent space\n"
700 " vec3 EyeVectorModelSpace;\n"
702 " EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
703 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
704 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
705 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
707 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
708 " VectorS = gl_MultiTexCoord1.xyz;\n"
709 " VectorT = gl_MultiTexCoord2.xyz;\n"
710 " VectorR = gl_MultiTexCoord3.xyz;\n"
713 "//#if defined(MODE_WATER) || defined(MODE_REFRACTION) || defined(USEREFLECTION)\n"
714 "// ModelViewProjectionPosition = gl_Vertex * gl_ModelViewProjectionMatrix;\n"
715 "// //ModelViewProjectionPosition_svector = (gl_Vertex + vec4(gl_MultiTexCoord1.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
716 "// //ModelViewProjectionPosition_tvector = (gl_Vertex + vec4(gl_MultiTexCoord2.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
719 "// transform vertex to camera space, using ftransform to match non-VS\n"
721 " gl_Position = ftransform();\n"
723 "#ifdef MODE_WATER\n"
724 " ModelViewProjectionPosition = gl_Position;\n"
726 "#ifdef MODE_REFRACTION\n"
727 " ModelViewProjectionPosition = gl_Position;\n"
729 "#ifdef USEREFLECTION\n"
730 " ModelViewProjectionPosition = gl_Position;\n"
734 "#endif // VERTEX_SHADER\n"
739 "// fragment shader specific:\n"
740 "#ifdef FRAGMENT_SHADER\n"
742 "// 13 textures, we can only use up to 16 on DX9-class hardware\n"
743 "uniform sampler2D Texture_Normal;\n"
744 "uniform sampler2D Texture_Color;\n"
745 "uniform sampler2D Texture_Gloss;\n"
746 "uniform sampler2D Texture_Glow;\n"
747 "uniform sampler2D Texture_SecondaryNormal;\n"
748 "uniform sampler2D Texture_SecondaryColor;\n"
749 "uniform sampler2D Texture_SecondaryGloss;\n"
750 "uniform sampler2D Texture_SecondaryGlow;\n"
751 "uniform sampler2D Texture_Pants;\n"
752 "uniform sampler2D Texture_Shirt;\n"
753 "uniform sampler2D Texture_FogMask;\n"
754 "uniform sampler2D Texture_Lightmap;\n"
755 "uniform sampler2D Texture_Deluxemap;\n"
756 "uniform sampler2D Texture_Refraction;\n"
757 "uniform sampler2D Texture_Reflection;\n"
758 "uniform sampler2D Texture_Attenuation;\n"
759 "uniform samplerCube Texture_Cube;\n"
761 "#define showshadowmap 0\n"
762 "#define useshadowsamplerrect 0\n"
763 "#define useshadowsampler2d 0\n"
764 "#define useshadowsamplercube 1\n"
766 "#ifdef USESHADOWMAPRECT\n"
767 "# if useshadowsamplerrect\n"
768 "uniform sampler2DRectShadow Texture_ShadowMapRect;\n"
770 "uniform sampler2DRect Texture_ShadowMapRect;\n"
774 "#ifdef USESHADOWMAP2D\n"
775 "# if useshadowsampler2d\n"
776 "uniform sampler2DShadow Texture_ShadowMap2D;\n"
778 "uniform sampler2D Texture_ShadowMap2D;\n"
782 "#ifdef USESHADOWMAPCUBE\n"
783 "# if useshadowsamplercube\n"
784 "uniform samplerCubeShadow Texture_ShadowMapCube;\n"
786 "uniform samplerCube Texture_ShadowMapCube;\n"
790 "uniform myhalf3 LightColor;\n"
791 "uniform myhalf3 AmbientColor;\n"
792 "uniform myhalf3 DiffuseColor;\n"
793 "uniform myhalf3 SpecularColor;\n"
794 "uniform myhalf3 Color_Pants;\n"
795 "uniform myhalf3 Color_Shirt;\n"
796 "uniform myhalf3 FogColor;\n"
798 "uniform myhalf4 TintColor;\n"
801 "//#ifdef MODE_WATER\n"
802 "uniform vec4 DistortScaleRefractReflect;\n"
803 "uniform vec4 ScreenScaleRefractReflect;\n"
804 "uniform vec4 ScreenCenterRefractReflect;\n"
805 "uniform myhalf4 RefractColor;\n"
806 "uniform myhalf4 ReflectColor;\n"
807 "uniform myhalf ReflectFactor;\n"
808 "uniform myhalf ReflectOffset;\n"
810 "//# ifdef MODE_REFRACTION\n"
811 "//uniform vec4 DistortScaleRefractReflect;\n"
812 "//uniform vec4 ScreenScaleRefractReflect;\n"
813 "//uniform vec4 ScreenCenterRefractReflect;\n"
814 "//uniform myhalf4 RefractColor;\n"
815 "//# ifdef USEREFLECTION\n"
816 "//uniform myhalf4 ReflectColor;\n"
819 "//# ifdef USEREFLECTION\n"
820 "//uniform vec4 DistortScaleRefractReflect;\n"
821 "//uniform vec4 ScreenScaleRefractReflect;\n"
822 "//uniform vec4 ScreenCenterRefractReflect;\n"
823 "//uniform myhalf4 ReflectColor;\n"
828 "uniform myhalf GlowScale;\n"
829 "uniform myhalf SceneBrightness;\n"
831 "uniform float OffsetMapping_Scale;\n"
832 "uniform float OffsetMapping_Bias;\n"
833 "uniform float FogRangeRecip;\n"
835 "uniform myhalf AmbientScale;\n"
836 "uniform myhalf DiffuseScale;\n"
837 "uniform myhalf SpecularScale;\n"
838 "uniform myhalf SpecularPower;\n"
840 "#ifdef USEOFFSETMAPPING\n"
841 "vec2 OffsetMapping(vec2 TexCoord)\n"
843 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
844 " // 14 sample relief mapping: linear search and then binary search\n"
845 " // this basically steps forward a small amount repeatedly until it finds\n"
846 " // itself inside solid, then jitters forward and back using decreasing\n"
847 " // amounts to find the impact\n"
848 " //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
849 " //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
850 " vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
851 " vec3 RT = vec3(TexCoord, 1);\n"
852 " OffsetVector *= 0.1;\n"
853 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
854 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
855 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
856 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
857 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
858 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
859 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
860 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
861 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
862 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) - 0.5);\n"
863 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5 - 0.25);\n"
864 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25 - 0.125);\n"
865 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125 - 0.0625);\n"
866 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
869 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
870 " // this basically moves forward the full distance, and then backs up based\n"
871 " // on height of samples\n"
872 " //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
873 " //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
874 " vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
875 " TexCoord += OffsetVector;\n"
876 " OffsetVector *= 0.333;\n"
877 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
878 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
879 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
880 " return TexCoord;\n"
883 "#endif // USEOFFSETMAPPING\n"
885 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
886 "//float ShadowMap_TextureSize = 1024.0;\n"
887 "//float ShadowMap_BorderSize = 6.0;\n"
888 "//float ShadowMap_NearClip = 0.0001;\n"
889 "//float ShadowMap_FarClip = 1.0;\n"
890 "//float ShadowMap_Bias = ShadowMap_NearClip * 64.0 / ShadowMap_TextureSize;\n"
891 "//vec2 ShadowMap_TextureScale = vec2(0.5, 0.25);\n"
892 "//vec4 ShadowMap_Parameters = vec3(1.0 - ShadowMap_BorderSize / ShadowMap_TextureSize, 1.0 - ShadowMap_BorderSize / ShadowMap_TextureSize, -(ShadowMap_FarClip + ShadowMap_NearClip) / (ShadowMap_FarClip - ShadowMap_NearClip), -2.0 * ShadowMap_NearClip * ShadowMap_FarClip / (ShadowMap_FarClip - ShadowMap_NearClip));\n"
893 "uniform float ShadowMap_Bias;\n"
894 "uniform vec2 ShadowMap_TextureScale;\n"
895 "uniform vec4 ShadowMap_Parameters;\n"
898 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
899 "vec3 GetShadowMapTC2D(vec3 dir)\n"
901 " vec3 adir = abs(dir);\n"
906 " if (adir.x > adir.y)\n"
908 " if (adir.x > adir.z)\n"
910 " d = 0.5 / adir.x;\n"
911 " if (dir.x >= 0.0)\n"
914 " tc = vec3(-dir.z, -dir.y, -dir.x);\n"
915 " offset = vec3(0.5, 0.5, 0.5);\n"
920 " tc = vec3( dir.z, -dir.y, dir.x);\n"
921 " offset = vec3(1.5, 0.5, 0.5);\n"
926 " d = 0.5 / adir.z;\n"
927 " if (dir.z >= 0.0)\n"
930 " tc = vec3( dir.x, -dir.y, -dir.z);\n"
931 " offset = vec3(0.5, 2.5, 0.5);\n"
936 " tc = vec3(-dir.x, -dir.y, dir.z);\n"
937 " offset = vec3(1.5, 2.5, 0.5);\n"
943 " if (adir.y > adir.z)\n"
945 " d = 0.5 / adir.y;\n"
946 " if (dir.y >= 0.0)\n"
949 " tc = vec3( dir.x, dir.z, -dir.y);\n"
950 " offset = vec3(0.5, 1.5, 0.5);\n"
955 " tc = vec3( dir.x, -dir.z, dir.y);\n"
956 " offset = vec3(1.5, 1.5, 0.5);\n"
961 " d = 0.5 / adir.z;\n"
962 " if (dir.z >= 0.0)\n"
965 " tc = vec3(dir.x, -dir.y, -dir.z);\n"
966 " offset = vec3(0.5, 2.5, 0.5);\n"
971 " tc = vec3(-dir.x, -dir.y, dir.z);\n"
972 " offset = vec3(1.5, 2.5, 0.5);\n"
976 " tc = tc * ShadowMap_Parameters.xyz * d + offset;\n"
977 " tc.xy *= ShadowMap_TextureScale;\n"
978 " tc.z += ShadowMap_Parameters.w * d - ShadowMap_Bias * d;\n"
980 " // experimental method by eihrul, needs overhaul\n"
981 " vec3 ma = vec3(0.0, 0.0, 1.0);\n"
982 " if (adir.x > adir.y)\n"
984 " if (adir.x > adir.z)\n"
985 " ma = vec3(1.0, 0.0, 0.0);\n"
987 " else if (adir.y > adir.z)\n"
988 " ma = vec3(0.0, 1.0, 0.0);\n"
990 " tc.xy = dir.xy - ma.xy*(dir.xy - dir.z);\n"
991 " tc.xy = (tc.xy/dot(ma, dir))*0.5 + 0.5;\n"
992 " tc.z = dot(ma, adir);\n"
993 " tc.xy = (tc.xy * tcscale + offset) * vec2(0.5, 0.25);\n"
998 "#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
1000 "#ifdef USESHADOWMAPCUBE\n"
1001 "vec4 GetShadowMapTCCube(vec3 dir)\n"
1003 " vec3 adir = abs(dir);\n"
1004 " float sidedist = max(adir.x, max(adir.y, adir.z));\n"
1005 " return vec4(dir, 0.5 - 0.5 * (ShadowMap_Parameters.z - (-ShadowMap_Bias + ShadowMap_Parameters.w) / sidedist));\n"
1009 "#if !showshadowmap\n"
1010 "# ifdef USESHADOWMAPRECT\n"
1011 "float ShadowMapCompare(vec3 dir)\n"
1013 " vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1015 "# if useshadowsamplerrect\n"
1016 " f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).a;\n"
1018 " f = step(shadowmaptc.z, texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
1024 "# ifdef USESHADOWMAP2D\n"
1025 "float ShadowMapCompare(vec3 dir)\n"
1027 " vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1029 "# if useshadowsampler2d\n"
1030 " f = shadow2D(Texture_ShadowMap2D, shadowmaptc).a;\n"
1032 " f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy).r);\n"
1038 "# ifdef USESHADOWMAPCUBE\n"
1039 "float ShadowMapCompare(vec3 dir)\n"
1041 " // apply depth texture cubemap as light filter\n"
1042 " vec4 shadowmaptc = GetShadowMapTCCube(dir);\n"
1044 "# if useshadowsamplercube\n"
1045 " f = shadowCube(Texture_ShadowMapCube, shadowmaptc).a;\n"
1047 " f = step(shadowmaptc.w, textureCube(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
1055 "#ifdef MODE_WATER\n"
1060 "#ifdef USEOFFSETMAPPING\n"
1061 " // apply offsetmapping\n"
1062 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1063 "#define TexCoord TexCoordOffset\n"
1066 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1067 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1068 " vec4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1069 " vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xyxy * DistortScaleRefractReflect;\n"
1070 " // FIXME temporary hack to detect the case that the reflection\n"
1071 " // gets blackened at edges due to leaving the area that contains actual\n"
1073 " // Remove this 'ack once we have a better way to stop this thing from\n"
1075 " float f = min(1, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.05, 0.05))) / 0.02);\n"
1076 " f *= min(1, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.05, -0.05))) / 0.02);\n"
1077 " f *= min(1, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.05, 0.05))) / 0.02);\n"
1078 " f *= min(1, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.05, -0.05))) / 0.02);\n"
1079 " ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
1080 " f = min(1, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.05, 0.05))) / 0.02);\n"
1081 " f *= min(1, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.05, -0.05))) / 0.02);\n"
1082 " f *= min(1, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.05, 0.05))) / 0.02);\n"
1083 " f *= min(1, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.05, -0.05))) / 0.02);\n"
1084 " ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
1085 " float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
1086 " gl_FragColor = mix(texture2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, texture2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
1089 "#else // !MODE_WATER\n"
1090 "#ifdef MODE_REFRACTION\n"
1092 "// refraction pass\n"
1095 "#ifdef USEOFFSETMAPPING\n"
1096 " // apply offsetmapping\n"
1097 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1098 "#define TexCoord TexCoordOffset\n"
1101 " vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
1102 " //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
1103 " vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
1104 " vec2 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
1105 " // FIXME temporary hack to detect the case that the reflection\n"
1106 " // gets blackened at edges due to leaving the area that contains actual\n"
1108 " // Remove this 'ack once we have a better way to stop this thing from\n"
1110 " float f = min(1, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.05, 0.05))) / 0.02);\n"
1111 " f *= min(1, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.05, -0.05))) / 0.02);\n"
1112 " f *= min(1, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.05, 0.05))) / 0.02);\n"
1113 " f *= min(1, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.05, -0.05))) / 0.02);\n"
1114 " ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1115 " gl_FragColor = texture2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
1118 "#else // !MODE_REFRACTION\n"
1121 "#ifdef USEOFFSETMAPPING\n"
1122 " // apply offsetmapping\n"
1123 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1124 "#define TexCoord TexCoordOffset\n"
1127 " // combine the diffuse textures (base, pants, shirt)\n"
1128 " myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
1129 "#ifdef USECOLORMAPPING\n"
1130 " color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
1132 "#ifdef USEVERTEXTEXTUREBLEND\n"
1133 " myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
1134 " //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
1135 " //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
1136 " color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
1138 " //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
1141 "#ifdef USEDIFFUSE\n"
1142 " // get the surface normal and the gloss color\n"
1143 "# ifdef USEVERTEXTEXTUREBLEND\n"
1144 " myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
1145 "# ifdef USESPECULAR\n"
1146 " myhalf3 glosscolor = mix(myhalf3(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf3(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
1149 " myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
1150 "# ifdef USESPECULAR\n"
1151 " myhalf3 glosscolor = myhalf3(texture2D(Texture_Gloss, TexCoord));\n"
1158 "#ifdef MODE_LIGHTSOURCE\n"
1159 " // light source\n"
1161 " // calculate surface normal, light normal, and specular normal\n"
1162 " // compute color intensity for the two textures (colormap and glossmap)\n"
1163 " // scale by light color and attenuation as efficiently as possible\n"
1164 " // (do as much scalar math as possible rather than vector math)\n"
1165 "# ifdef USEDIFFUSE\n"
1166 " // get the light normal\n"
1167 " myhalf3 diffusenormal = myhalf3(normalize(LightVector));\n"
1169 "# ifdef USESPECULAR\n"
1170 "# ifndef USEEXACTSPECULARMATH\n"
1171 " myhalf3 specularnormal = normalize(diffusenormal + myhalf3(normalize(EyeVector)));\n"
1174 " // calculate directional shading\n"
1175 "# ifdef USEEXACTSPECULARMATH\n"
1176 " 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(reflect(diffusenormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower)) * glosscolor);\n"
1178 " 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"
1181 "# ifdef USEDIFFUSE\n"
1182 " // calculate directional shading\n"
1183 " color.rgb = color.rgb * (myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0))) * (AmbientScale + DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0))));\n"
1185 " // calculate directionless shading\n"
1186 " color.rgb = color.rgb * myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1190 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1191 "#if !showshadowmap\n"
1192 " color.rgb *= ShadowMapCompare(CubeVector);\n"
1196 "# ifdef USECUBEFILTER\n"
1197 " // apply light cubemap filter\n"
1198 " //color.rgb *= normalize(CubeVector) * 0.5 + 0.5;//vec3(textureCube(Texture_Cube, CubeVector));\n"
1199 " color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
1201 "#endif // MODE_LIGHTSOURCE\n"
1206 "#ifdef MODE_LIGHTDIRECTION\n"
1207 " // directional model lighting\n"
1208 "# ifdef USEDIFFUSE\n"
1209 " // get the light normal\n"
1210 " myhalf3 diffusenormal = myhalf3(normalize(LightVector));\n"
1212 "# ifdef USESPECULAR\n"
1213 " // calculate directional shading\n"
1214 " color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
1215 "# ifdef USEEXACTSPECULARMATH\n"
1216 " color.rgb += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(myhalf(max(float(dot(reflect(diffusenormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1218 " myhalf3 specularnormal = normalize(diffusenormal + myhalf3(normalize(EyeVector)));\n"
1219 " color.rgb += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1222 "# ifdef USEDIFFUSE\n"
1224 " // calculate directional shading\n"
1225 " color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
1227 " color.rgb *= AmbientColor;\n"
1230 "#endif // MODE_LIGHTDIRECTION\n"
1235 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1236 " // deluxemap lightmapping using light vectors in modelspace (evil q3map2)\n"
1238 " // get the light normal\n"
1239 " myhalf3 diffusenormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1240 " myhalf3 diffusenormal;\n"
1241 " diffusenormal.x = dot(diffusenormal_modelspace, myhalf3(VectorS));\n"
1242 " diffusenormal.y = dot(diffusenormal_modelspace, myhalf3(VectorT));\n"
1243 " diffusenormal.z = dot(diffusenormal_modelspace, myhalf3(VectorR));\n"
1244 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1245 " // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
1246 " // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
1247 " // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
1248 " // to map the luxels to coordinates on the draw surfaces), which also causes\n"
1249 " // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
1250 " // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
1251 " // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
1252 " // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
1253 " myhalf3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal) / max(0.25, diffusenormal.z)), 0.0)));\n"
1254 " // 0.25 supports up to 75.5 degrees normal/deluxe angle\n"
1255 "# ifdef USESPECULAR\n"
1256 "# ifdef USEEXACTSPECULARMATH\n"
1257 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(reflect(normalize(diffusenormal), surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1259 " myhalf3 specularnormal = myhalf3(normalize(diffusenormal + myhalf3(normalize(EyeVector))));\n"
1260 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1264 " // apply lightmap color\n"
1265 " color.rgb = color.rgb * AmbientScale + tempcolor * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1266 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1271 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1272 " // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1274 " // get the light normal\n"
1275 " myhalf3 diffusenormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1276 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1277 " myhalf3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal) / diffusenormal.z), 0.0)));\n"
1278 "# ifdef USESPECULAR\n"
1279 "# ifdef USEEXACTSPECULARMATH\n"
1280 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(reflect(diffusenormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1282 " myhalf3 specularnormal = myhalf3(normalize(diffusenormal + myhalf3(normalize(EyeVector))));\n"
1283 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1287 " // apply lightmap color\n"
1288 " color.rgb = color.rgb * AmbientScale + tempcolor * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1289 "#endif // MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1294 "#ifdef MODE_LIGHTMAP\n"
1295 " // apply lightmap color\n"
1296 " color.rgb = color.rgb * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * DiffuseScale + color.rgb * AmbientScale;\n"
1297 "#endif // MODE_LIGHTMAP\n"
1302 "#ifdef MODE_VERTEXCOLOR\n"
1303 " // apply lightmap color\n"
1304 " color.rgb = color.rgb * myhalf3(gl_Color.rgb) * DiffuseScale + color.rgb * AmbientScale;\n"
1305 "#endif // MODE_VERTEXCOLOR\n"
1310 "#ifdef MODE_FLATCOLOR\n"
1311 "#endif // MODE_FLATCOLOR\n"
1319 " color *= TintColor;\n"
1322 "#ifdef USEVERTEXTEXTUREBLEND\n"
1323 " color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend);\n"
1325 " color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * GlowScale;\n"
1329 " color.rgb *= SceneBrightness;\n"
1331 " // apply fog after Contrastboost/SceneBrightness because its color is already modified appropriately\n"
1333 " color.rgb = mix(FogColor, color.rgb, myhalf(texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*FogRangeRecip, 0.0))));\n"
1336 " // 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"
1337 "#ifdef USEREFLECTION\n"
1338 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1339 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1340 " vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
1341 " vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
1342 " // FIXME temporary hack to detect the case that the reflection\n"
1343 " // gets blackened at edges due to leaving the area that contains actual\n"
1345 " // Remove this 'ack once we have a better way to stop this thing from\n"
1347 " float f = min(1, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.05, 0.05))) / 0.02);\n"
1348 " f *= min(1, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.05, -0.05))) / 0.02);\n"
1349 " f *= min(1, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.05, 0.05))) / 0.02);\n"
1350 " f *= min(1, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.05, -0.05))) / 0.02);\n"
1351 " ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1352 " color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
1355 " gl_FragColor = vec4(color);\n"
1357 "#if showshadowmap\n"
1358 "# ifdef USESHADOWMAPRECT\n"
1359 "# if useshadowsamplerrect\n"
1360 " gl_FragColor = shadow2DRect(Texture_ShadowMapRect, GetShadowMapTC2D(CubeVector).xyz);\n"
1362 " gl_FragColor = texture2DRect(Texture_ShadowMapRect, GetShadowMapTC2D(CubeVector).xy);\n"
1366 "# ifdef USESHADOWMAP2D\n"
1367 "# if useshadowsampler2d\n"
1368 " gl_FragColor = shadow2D(Texture_ShadowMap2D, GetShadowMapTC2D(CubeVector).xyz);\n"
1370 " gl_FragColor = texture2D(Texture_ShadowMap2D, GetShadowMapTC2D(CubeVector).xy);\n"
1374 "# ifdef USESHADOWMAPCUBE\n"
1375 "# if useshadowsamplercube\n"
1376 " gl_FragColor = shadowCube(Texture_ShadowMapCube, GetShadowMapTCCube(CubeVector));\n"
1378 " gl_FragColor = textureCube(Texture_ShadowMapCube, GetShadowMapTCCube(CubeVector).xyz);\n"
1383 "#endif // !MODE_REFRACTION\n"
1384 "#endif // !MODE_WATER\n"
1386 "#endif // FRAGMENT_SHADER\n"
1388 "#endif // !MODE_GENERIC\n"
1389 "#endif // !MODE_POSTPROCESS\n"
1390 "#endif // !MODE_SHOWDEPTH\n"
1391 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1394 typedef struct shaderpermutationinfo_s
1396 const char *pretext;
1399 shaderpermutationinfo_t;
1401 typedef struct shadermodeinfo_s
1403 const char *vertexfilename;
1404 const char *geometryfilename;
1405 const char *fragmentfilename;
1406 const char *pretext;
1411 typedef enum shaderpermutation_e
1413 SHADERPERMUTATION_DIFFUSE = 1<<0, ///< (lightsource) whether to use directional shading
1414 SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, ///< indicates this is a two-layer material blend based on vertex alpha (q3bsp)
1415 SHADERPERMUTATION_VIEWTINT = 1<<1, ///< view tint (postprocessing only)
1416 SHADERPERMUTATION_COLORMAPPING = 1<<2, ///< indicates this is a colormapped skin
1417 SHADERPERMUTATION_SATURATION = 1<<2, ///< saturation (postprocessing only)
1418 SHADERPERMUTATION_FOG = 1<<3, ///< tint the color by fog color or black if using additive blend mode
1419 SHADERPERMUTATION_GAMMARAMPS = 1<<3, ///< gamma (postprocessing only)
1420 SHADERPERMUTATION_CUBEFILTER = 1<<4, ///< (lightsource) use cubemap light filter
1421 SHADERPERMUTATION_GLOW = 1<<5, ///< (lightmap) blend in an additive glow texture
1422 SHADERPERMUTATION_BLOOM = 1<<5, ///< bloom (postprocessing only)
1423 SHADERPERMUTATION_SPECULAR = 1<<6, ///< (lightsource or deluxemapping) render specular effects
1424 SHADERPERMUTATION_POSTPROCESSING = 1<<6, ///< user defined postprocessing (postprocessing only)
1425 SHADERPERMUTATION_EXACTSPECULARMATH = 1<<7, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
1426 SHADERPERMUTATION_REFLECTION = 1<<8, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
1427 SHADERPERMUTATION_OFFSETMAPPING = 1<<9, ///< adjust texcoords to roughly simulate a displacement mapped surface
1428 SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<10, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
1429 SHADERPERMUTATION_SHADOWMAPRECT = 1<<11, ///< (lightsource) use shadowmap rectangle texture as light filter
1430 SHADERPERMUTATION_SHADOWMAPCUBE = 1<<12, ///< (lightsource) use shadowmap cubemap texture as light filter
1431 SHADERPERMUTATION_SHADOWMAP2D = 1<<13, ///< (lightsource) use shadowmap rectangle texture as light filter
1432 SHADERPERMUTATION_LIMIT = 1<<14, ///< size of permutations array
1433 SHADERPERMUTATION_COUNT = 14 ///< size of shaderpermutationinfo array
1435 shaderpermutation_t;
1437 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
1438 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
1440 {"#define USEDIFFUSE\n", " diffuse"},
1441 {"#define USEVERTEXTEXTUREBLEND\n#define USEVIEWTINT\n", " vertextextureblend/tint"},
1442 {"#define USECOLORMAPPING\n#define USESATURATION\n", " colormapping/saturation"},
1443 {"#define USEFOG\n#define USEGAMMARAMPS\n", " fog/gammaramps"},
1444 {"#define USECUBEFILTER\n", " cubefilter"},
1445 {"#define USEGLOW\n#define USEBLOOM\n", " glow/bloom"},
1446 {"#define USESPECULAR\n#define USEPOSTPROCESSING", " specular/postprocessing"},
1447 {"#define USEEXACTSPECULARMATH\n", " exactspecularmath"},
1448 {"#define USEREFLECTION\n", " reflection"},
1449 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
1450 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
1451 {"#define USESHADOWMAPRECT\n", " shadowmaprect"},
1452 {"#define USESHADOWMAPCUBE\n", " shadowmapcube"},
1453 {"#define USESHADOWMAP2D\n", " shadowmap2d"},
1456 /// this enum is multiplied by SHADERPERMUTATION_MODEBASE
1457 typedef enum shadermode_e
1459 SHADERMODE_GENERIC, ///< (particles/HUD/etc) vertex color, optionally multiplied by one texture
1460 SHADERMODE_POSTPROCESS, ///< postprocessing shader (r_glsl_postprocess)
1461 SHADERMODE_DEPTH_OR_SHADOW, ///< (depthfirst/shadows) vertex shader only
1462 SHADERMODE_FLATCOLOR, ///< (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
1463 SHADERMODE_VERTEXCOLOR, ///< (lightmap) modulate texture by vertex colors (q3bsp)
1464 SHADERMODE_LIGHTMAP, ///< (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
1465 SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, ///< (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
1466 SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, ///< (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
1467 SHADERMODE_LIGHTDIRECTION, ///< (lightmap) use directional pixel shading from fixed light direction (q3bsp)
1468 SHADERMODE_LIGHTSOURCE, ///< (lightsource) use directional pixel shading from light source (rtlight)
1469 SHADERMODE_REFRACTION, ///< refract background (the material is rendered normally after this pass)
1470 SHADERMODE_WATER, ///< refract background and reflection (the material is rendered normally after this pass)
1471 SHADERMODE_SHOWDEPTH, ///< (debugging) renders depth as color
1476 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
1477 shadermodeinfo_t shadermodeinfo[SHADERMODE_COUNT] =
1479 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
1480 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
1481 {"glsl/default.glsl", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
1482 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
1483 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
1484 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
1485 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
1486 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
1487 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
1488 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
1489 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
1490 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
1491 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
1494 typedef struct r_glsl_permutation_s
1496 /// indicates if we have tried compiling this permutation already
1498 /// 0 if compilation failed
1500 /// locations of detected uniforms in program object, or -1 if not found
1501 int loc_Texture_First;
1502 int loc_Texture_Second;
1503 int loc_Texture_GammaRamps;
1504 int loc_Texture_Normal;
1505 int loc_Texture_Color;
1506 int loc_Texture_Gloss;
1507 int loc_Texture_Glow;
1508 int loc_Texture_SecondaryNormal;
1509 int loc_Texture_SecondaryColor;
1510 int loc_Texture_SecondaryGloss;
1511 int loc_Texture_SecondaryGlow;
1512 int loc_Texture_Pants;
1513 int loc_Texture_Shirt;
1514 int loc_Texture_FogMask;
1515 int loc_Texture_Lightmap;
1516 int loc_Texture_Deluxemap;
1517 int loc_Texture_Attenuation;
1518 int loc_Texture_Cube;
1519 int loc_Texture_Refraction;
1520 int loc_Texture_Reflection;
1521 int loc_Texture_ShadowMapRect;
1522 int loc_Texture_ShadowMapCube;
1523 int loc_Texture_ShadowMap2D;
1525 int loc_LightPosition;
1526 int loc_EyePosition;
1527 int loc_Color_Pants;
1528 int loc_Color_Shirt;
1529 int loc_FogRangeRecip;
1530 int loc_AmbientScale;
1531 int loc_DiffuseScale;
1532 int loc_SpecularScale;
1533 int loc_SpecularPower;
1535 int loc_SceneBrightness; // or: Scenebrightness * ContrastBoost
1536 int loc_OffsetMapping_Scale;
1538 int loc_AmbientColor;
1539 int loc_DiffuseColor;
1540 int loc_SpecularColor;
1542 int loc_ContrastBoostCoeff; ///< 1 - 1/ContrastBoost
1543 int loc_GammaCoeff; ///< 1 / gamma
1544 int loc_DistortScaleRefractReflect;
1545 int loc_ScreenScaleRefractReflect;
1546 int loc_ScreenCenterRefractReflect;
1547 int loc_RefractColor;
1548 int loc_ReflectColor;
1549 int loc_ReflectFactor;
1550 int loc_ReflectOffset;
1558 int loc_ShadowMap_Bias;
1559 int loc_ShadowMap_TextureScale;
1560 int loc_ShadowMap_Parameters;
1562 r_glsl_permutation_t;
1564 /// information about each possible shader permutation
1565 r_glsl_permutation_t r_glsl_permutations[SHADERMODE_COUNT][SHADERPERMUTATION_LIMIT];
1566 /// currently selected permutation
1567 r_glsl_permutation_t *r_glsl_permutation;
1569 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
1572 if (!filename || !filename[0])
1574 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1577 if (printfromdisknotice)
1578 Con_DPrint("from disk... ");
1579 return shaderstring;
1581 else if (!strcmp(filename, "glsl/default.glsl"))
1583 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(builtinshaderstring) + 1);
1584 memcpy(shaderstring, builtinshaderstring, strlen(builtinshaderstring) + 1);
1586 return shaderstring;
1589 static void R_GLSL_CompilePermutation(unsigned int mode, unsigned int permutation)
1592 shadermodeinfo_t *modeinfo = shadermodeinfo + mode;
1593 r_glsl_permutation_t *p = &r_glsl_permutations[mode][permutation];
1594 int vertstrings_count = 0;
1595 int geomstrings_count = 0;
1596 int fragstrings_count = 0;
1597 char *vertexstring, *geometrystring, *fragmentstring;
1598 const char *vertstrings_list[32+3];
1599 const char *geomstrings_list[32+3];
1600 const char *fragstrings_list[32+3];
1601 char permutationname[256];
1608 permutationname[0] = 0;
1609 vertexstring = R_GLSL_GetText(modeinfo->vertexfilename, true);
1610 geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1611 fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1613 strlcat(permutationname, shadermodeinfo[mode].vertexfilename, sizeof(permutationname));
1615 // the first pretext is which type of shader to compile as
1616 // (later these will all be bound together as a program object)
1617 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1618 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1619 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1621 // the second pretext is the mode (for example a light source)
1622 vertstrings_list[vertstrings_count++] = shadermodeinfo[mode].pretext;
1623 geomstrings_list[geomstrings_count++] = shadermodeinfo[mode].pretext;
1624 fragstrings_list[fragstrings_count++] = shadermodeinfo[mode].pretext;
1625 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1627 // now add all the permutation pretexts
1628 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1630 if (permutation & (1<<i))
1632 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1633 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1634 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1635 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1639 // keep line numbers correct
1640 vertstrings_list[vertstrings_count++] = "\n";
1641 geomstrings_list[geomstrings_count++] = "\n";
1642 fragstrings_list[fragstrings_count++] = "\n";
1646 // now append the shader text itself
1647 vertstrings_list[vertstrings_count++] = vertexstring;
1648 geomstrings_list[geomstrings_count++] = geometrystring;
1649 fragstrings_list[fragstrings_count++] = fragmentstring;
1651 // if any sources were NULL, clear the respective list
1653 vertstrings_count = 0;
1654 if (!geometrystring)
1655 geomstrings_count = 0;
1656 if (!fragmentstring)
1657 fragstrings_count = 0;
1659 // compile the shader program
1660 if (vertstrings_count + geomstrings_count + fragstrings_count)
1661 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1665 qglUseProgramObjectARB(p->program);CHECKGLERROR
1666 // look up all the uniform variable names we care about, so we don't
1667 // have to look them up every time we set them
1668 p->loc_Texture_First = qglGetUniformLocationARB(p->program, "Texture_First");
1669 p->loc_Texture_Second = qglGetUniformLocationARB(p->program, "Texture_Second");
1670 p->loc_Texture_GammaRamps = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
1671 p->loc_Texture_Normal = qglGetUniformLocationARB(p->program, "Texture_Normal");
1672 p->loc_Texture_Color = qglGetUniformLocationARB(p->program, "Texture_Color");
1673 p->loc_Texture_Gloss = qglGetUniformLocationARB(p->program, "Texture_Gloss");
1674 p->loc_Texture_Glow = qglGetUniformLocationARB(p->program, "Texture_Glow");
1675 p->loc_Texture_SecondaryNormal = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
1676 p->loc_Texture_SecondaryColor = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
1677 p->loc_Texture_SecondaryGloss = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
1678 p->loc_Texture_SecondaryGlow = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
1679 p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
1680 p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
1681 p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
1682 p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
1683 p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
1684 p->loc_Texture_Refraction = qglGetUniformLocationARB(p->program, "Texture_Refraction");
1685 p->loc_Texture_Reflection = qglGetUniformLocationARB(p->program, "Texture_Reflection");
1686 p->loc_Texture_Attenuation = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
1687 p->loc_Texture_Cube = qglGetUniformLocationARB(p->program, "Texture_Cube");
1688 p->loc_Texture_ShadowMapRect = qglGetUniformLocationARB(p->program, "Texture_ShadowMapRect");
1689 p->loc_Texture_ShadowMapCube = qglGetUniformLocationARB(p->program, "Texture_ShadowMapCube");
1690 p->loc_Texture_ShadowMap2D = qglGetUniformLocationARB(p->program, "Texture_ShadowMap2D");
1691 p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
1692 p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
1693 p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
1694 p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants");
1695 p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt");
1696 p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip");
1697 p->loc_AmbientScale = qglGetUniformLocationARB(p->program, "AmbientScale");
1698 p->loc_DiffuseScale = qglGetUniformLocationARB(p->program, "DiffuseScale");
1699 p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
1700 p->loc_SpecularScale = qglGetUniformLocationARB(p->program, "SpecularScale");
1701 p->loc_GlowScale = qglGetUniformLocationARB(p->program, "GlowScale");
1702 p->loc_SceneBrightness = qglGetUniformLocationARB(p->program, "SceneBrightness");
1703 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
1704 p->loc_TintColor = qglGetUniformLocationARB(p->program, "TintColor");
1705 p->loc_AmbientColor = qglGetUniformLocationARB(p->program, "AmbientColor");
1706 p->loc_DiffuseColor = qglGetUniformLocationARB(p->program, "DiffuseColor");
1707 p->loc_SpecularColor = qglGetUniformLocationARB(p->program, "SpecularColor");
1708 p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
1709 p->loc_ContrastBoostCoeff = qglGetUniformLocationARB(p->program, "ContrastBoostCoeff");
1710 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
1711 p->loc_ScreenScaleRefractReflect = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
1712 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
1713 p->loc_RefractColor = qglGetUniformLocationARB(p->program, "RefractColor");
1714 p->loc_ReflectColor = qglGetUniformLocationARB(p->program, "ReflectColor");
1715 p->loc_ReflectFactor = qglGetUniformLocationARB(p->program, "ReflectFactor");
1716 p->loc_ReflectOffset = qglGetUniformLocationARB(p->program, "ReflectOffset");
1717 p->loc_GammaCoeff = qglGetUniformLocationARB(p->program, "GammaCoeff");
1718 p->loc_UserVec1 = qglGetUniformLocationARB(p->program, "UserVec1");
1719 p->loc_UserVec2 = qglGetUniformLocationARB(p->program, "UserVec2");
1720 p->loc_UserVec3 = qglGetUniformLocationARB(p->program, "UserVec3");
1721 p->loc_UserVec4 = qglGetUniformLocationARB(p->program, "UserVec4");
1722 p->loc_ClientTime = qglGetUniformLocationARB(p->program, "ClientTime");
1723 p->loc_PixelSize = qglGetUniformLocationARB(p->program, "PixelSize");
1724 p->loc_Saturation = qglGetUniformLocationARB(p->program, "Saturation");
1725 p->loc_ShadowMap_Bias = qglGetUniformLocationARB(p->program, "ShadowMap_Bias");
1726 p->loc_ShadowMap_TextureScale = qglGetUniformLocationARB(p->program, "ShadowMap_TextureScale");
1727 p->loc_ShadowMap_Parameters = qglGetUniformLocationARB(p->program, "ShadowMap_Parameters");
1728 // initialize the samplers to refer to the texture units we use
1729 if (p->loc_Texture_First >= 0) qglUniform1iARB(p->loc_Texture_First , GL20TU_FIRST);
1730 if (p->loc_Texture_Second >= 0) qglUniform1iARB(p->loc_Texture_Second , GL20TU_SECOND);
1731 if (p->loc_Texture_GammaRamps >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps , GL20TU_GAMMARAMPS);
1732 if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal , GL20TU_NORMAL);
1733 if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color , GL20TU_COLOR);
1734 if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss , GL20TU_GLOSS);
1735 if (p->loc_Texture_Glow >= 0) qglUniform1iARB(p->loc_Texture_Glow , GL20TU_GLOW);
1736 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
1737 if (p->loc_Texture_SecondaryColor >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
1738 if (p->loc_Texture_SecondaryGloss >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
1739 if (p->loc_Texture_SecondaryGlow >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow , GL20TU_SECONDARY_GLOW);
1740 if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants , GL20TU_PANTS);
1741 if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt , GL20TU_SHIRT);
1742 if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask , GL20TU_FOGMASK);
1743 if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap , GL20TU_LIGHTMAP);
1744 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap , GL20TU_DELUXEMAP);
1745 if (p->loc_Texture_Attenuation >= 0) qglUniform1iARB(p->loc_Texture_Attenuation , GL20TU_ATTENUATION);
1746 if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube , GL20TU_CUBE);
1747 if (p->loc_Texture_Refraction >= 0) qglUniform1iARB(p->loc_Texture_Refraction , GL20TU_REFRACTION);
1748 if (p->loc_Texture_Reflection >= 0) qglUniform1iARB(p->loc_Texture_Reflection , GL20TU_REFLECTION);
1749 if (p->loc_Texture_ShadowMapRect >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapRect , GL20TU_SHADOWMAPRECT);
1750 if (p->loc_Texture_ShadowMapCube >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapCube , GL20TU_SHADOWMAPCUBE);
1751 if (p->loc_Texture_ShadowMap2D >= 0) qglUniform1iARB(p->loc_Texture_ShadowMap2D , GL20TU_SHADOWMAP2D);
1753 if (developer.integer)
1754 Con_Printf("GLSL shader %s compiled.\n", permutationname);
1757 Con_Printf("GLSL shader %s failed! some features may not work properly.\n", permutationname);
1761 Mem_Free(vertexstring);
1763 Mem_Free(geometrystring);
1765 Mem_Free(fragmentstring);
1768 void R_GLSL_Restart_f(void)
1771 unsigned int permutation;
1772 for (mode = 0;mode < SHADERMODE_COUNT;mode++)
1773 for (permutation = 0;permutation < SHADERPERMUTATION_LIMIT;permutation++)
1774 if (r_glsl_permutations[mode][permutation].program)
1775 GL_Backend_FreeProgram(r_glsl_permutations[mode][permutation].program);
1776 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
1779 void R_GLSL_DumpShader_f(void)
1783 qfile_t *file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1786 Con_Printf("failed to write to glsl/default.glsl\n");
1790 FS_Print(file, "/* The engine may define the following macros:\n");
1791 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1792 for (i = 0;i < SHADERMODE_COUNT;i++)
1793 FS_Print(file, shadermodeinfo[i].pretext);
1794 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1795 FS_Print(file, shaderpermutationinfo[i].pretext);
1796 FS_Print(file, "*/\n");
1797 FS_Print(file, builtinshaderstring);
1800 Con_Printf("glsl/default.glsl written\n");
1803 void R_SetupShader_SetPermutation(unsigned int mode, unsigned int permutation)
1805 r_glsl_permutation_t *perm = &r_glsl_permutations[mode][permutation];
1806 if (r_glsl_permutation != perm)
1808 r_glsl_permutation = perm;
1809 if (!r_glsl_permutation->program)
1811 if (!r_glsl_permutation->compiled)
1812 R_GLSL_CompilePermutation(mode, permutation);
1813 if (!r_glsl_permutation->program)
1815 // remove features until we find a valid permutation
1817 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1819 // reduce i more quickly whenever it would not remove any bits
1820 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1821 if (!(permutation & j))
1824 r_glsl_permutation = &r_glsl_permutations[mode][permutation];
1825 if (!r_glsl_permutation->compiled)
1826 R_GLSL_CompilePermutation(mode, permutation);
1827 if (r_glsl_permutation->program)
1830 if (i >= SHADERPERMUTATION_COUNT)
1832 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");
1833 Cvar_SetValueQuick(&r_glsl, 0);
1834 R_GLSL_Restart_f(); // unload shaders
1835 return; // no bit left to clear
1840 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
1844 void R_SetupGenericShader(qboolean usetexture)
1846 if (gl_support_fragment_shader)
1848 if (r_glsl.integer && r_glsl_usegeneric.integer)
1849 R_SetupShader_SetPermutation(SHADERMODE_GENERIC, usetexture ? SHADERPERMUTATION_DIFFUSE : 0);
1850 else if (r_glsl_permutation)
1852 r_glsl_permutation = NULL;
1853 qglUseProgramObjectARB(0);CHECKGLERROR
1858 void R_SetupGenericTwoTextureShader(int texturemode)
1860 if (gl_support_fragment_shader)
1862 if (r_glsl.integer && r_glsl_usegeneric.integer)
1863 R_SetupShader_SetPermutation(SHADERMODE_GENERIC, SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | (r_shadow_glossexact.integer ? SHADERPERMUTATION_EXACTSPECULARMATH : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
1864 else if (r_glsl_permutation)
1866 r_glsl_permutation = NULL;
1867 qglUseProgramObjectARB(0);CHECKGLERROR
1870 if (!r_glsl_permutation)
1872 if (texturemode == GL_DECAL && gl_combine.integer)
1873 texturemode = GL_INTERPOLATE_ARB;
1874 R_Mesh_TexCombine(1, texturemode, texturemode, 1, 1);
1878 void R_SetupDepthOrShadowShader(void)
1880 if (gl_support_fragment_shader)
1882 if (r_glsl.integer && r_glsl_usegeneric.integer)
1883 R_SetupShader_SetPermutation(SHADERMODE_DEPTH_OR_SHADOW, 0);
1884 else if (r_glsl_permutation)
1886 r_glsl_permutation = NULL;
1887 qglUseProgramObjectARB(0);CHECKGLERROR
1892 void R_SetupShowDepthShader(void)
1894 if (gl_support_fragment_shader)
1896 if (r_glsl.integer && r_glsl_usegeneric.integer)
1897 R_SetupShader_SetPermutation(SHADERMODE_SHOWDEPTH, 0);
1898 else if (r_glsl_permutation)
1900 r_glsl_permutation = NULL;
1901 qglUseProgramObjectARB(0);CHECKGLERROR
1906 extern rtexture_t *r_shadow_attenuationgradienttexture;
1907 extern rtexture_t *r_shadow_attenuation2dtexture;
1908 extern rtexture_t *r_shadow_attenuation3dtexture;
1909 extern qboolean r_shadow_usingshadowmaprect;
1910 extern qboolean r_shadow_usingshadowmapcube;
1911 extern qboolean r_shadow_usingshadowmap2d;
1912 extern float r_shadow_shadowmap_bias;
1913 extern float r_shadow_shadowmap_texturescale[2];
1914 extern float r_shadow_shadowmap_parameters[4];
1915 void R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass)
1917 // select a permutation of the lighting shader appropriate to this
1918 // combination of texture, entity, light source, and fogging, only use the
1919 // minimum features necessary to avoid wasting rendering time in the
1920 // fragment shader on features that are not being used
1921 unsigned int permutation = 0;
1922 unsigned int mode = 0;
1923 // TODO: implement geometry-shader based shadow volumes someday
1924 if (r_glsl_offsetmapping.integer)
1926 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
1927 if (r_glsl_offsetmapping_reliefmapping.integer)
1928 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
1930 if (rsurfacepass == RSURFPASS_BACKGROUND)
1932 // distorted background
1933 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
1934 mode = SHADERMODE_WATER;
1936 mode = SHADERMODE_REFRACTION;
1938 else if (rsurfacepass == RSURFPASS_RTLIGHT)
1941 mode = SHADERMODE_LIGHTSOURCE;
1942 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1943 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1944 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
1945 permutation |= SHADERPERMUTATION_CUBEFILTER;
1946 if (diffusescale > 0)
1947 permutation |= SHADERPERMUTATION_DIFFUSE;
1948 if (specularscale > 0)
1949 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
1950 if (r_refdef.fogenabled)
1951 permutation |= SHADERPERMUTATION_FOG;
1952 if (rsurface.texture->colormapping)
1953 permutation |= SHADERPERMUTATION_COLORMAPPING;
1954 if (r_shadow_usingshadowmaprect)
1955 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
1956 if (r_shadow_usingshadowmapcube)
1957 permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
1958 if (r_shadow_usingshadowmap2d)
1959 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
1961 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
1963 // unshaded geometry (fullbright or ambient model lighting)
1964 mode = SHADERMODE_FLATCOLOR;
1965 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1966 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1967 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
1968 permutation |= SHADERPERMUTATION_GLOW;
1969 if (r_refdef.fogenabled)
1970 permutation |= SHADERPERMUTATION_FOG;
1971 if (rsurface.texture->colormapping)
1972 permutation |= SHADERPERMUTATION_COLORMAPPING;
1973 if (r_glsl_offsetmapping.integer)
1975 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
1976 if (r_glsl_offsetmapping_reliefmapping.integer)
1977 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
1979 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1980 permutation |= SHADERPERMUTATION_REFLECTION;
1982 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
1984 // directional model lighting
1985 mode = SHADERMODE_LIGHTDIRECTION;
1986 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1987 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1988 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
1989 permutation |= SHADERPERMUTATION_GLOW;
1990 permutation |= SHADERPERMUTATION_DIFFUSE;
1991 if (specularscale > 0)
1992 permutation |= SHADERPERMUTATION_SPECULAR;
1993 if (r_refdef.fogenabled)
1994 permutation |= SHADERPERMUTATION_FOG;
1995 if (rsurface.texture->colormapping)
1996 permutation |= SHADERPERMUTATION_COLORMAPPING;
1997 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1998 permutation |= SHADERPERMUTATION_REFLECTION;
2000 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2002 // ambient model lighting
2003 mode = SHADERMODE_LIGHTDIRECTION;
2004 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2005 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2006 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2007 permutation |= SHADERPERMUTATION_GLOW;
2008 if (r_refdef.fogenabled)
2009 permutation |= SHADERPERMUTATION_FOG;
2010 if (rsurface.texture->colormapping)
2011 permutation |= SHADERPERMUTATION_COLORMAPPING;
2012 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2013 permutation |= SHADERPERMUTATION_REFLECTION;
2018 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2020 // deluxemapping (light direction texture)
2021 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2022 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2024 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2025 permutation |= SHADERPERMUTATION_DIFFUSE;
2026 if (specularscale > 0)
2027 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2029 else if (r_glsl_deluxemapping.integer >= 2)
2031 // fake deluxemapping (uniform light direction in tangentspace)
2032 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2033 permutation |= SHADERPERMUTATION_DIFFUSE;
2034 if (specularscale > 0)
2035 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2037 else if (rsurface.uselightmaptexture)
2039 // ordinary lightmapping (q1bsp, q3bsp)
2040 mode = SHADERMODE_LIGHTMAP;
2044 // ordinary vertex coloring (q3bsp)
2045 mode = SHADERMODE_VERTEXCOLOR;
2047 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2048 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2049 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2050 permutation |= SHADERPERMUTATION_GLOW;
2051 if (r_refdef.fogenabled)
2052 permutation |= SHADERPERMUTATION_FOG;
2053 if (rsurface.texture->colormapping)
2054 permutation |= SHADERPERMUTATION_COLORMAPPING;
2055 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2056 permutation |= SHADERPERMUTATION_REFLECTION;
2058 if(permutation & SHADERPERMUTATION_SPECULAR)
2059 if(r_shadow_glossexact.integer)
2060 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
2061 R_SetupShader_SetPermutation(mode, permutation);
2062 if (mode == SHADERMODE_LIGHTSOURCE)
2064 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2065 if (permutation & SHADERPERMUTATION_DIFFUSE)
2067 if (r_glsl_permutation->loc_TintColor >= 0) qglUniform4fARB(r_glsl_permutation->loc_TintColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2], rsurface.texture->lightmapcolor[3]);
2068 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, ambientscale);
2069 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, diffusescale);
2070 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, specularscale);
2074 // ambient only is simpler
2075 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]);
2076 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, 1);
2077 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, 0);
2078 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, 0);
2080 // additive passes are only darkened by fog, not tinted
2081 if (r_glsl_permutation->loc_FogColor >= 0)
2082 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2083 if (r_glsl_permutation->loc_ShadowMap_Bias >= 0) qglUniform1fARB(r_glsl_permutation->loc_ShadowMap_Bias, r_shadow_shadowmap_bias);
2084 if (r_glsl_permutation->loc_ShadowMap_TextureScale >= 0) qglUniform2fARB(r_glsl_permutation->loc_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2085 if (r_glsl_permutation->loc_ShadowMap_Parameters >= 0) qglUniform4fARB(r_glsl_permutation->loc_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2089 if (mode == SHADERMODE_LIGHTDIRECTION)
2091 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);
2092 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);
2093 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);
2094 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]);
2098 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_refdef.scene.ambient * 1.0f / 128.0f);
2099 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_refdef.lightmapintensity);
2100 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, r_refdef.lightmapintensity * specularscale);
2102 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]);
2103 if (r_glsl_permutation->loc_GlowScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_GlowScale, r_hdr_glowintensity.value);
2104 // additive passes are only darkened by fog, not tinted
2105 if (r_glsl_permutation->loc_FogColor >= 0)
2107 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
2108 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2110 qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2112 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);
2113 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]);
2114 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]);
2115 if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f);
2116 if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f);
2117 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2118 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2120 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_refdef.view.colorscale);
2121 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.modelorg[0], rsurface.modelorg[1], rsurface.modelorg[2]);
2122 if (r_glsl_permutation->loc_Color_Pants >= 0)
2124 if (rsurface.texture->currentskinframe->pants)
2125 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2127 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2129 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2131 if (rsurface.texture->currentskinframe->shirt)
2132 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2134 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2136 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, r_refdef.fograngerecip * Matrix4x4_ScaleFromMatrix(&rsurface.matrix));
2137 if(permutation & SHADERPERMUTATION_EXACTSPECULARMATH)
2139 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * 0.25);
2143 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower);
2145 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
2149 #define SKINFRAME_HASH 1024
2153 int loadsequence; // incremented each level change
2154 memexpandablearray_t array;
2155 skinframe_t *hash[SKINFRAME_HASH];
2158 r_skinframe_t r_skinframe;
2160 void R_SkinFrame_PrepareForPurge(void)
2162 r_skinframe.loadsequence++;
2163 // wrap it without hitting zero
2164 if (r_skinframe.loadsequence >= 200)
2165 r_skinframe.loadsequence = 1;
2168 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
2172 // mark the skinframe as used for the purging code
2173 skinframe->loadsequence = r_skinframe.loadsequence;
2176 void R_SkinFrame_Purge(void)
2180 for (i = 0;i < SKINFRAME_HASH;i++)
2182 for (s = r_skinframe.hash[i];s;s = s->next)
2184 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
2186 if (s->merged == s->base)
2188 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
2189 R_PurgeTexture(s->stain );s->stain = NULL;
2190 R_PurgeTexture(s->merged);s->merged = NULL;
2191 R_PurgeTexture(s->base );s->base = NULL;
2192 R_PurgeTexture(s->pants );s->pants = NULL;
2193 R_PurgeTexture(s->shirt );s->shirt = NULL;
2194 R_PurgeTexture(s->nmap );s->nmap = NULL;
2195 R_PurgeTexture(s->gloss );s->gloss = NULL;
2196 R_PurgeTexture(s->glow );s->glow = NULL;
2197 R_PurgeTexture(s->fog );s->fog = NULL;
2198 s->loadsequence = 0;
2204 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
2206 char basename[MAX_QPATH];
2208 Image_StripImageExtension(name, basename, sizeof(basename));
2210 if( last == NULL ) {
2212 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
2213 item = r_skinframe.hash[hashindex];
2218 // linearly search through the hash bucket
2219 for( ; item ; item = item->next ) {
2220 if( !strcmp( item->basename, basename ) ) {
2227 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
2231 char basename[MAX_QPATH];
2233 Image_StripImageExtension(name, basename, sizeof(basename));
2235 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
2236 for (item = r_skinframe.hash[hashindex];item;item = item->next)
2237 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
2241 rtexture_t *dyntexture;
2242 // check whether its a dynamic texture
2243 dyntexture = CL_GetDynTexture( basename );
2244 if (!add && !dyntexture)
2246 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
2247 memset(item, 0, sizeof(*item));
2248 strlcpy(item->basename, basename, sizeof(item->basename));
2249 item->base = dyntexture; // either NULL or dyntexture handle
2250 item->textureflags = textureflags;
2251 item->comparewidth = comparewidth;
2252 item->compareheight = compareheight;
2253 item->comparecrc = comparecrc;
2254 item->next = r_skinframe.hash[hashindex];
2255 r_skinframe.hash[hashindex] = item;
2257 else if( item->base == NULL )
2259 rtexture_t *dyntexture;
2260 // check whether its a dynamic texture
2261 // 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]
2262 dyntexture = CL_GetDynTexture( basename );
2263 item->base = dyntexture; // either NULL or dyntexture handle
2266 R_SkinFrame_MarkUsed(item);
2270 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
2272 unsigned long long avgcolor[5], wsum; \
2280 for(pix = 0; pix < cnt; ++pix) \
2283 for(comp = 0; comp < 3; ++comp) \
2285 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
2288 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
2290 for(comp = 0; comp < 3; ++comp) \
2291 avgcolor[comp] += getpixel * w; \
2294 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
2295 avgcolor[4] += getpixel; \
2297 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
2299 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
2300 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
2301 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
2302 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
2305 skinframe_t *R_SkinFrame_LoadExternal_CheckAlpha(const char *name, int textureflags, qboolean complain, qboolean *has_alpha)
2307 // FIXME: it should be possible to disable loading various layers using
2308 // cvars, to prevent wasted loading time and memory usage if the user does
2310 qboolean loadnormalmap = true;
2311 qboolean loadgloss = true;
2312 qboolean loadpantsandshirt = true;
2313 qboolean loadglow = true;
2315 unsigned char *pixels;
2316 unsigned char *bumppixels;
2317 unsigned char *basepixels = NULL;
2318 int basepixels_width;
2319 int basepixels_height;
2320 skinframe_t *skinframe;
2324 if (cls.state == ca_dedicated)
2327 // return an existing skinframe if already loaded
2328 // if loading of the first image fails, don't make a new skinframe as it
2329 // would cause all future lookups of this to be missing
2330 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
2331 if (skinframe && skinframe->base)
2334 basepixels = loadimagepixelsbgra(name, complain, true);
2335 if (basepixels == NULL)
2338 if (developer_loading.integer)
2339 Con_Printf("loading skin \"%s\"\n", name);
2341 // we've got some pixels to store, so really allocate this new texture now
2343 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
2344 skinframe->stain = NULL;
2345 skinframe->merged = NULL;
2346 skinframe->base = r_texture_notexture;
2347 skinframe->pants = NULL;
2348 skinframe->shirt = NULL;
2349 skinframe->nmap = r_texture_blanknormalmap;
2350 skinframe->gloss = NULL;
2351 skinframe->glow = NULL;
2352 skinframe->fog = NULL;
2354 basepixels_width = image_width;
2355 basepixels_height = image_height;
2356 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);
2358 if (textureflags & TEXF_ALPHA)
2360 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
2361 if (basepixels[j] < 255)
2363 if (j < basepixels_width * basepixels_height * 4)
2365 // has transparent pixels
2367 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
2368 for (j = 0;j < image_width * image_height * 4;j += 4)
2373 pixels[j+3] = basepixels[j+3];
2375 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);
2380 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
2381 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
2383 // _norm is the name used by tenebrae and has been adopted as standard
2386 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false)) != NULL)
2388 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | skinframe->textureflags) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), NULL);
2392 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false)) != NULL)
2394 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
2395 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
2396 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | skinframe->textureflags) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), NULL);
2398 Mem_Free(bumppixels);
2400 else if (r_shadow_bumpscale_basetexture.value > 0)
2402 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
2403 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
2404 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), basepixels_width, basepixels_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | skinframe->textureflags) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), NULL);
2408 // _luma is supported for tenebrae compatibility
2409 // (I think it's a very stupid name, but oh well)
2410 // _glow is the preferred name
2411 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;}
2412 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;}
2413 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;}
2414 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;}
2417 Mem_Free(basepixels);
2422 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
2425 return R_SkinFrame_LoadExternal_CheckAlpha(name, textureflags, complain, &has_alpha);
2428 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)
2433 for (i = 0;i < width*height;i++)
2434 if (((unsigned char *)&palette[in[i]])[3] > 0)
2436 if (i == width*height)
2439 return R_LoadTexture2D (r_main_texturepool, name, width, height, in, TEXTYPE_PALETTE, textureflags, palette);
2442 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
2443 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
2446 unsigned char *temp1, *temp2;
2447 skinframe_t *skinframe;
2449 if (cls.state == ca_dedicated)
2452 // if already loaded just return it, otherwise make a new skinframe
2453 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
2454 if (skinframe && skinframe->base)
2457 skinframe->stain = NULL;
2458 skinframe->merged = NULL;
2459 skinframe->base = r_texture_notexture;
2460 skinframe->pants = NULL;
2461 skinframe->shirt = NULL;
2462 skinframe->nmap = r_texture_blanknormalmap;
2463 skinframe->gloss = NULL;
2464 skinframe->glow = NULL;
2465 skinframe->fog = NULL;
2467 // if no data was provided, then clearly the caller wanted to get a blank skinframe
2471 if (developer_loading.integer)
2472 Con_Printf("loading 32bit skin \"%s\"\n", name);
2474 if (r_shadow_bumpscale_basetexture.value > 0)
2476 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
2477 temp2 = temp1 + width * height * 4;
2478 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
2479 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
2482 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, skinframe->textureflags, NULL);
2483 if (textureflags & TEXF_ALPHA)
2485 for (i = 3;i < width * height * 4;i += 4)
2486 if (skindata[i] < 255)
2488 if (i < width * height * 4)
2490 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
2491 memcpy(fogpixels, skindata, width * height * 4);
2492 for (i = 0;i < width * height * 4;i += 4)
2493 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
2494 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, skinframe->textureflags, NULL);
2495 Mem_Free(fogpixels);
2499 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
2500 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
2505 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
2508 unsigned char *temp1, *temp2;
2509 unsigned int *palette;
2510 skinframe_t *skinframe;
2512 if (cls.state == ca_dedicated)
2515 // if already loaded just return it, otherwise make a new skinframe
2516 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
2517 if (skinframe && skinframe->base)
2520 palette = (loadglowtexture ? palette_bgra_nofullbrights : ((skinframe->textureflags & TEXF_ALPHA) ? palette_bgra_transparent : palette_bgra_complete));
2522 skinframe->stain = NULL;
2523 skinframe->merged = NULL;
2524 skinframe->base = r_texture_notexture;
2525 skinframe->pants = NULL;
2526 skinframe->shirt = NULL;
2527 skinframe->nmap = r_texture_blanknormalmap;
2528 skinframe->gloss = NULL;
2529 skinframe->glow = NULL;
2530 skinframe->fog = NULL;
2532 // if no data was provided, then clearly the caller wanted to get a blank skinframe
2536 if (developer_loading.integer)
2537 Con_Printf("loading quake skin \"%s\"\n", name);
2539 if (r_shadow_bumpscale_basetexture.value > 0)
2541 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
2542 temp2 = temp1 + width * height * 4;
2543 // use either a custom palette or the quake palette
2544 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
2545 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
2546 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
2549 // use either a custom palette, or the quake palette
2550 skinframe->base = skinframe->merged = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_merged", skinframe->basename), palette, skinframe->textureflags, true); // all
2551 if (loadglowtexture)
2552 skinframe->glow = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_glow", skinframe->basename), palette_bgra_onlyfullbrights, skinframe->textureflags, false); // glow
2553 if (loadpantsandshirt)
2555 skinframe->pants = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_pants", skinframe->basename), palette_bgra_pantsaswhite, skinframe->textureflags, false); // pants
2556 skinframe->shirt = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_shirt", skinframe->basename), palette_bgra_shirtaswhite, skinframe->textureflags, false); // shirt
2558 if (skinframe->pants || skinframe->shirt)
2559 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
2560 if (textureflags & TEXF_ALPHA)
2562 for (i = 0;i < width * height;i++)
2563 if (((unsigned char *)palette_bgra_alpha)[skindata[i]*4+3] < 255)
2565 if (i < width * height)
2566 skinframe->fog = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_fog", skinframe->basename), palette_bgra_alpha, skinframe->textureflags, true); // fog mask
2569 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
2570 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
2575 skinframe_t *R_SkinFrame_LoadMissing(void)
2577 skinframe_t *skinframe;
2579 if (cls.state == ca_dedicated)
2582 skinframe = R_SkinFrame_Find("missing", TEXF_PRECACHE | TEXF_FORCENEAREST, 0, 0, 0, true);
2583 skinframe->stain = NULL;
2584 skinframe->merged = NULL;
2585 skinframe->base = r_texture_notexture;
2586 skinframe->pants = NULL;
2587 skinframe->shirt = NULL;
2588 skinframe->nmap = r_texture_blanknormalmap;
2589 skinframe->gloss = NULL;
2590 skinframe->glow = NULL;
2591 skinframe->fog = NULL;
2593 skinframe->avgcolor[0] = rand() / RAND_MAX;
2594 skinframe->avgcolor[1] = rand() / RAND_MAX;
2595 skinframe->avgcolor[2] = rand() / RAND_MAX;
2596 skinframe->avgcolor[3] = 1;
2601 void gl_main_start(void)
2605 memset(r_queries, 0, sizeof(r_queries));
2607 memset(r_qwskincache, 0, sizeof(r_qwskincache));
2608 memset(r_qwskincache_skinframe, 0, sizeof(r_qwskincache_skinframe));
2610 // set up r_skinframe loading system for textures
2611 memset(&r_skinframe, 0, sizeof(r_skinframe));
2612 r_skinframe.loadsequence = 1;
2613 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
2615 r_main_texturepool = R_AllocTexturePool();
2616 R_BuildBlankTextures();
2618 if (gl_texturecubemap)
2621 R_BuildNormalizationCube();
2623 r_texture_fogattenuation = NULL;
2624 r_texture_gammaramps = NULL;
2625 //r_texture_fogintensity = NULL;
2626 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
2627 memset(&r_waterstate, 0, sizeof(r_waterstate));
2628 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
2629 memset(&r_svbsp, 0, sizeof (r_svbsp));
2631 r_refdef.fogmasktable_density = 0;
2634 extern rtexture_t *loadingscreentexture;
2635 void gl_main_shutdown(void)
2638 qglDeleteQueriesARB(r_maxqueries, r_queries);
2642 memset(r_queries, 0, sizeof(r_queries));
2644 memset(r_qwskincache, 0, sizeof(r_qwskincache));
2645 memset(r_qwskincache_skinframe, 0, sizeof(r_qwskincache_skinframe));
2647 // clear out the r_skinframe state
2648 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
2649 memset(&r_skinframe, 0, sizeof(r_skinframe));
2652 Mem_Free(r_svbsp.nodes);
2653 memset(&r_svbsp, 0, sizeof (r_svbsp));
2654 R_FreeTexturePool(&r_main_texturepool);
2655 loadingscreentexture = NULL;
2656 r_texture_blanknormalmap = NULL;
2657 r_texture_white = NULL;
2658 r_texture_grey128 = NULL;
2659 r_texture_black = NULL;
2660 r_texture_whitecube = NULL;
2661 r_texture_normalizationcube = NULL;
2662 r_texture_fogattenuation = NULL;
2663 r_texture_gammaramps = NULL;
2664 //r_texture_fogintensity = NULL;
2665 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
2666 memset(&r_waterstate, 0, sizeof(r_waterstate));
2670 extern void CL_ParseEntityLump(char *entitystring);
2671 void gl_main_newmap(void)
2673 // FIXME: move this code to client
2675 char *entities, entname[MAX_QPATH];
2678 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
2679 l = (int)strlen(entname) - 4;
2680 if (l >= 0 && !strcmp(entname + l, ".bsp"))
2682 memcpy(entname + l, ".ent", 5);
2683 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
2685 CL_ParseEntityLump(entities);
2690 if (cl.worldmodel->brush.entities)
2691 CL_ParseEntityLump(cl.worldmodel->brush.entities);
2695 void GL_Main_Init(void)
2697 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
2699 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
2700 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
2701 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
2702 if (gamemode == GAME_NEHAHRA)
2704 Cvar_RegisterVariable (&gl_fogenable);
2705 Cvar_RegisterVariable (&gl_fogdensity);
2706 Cvar_RegisterVariable (&gl_fogred);
2707 Cvar_RegisterVariable (&gl_foggreen);
2708 Cvar_RegisterVariable (&gl_fogblue);
2709 Cvar_RegisterVariable (&gl_fogstart);
2710 Cvar_RegisterVariable (&gl_fogend);
2711 Cvar_RegisterVariable (&gl_skyclip);
2713 Cvar_RegisterVariable(&r_motionblur);
2714 Cvar_RegisterVariable(&r_motionblur_maxblur);
2715 Cvar_RegisterVariable(&r_motionblur_bmin);
2716 Cvar_RegisterVariable(&r_motionblur_vmin);
2717 Cvar_RegisterVariable(&r_motionblur_vmax);
2718 Cvar_RegisterVariable(&r_motionblur_vcoeff);
2719 Cvar_RegisterVariable(&r_motionblur_randomize);
2720 Cvar_RegisterVariable(&r_damageblur);
2721 Cvar_RegisterVariable(&r_animcache);
2722 Cvar_RegisterVariable(&r_depthfirst);
2723 Cvar_RegisterVariable(&r_useinfinitefarclip);
2724 Cvar_RegisterVariable(&r_nearclip);
2725 Cvar_RegisterVariable(&r_showbboxes);
2726 Cvar_RegisterVariable(&r_showsurfaces);
2727 Cvar_RegisterVariable(&r_showtris);
2728 Cvar_RegisterVariable(&r_shownormals);
2729 Cvar_RegisterVariable(&r_showlighting);
2730 Cvar_RegisterVariable(&r_showshadowvolumes);
2731 Cvar_RegisterVariable(&r_showcollisionbrushes);
2732 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
2733 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
2734 Cvar_RegisterVariable(&r_showdisabledepthtest);
2735 Cvar_RegisterVariable(&r_drawportals);
2736 Cvar_RegisterVariable(&r_drawentities);
2737 Cvar_RegisterVariable(&r_cullentities_trace);
2738 Cvar_RegisterVariable(&r_cullentities_trace_samples);
2739 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
2740 Cvar_RegisterVariable(&r_cullentities_trace_delay);
2741 Cvar_RegisterVariable(&r_drawviewmodel);
2742 Cvar_RegisterVariable(&r_speeds);
2743 Cvar_RegisterVariable(&r_fullbrights);
2744 Cvar_RegisterVariable(&r_wateralpha);
2745 Cvar_RegisterVariable(&r_dynamic);
2746 Cvar_RegisterVariable(&r_fullbright);
2747 Cvar_RegisterVariable(&r_shadows);
2748 Cvar_RegisterVariable(&r_shadows_darken);
2749 Cvar_RegisterVariable(&r_shadows_drawafterrtlightning);
2750 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
2751 Cvar_RegisterVariable(&r_shadows_throwdistance);
2752 Cvar_RegisterVariable(&r_shadows_throwdirection);
2753 Cvar_RegisterVariable(&r_q1bsp_skymasking);
2754 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
2755 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
2756 Cvar_RegisterVariable(&r_fog_exp2);
2757 Cvar_RegisterVariable(&r_drawfog);
2758 Cvar_RegisterVariable(&r_textureunits);
2759 Cvar_RegisterVariable(&r_glsl);
2760 Cvar_RegisterVariable(&r_glsl_deluxemapping);
2761 Cvar_RegisterVariable(&r_glsl_offsetmapping);
2762 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
2763 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
2764 Cvar_RegisterVariable(&r_glsl_postprocess);
2765 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
2766 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
2767 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
2768 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
2769 Cvar_RegisterVariable(&r_glsl_usegeneric);
2770 Cvar_RegisterVariable(&r_water);
2771 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
2772 Cvar_RegisterVariable(&r_water_clippingplanebias);
2773 Cvar_RegisterVariable(&r_water_refractdistort);
2774 Cvar_RegisterVariable(&r_water_reflectdistort);
2775 Cvar_RegisterVariable(&r_lerpsprites);
2776 Cvar_RegisterVariable(&r_lerpmodels);
2777 Cvar_RegisterVariable(&r_lerplightstyles);
2778 Cvar_RegisterVariable(&r_waterscroll);
2779 Cvar_RegisterVariable(&r_bloom);
2780 Cvar_RegisterVariable(&r_bloom_colorscale);
2781 Cvar_RegisterVariable(&r_bloom_brighten);
2782 Cvar_RegisterVariable(&r_bloom_blur);
2783 Cvar_RegisterVariable(&r_bloom_resolution);
2784 Cvar_RegisterVariable(&r_bloom_colorexponent);
2785 Cvar_RegisterVariable(&r_bloom_colorsubtract);
2786 Cvar_RegisterVariable(&r_hdr);
2787 Cvar_RegisterVariable(&r_hdr_scenebrightness);
2788 Cvar_RegisterVariable(&r_hdr_glowintensity);
2789 Cvar_RegisterVariable(&r_hdr_range);
2790 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
2791 Cvar_RegisterVariable(&developer_texturelogging);
2792 Cvar_RegisterVariable(&gl_lightmaps);
2793 Cvar_RegisterVariable(&r_test);
2794 Cvar_RegisterVariable(&r_batchmode);
2795 Cvar_RegisterVariable(&r_glsl_saturation);
2796 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
2797 Cvar_SetValue("r_fullbrights", 0);
2798 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
2800 Cvar_RegisterVariable(&r_track_sprites);
2801 Cvar_RegisterVariable(&r_track_sprites_flags);
2802 Cvar_RegisterVariable(&r_track_sprites_scalew);
2803 Cvar_RegisterVariable(&r_track_sprites_scaleh);
2806 extern void R_Textures_Init(void);
2807 extern void GL_Draw_Init(void);
2808 extern void GL_Main_Init(void);
2809 extern void R_Shadow_Init(void);
2810 extern void R_Sky_Init(void);
2811 extern void GL_Surf_Init(void);
2812 extern void R_Particles_Init(void);
2813 extern void R_Explosion_Init(void);
2814 extern void gl_backend_init(void);
2815 extern void Sbar_Init(void);
2816 extern void R_LightningBeams_Init(void);
2817 extern void Mod_RenderInit(void);
2819 void Render_Init(void)
2831 R_LightningBeams_Init();
2840 extern char *ENGINE_EXTENSIONS;
2843 gl_renderer = (const char *)qglGetString(GL_RENDERER);
2844 gl_vendor = (const char *)qglGetString(GL_VENDOR);
2845 gl_version = (const char *)qglGetString(GL_VERSION);
2846 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
2850 if (!gl_platformextensions)
2851 gl_platformextensions = "";
2853 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
2854 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
2855 Con_Printf("GL_VERSION: %s\n", gl_version);
2856 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
2857 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
2859 VID_CheckExtensions();
2861 // LordHavoc: report supported extensions
2862 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
2864 // clear to black (loading plaque will be seen over this)
2866 qglClearColor(0,0,0,1);CHECKGLERROR
2867 qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
2870 int R_CullBox(const vec3_t mins, const vec3_t maxs)
2874 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
2876 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
2879 p = r_refdef.view.frustum + i;
2884 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2888 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2892 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2896 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2900 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2904 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2908 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2912 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2920 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
2924 for (i = 0;i < numplanes;i++)
2931 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2935 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2939 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2943 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2947 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2951 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2955 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2959 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2967 //==================================================================================
2969 // LordHavoc: animcache written by Echon, refactored and reformatted by me
2972 * Animation cache helps save re-animating a player mesh if it's re-rendered again in a given frame
2973 * (reflections, lighting, etc). All animation cache becomes invalid on the next frame and is flushed
2974 * (well, over-wrote). The memory for each cache is kept around to save on allocation thrashing.
2977 typedef struct r_animcache_entity_s
2984 qboolean wantnormals;
2985 qboolean wanttangents;
2987 r_animcache_entity_t;
2989 typedef struct r_animcache_s
2991 r_animcache_entity_t entity[MAX_EDICTS*2];
2997 static r_animcache_t r_animcachestate;
2999 void R_AnimCache_Free(void)
3002 for (idx=0 ; idx<r_animcachestate.maxindex ; idx++)
3004 r_animcachestate.entity[idx].maxvertices = 0;
3005 Mem_Free(r_animcachestate.entity[idx].vertex3f);
3006 r_animcachestate.entity[idx].vertex3f = NULL;
3007 r_animcachestate.entity[idx].normal3f = NULL;
3008 r_animcachestate.entity[idx].svector3f = NULL;
3009 r_animcachestate.entity[idx].tvector3f = NULL;
3011 r_animcachestate.currentindex = 0;
3012 r_animcachestate.maxindex = 0;
3015 void R_AnimCache_ResizeEntityCache(const int cacheIdx, const int numvertices)
3019 r_animcache_entity_t *cache = &r_animcachestate.entity[cacheIdx];
3021 if (cache->maxvertices >= numvertices)
3024 // Release existing memory
3025 if (cache->vertex3f)
3026 Mem_Free(cache->vertex3f);
3028 // Pad by 1024 verts
3029 cache->maxvertices = (numvertices + 1023) & ~1023;
3030 arraySize = cache->maxvertices * 3;
3032 // Allocate, even if we don't need this memory in this instance it will get ignored and potentially used later
3033 base = (float *)Mem_Alloc(r_main_mempool, arraySize * sizeof(float) * 4);
3034 r_animcachestate.entity[cacheIdx].vertex3f = base;
3035 r_animcachestate.entity[cacheIdx].normal3f = base + arraySize;
3036 r_animcachestate.entity[cacheIdx].svector3f = base + arraySize*2;
3037 r_animcachestate.entity[cacheIdx].tvector3f = base + arraySize*3;
3039 // Con_Printf("allocated cache for %i (%f KB)\n", cacheIdx, (arraySize*sizeof(float)*4)/1024.0f);
3042 void R_AnimCache_NewFrame(void)
3046 if (r_animcache.integer && r_drawentities.integer)
3047 r_animcachestate.maxindex = sizeof(r_animcachestate.entity) / sizeof(r_animcachestate.entity[0]);
3048 else if (r_animcachestate.maxindex)
3051 r_animcachestate.currentindex = 0;
3053 for (i = 0;i < r_refdef.scene.numentities;i++)
3054 r_refdef.scene.entities[i]->animcacheindex = -1;
3057 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
3059 dp_model_t *model = ent->model;
3060 r_animcache_entity_t *c;
3061 // see if it's already cached this frame
3062 if (ent->animcacheindex >= 0)
3064 // add normals/tangents if needed
3065 c = r_animcachestate.entity + ent->animcacheindex;
3067 wantnormals = false;
3068 if (c->wanttangents)
3069 wanttangents = false;
3070 if (wantnormals || wanttangents)
3071 model->AnimateVertices(model, ent->frameblend, NULL, wantnormals ? c->normal3f : NULL, wanttangents ? c->svector3f : NULL, wanttangents ? c->tvector3f : NULL);
3075 // see if this ent is worth caching
3076 if (r_animcachestate.maxindex <= r_animcachestate.currentindex)
3078 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0))
3080 // assign it a cache entry and make sure the arrays are big enough
3081 R_AnimCache_ResizeEntityCache(r_animcachestate.currentindex, model->surfmesh.num_vertices);
3082 ent->animcacheindex = r_animcachestate.currentindex++;
3083 c = r_animcachestate.entity + ent->animcacheindex;
3084 c->wantnormals = wantnormals;
3085 c->wanttangents = wanttangents;
3086 model->AnimateVertices(model, ent->frameblend, c->vertex3f, wantnormals ? c->normal3f : NULL, wanttangents ? c->svector3f : NULL, wanttangents ? c->tvector3f : NULL);
3091 void R_AnimCache_CacheVisibleEntities(void)
3094 qboolean wantnormals;
3095 qboolean wanttangents;
3097 if (!r_animcachestate.maxindex)
3100 wantnormals = !r_showsurfaces.integer;
3101 wanttangents = !r_showsurfaces.integer && (r_glsl.integer || r_refdef.scene.rtworld || r_refdef.scene.rtdlight);
3103 // TODO: thread this?
3105 for (i = 0;i < r_refdef.scene.numentities;i++)
3107 if (!r_refdef.viewcache.entityvisible[i])
3109 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
3113 //==================================================================================
3115 static void R_View_UpdateEntityLighting (void)
3118 entity_render_t *ent;
3119 vec3_t tempdiffusenormal;
3121 for (i = 0;i < r_refdef.scene.numentities;i++)
3123 ent = r_refdef.scene.entities[i];
3125 // skip unseen models
3126 if (!r_refdef.viewcache.entityvisible[i] && r_shadows.integer != 1)
3130 if (ent->model && ent->model->brush.num_leafs)
3132 // TODO: use modellight for r_ambient settings on world?
3133 VectorSet(ent->modellight_ambient, 0, 0, 0);
3134 VectorSet(ent->modellight_diffuse, 0, 0, 0);
3135 VectorSet(ent->modellight_lightdir, 0, 0, 1);
3139 // fetch the lighting from the worldmodel data
3140 VectorSet(ent->modellight_ambient, r_refdef.scene.ambient * (2.0f / 128.0f), r_refdef.scene.ambient * (2.0f / 128.0f), r_refdef.scene.ambient * (2.0f / 128.0f));
3141 VectorClear(ent->modellight_diffuse);
3142 VectorClear(tempdiffusenormal);
3143 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
3146 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
3147 r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
3150 VectorSet(ent->modellight_ambient, 1, 1, 1);
3152 // move the light direction into modelspace coordinates for lighting code
3153 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
3154 if(VectorLength2(ent->modellight_lightdir) == 0)
3155 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
3156 VectorNormalize(ent->modellight_lightdir);
3160 static void R_View_UpdateEntityVisible (void)
3163 entity_render_t *ent;
3165 if (!r_drawentities.integer)
3168 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : ((chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL : RENDER_EXTERIORMODEL);
3169 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
3171 // worldmodel can check visibility
3172 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
3173 for (i = 0;i < r_refdef.scene.numentities;i++)
3175 ent = r_refdef.scene.entities[i];
3176 if (!(ent->flags & renderimask))
3177 if (!R_CullBox(ent->mins, ent->maxs) || (ent->model->type == mod_sprite && (ent->model->sprite.sprnum_type == SPR_LABEL || ent->model->sprite.sprnum_type == SPR_LABEL_SCALE)))
3178 if ((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))
3179 r_refdef.viewcache.entityvisible[i] = true;
3181 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight)
3183 for (i = 0;i < r_refdef.scene.numentities;i++)
3185 ent = r_refdef.scene.entities[i];
3186 if(r_refdef.viewcache.entityvisible[i] && !(ent->effects & EF_NODEPTHTEST) && !(ent->flags & RENDER_VIEWMODEL) && !(ent->model && (ent->model->name[0] == '*')))
3188 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))
3189 ent->last_trace_visibility = realtime;
3190 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
3191 r_refdef.viewcache.entityvisible[i] = 0;
3198 // no worldmodel or it can't check visibility
3199 for (i = 0;i < r_refdef.scene.numentities;i++)
3201 ent = r_refdef.scene.entities[i];
3202 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));
3207 /// only used if skyrendermasked, and normally returns false
3208 int R_DrawBrushModelsSky (void)
3211 entity_render_t *ent;
3213 if (!r_drawentities.integer)
3217 for (i = 0;i < r_refdef.scene.numentities;i++)
3219 if (!r_refdef.viewcache.entityvisible[i])
3221 ent = r_refdef.scene.entities[i];
3222 if (!ent->model || !ent->model->DrawSky)
3224 ent->model->DrawSky(ent);
3230 static void R_DrawNoModel(entity_render_t *ent);
3231 static void R_DrawModels(void)
3234 entity_render_t *ent;
3236 if (!r_drawentities.integer)
3239 for (i = 0;i < r_refdef.scene.numentities;i++)
3241 if (!r_refdef.viewcache.entityvisible[i])
3243 ent = r_refdef.scene.entities[i];
3244 r_refdef.stats.entities++;
3245 if (ent->model && ent->model->Draw != NULL)
3246 ent->model->Draw(ent);
3252 static void R_DrawModelsDepth(void)
3255 entity_render_t *ent;
3257 if (!r_drawentities.integer)
3260 for (i = 0;i < r_refdef.scene.numentities;i++)
3262 if (!r_refdef.viewcache.entityvisible[i])
3264 ent = r_refdef.scene.entities[i];
3265 if (ent->model && ent->model->DrawDepth != NULL)
3266 ent->model->DrawDepth(ent);
3270 static void R_DrawModelsDebug(void)
3273 entity_render_t *ent;
3275 if (!r_drawentities.integer)
3278 for (i = 0;i < r_refdef.scene.numentities;i++)
3280 if (!r_refdef.viewcache.entityvisible[i])
3282 ent = r_refdef.scene.entities[i];
3283 if (ent->model && ent->model->DrawDebug != NULL)
3284 ent->model->DrawDebug(ent);
3288 static void R_DrawModelsAddWaterPlanes(void)
3291 entity_render_t *ent;
3293 if (!r_drawentities.integer)
3296 for (i = 0;i < r_refdef.scene.numentities;i++)
3298 if (!r_refdef.viewcache.entityvisible[i])
3300 ent = r_refdef.scene.entities[i];
3301 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
3302 ent->model->DrawAddWaterPlanes(ent);
3306 static void R_View_SetFrustum(void)
3309 double slopex, slopey;
3310 vec3_t forward, left, up, origin;
3312 // we can't trust r_refdef.view.forward and friends in reflected scenes
3313 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
3316 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
3317 r_refdef.view.frustum[0].normal[1] = 0 - 0;
3318 r_refdef.view.frustum[0].normal[2] = -1 - 0;
3319 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
3320 r_refdef.view.frustum[1].normal[1] = 0 + 0;
3321 r_refdef.view.frustum[1].normal[2] = -1 + 0;
3322 r_refdef.view.frustum[2].normal[0] = 0 - 0;
3323 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
3324 r_refdef.view.frustum[2].normal[2] = -1 - 0;
3325 r_refdef.view.frustum[3].normal[0] = 0 + 0;
3326 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
3327 r_refdef.view.frustum[3].normal[2] = -1 + 0;
3331 zNear = r_refdef.nearclip;
3332 nudge = 1.0 - 1.0 / (1<<23);
3333 r_refdef.view.frustum[4].normal[0] = 0 - 0;
3334 r_refdef.view.frustum[4].normal[1] = 0 - 0;
3335 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
3336 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
3337 r_refdef.view.frustum[5].normal[0] = 0 + 0;
3338 r_refdef.view.frustum[5].normal[1] = 0 + 0;
3339 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
3340 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
3346 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
3347 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
3348 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
3349 r_refdef.view.frustum[0].dist = m[15] - m[12];
3351 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
3352 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
3353 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
3354 r_refdef.view.frustum[1].dist = m[15] + m[12];
3356 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
3357 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
3358 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
3359 r_refdef.view.frustum[2].dist = m[15] - m[13];
3361 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
3362 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
3363 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
3364 r_refdef.view.frustum[3].dist = m[15] + m[13];
3366 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
3367 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
3368 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
3369 r_refdef.view.frustum[4].dist = m[15] - m[14];
3371 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
3372 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
3373 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
3374 r_refdef.view.frustum[5].dist = m[15] + m[14];
3377 if (r_refdef.view.useperspective)
3379 slopex = 1.0 / r_refdef.view.frustum_x;
3380 slopey = 1.0 / r_refdef.view.frustum_y;
3381 VectorMA(forward, -slopex, left, r_refdef.view.frustum[0].normal);
3382 VectorMA(forward, slopex, left, r_refdef.view.frustum[1].normal);
3383 VectorMA(forward, -slopey, up , r_refdef.view.frustum[2].normal);
3384 VectorMA(forward, slopey, up , r_refdef.view.frustum[3].normal);
3385 VectorCopy(forward, r_refdef.view.frustum[4].normal);
3387 // Leaving those out was a mistake, those were in the old code, and they
3388 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
3389 // I couldn't reproduce it after adding those normalizations. --blub
3390 VectorNormalize(r_refdef.view.frustum[0].normal);
3391 VectorNormalize(r_refdef.view.frustum[1].normal);
3392 VectorNormalize(r_refdef.view.frustum[2].normal);
3393 VectorNormalize(r_refdef.view.frustum[3].normal);
3395 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
3396 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, -1024 * r_refdef.view.frustum_x, left, -1024 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[0]);
3397 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, 1024 * r_refdef.view.frustum_x, left, -1024 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[1]);
3398 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, -1024 * r_refdef.view.frustum_x, left, 1024 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[2]);
3399 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, 1024 * r_refdef.view.frustum_x, left, 1024 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[3]);
3401 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
3402 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
3403 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
3404 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
3405 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
3409 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
3410 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
3411 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
3412 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
3413 VectorCopy(forward, r_refdef.view.frustum[4].normal);
3414 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
3415 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
3416 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
3417 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
3418 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
3420 r_refdef.view.numfrustumplanes = 5;
3422 if (r_refdef.view.useclipplane)
3424 r_refdef.view.numfrustumplanes = 6;
3425 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
3428 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
3429 PlaneClassify(r_refdef.view.frustum + i);
3431 // LordHavoc: note to all quake engine coders, Quake had a special case
3432 // for 90 degrees which assumed a square view (wrong), so I removed it,
3433 // Quake2 has it disabled as well.
3435 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
3436 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
3437 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
3438 //PlaneClassify(&frustum[0]);
3440 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
3441 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
3442 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
3443 //PlaneClassify(&frustum[1]);
3445 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
3446 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
3447 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
3448 //PlaneClassify(&frustum[2]);
3450 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
3451 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
3452 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
3453 //PlaneClassify(&frustum[3]);
3456 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
3457 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
3458 //PlaneClassify(&frustum[4]);
3461 void R_View_Update(void)
3463 R_View_SetFrustum();
3464 R_View_WorldVisibility(r_refdef.view.useclipplane);
3465 R_View_UpdateEntityVisible();
3466 R_View_UpdateEntityLighting();
3469 void R_SetupView(qboolean allowwaterclippingplane)
3471 const double *customclipplane = NULL;
3473 if (r_refdef.view.useclipplane && allowwaterclippingplane)
3475 // LordHavoc: couldn't figure out how to make this approach the
3476 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
3477 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
3478 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
3479 dist = r_refdef.view.clipplane.dist;
3480 plane[0] = r_refdef.view.clipplane.normal[0];
3481 plane[1] = r_refdef.view.clipplane.normal[1];
3482 plane[2] = r_refdef.view.clipplane.normal[2];
3484 customclipplane = plane;
3487 if (!r_refdef.view.useperspective)
3488 R_Viewport_InitOrtho(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, r_refdef.view.y, r_refdef.view.width, r_refdef.view.height, -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, customclipplane);
3489 else if (gl_stencil && r_useinfinitefarclip.integer)
3490 R_Viewport_InitPerspectiveInfinite(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, r_refdef.view.y, r_refdef.view.width, r_refdef.view.height, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, customclipplane);
3492 R_Viewport_InitPerspective(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, r_refdef.view.y, r_refdef.view.width, r_refdef.view.height, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, r_refdef.farclip, customclipplane);
3493 R_SetViewport(&r_refdef.view.viewport);
3496 void R_ResetViewRendering2D(void)
3498 r_viewport_t viewport;
3501 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
3502 R_Viewport_InitOrtho(&viewport, &identitymatrix, r_refdef.view.x, r_refdef.view.y, r_refdef.view.width, r_refdef.view.height, 0, 0, 1, 1, -10, 100, NULL);
3503 R_SetViewport(&viewport);
3504 GL_Scissor(r_refdef.view.x, vid.height - r_refdef.view.y - r_refdef.view.height, r_refdef.view.width, r_refdef.view.height);
3505 GL_Color(1, 1, 1, 1);
3506 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
3507 GL_BlendFunc(GL_ONE, GL_ZERO);
3508 GL_AlphaTest(false);
3509 GL_ScissorTest(false);
3510 GL_DepthMask(false);
3511 GL_DepthRange(0, 1);
3512 GL_DepthTest(false);
3513 R_Mesh_Matrix(&identitymatrix);
3514 R_Mesh_ResetTextureState();
3515 GL_PolygonOffset(0, 0);
3516 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
3517 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3518 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
3519 qglStencilMask(~0);CHECKGLERROR
3520 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
3521 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
3522 GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
3523 R_SetupGenericShader(true);
3526 void R_ResetViewRendering3D(void)
3530 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
3531 qglViewport(r_refdef.view.x, vid.height - (r_refdef.view.y + r_refdef.view.height), r_refdef.view.width, r_refdef.view.height);CHECKGLERROR
3533 GL_Scissor(r_refdef.view.x, vid.height - r_refdef.view.y - r_refdef.view.height, r_refdef.view.width, r_refdef.view.height);
3534 GL_Color(1, 1, 1, 1);
3535 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
3536 GL_BlendFunc(GL_ONE, GL_ZERO);
3537 GL_AlphaTest(false);
3538 GL_ScissorTest(true);
3540 GL_DepthRange(0, 1);
3542 R_Mesh_Matrix(&identitymatrix);
3543 R_Mesh_ResetTextureState();
3544 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3545 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
3546 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3547 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
3548 qglStencilMask(~0);CHECKGLERROR
3549 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
3550 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
3551 GL_CullFace(r_refdef.view.cullface_back);
3552 R_SetupGenericShader(true);
3555 void R_RenderScene(void);
3556 void R_RenderWaterPlanes(void);
3558 static void R_Water_StartFrame(void)
3561 int waterwidth, waterheight, texturewidth, textureheight;
3562 r_waterstate_waterplane_t *p;
3564 // set waterwidth and waterheight to the water resolution that will be
3565 // used (often less than the screen resolution for faster rendering)
3566 waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
3567 waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
3569 // calculate desired texture sizes
3570 // can't use water if the card does not support the texture size
3571 if (!r_water.integer || !r_glsl.integer || !gl_support_fragment_shader || waterwidth > gl_max_texture_size || waterheight > gl_max_texture_size || r_showsurfaces.integer)
3572 texturewidth = textureheight = waterwidth = waterheight = 0;
3573 else if (gl_support_arb_texture_non_power_of_two)
3575 texturewidth = waterwidth;
3576 textureheight = waterheight;
3580 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
3581 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
3584 // allocate textures as needed
3585 if (r_waterstate.waterwidth != waterwidth || r_waterstate.waterheight != waterheight || r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight)
3587 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
3588 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
3590 if (p->texture_refraction)
3591 R_FreeTexture(p->texture_refraction);
3592 p->texture_refraction = NULL;
3593 if (p->texture_reflection)
3594 R_FreeTexture(p->texture_reflection);
3595 p->texture_reflection = NULL;
3597 memset(&r_waterstate, 0, sizeof(r_waterstate));
3598 r_waterstate.waterwidth = waterwidth;
3599 r_waterstate.waterheight = waterheight;
3600 r_waterstate.texturewidth = texturewidth;
3601 r_waterstate.textureheight = textureheight;
3604 if (r_waterstate.waterwidth)
3606 r_waterstate.enabled = true;
3608 // set up variables that will be used in shader setup
3609 r_waterstate.screenscale[0] = 0.5f * (float)waterwidth / (float)texturewidth;
3610 r_waterstate.screenscale[1] = 0.5f * (float)waterheight / (float)textureheight;
3611 r_waterstate.screencenter[0] = 0.5f * (float)waterwidth / (float)texturewidth;
3612 r_waterstate.screencenter[1] = 0.5f * (float)waterheight / (float)textureheight;
3615 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
3616 r_waterstate.numwaterplanes = 0;
3619 void R_Water_AddWaterPlane(msurface_t *surface)
3621 int triangleindex, planeindex;
3627 r_waterstate_waterplane_t *p;
3628 texture_t *t = R_GetCurrentTexture(surface->texture);
3629 // just use the first triangle with a valid normal for any decisions
3630 VectorClear(normal);
3631 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
3633 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
3634 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
3635 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
3636 TriangleNormal(vert[0], vert[1], vert[2], normal);
3637 if (VectorLength2(normal) >= 0.001)
3641 VectorCopy(normal, plane.normal);
3642 VectorNormalize(plane.normal);
3643 plane.dist = DotProduct(vert[0], plane.normal);
3644 PlaneClassify(&plane);
3645 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
3647 // skip backfaces (except if nocullface is set)
3648 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
3650 VectorNegate(plane.normal, plane.normal);
3652 PlaneClassify(&plane);
3656 // find a matching plane if there is one
3657 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
3658 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
3660 if (planeindex >= r_waterstate.maxwaterplanes)
3661 return; // nothing we can do, out of planes
3663 // if this triangle does not fit any known plane rendered this frame, add one
3664 if (planeindex >= r_waterstate.numwaterplanes)
3666 // store the new plane
3667 r_waterstate.numwaterplanes++;
3669 // clear materialflags and pvs
3670 p->materialflags = 0;
3671 p->pvsvalid = false;
3673 // merge this surface's materialflags into the waterplane
3674 p->materialflags |= t->currentmaterialflags;
3675 // merge this surface's PVS into the waterplane
3676 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
3677 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
3678 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
3680 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
3685 static void R_Water_ProcessPlanes(void)
3687 r_refdef_view_t originalview;
3688 r_refdef_view_t myview;
3690 r_waterstate_waterplane_t *p;
3692 originalview = r_refdef.view;
3694 // make sure enough textures are allocated
3695 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
3697 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
3699 if (!p->texture_refraction)
3700 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);
3701 if (!p->texture_refraction)
3705 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
3707 if (!p->texture_reflection)
3708 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);
3709 if (!p->texture_reflection)
3715 r_refdef.view = originalview;
3716 r_refdef.view.showdebug = false;
3717 r_refdef.view.width = r_waterstate.waterwidth;
3718 r_refdef.view.height = r_waterstate.waterheight;
3719 r_refdef.view.useclipplane = true;
3720 myview = r_refdef.view;
3721 r_waterstate.renderingscene = true;
3722 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
3724 // render the normal view scene and copy into texture
3725 // (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)
3726 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
3728 r_refdef.view = myview;
3729 r_refdef.view.clipplane = p->plane;
3730 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
3731 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
3732 PlaneClassify(&r_refdef.view.clipplane);
3734 R_ResetViewRendering3D();
3735 R_ClearScreen(r_refdef.fogenabled);
3739 // copy view into the screen texture
3740 R_Mesh_TexBind(0, R_GetTexture(p->texture_refraction));
3741 GL_ActiveTexture(0);
3743 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
3746 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
3748 r_refdef.view = myview;
3749 // render reflected scene and copy into texture
3750 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
3751 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
3752 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
3753 r_refdef.view.clipplane = p->plane;
3754 // reverse the cullface settings for this render
3755 r_refdef.view.cullface_front = GL_FRONT;
3756 r_refdef.view.cullface_back = GL_BACK;
3757 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
3759 r_refdef.view.usecustompvs = true;
3761 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
3763 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
3766 R_ResetViewRendering3D();
3767 R_ClearScreen(r_refdef.fogenabled);
3771 R_Mesh_TexBind(0, R_GetTexture(p->texture_reflection));
3772 GL_ActiveTexture(0);
3774 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
3777 r_waterstate.renderingscene = false;
3778 r_refdef.view = originalview;
3779 R_ResetViewRendering3D();
3780 R_ClearScreen(r_refdef.fogenabled);
3784 r_refdef.view = originalview;
3785 r_waterstate.renderingscene = false;
3786 Cvar_SetValueQuick(&r_water, 0);
3787 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
3791 void R_Bloom_StartFrame(void)
3793 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
3795 // set bloomwidth and bloomheight to the bloom resolution that will be
3796 // used (often less than the screen resolution for faster rendering)
3797 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.width);
3798 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
3799 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
3800 r_bloomstate.bloomwidth = min(r_bloomstate.bloomwidth, gl_max_texture_size);
3801 r_bloomstate.bloomheight = min(r_bloomstate.bloomheight, gl_max_texture_size);
3803 // calculate desired texture sizes
3804 if (gl_support_arb_texture_non_power_of_two)
3806 screentexturewidth = r_refdef.view.width;
3807 screentextureheight = r_refdef.view.height;
3808 bloomtexturewidth = r_bloomstate.bloomwidth;
3809 bloomtextureheight = r_bloomstate.bloomheight;
3813 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
3814 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
3815 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
3816 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
3819 if ((r_hdr.integer || r_bloom.integer || (!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))) && ((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))
3821 Cvar_SetValueQuick(&r_hdr, 0);
3822 Cvar_SetValueQuick(&r_bloom, 0);
3823 Cvar_SetValueQuick(&r_motionblur, 0);
3824 Cvar_SetValueQuick(&r_damageblur, 0);
3827 if (!(r_glsl.integer && (r_glsl_postprocess.integer || (!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) || (v_glslgamma.integer && !vid_gammatables_trivial))) && !r_bloom.integer && !r_hdr.integer && (R_Stereo_Active() || (r_motionblur.value <= 0 && r_damageblur.value <= 0)))
3828 screentexturewidth = screentextureheight = 0;
3829 if (!r_hdr.integer && !r_bloom.integer)
3830 bloomtexturewidth = bloomtextureheight = 0;
3832 // allocate textures as needed
3833 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
3835 if (r_bloomstate.texture_screen)
3836 R_FreeTexture(r_bloomstate.texture_screen);
3837 r_bloomstate.texture_screen = NULL;
3838 r_bloomstate.screentexturewidth = screentexturewidth;
3839 r_bloomstate.screentextureheight = screentextureheight;
3840 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
3841 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);
3843 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
3845 if (r_bloomstate.texture_bloom)
3846 R_FreeTexture(r_bloomstate.texture_bloom);
3847 r_bloomstate.texture_bloom = NULL;
3848 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
3849 r_bloomstate.bloomtextureheight = bloomtextureheight;
3850 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
3851 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);
3854 // set up a texcoord array for the full resolution screen image
3855 // (we have to keep this around to copy back during final render)
3856 r_bloomstate.screentexcoord2f[0] = 0;
3857 r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
3858 r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
3859 r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
3860 r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
3861 r_bloomstate.screentexcoord2f[5] = 0;
3862 r_bloomstate.screentexcoord2f[6] = 0;
3863 r_bloomstate.screentexcoord2f[7] = 0;
3865 // set up a texcoord array for the reduced resolution bloom image
3866 // (which will be additive blended over the screen image)
3867 r_bloomstate.bloomtexcoord2f[0] = 0;
3868 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3869 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3870 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3871 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3872 r_bloomstate.bloomtexcoord2f[5] = 0;
3873 r_bloomstate.bloomtexcoord2f[6] = 0;
3874 r_bloomstate.bloomtexcoord2f[7] = 0;
3876 if (r_hdr.integer || r_bloom.integer)
3878 r_bloomstate.enabled = true;
3879 r_bloomstate.hdr = r_hdr.integer != 0;
3883 void R_Bloom_CopyBloomTexture(float colorscale)
3885 r_refdef.stats.bloom++;
3887 // scale down screen texture to the bloom texture size
3889 qglViewport(r_refdef.view.x, vid.height - (r_refdef.view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
3890 GL_BlendFunc(GL_ONE, GL_ZERO);
3891 GL_Color(colorscale, colorscale, colorscale, 1);
3892 // TODO: optimize with multitexture or GLSL
3893 R_SetupGenericShader(true);
3894 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
3895 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
3896 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3897 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3899 // we now have a bloom image in the framebuffer
3900 // copy it into the bloom image texture for later processing
3901 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3902 GL_ActiveTexture(0);
3904 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
3905 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3908 void R_Bloom_CopyHDRTexture(void)
3910 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3911 GL_ActiveTexture(0);
3913 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
3914 r_refdef.stats.bloom_copypixels += r_refdef.view.width * r_refdef.view.height;
3917 void R_Bloom_MakeTexture(void)
3920 float xoffset, yoffset, r, brighten;
3922 r_refdef.stats.bloom++;
3924 R_ResetViewRendering2D();
3925 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3926 R_Mesh_ColorPointer(NULL, 0, 0);
3927 R_SetupGenericShader(true);
3929 // we have a bloom image in the framebuffer
3931 qglViewport(r_refdef.view.x, vid.height - (r_refdef.view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
3933 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
3936 r = bound(0, r_bloom_colorexponent.value / x, 1);
3937 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
3938 GL_Color(r, r, r, 1);
3939 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3940 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3941 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3942 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3944 // copy the vertically blurred bloom view to a texture
3945 GL_ActiveTexture(0);
3947 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
3948 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3951 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
3952 brighten = r_bloom_brighten.value;
3954 brighten *= r_hdr_range.value;
3955 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3956 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
3958 for (dir = 0;dir < 2;dir++)
3960 // blend on at multiple vertical offsets to achieve a vertical blur
3961 // TODO: do offset blends using GLSL
3962 GL_BlendFunc(GL_ONE, GL_ZERO);
3963 for (x = -range;x <= range;x++)
3965 if (!dir){xoffset = 0;yoffset = x;}
3966 else {xoffset = x;yoffset = 0;}
3967 xoffset /= (float)r_bloomstate.bloomtexturewidth;
3968 yoffset /= (float)r_bloomstate.bloomtextureheight;
3969 // compute a texcoord array with the specified x and y offset
3970 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
3971 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3972 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3973 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3974 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3975 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
3976 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
3977 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
3978 // this r value looks like a 'dot' particle, fading sharply to
3979 // black at the edges
3980 // (probably not realistic but looks good enough)
3981 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
3982 //r = (dir ? 1.0f : brighten)/(range*2+1);
3983 r = (dir ? 1.0f : brighten)/(range*2+1)*(1 - x*x/(float)(range*range));
3984 GL_Color(r, r, r, 1);
3985 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3986 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3987 GL_BlendFunc(GL_ONE, GL_ONE);
3990 // copy the vertically blurred bloom view to a texture
3991 GL_ActiveTexture(0);
3993 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
3994 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3997 // apply subtract last
3998 // (just like it would be in a GLSL shader)
3999 if (r_bloom_colorsubtract.value > 0 && gl_support_ext_blend_subtract)
4001 GL_BlendFunc(GL_ONE, GL_ZERO);
4002 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4003 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4004 GL_Color(1, 1, 1, 1);
4005 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4006 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4008 GL_BlendFunc(GL_ONE, GL_ONE);
4009 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
4010 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
4011 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4012 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
4013 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4014 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4015 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
4017 // copy the darkened bloom view to a texture
4018 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4019 GL_ActiveTexture(0);
4021 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
4022 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4026 void R_HDR_RenderBloomTexture(void)
4028 int oldwidth, oldheight;
4029 float oldcolorscale;
4031 oldcolorscale = r_refdef.view.colorscale;
4032 oldwidth = r_refdef.view.width;
4033 oldheight = r_refdef.view.height;
4034 r_refdef.view.width = r_bloomstate.bloomwidth;
4035 r_refdef.view.height = r_bloomstate.bloomheight;
4037 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
4038 // TODO: add exposure compensation features
4039 // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
4041 r_refdef.view.showdebug = false;
4042 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
4044 R_ResetViewRendering3D();
4046 R_ClearScreen(r_refdef.fogenabled);
4047 if (r_timereport_active)
4048 R_TimeReport("HDRclear");
4051 if (r_timereport_active)
4052 R_TimeReport("visibility");
4054 r_waterstate.numwaterplanes = 0;
4055 if (r_waterstate.enabled)
4056 R_RenderWaterPlanes();
4058 r_refdef.view.showdebug = true;
4060 r_waterstate.numwaterplanes = 0;
4062 R_ResetViewRendering2D();
4064 R_Bloom_CopyHDRTexture();
4065 R_Bloom_MakeTexture();
4067 // restore the view settings
4068 r_refdef.view.width = oldwidth;
4069 r_refdef.view.height = oldheight;
4070 r_refdef.view.colorscale = oldcolorscale;
4072 R_ResetViewRendering3D();
4074 R_ClearScreen(r_refdef.fogenabled);
4075 if (r_timereport_active)
4076 R_TimeReport("viewclear");
4079 static void R_BlendView(void)
4081 if (r_bloomstate.texture_screen)
4083 // make sure the buffer is available
4084 if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
4086 R_ResetViewRendering2D();
4087 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4088 R_Mesh_ColorPointer(NULL, 0, 0);
4089 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4090 GL_ActiveTexture(0);CHECKGLERROR
4092 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
4094 // declare variables
4096 static float avgspeed;
4098 speed = VectorLength(cl.movement_velocity);
4100 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
4101 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
4103 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
4104 speed = bound(0, speed, 1);
4105 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
4107 // calculate values into a standard alpha
4108 cl.motionbluralpha = 1 - exp(-
4110 (r_motionblur.value * speed / 80)
4112 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
4115 max(0.0001, cl.time - cl.oldtime) // fps independent
4118 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
4119 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
4121 if (cl.motionbluralpha > 0)
4123 R_SetupGenericShader(true);
4124 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4125 GL_Color(1, 1, 1, cl.motionbluralpha);
4126 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4127 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
4128 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4129 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
4133 // copy view into the screen texture
4134 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
4135 r_refdef.stats.bloom_copypixels += r_refdef.view.width * r_refdef.view.height;
4138 if (r_glsl.integer && gl_support_fragment_shader && (r_bloomstate.texture_screen || r_bloomstate.texture_bloom))
4140 unsigned int permutation =
4141 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
4142 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
4143 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
4144 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
4145 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
4147 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
4149 // render simple bloom effect
4150 // copy the screen and shrink it and darken it for the bloom process
4151 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
4152 // make the bloom texture
4153 R_Bloom_MakeTexture();
4156 R_ResetViewRendering2D();
4157 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4158 R_Mesh_ColorPointer(NULL, 0, 0);
4159 GL_Color(1, 1, 1, 1);
4160 GL_BlendFunc(GL_ONE, GL_ZERO);
4161 R_SetupShader_SetPermutation(SHADERMODE_POSTPROCESS, permutation);
4162 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4163 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
4164 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_bloom));
4165 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4166 if (r_glsl_permutation->loc_Texture_GammaRamps >= 0)
4167 R_Mesh_TexBind(GL20TU_GAMMARAMPS, R_GetTexture(r_texture_gammaramps));
4168 if (r_glsl_permutation->loc_TintColor >= 0)
4169 qglUniform4fARB(r_glsl_permutation->loc_TintColor, r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
4170 if (r_glsl_permutation->loc_ClientTime >= 0)
4171 qglUniform1fARB(r_glsl_permutation->loc_ClientTime, cl.time);
4172 if (r_glsl_permutation->loc_PixelSize >= 0)
4173 qglUniform2fARB(r_glsl_permutation->loc_PixelSize, 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
4174 if (r_glsl_permutation->loc_UserVec1 >= 0)
4176 float a=0, b=0, c=0, d=0;
4177 #if _MSC_VER >= 1400
4178 #define sscanf sscanf_s
4180 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &a, &b, &c, &d);
4181 qglUniform4fARB(r_glsl_permutation->loc_UserVec1, a, b, c, d);
4183 if (r_glsl_permutation->loc_UserVec2 >= 0)
4185 float a=0, b=0, c=0, d=0;
4186 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &a, &b, &c, &d);
4187 qglUniform4fARB(r_glsl_permutation->loc_UserVec2, a, b, c, d);
4189 if (r_glsl_permutation->loc_UserVec3 >= 0)
4191 float a=0, b=0, c=0, d=0;
4192 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &a, &b, &c, &d);
4193 qglUniform4fARB(r_glsl_permutation->loc_UserVec3, a, b, c, d);
4195 if (r_glsl_permutation->loc_UserVec4 >= 0)
4197 float a=0, b=0, c=0, d=0;
4198 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &a, &b, &c, &d);
4199 qglUniform4fARB(r_glsl_permutation->loc_UserVec4, a, b, c, d);
4201 if (r_glsl_permutation->loc_Saturation >= 0)
4202 qglUniform1fARB(r_glsl_permutation->loc_Saturation, r_glsl_saturation.value);
4203 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4204 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
4210 if (r_bloomstate.texture_bloom && r_bloomstate.hdr)
4212 // render high dynamic range bloom effect
4213 // the bloom texture was made earlier this render, so we just need to
4214 // blend it onto the screen...
4215 R_ResetViewRendering2D();
4216 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4217 R_Mesh_ColorPointer(NULL, 0, 0);
4218 R_SetupGenericShader(true);
4219 GL_Color(1, 1, 1, 1);
4220 GL_BlendFunc(GL_ONE, GL_ONE);
4221 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4222 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4223 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4224 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
4226 else if (r_bloomstate.texture_bloom)
4228 // render simple bloom effect
4229 // copy the screen and shrink it and darken it for the bloom process
4230 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
4231 // make the bloom texture
4232 R_Bloom_MakeTexture();
4233 // put the original screen image back in place and blend the bloom
4235 R_ResetViewRendering2D();
4236 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4237 R_Mesh_ColorPointer(NULL, 0, 0);
4238 GL_Color(1, 1, 1, 1);
4239 GL_BlendFunc(GL_ONE, GL_ZERO);
4240 // do both in one pass if possible
4241 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4242 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4243 if (r_textureunits.integer >= 2 && gl_combine.integer)
4245 R_SetupGenericTwoTextureShader(GL_ADD);
4246 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_screen));
4247 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.screentexcoord2f, 0, 0);
4251 R_SetupGenericShader(true);
4252 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4253 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
4254 // now blend on the bloom texture
4255 GL_BlendFunc(GL_ONE, GL_ONE);
4256 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4257 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
4259 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4260 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
4262 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
4264 // apply a color tint to the whole view
4265 R_ResetViewRendering2D();
4266 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4267 R_Mesh_ColorPointer(NULL, 0, 0);
4268 R_SetupGenericShader(false);
4269 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4270 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
4271 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4275 matrix4x4_t r_waterscrollmatrix;
4277 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
4279 if (r_refdef.fog_density)
4281 r_refdef.fogcolor[0] = r_refdef.fog_red;
4282 r_refdef.fogcolor[1] = r_refdef.fog_green;
4283 r_refdef.fogcolor[2] = r_refdef.fog_blue;
4287 VectorCopy(r_refdef.fogcolor, fogvec);
4288 // color.rgb *= ContrastBoost * SceneBrightness;
4289 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
4290 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
4291 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
4292 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
4297 void R_UpdateVariables(void)
4301 r_refdef.scene.ambient = r_ambient.value;
4303 r_refdef.farclip = 4096;
4304 if (r_refdef.scene.worldmodel)
4305 r_refdef.farclip += r_refdef.scene.worldmodel->radius * 2;
4306 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
4308 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
4309 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
4310 r_refdef.polygonfactor = 0;
4311 r_refdef.polygonoffset = 0;
4312 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
4313 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
4315 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
4316 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
4317 r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
4318 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && gl_stencil;
4319 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
4320 if (r_showsurfaces.integer)
4322 r_refdef.scene.rtworld = false;
4323 r_refdef.scene.rtworldshadows = false;
4324 r_refdef.scene.rtdlight = false;
4325 r_refdef.scene.rtdlightshadows = false;
4326 r_refdef.lightmapintensity = 0;
4329 if (gamemode == GAME_NEHAHRA)
4331 if (gl_fogenable.integer)
4333 r_refdef.oldgl_fogenable = true;
4334 r_refdef.fog_density = gl_fogdensity.value;
4335 r_refdef.fog_red = gl_fogred.value;
4336 r_refdef.fog_green = gl_foggreen.value;
4337 r_refdef.fog_blue = gl_fogblue.value;
4338 r_refdef.fog_alpha = 1;
4339 r_refdef.fog_start = 0;
4340 r_refdef.fog_end = gl_skyclip.value;
4342 else if (r_refdef.oldgl_fogenable)
4344 r_refdef.oldgl_fogenable = false;
4345 r_refdef.fog_density = 0;
4346 r_refdef.fog_red = 0;
4347 r_refdef.fog_green = 0;
4348 r_refdef.fog_blue = 0;
4349 r_refdef.fog_alpha = 0;
4350 r_refdef.fog_start = 0;
4351 r_refdef.fog_end = 0;
4355 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
4356 r_refdef.fog_start = max(0, r_refdef.fog_start);
4357 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
4359 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
4361 if (r_refdef.fog_density && r_drawfog.integer)
4363 r_refdef.fogenabled = true;
4364 // this is the point where the fog reaches 0.9986 alpha, which we
4365 // consider a good enough cutoff point for the texture
4366 // (0.9986 * 256 == 255.6)
4367 if (r_fog_exp2.integer)
4368 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
4370 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
4371 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
4372 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
4373 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
4374 // fog color was already set
4375 // update the fog texture
4376 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)
4377 R_BuildFogTexture();
4380 r_refdef.fogenabled = false;
4382 if(r_glsl.integer && v_glslgamma.integer && !vid_gammatables_trivial)
4384 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
4386 // build GLSL gamma texture
4387 #define RAMPWIDTH 256
4388 unsigned short ramp[RAMPWIDTH * 3];
4389 unsigned char rampbgr[RAMPWIDTH][4];
4392 r_texture_gammaramps_serial = vid_gammatables_serial;
4394 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
4395 for(i = 0; i < RAMPWIDTH; ++i)
4397 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
4398 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
4399 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
4402 if (r_texture_gammaramps)
4404 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
4408 r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, NULL);
4414 // remove GLSL gamma texture
4418 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
4419 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
4425 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
4426 if( scenetype != r_currentscenetype ) {
4427 // store the old scenetype
4428 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
4429 r_currentscenetype = scenetype;
4430 // move in the new scene
4431 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
4440 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
4442 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
4443 if( scenetype == r_currentscenetype ) {
4444 return &r_refdef.scene;
4446 return &r_scenes_store[ scenetype ];
4455 void R_RenderView(void)
4457 if (r_timereport_active)
4458 R_TimeReport("start");
4459 r_frame++; // used only by R_GetCurrentTexture
4460 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
4462 R_AnimCache_NewFrame();
4464 if (r_refdef.view.isoverlay)
4466 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
4467 GL_Clear( GL_DEPTH_BUFFER_BIT );
4468 R_TimeReport("depthclear");
4470 r_refdef.view.showdebug = false;
4472 r_waterstate.enabled = false;
4473 r_waterstate.numwaterplanes = 0;
4481 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0/* || !r_refdef.scene.worldmodel*/)
4482 return; //Host_Error ("R_RenderView: NULL worldmodel");
4484 r_refdef.view.colorscale = r_hdr_scenebrightness.value;
4486 // break apart the view matrix into vectors for various purposes
4487 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
4488 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
4489 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
4490 VectorNegate(r_refdef.view.left, r_refdef.view.right);
4491 // make an inverted copy of the view matrix for tracking sprites
4492 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
4494 R_Shadow_UpdateWorldLightSelection();
4496 R_Bloom_StartFrame();
4497 R_Water_StartFrame();
4500 if (r_timereport_active)
4501 R_TimeReport("viewsetup");
4503 R_ResetViewRendering3D();
4505 if (r_refdef.view.clear || r_refdef.fogenabled)
4507 R_ClearScreen(r_refdef.fogenabled);
4508 if (r_timereport_active)
4509 R_TimeReport("viewclear");
4511 r_refdef.view.clear = true;
4513 // this produces a bloom texture to be used in R_BlendView() later
4515 R_HDR_RenderBloomTexture();
4517 r_refdef.view.showdebug = true;
4520 if (r_timereport_active)
4521 R_TimeReport("visibility");
4523 r_waterstate.numwaterplanes = 0;
4524 if (r_waterstate.enabled)
4525 R_RenderWaterPlanes();
4528 r_waterstate.numwaterplanes = 0;
4531 if (r_timereport_active)
4532 R_TimeReport("blendview");
4534 GL_Scissor(0, 0, vid.width, vid.height);
4535 GL_ScissorTest(false);
4539 void R_RenderWaterPlanes(void)
4541 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
4543 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
4544 if (r_timereport_active)
4545 R_TimeReport("waterworld");
4548 // don't let sound skip if going slow
4549 if (r_refdef.scene.extraupdate)
4552 R_DrawModelsAddWaterPlanes();
4553 if (r_timereport_active)
4554 R_TimeReport("watermodels");
4556 if (r_waterstate.numwaterplanes)
4558 R_Water_ProcessPlanes();
4559 if (r_timereport_active)
4560 R_TimeReport("waterscenes");
4564 extern void R_DrawLightningBeams (void);
4565 extern void VM_CL_AddPolygonsToMeshQueue (void);
4566 extern void R_DrawPortals (void);
4567 extern cvar_t cl_locs_show;
4568 static void R_DrawLocs(void);
4569 static void R_DrawEntityBBoxes(void);
4570 void R_RenderScene(void)
4572 r_refdef.stats.renders++;
4576 // don't let sound skip if going slow
4577 if (r_refdef.scene.extraupdate)
4580 R_MeshQueue_BeginScene();
4584 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);
4586 if (cl.csqc_vidvars.drawworld)
4588 // don't let sound skip if going slow
4589 if (r_refdef.scene.extraupdate)
4592 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
4594 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
4595 if (r_timereport_active)
4596 R_TimeReport("worldsky");
4599 if (R_DrawBrushModelsSky() && r_timereport_active)
4600 R_TimeReport("bmodelsky");
4603 R_AnimCache_CacheVisibleEntities();
4605 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
4607 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
4608 if (r_timereport_active)
4609 R_TimeReport("worlddepth");
4611 if (r_depthfirst.integer >= 2)
4613 R_DrawModelsDepth();
4614 if (r_timereport_active)
4615 R_TimeReport("modeldepth");
4618 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
4620 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
4621 if (r_timereport_active)
4622 R_TimeReport("world");
4625 // don't let sound skip if going slow
4626 if (r_refdef.scene.extraupdate)
4630 if (r_timereport_active)
4631 R_TimeReport("models");
4633 // don't let sound skip if going slow
4634 if (r_refdef.scene.extraupdate)
4637 if (r_shadows.integer > 0 && !r_shadows_drawafterrtlightning.integer && r_refdef.lightmapintensity > 0)
4639 R_DrawModelShadows();
4640 R_ResetViewRendering3D();
4641 // don't let sound skip if going slow
4642 if (r_refdef.scene.extraupdate)
4646 R_ShadowVolumeLighting(false);
4647 if (r_timereport_active)
4648 R_TimeReport("rtlights");
4650 // don't let sound skip if going slow
4651 if (r_refdef.scene.extraupdate)
4654 if (r_shadows.integer > 0 && r_shadows_drawafterrtlightning.integer && r_refdef.lightmapintensity > 0)
4656 R_DrawModelShadows();
4657 R_ResetViewRendering3D();
4658 // don't let sound skip if going slow
4659 if (r_refdef.scene.extraupdate)
4663 if (cl.csqc_vidvars.drawworld)
4665 R_DrawLightningBeams();
4666 if (r_timereport_active)
4667 R_TimeReport("lightning");
4670 if (r_timereport_active)
4671 R_TimeReport("decals");
4674 if (r_timereport_active)
4675 R_TimeReport("particles");
4678 if (r_timereport_active)
4679 R_TimeReport("explosions");
4682 R_SetupGenericShader(true);
4683 VM_CL_AddPolygonsToMeshQueue();
4685 if (r_refdef.view.showdebug)
4687 if (cl_locs_show.integer)
4690 if (r_timereport_active)
4691 R_TimeReport("showlocs");
4694 if (r_drawportals.integer)
4697 if (r_timereport_active)
4698 R_TimeReport("portals");
4701 if (r_showbboxes.value > 0)
4703 R_DrawEntityBBoxes();
4704 if (r_timereport_active)
4705 R_TimeReport("bboxes");
4709 R_SetupGenericShader(true);
4710 R_MeshQueue_RenderTransparent();
4711 if (r_timereport_active)
4712 R_TimeReport("drawtrans");
4714 R_SetupGenericShader(true);
4716 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))
4718 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
4719 if (r_timereport_active)
4720 R_TimeReport("worlddebug");
4721 R_DrawModelsDebug();
4722 if (r_timereport_active)
4723 R_TimeReport("modeldebug");
4726 R_SetupGenericShader(true);
4728 if (cl.csqc_vidvars.drawworld)
4731 if (r_timereport_active)
4732 R_TimeReport("coronas");
4735 // don't let sound skip if going slow
4736 if (r_refdef.scene.extraupdate)
4739 R_ResetViewRendering2D();
4742 static const unsigned short bboxelements[36] =
4752 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
4755 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
4756 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4757 GL_DepthMask(false);
4758 GL_DepthRange(0, 1);
4759 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
4760 R_Mesh_Matrix(&identitymatrix);
4761 R_Mesh_ResetTextureState();
4763 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
4764 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
4765 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
4766 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
4767 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
4768 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
4769 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
4770 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
4771 R_FillColors(color4f, 8, cr, cg, cb, ca);
4772 if (r_refdef.fogenabled)
4774 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
4776 f1 = FogPoint_World(v);
4778 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
4779 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
4780 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
4783 R_Mesh_VertexPointer(vertex3f, 0, 0);
4784 R_Mesh_ColorPointer(color4f, 0, 0);
4785 R_Mesh_ResetTextureState();
4786 R_SetupGenericShader(false);
4787 R_Mesh_Draw(0, 8, 0, 12, NULL, bboxelements, 0, 0);
4790 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
4794 prvm_edict_t *edict;
4795 prvm_prog_t *prog_save = prog;
4797 // this function draws bounding boxes of server entities
4801 GL_CullFace(GL_NONE);
4802 R_SetupGenericShader(false);
4806 for (i = 0;i < numsurfaces;i++)
4808 edict = PRVM_EDICT_NUM(surfacelist[i]);
4809 switch ((int)edict->fields.server->solid)
4811 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
4812 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
4813 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
4814 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
4815 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
4816 default: Vector4Set(color, 0, 0, 0, 0.50);break;
4818 color[3] *= r_showbboxes.value;
4819 color[3] = bound(0, color[3], 1);
4820 GL_DepthTest(!r_showdisabledepthtest.integer);
4821 GL_CullFace(r_refdef.view.cullface_front);
4822 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
4828 static void R_DrawEntityBBoxes(void)
4831 prvm_edict_t *edict;
4833 prvm_prog_t *prog_save = prog;
4835 // this function draws bounding boxes of server entities
4841 for (i = 0;i < prog->num_edicts;i++)
4843 edict = PRVM_EDICT_NUM(i);
4844 if (edict->priv.server->free)
4846 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
4847 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
4849 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
4851 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
4852 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
4858 unsigned short nomodelelements[24] =
4870 float nomodelvertex3f[6*3] =
4880 float nomodelcolor4f[6*4] =
4882 0.0f, 0.0f, 0.5f, 1.0f,
4883 0.0f, 0.0f, 0.5f, 1.0f,
4884 0.0f, 0.5f, 0.0f, 1.0f,
4885 0.0f, 0.5f, 0.0f, 1.0f,
4886 0.5f, 0.0f, 0.0f, 1.0f,
4887 0.5f, 0.0f, 0.0f, 1.0f
4890 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
4895 // this is only called once per entity so numsurfaces is always 1, and
4896 // surfacelist is always {0}, so this code does not handle batches
4897 R_Mesh_Matrix(&ent->matrix);
4899 if (ent->flags & EF_ADDITIVE)
4901 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
4902 GL_DepthMask(false);
4904 else if (ent->alpha < 1)
4906 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4907 GL_DepthMask(false);
4911 GL_BlendFunc(GL_ONE, GL_ZERO);
4914 GL_DepthRange(0, (ent->flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
4915 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
4916 GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
4917 GL_CullFace((ent->effects & EF_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
4918 R_SetupGenericShader(false);
4919 R_Mesh_VertexPointer(nomodelvertex3f, 0, 0);
4920 if (r_refdef.fogenabled)
4923 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
4924 R_Mesh_ColorPointer(color4f, 0, 0);
4925 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4926 f1 = FogPoint_World(org);
4928 for (i = 0, c = color4f;i < 6;i++, c += 4)
4930 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
4931 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
4932 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
4936 else if (ent->alpha != 1)
4938 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
4939 R_Mesh_ColorPointer(color4f, 0, 0);
4940 for (i = 0, c = color4f;i < 6;i++, c += 4)
4944 R_Mesh_ColorPointer(nomodelcolor4f, 0, 0);
4945 R_Mesh_ResetTextureState();
4946 R_Mesh_Draw(0, 6, 0, 8, NULL, nomodelelements, 0, 0);
4949 void R_DrawNoModel(entity_render_t *ent)
4952 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4953 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
4954 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
4956 // R_DrawNoModelCallback(ent, 0);
4959 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
4961 vec3_t right1, right2, diff, normal;
4963 VectorSubtract (org2, org1, normal);
4965 // calculate 'right' vector for start
4966 VectorSubtract (r_refdef.view.origin, org1, diff);
4967 CrossProduct (normal, diff, right1);
4968 VectorNormalize (right1);
4970 // calculate 'right' vector for end
4971 VectorSubtract (r_refdef.view.origin, org2, diff);
4972 CrossProduct (normal, diff, right2);
4973 VectorNormalize (right2);
4975 vert[ 0] = org1[0] + width * right1[0];
4976 vert[ 1] = org1[1] + width * right1[1];
4977 vert[ 2] = org1[2] + width * right1[2];
4978 vert[ 3] = org1[0] - width * right1[0];
4979 vert[ 4] = org1[1] - width * right1[1];
4980 vert[ 5] = org1[2] - width * right1[2];
4981 vert[ 6] = org2[0] - width * right2[0];
4982 vert[ 7] = org2[1] - width * right2[1];
4983 vert[ 8] = org2[2] - width * right2[2];
4984 vert[ 9] = org2[0] + width * right2[0];
4985 vert[10] = org2[1] + width * right2[1];
4986 vert[11] = org2[2] + width * right2[2];
4989 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
4991 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)
4993 // NOTE: this must not call qglDepthFunc (see r_shadow.c, R_BeginCoronaQuery) thanks to ATI
4997 if (r_refdef.fogenabled && !depthdisable) // TODO maybe make the unfog effect a separate flag?
4998 fog = FogPoint_World(origin);
5000 R_Mesh_Matrix(&identitymatrix);
5001 GL_BlendFunc(blendfunc1, blendfunc2);
5003 GL_CullFace(GL_NONE);
5005 GL_DepthMask(false);
5006 GL_DepthRange(0, depthshort ? 0.0625 : 1);
5007 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5008 GL_DepthTest(!depthdisable);
5010 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
5011 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
5012 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
5013 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
5014 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
5015 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
5016 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
5017 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
5018 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
5019 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
5020 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
5021 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
5023 R_Mesh_VertexPointer(vertex3f, 0, 0);
5024 R_Mesh_ColorPointer(NULL, 0, 0);
5025 R_Mesh_ResetTextureState();
5026 R_SetupGenericShader(true);
5027 R_Mesh_TexBind(0, R_GetTexture(texture));
5028 R_Mesh_TexCoordPointer(0, 2, spritetexcoord2f, 0, 0);
5029 // FIXME: fixed function path can't properly handle r_refdef.view.colorscale > 1
5030 GL_Color(cr * fog * r_refdef.view.colorscale, cg * fog * r_refdef.view.colorscale, cb * fog * r_refdef.view.colorscale, ca);
5031 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
5033 if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
5035 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
5036 GL_BlendFunc(blendfunc1, GL_ONE);
5038 GL_Color(r_refdef.fogcolor[0] * fog, r_refdef.fogcolor[1] * fog, r_refdef.fogcolor[2] * fog, ca);
5039 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
5043 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
5048 VectorSet(v, x, y, z);
5049 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
5050 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
5052 if (i == mesh->numvertices)
5054 if (mesh->numvertices < mesh->maxvertices)
5056 VectorCopy(v, vertex3f);
5057 mesh->numvertices++;
5059 return mesh->numvertices;
5065 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
5069 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
5070 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
5071 e = mesh->element3i + mesh->numtriangles * 3;
5072 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
5074 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
5075 if (mesh->numtriangles < mesh->maxtriangles)
5080 mesh->numtriangles++;
5082 element[1] = element[2];
5086 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
5090 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
5091 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
5092 e = mesh->element3i + mesh->numtriangles * 3;
5093 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
5095 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
5096 if (mesh->numtriangles < mesh->maxtriangles)
5101 mesh->numtriangles++;
5103 element[1] = element[2];
5107 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
5108 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
5110 int planenum, planenum2;
5113 mplane_t *plane, *plane2;
5115 double temppoints[2][256*3];
5116 // figure out how large a bounding box we need to properly compute this brush
5118 for (w = 0;w < numplanes;w++)
5119 maxdist = max(maxdist, planes[w].dist);
5120 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
5121 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
5122 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
5126 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
5127 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
5129 if (planenum2 == planenum)
5131 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);
5134 if (tempnumpoints < 3)
5136 // generate elements forming a triangle fan for this polygon
5137 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
5141 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)
5143 texturelayer_t *layer;
5144 layer = t->currentlayers + t->currentnumlayers++;
5146 layer->depthmask = depthmask;
5147 layer->blendfunc1 = blendfunc1;
5148 layer->blendfunc2 = blendfunc2;
5149 layer->texture = texture;
5150 layer->texmatrix = *matrix;
5151 layer->color[0] = r * r_refdef.view.colorscale;
5152 layer->color[1] = g * r_refdef.view.colorscale;
5153 layer->color[2] = b * r_refdef.view.colorscale;
5154 layer->color[3] = a;
5157 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
5160 index = parms[2] + r_refdef.scene.time * parms[3];
5161 index -= floor(index);
5165 case Q3WAVEFUNC_NONE:
5166 case Q3WAVEFUNC_NOISE:
5167 case Q3WAVEFUNC_COUNT:
5170 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
5171 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
5172 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
5173 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
5174 case Q3WAVEFUNC_TRIANGLE:
5176 f = index - floor(index);
5187 return (float)(parms[0] + parms[1] * f);
5190 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
5195 matrix4x4_t matrix, temp;
5196 switch(tcmod->tcmod)
5200 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
5201 matrix = r_waterscrollmatrix;
5203 matrix = identitymatrix;
5205 case Q3TCMOD_ENTITYTRANSLATE:
5206 // this is used in Q3 to allow the gamecode to control texcoord
5207 // scrolling on the entity, which is not supported in darkplaces yet.
5208 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
5210 case Q3TCMOD_ROTATE:
5211 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
5212 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
5213 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
5216 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
5218 case Q3TCMOD_SCROLL:
5219 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
5221 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
5222 w = (int) tcmod->parms[0];
5223 h = (int) tcmod->parms[1];
5224 f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
5226 idx = (int) floor(f * w * h);
5227 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
5229 case Q3TCMOD_STRETCH:
5230 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
5231 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
5233 case Q3TCMOD_TRANSFORM:
5234 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
5235 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
5236 VectorSet(tcmat + 6, 0 , 0 , 1);
5237 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
5238 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
5240 case Q3TCMOD_TURBULENT:
5241 // this is handled in the RSurf_PrepareVertices function
5242 matrix = identitymatrix;
5246 Matrix4x4_Concat(texmatrix, &matrix, &temp);
5249 texture_t *R_GetCurrentTexture(texture_t *t)
5252 const entity_render_t *ent = rsurface.entity;
5253 dp_model_t *model = ent->model;
5254 q3shaderinfo_layer_tcmod_t *tcmod;
5256 if (t->update_lastrenderframe == r_frame && t->update_lastrenderentity == (void *)ent)
5257 return t->currentframe;
5258 t->update_lastrenderframe = r_frame;
5259 t->update_lastrenderentity = (void *)ent;
5261 // switch to an alternate material if this is a q1bsp animated material
5263 texture_t *texture = t;
5264 int s = ent->skinnum;
5265 if ((unsigned int)s >= (unsigned int)model->numskins)
5267 if (model->skinscenes)
5269 if (model->skinscenes[s].framecount > 1)
5270 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
5272 s = model->skinscenes[s].firstframe;
5275 t = t + s * model->num_surfaces;
5278 // use an alternate animation if the entity's frame is not 0,
5279 // and only if the texture has an alternate animation
5280 if (ent->framegroupblend[0].frame != 0 && t->anim_total[1])
5281 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
5283 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
5285 texture->currentframe = t;
5288 // update currentskinframe to be a qw skin or animation frame
5289 if ((i = ent->entitynumber - 1) >= 0 && i < cl.maxclients && cls.protocol == PROTOCOL_QUAKEWORLD && cl.scores[i].qw_skin[0] && !strcmp(ent->model->name, "progs/player.mdl"))
5291 if (strcmp(r_qwskincache[i], cl.scores[i].qw_skin))
5293 strlcpy(r_qwskincache[i], cl.scores[i].qw_skin, sizeof(r_qwskincache[i]));
5294 if (developer_loading.integer)
5295 Con_Printf("loading skins/%s\n", r_qwskincache[i]);
5296 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);
5298 t->currentskinframe = r_qwskincache_skinframe[i];
5299 if (t->currentskinframe == NULL)
5300 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->shadertime)) % t->numskinframes];
5302 else if (t->numskinframes >= 2)
5303 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->shadertime)) % t->numskinframes];
5304 if (t->backgroundnumskinframes >= 2)
5305 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - ent->shadertime)) % t->backgroundnumskinframes];
5307 t->currentmaterialflags = t->basematerialflags;
5308 t->currentalpha = ent->alpha;
5309 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
5310 t->currentalpha *= r_wateralpha.value;
5311 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
5312 t->currentalpha *= t->r_water_wateralpha;
5313 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
5314 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION);
5315 if (!(ent->flags & RENDER_LIGHT))
5316 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
5317 else if (rsurface.modeltexcoordlightmap2f == NULL)
5319 // pick a model lighting mode
5320 if (VectorLength2(ent->modellight_diffuse) >= (1.0f / 256.0f))
5321 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
5323 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
5325 if (ent->effects & EF_ADDITIVE)
5326 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
5327 else if (t->currentalpha < 1)
5328 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
5329 if (ent->effects & EF_DOUBLESIDED)
5330 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
5331 if (ent->effects & EF_NODEPTHTEST)
5332 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
5333 if (ent->flags & RENDER_VIEWMODEL)
5334 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
5335 if (t->backgroundnumskinframes)
5336 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
5337 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
5339 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER))
5340 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
5343 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER);
5345 // there is no tcmod
5346 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
5348 t->currenttexmatrix = r_waterscrollmatrix;
5349 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
5353 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
5354 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
5357 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
5358 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
5359 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
5360 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
5362 t->colormapping = VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f);
5363 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
5364 t->glosstexture = r_texture_black;
5365 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
5366 t->backgroundglosstexture = r_texture_black;
5367 t->specularpower = r_shadow_glossexponent.value;
5368 // TODO: store reference values for these in the texture?
5369 t->specularscale = 0;
5370 if (r_shadow_gloss.integer > 0)
5372 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
5374 if (r_shadow_glossintensity.value > 0)
5376 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
5377 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
5378 t->specularscale = r_shadow_glossintensity.value;
5381 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
5383 t->glosstexture = r_texture_white;
5384 t->backgroundglosstexture = r_texture_white;
5385 t->specularscale = r_shadow_gloss2intensity.value;
5389 // lightmaps mode looks bad with dlights using actual texturing, so turn
5390 // off the colormap and glossmap, but leave the normalmap on as it still
5391 // accurately represents the shading involved
5392 if (gl_lightmaps.integer)
5394 t->basetexture = r_texture_grey128;
5395 t->backgroundbasetexture = NULL;
5396 t->specularscale = 0;
5397 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
5400 Vector4Set(t->lightmapcolor, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
5401 VectorClear(t->dlightcolor);
5402 t->currentnumlayers = 0;
5403 if (t->currentmaterialflags & MATERIALFLAG_WALL)
5406 int blendfunc1, blendfunc2;
5408 if (t->currentmaterialflags & MATERIALFLAG_ADD)
5410 blendfunc1 = GL_SRC_ALPHA;
5411 blendfunc2 = GL_ONE;
5413 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
5415 blendfunc1 = GL_SRC_ALPHA;
5416 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
5418 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
5420 blendfunc1 = t->customblendfunc[0];
5421 blendfunc2 = t->customblendfunc[1];
5425 blendfunc1 = GL_ONE;
5426 blendfunc2 = GL_ZERO;
5428 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
5429 if (r_refdef.fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED))
5430 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
5431 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
5433 // fullbright is not affected by r_refdef.lightmapintensity
5434 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]);
5435 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
5436 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]);
5437 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
5438 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]);
5442 vec3_t ambientcolor;
5444 // set the color tint used for lights affecting this surface
5445 VectorSet(t->dlightcolor, ent->colormod[0] * t->lightmapcolor[3], ent->colormod[1] * t->lightmapcolor[3], ent->colormod[2] * t->lightmapcolor[3]);
5447 // q3bsp has no lightmap updates, so the lightstylevalue that
5448 // would normally be baked into the lightmap must be
5449 // applied to the color
5450 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
5451 if (ent->model->type == mod_brushq3)
5452 colorscale *= r_refdef.scene.rtlightstylevalue[0];
5453 colorscale *= r_refdef.lightmapintensity;
5454 VectorScale(t->lightmapcolor, r_refdef.scene.ambient * (1.0f / 64.0f), ambientcolor);
5455 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
5456 // basic lit geometry
5457 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]);
5458 // add pants/shirt if needed
5459 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
5460 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]);
5461 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
5462 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]);
5463 // now add ambient passes if needed
5464 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
5466 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]);
5467 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
5468 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]);
5469 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
5470 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]);
5473 if (t->currentskinframe->glow != NULL && !gl_lightmaps.integer)
5474 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]);
5475 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
5477 // if this is opaque use alpha blend which will darken the earlier
5480 // if this is an alpha blended material, all the earlier passes
5481 // were darkened by fog already, so we only need to add the fog
5482 // color ontop through the fog mask texture
5484 // if this is an additive blended material, all the earlier passes
5485 // were darkened by fog already, and we should not add fog color
5486 // (because the background was not darkened, there is no fog color
5487 // that was lost behind it).
5488 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]);
5492 return t->currentframe;
5495 rsurfacestate_t rsurface;
5497 void R_Mesh_ResizeArrays(int newvertices)
5500 if (rsurface.array_size >= newvertices)
5502 if (rsurface.array_modelvertex3f)
5503 Mem_Free(rsurface.array_modelvertex3f);
5504 rsurface.array_size = (newvertices + 1023) & ~1023;
5505 base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
5506 rsurface.array_modelvertex3f = base + rsurface.array_size * 0;
5507 rsurface.array_modelsvector3f = base + rsurface.array_size * 3;
5508 rsurface.array_modeltvector3f = base + rsurface.array_size * 6;
5509 rsurface.array_modelnormal3f = base + rsurface.array_size * 9;
5510 rsurface.array_deformedvertex3f = base + rsurface.array_size * 12;
5511 rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
5512 rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
5513 rsurface.array_deformednormal3f = base + rsurface.array_size * 21;
5514 rsurface.array_texcoord3f = base + rsurface.array_size * 24;
5515 rsurface.array_color4f = base + rsurface.array_size * 27;
5516 rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
5519 void RSurf_ActiveWorldEntity(void)
5521 dp_model_t *model = r_refdef.scene.worldmodel;
5522 //if (rsurface.entity == r_refdef.scene.worldentity)
5524 rsurface.entity = r_refdef.scene.worldentity;
5525 if (rsurface.array_size < model->surfmesh.num_vertices)
5526 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
5527 rsurface.matrix = identitymatrix;
5528 rsurface.inversematrix = identitymatrix;
5529 R_Mesh_Matrix(&identitymatrix);
5530 VectorCopy(r_refdef.view.origin, rsurface.modelorg);
5531 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
5532 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
5533 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
5534 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
5535 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
5536 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
5537 rsurface.frameblend[0].lerp = 1;
5538 rsurface.basepolygonfactor = r_refdef.polygonfactor;
5539 rsurface.basepolygonoffset = r_refdef.polygonoffset;
5540 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
5541 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
5542 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
5543 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
5544 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
5545 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
5546 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
5547 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
5548 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
5549 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
5550 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
5551 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
5552 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
5553 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
5554 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
5555 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
5556 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
5557 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
5558 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
5559 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
5560 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
5561 rsurface.modelelement3i = model->surfmesh.data_element3i;
5562 rsurface.modelelement3s = model->surfmesh.data_element3s;
5563 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
5564 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
5565 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
5566 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
5567 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
5568 rsurface.modelsurfaces = model->data_surfaces;
5569 rsurface.generatedvertex = false;
5570 rsurface.vertex3f = rsurface.modelvertex3f;
5571 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
5572 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
5573 rsurface.svector3f = rsurface.modelsvector3f;
5574 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
5575 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
5576 rsurface.tvector3f = rsurface.modeltvector3f;
5577 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
5578 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
5579 rsurface.normal3f = rsurface.modelnormal3f;
5580 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
5581 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
5582 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
5585 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
5587 dp_model_t *model = ent->model;
5588 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
5590 rsurface.entity = (entity_render_t *)ent;
5591 if (rsurface.array_size < model->surfmesh.num_vertices)
5592 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
5593 rsurface.matrix = ent->matrix;
5594 rsurface.inversematrix = ent->inversematrix;
5595 R_Mesh_Matrix(&rsurface.matrix);
5596 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.modelorg);
5597 rsurface.modellight_ambient[0] = ent->modellight_ambient[0] * ent->colormod[0];
5598 rsurface.modellight_ambient[1] = ent->modellight_ambient[1] * ent->colormod[1];
5599 rsurface.modellight_ambient[2] = ent->modellight_ambient[2] * ent->colormod[2];
5600 rsurface.modellight_diffuse[0] = ent->modellight_diffuse[0] * ent->colormod[0];
5601 rsurface.modellight_diffuse[1] = ent->modellight_diffuse[1] * ent->colormod[1];
5602 rsurface.modellight_diffuse[2] = ent->modellight_diffuse[2] * ent->colormod[2];
5603 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
5604 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
5605 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
5606 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
5607 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
5608 rsurface.basepolygonfactor = r_refdef.polygonfactor;
5609 rsurface.basepolygonoffset = r_refdef.polygonoffset;
5610 if (ent->model->brush.submodel)
5612 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
5613 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
5615 if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
5617 if (R_AnimCache_GetEntity((entity_render_t *)ent, wantnormals, wanttangents))
5619 rsurface.modelvertex3f = r_animcachestate.entity[ent->animcacheindex].vertex3f;
5620 rsurface.modelsvector3f = wanttangents ? r_animcachestate.entity[ent->animcacheindex].svector3f : NULL;
5621 rsurface.modeltvector3f = wanttangents ? r_animcachestate.entity[ent->animcacheindex].tvector3f : NULL;
5622 rsurface.modelnormal3f = wantnormals ? r_animcachestate.entity[ent->animcacheindex].normal3f : NULL;
5624 else if (wanttangents)
5626 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
5627 rsurface.modelsvector3f = rsurface.array_modelsvector3f;
5628 rsurface.modeltvector3f = rsurface.array_modeltvector3f;
5629 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
5630 model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
5632 else if (wantnormals)
5634 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
5635 rsurface.modelsvector3f = NULL;
5636 rsurface.modeltvector3f = NULL;
5637 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
5638 model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
5642 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
5643 rsurface.modelsvector3f = NULL;
5644 rsurface.modeltvector3f = NULL;
5645 rsurface.modelnormal3f = NULL;
5646 model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, NULL, NULL, NULL);
5648 rsurface.modelvertex3f_bufferobject = 0;
5649 rsurface.modelvertex3f_bufferoffset = 0;
5650 rsurface.modelsvector3f_bufferobject = 0;
5651 rsurface.modelsvector3f_bufferoffset = 0;
5652 rsurface.modeltvector3f_bufferobject = 0;
5653 rsurface.modeltvector3f_bufferoffset = 0;
5654 rsurface.modelnormal3f_bufferobject = 0;
5655 rsurface.modelnormal3f_bufferoffset = 0;
5656 rsurface.generatedvertex = true;
5660 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
5661 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
5662 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
5663 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
5664 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
5665 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
5666 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
5667 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
5668 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
5669 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
5670 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
5671 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
5672 rsurface.generatedvertex = false;
5674 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
5675 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
5676 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
5677 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
5678 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
5679 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
5680 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
5681 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
5682 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
5683 rsurface.modelelement3i = model->surfmesh.data_element3i;
5684 rsurface.modelelement3s = model->surfmesh.data_element3s;
5685 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
5686 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
5687 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
5688 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
5689 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
5690 rsurface.modelsurfaces = model->data_surfaces;
5691 rsurface.vertex3f = rsurface.modelvertex3f;
5692 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
5693 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
5694 rsurface.svector3f = rsurface.modelsvector3f;
5695 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
5696 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
5697 rsurface.tvector3f = rsurface.modeltvector3f;
5698 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
5699 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
5700 rsurface.normal3f = rsurface.modelnormal3f;
5701 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
5702 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
5703 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
5706 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
5707 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, msurface_t **texturesurfacelist)
5710 int texturesurfaceindex;
5715 const float *v1, *in_tc;
5717 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
5719 q3shaderinfo_deform_t *deform;
5720 // 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
5721 if (rsurface.generatedvertex)
5723 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
5724 generatenormals = true;
5725 for (i = 0;i < Q3MAXDEFORMS;i++)
5727 if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
5729 generatetangents = true;
5730 generatenormals = true;
5732 if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
5733 generatenormals = true;
5735 if (generatenormals && !rsurface.modelnormal3f)
5737 rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
5738 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
5739 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
5740 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
5742 if (generatetangents && !rsurface.modelsvector3f)
5744 rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
5745 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
5746 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
5747 rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
5748 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
5749 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
5750 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 != 0);
5753 rsurface.vertex3f = rsurface.modelvertex3f;
5754 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
5755 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
5756 rsurface.svector3f = rsurface.modelsvector3f;
5757 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
5758 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
5759 rsurface.tvector3f = rsurface.modeltvector3f;
5760 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
5761 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
5762 rsurface.normal3f = rsurface.modelnormal3f;
5763 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
5764 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
5765 // if vertices are deformed (sprite flares and things in maps, possibly
5766 // water waves, bulges and other deformations), generate them into
5767 // rsurface.deform* arrays from whatever the rsurface.* arrays point to
5768 // (may be static model data or generated data for an animated model, or
5769 // the previous deform pass)
5770 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
5772 switch (deform->deform)
5775 case Q3DEFORM_PROJECTIONSHADOW:
5776 case Q3DEFORM_TEXT0:
5777 case Q3DEFORM_TEXT1:
5778 case Q3DEFORM_TEXT2:
5779 case Q3DEFORM_TEXT3:
5780 case Q3DEFORM_TEXT4:
5781 case Q3DEFORM_TEXT5:
5782 case Q3DEFORM_TEXT6:
5783 case Q3DEFORM_TEXT7:
5786 case Q3DEFORM_AUTOSPRITE:
5787 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
5788 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
5789 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
5790 VectorNormalize(newforward);
5791 VectorNormalize(newright);
5792 VectorNormalize(newup);
5793 // make deformed versions of only the model vertices used by the specified surfaces
5794 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5796 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5797 // a single autosprite surface can contain multiple sprites...
5798 for (j = 0;j < surface->num_vertices - 3;j += 4)
5800 VectorClear(center);
5801 for (i = 0;i < 4;i++)
5802 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
5803 VectorScale(center, 0.25f, center);
5804 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, forward);
5805 VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
5806 VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
5807 for (i = 0;i < 4;i++)
5809 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
5810 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
5813 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 != 0);
5814 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 != 0);
5816 rsurface.vertex3f = rsurface.array_deformedvertex3f;
5817 rsurface.vertex3f_bufferobject = 0;
5818 rsurface.vertex3f_bufferoffset = 0;
5819 rsurface.svector3f = rsurface.array_deformedsvector3f;
5820 rsurface.svector3f_bufferobject = 0;
5821 rsurface.svector3f_bufferoffset = 0;
5822 rsurface.tvector3f = rsurface.array_deformedtvector3f;
5823 rsurface.tvector3f_bufferobject = 0;
5824 rsurface.tvector3f_bufferoffset = 0;
5825 rsurface.normal3f = rsurface.array_deformednormal3f;
5826 rsurface.normal3f_bufferobject = 0;
5827 rsurface.normal3f_bufferoffset = 0;
5829 case Q3DEFORM_AUTOSPRITE2:
5830 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
5831 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
5832 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
5833 VectorNormalize(newforward);
5834 VectorNormalize(newright);
5835 VectorNormalize(newup);
5836 // make deformed versions of only the model vertices used by the specified surfaces
5837 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5839 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5840 const float *v1, *v2;
5850 memset(shortest, 0, sizeof(shortest));
5851 // a single autosprite surface can contain multiple sprites...
5852 for (j = 0;j < surface->num_vertices - 3;j += 4)
5854 VectorClear(center);
5855 for (i = 0;i < 4;i++)
5856 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
5857 VectorScale(center, 0.25f, center);
5858 // find the two shortest edges, then use them to define the
5859 // axis vectors for rotating around the central axis
5860 for (i = 0;i < 6;i++)
5862 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
5863 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
5865 Debug_PolygonBegin(NULL, 0);
5866 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
5867 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);
5868 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
5871 l = VectorDistance2(v1, v2);
5872 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
5874 l += (1.0f / 1024.0f);
5875 if (shortest[0].length2 > l || i == 0)
5877 shortest[1] = shortest[0];
5878 shortest[0].length2 = l;
5879 shortest[0].v1 = v1;
5880 shortest[0].v2 = v2;
5882 else if (shortest[1].length2 > l || i == 1)
5884 shortest[1].length2 = l;
5885 shortest[1].v1 = v1;
5886 shortest[1].v2 = v2;
5889 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
5890 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
5892 Debug_PolygonBegin(NULL, 0);
5893 Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
5894 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);
5895 Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
5898 // this calculates the right vector from the shortest edge
5899 // and the up vector from the edge midpoints
5900 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
5901 VectorNormalize(right);
5902 VectorSubtract(end, start, up);
5903 VectorNormalize(up);
5904 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
5905 VectorSubtract(rsurface.modelorg, center, forward);
5906 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
5907 VectorNegate(forward, forward);
5908 VectorReflect(forward, 0, up, forward);
5909 VectorNormalize(forward);
5910 CrossProduct(up, forward, newright);
5911 VectorNormalize(newright);
5913 Debug_PolygonBegin(NULL, 0);
5914 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);
5915 Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
5916 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
5920 Debug_PolygonBegin(NULL, 0);
5921 Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
5922 Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
5923 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
5926 // rotate the quad around the up axis vector, this is made
5927 // especially easy by the fact we know the quad is flat,
5928 // so we only have to subtract the center position and
5929 // measure distance along the right vector, and then
5930 // multiply that by the newright vector and add back the
5932 // we also need to subtract the old position to undo the
5933 // displacement from the center, which we do with a
5934 // DotProduct, the subtraction/addition of center is also
5935 // optimized into DotProducts here
5936 l = DotProduct(right, center);
5937 for (i = 0;i < 4;i++)
5939 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
5940 f = DotProduct(right, v1) - l;
5941 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
5944 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 != 0);
5945 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 != 0);
5947 rsurface.vertex3f = rsurface.array_deformedvertex3f;
5948 rsurface.vertex3f_bufferobject = 0;
5949 rsurface.vertex3f_bufferoffset = 0;
5950 rsurface.svector3f = rsurface.array_deformedsvector3f;
5951 rsurface.svector3f_bufferobject = 0;
5952 rsurface.svector3f_bufferoffset = 0;
5953 rsurface.tvector3f = rsurface.array_deformedtvector3f;
5954 rsurface.tvector3f_bufferobject = 0;
5955 rsurface.tvector3f_bufferoffset = 0;
5956 rsurface.normal3f = rsurface.array_deformednormal3f;
5957 rsurface.normal3f_bufferobject = 0;
5958 rsurface.normal3f_bufferoffset = 0;
5960 case Q3DEFORM_NORMAL:
5961 // deform the normals to make reflections wavey
5962 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5964 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5965 for (j = 0;j < surface->num_vertices;j++)
5968 float *normal = (rsurface.array_deformednormal3f + 3 * surface->num_firstvertex) + j*3;
5969 VectorScale((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
5970 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, normal);
5971 normal[0] += deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
5972 normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
5973 normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
5974 VectorNormalize(normal);
5976 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 != 0);
5978 rsurface.svector3f = rsurface.array_deformedsvector3f;
5979 rsurface.svector3f_bufferobject = 0;
5980 rsurface.svector3f_bufferoffset = 0;
5981 rsurface.tvector3f = rsurface.array_deformedtvector3f;
5982 rsurface.tvector3f_bufferobject = 0;
5983 rsurface.tvector3f_bufferoffset = 0;
5984 rsurface.normal3f = rsurface.array_deformednormal3f;
5985 rsurface.normal3f_bufferobject = 0;
5986 rsurface.normal3f_bufferoffset = 0;
5989 // deform vertex array to make wavey water and flags and such
5990 waveparms[0] = deform->waveparms[0];
5991 waveparms[1] = deform->waveparms[1];
5992 waveparms[2] = deform->waveparms[2];
5993 waveparms[3] = deform->waveparms[3];
5994 // this is how a divisor of vertex influence on deformation
5995 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
5996 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
5997 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5999 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6000 for (j = 0;j < surface->num_vertices;j++)
6002 float *vertex = (rsurface.array_deformedvertex3f + 3 * surface->num_firstvertex) + j*3;
6003 VectorCopy((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, vertex);
6004 // if the wavefunc depends on time, evaluate it per-vertex
6007 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
6008 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
6010 VectorMA(vertex, scale, (rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, vertex);
6013 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6014 rsurface.vertex3f_bufferobject = 0;
6015 rsurface.vertex3f_bufferoffset = 0;
6017 case Q3DEFORM_BULGE:
6018 // deform vertex array to make the surface have moving bulges
6019 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6021 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6022 for (j = 0;j < surface->num_vertices;j++)
6024 scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.scene.time * deform->parms[2])) * deform->parms[1];
6025 VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
6028 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6029 rsurface.vertex3f_bufferobject = 0;
6030 rsurface.vertex3f_bufferoffset = 0;
6033 // deform vertex array
6034 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
6035 VectorScale(deform->parms, scale, waveparms);
6036 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6038 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6039 for (j = 0;j < surface->num_vertices;j++)
6040 VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
6042 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6043 rsurface.vertex3f_bufferobject = 0;
6044 rsurface.vertex3f_bufferoffset = 0;
6048 // generate texcoords based on the chosen texcoord source
6049 switch(rsurface.texture->tcgen.tcgen)
6052 case Q3TCGEN_TEXTURE:
6053 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
6054 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordtexture2f_bufferobject;
6055 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
6057 case Q3TCGEN_LIGHTMAP:
6058 rsurface.texcoordtexture2f = rsurface.modeltexcoordlightmap2f;
6059 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
6060 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
6062 case Q3TCGEN_VECTOR:
6063 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6065 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6066 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)
6068 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
6069 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
6072 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
6073 rsurface.texcoordtexture2f_bufferobject = 0;
6074 rsurface.texcoordtexture2f_bufferoffset = 0;
6076 case Q3TCGEN_ENVIRONMENT:
6077 // make environment reflections using a spheremap
6078 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6080 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6081 const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
6082 const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
6083 float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
6084 for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
6086 // identical to Q3A's method, but executed in worldspace so
6087 // carried models can be shiny too
6089 float viewer[3], d, reflected[3], worldreflected[3];
6091 VectorSubtract(rsurface.modelorg, vertex, viewer);
6092 // VectorNormalize(viewer);
6094 d = DotProduct(normal, viewer);
6096 reflected[0] = normal[0]*2*d - viewer[0];
6097 reflected[1] = normal[1]*2*d - viewer[1];
6098 reflected[2] = normal[2]*2*d - viewer[2];
6099 // note: this is proportinal to viewer, so we can normalize later
6101 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
6102 VectorNormalize(worldreflected);
6104 // note: this sphere map only uses world x and z!
6105 // so positive and negative y will LOOK THE SAME.
6106 out_tc[0] = 0.5 + 0.5 * worldreflected[1];
6107 out_tc[1] = 0.5 - 0.5 * worldreflected[2];
6110 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
6111 rsurface.texcoordtexture2f_bufferobject = 0;
6112 rsurface.texcoordtexture2f_bufferoffset = 0;
6115 // the only tcmod that needs software vertex processing is turbulent, so
6116 // check for it here and apply the changes if needed
6117 // and we only support that as the first one
6118 // (handling a mixture of turbulent and other tcmods would be problematic
6119 // without punting it entirely to a software path)
6120 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
6122 amplitude = rsurface.texture->tcmods[0].parms[1];
6123 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
6124 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6126 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6127 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)
6129 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
6130 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
6133 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
6134 rsurface.texcoordtexture2f_bufferobject = 0;
6135 rsurface.texcoordtexture2f_bufferoffset = 0;
6137 rsurface.texcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
6138 rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
6139 rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
6140 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
6143 void RSurf_DrawBatch_Simple(int texturenumsurfaces, msurface_t **texturesurfacelist)
6146 const msurface_t *surface = texturesurfacelist[0];
6147 const msurface_t *surface2;
6152 // TODO: lock all array ranges before render, rather than on each surface
6153 if (texturenumsurfaces == 1)
6155 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6156 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
6158 else if (r_batchmode.integer == 2)
6160 #define MAXBATCHTRIANGLES 4096
6161 int batchtriangles = 0;
6162 int batchelements[MAXBATCHTRIANGLES*3];
6163 for (i = 0;i < texturenumsurfaces;i = j)
6165 surface = texturesurfacelist[i];
6167 if (surface->num_triangles > MAXBATCHTRIANGLES)
6169 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
6172 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
6173 batchtriangles = surface->num_triangles;
6174 firstvertex = surface->num_firstvertex;
6175 endvertex = surface->num_firstvertex + surface->num_vertices;
6176 for (;j < texturenumsurfaces;j++)
6178 surface2 = texturesurfacelist[j];
6179 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
6181 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
6182 batchtriangles += surface2->num_triangles;
6183 firstvertex = min(firstvertex, surface2->num_firstvertex);
6184 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
6186 surface2 = texturesurfacelist[j-1];
6187 numvertices = endvertex - firstvertex;
6188 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
6191 else if (r_batchmode.integer == 1)
6193 for (i = 0;i < texturenumsurfaces;i = j)
6195 surface = texturesurfacelist[i];
6196 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
6197 if (texturesurfacelist[j] != surface2)
6199 surface2 = texturesurfacelist[j-1];
6200 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
6201 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
6202 GL_LockArrays(surface->num_firstvertex, numvertices);
6203 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
6208 for (i = 0;i < texturenumsurfaces;i++)
6210 surface = texturesurfacelist[i];
6211 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6212 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
6217 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit, int refractiontexunit, int reflectiontexunit)
6219 int i, planeindex, vertexindex;
6223 r_waterstate_waterplane_t *p, *bestp;
6224 msurface_t *surface;
6225 if (r_waterstate.renderingscene)
6227 for (i = 0;i < texturenumsurfaces;i++)
6229 surface = texturesurfacelist[i];
6230 if (lightmaptexunit >= 0)
6231 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6232 if (deluxemaptexunit >= 0)
6233 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6234 // pick the closest matching water plane
6237 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
6240 for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
6242 Matrix4x4_Transform(&rsurface.matrix, v, vert);
6243 d += fabs(PlaneDiff(vert, &p->plane));
6245 if (bestd > d || !bestp)
6253 if (refractiontexunit >= 0)
6254 R_Mesh_TexBind(refractiontexunit, R_GetTexture(bestp->texture_refraction));
6255 if (reflectiontexunit >= 0)
6256 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(bestp->texture_reflection));
6260 if (refractiontexunit >= 0)
6261 R_Mesh_TexBind(refractiontexunit, R_GetTexture(r_texture_black));
6262 if (reflectiontexunit >= 0)
6263 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(r_texture_black));
6265 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6266 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
6270 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit)
6274 const msurface_t *surface = texturesurfacelist[0];
6275 const msurface_t *surface2;
6280 // TODO: lock all array ranges before render, rather than on each surface
6281 if (texturenumsurfaces == 1)
6283 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6284 if (deluxemaptexunit >= 0)
6285 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6286 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6287 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
6289 else if (r_batchmode.integer == 2)
6291 #define MAXBATCHTRIANGLES 4096
6292 int batchtriangles = 0;
6293 int batchelements[MAXBATCHTRIANGLES*3];
6294 for (i = 0;i < texturenumsurfaces;i = j)
6296 surface = texturesurfacelist[i];
6297 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6298 if (deluxemaptexunit >= 0)
6299 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6301 if (surface->num_triangles > MAXBATCHTRIANGLES)
6303 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
6306 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
6307 batchtriangles = surface->num_triangles;
6308 firstvertex = surface->num_firstvertex;
6309 endvertex = surface->num_firstvertex + surface->num_vertices;
6310 for (;j < texturenumsurfaces;j++)
6312 surface2 = texturesurfacelist[j];
6313 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
6315 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
6316 batchtriangles += surface2->num_triangles;
6317 firstvertex = min(firstvertex, surface2->num_firstvertex);
6318 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
6320 surface2 = texturesurfacelist[j-1];
6321 numvertices = endvertex - firstvertex;
6322 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
6325 else if (r_batchmode.integer == 1)
6328 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
6329 for (i = 0;i < texturenumsurfaces;i = j)
6331 surface = texturesurfacelist[i];
6332 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
6333 if (texturesurfacelist[j] != surface2)
6335 Con_Printf(" %i", j - i);
6338 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
6340 for (i = 0;i < texturenumsurfaces;i = j)
6342 surface = texturesurfacelist[i];
6343 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6344 if (deluxemaptexunit >= 0)
6345 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6346 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
6347 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
6350 Con_Printf(" %i", j - i);
6352 surface2 = texturesurfacelist[j-1];
6353 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
6354 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
6355 GL_LockArrays(surface->num_firstvertex, numvertices);
6356 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
6364 for (i = 0;i < texturenumsurfaces;i++)
6366 surface = texturesurfacelist[i];
6367 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6368 if (deluxemaptexunit >= 0)
6369 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6370 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6371 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
6376 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
6379 int texturesurfaceindex;
6380 if (r_showsurfaces.integer == 2)
6382 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6384 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6385 for (j = 0;j < surface->num_triangles;j++)
6387 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_refdef.view.colorscale;
6388 GL_Color(f, f, f, 1);
6389 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle + j, 1, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
6395 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6397 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6398 int k = (int)(((size_t)surface) / sizeof(msurface_t));
6399 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);
6400 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6401 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
6406 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(int texturenumsurfaces, msurface_t **texturesurfacelist)
6408 int texturesurfaceindex;
6411 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6413 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6414 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)
6422 rsurface.lightmapcolor4f = rsurface.array_color4f;
6423 rsurface.lightmapcolor4f_bufferobject = 0;
6424 rsurface.lightmapcolor4f_bufferoffset = 0;
6427 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, msurface_t **texturesurfacelist)
6429 int texturesurfaceindex;
6433 if (rsurface.lightmapcolor4f)
6435 // generate color arrays for the surfaces in this list
6436 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6438 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6439 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)
6441 f = FogPoint_Model(v);
6451 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6453 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6454 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)
6456 f = FogPoint_Model(v);
6464 rsurface.lightmapcolor4f = rsurface.array_color4f;
6465 rsurface.lightmapcolor4f_bufferobject = 0;
6466 rsurface.lightmapcolor4f_bufferoffset = 0;
6469 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(int texturenumsurfaces, msurface_t **texturesurfacelist)
6471 int texturesurfaceindex;
6475 if (!rsurface.lightmapcolor4f)
6477 // generate color arrays for the surfaces in this list
6478 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6480 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6481 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)
6483 f = FogPoint_Model(v);
6484 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
6485 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
6486 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
6490 rsurface.lightmapcolor4f = rsurface.array_color4f;
6491 rsurface.lightmapcolor4f_bufferobject = 0;
6492 rsurface.lightmapcolor4f_bufferoffset = 0;
6495 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a)
6497 int texturesurfaceindex;
6500 if (!rsurface.lightmapcolor4f)
6502 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6504 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6505 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)
6513 rsurface.lightmapcolor4f = rsurface.array_color4f;
6514 rsurface.lightmapcolor4f_bufferobject = 0;
6515 rsurface.lightmapcolor4f_bufferoffset = 0;
6518 static void RSurf_DrawBatch_GL11_ApplyAmbient(int texturenumsurfaces, msurface_t **texturesurfacelist)
6520 int texturesurfaceindex;
6523 if (!rsurface.lightmapcolor4f)
6525 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6527 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6528 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)
6530 c2[0] = c[0] + r_refdef.scene.ambient / 128.0;
6531 c2[1] = c[1] + r_refdef.scene.ambient / 128.0;
6532 c2[2] = c[2] + r_refdef.scene.ambient / 128.0;
6536 rsurface.lightmapcolor4f = rsurface.array_color4f;
6537 rsurface.lightmapcolor4f_bufferobject = 0;
6538 rsurface.lightmapcolor4f_bufferoffset = 0;
6541 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
6544 rsurface.lightmapcolor4f = NULL;
6545 rsurface.lightmapcolor4f_bufferobject = 0;
6546 rsurface.lightmapcolor4f_bufferoffset = 0;
6547 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
6548 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
6549 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
6550 GL_Color(r, g, b, a);
6551 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 0, -1);
6554 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
6556 // TODO: optimize applyfog && applycolor case
6557 // just apply fog if necessary, and tint the fog color array if necessary
6558 rsurface.lightmapcolor4f = NULL;
6559 rsurface.lightmapcolor4f_bufferobject = 0;
6560 rsurface.lightmapcolor4f_bufferoffset = 0;
6561 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
6562 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
6563 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
6564 GL_Color(r, g, b, a);
6565 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6568 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
6570 int texturesurfaceindex;
6574 if (texturesurfacelist[0]->lightmapinfo)
6576 // generate color arrays for the surfaces in this list
6577 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6579 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6580 for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
6582 if (surface->lightmapinfo->samples)
6584 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
6585 float scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
6586 VectorScale(lm, scale, c);
6587 if (surface->lightmapinfo->styles[1] != 255)
6589 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
6591 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
6592 VectorMA(c, scale, lm, c);
6593 if (surface->lightmapinfo->styles[2] != 255)
6596 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
6597 VectorMA(c, scale, lm, c);
6598 if (surface->lightmapinfo->styles[3] != 255)
6601 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
6602 VectorMA(c, scale, lm, c);
6612 rsurface.lightmapcolor4f = rsurface.array_color4f;
6613 rsurface.lightmapcolor4f_bufferobject = 0;
6614 rsurface.lightmapcolor4f_bufferoffset = 0;
6618 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
6619 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
6620 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
6622 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
6623 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
6624 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
6625 GL_Color(r, g, b, a);
6626 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6629 static void RSurf_DrawBatch_GL11_ApplyVertexShade(int texturenumsurfaces, msurface_t **texturesurfacelist, float *r, float *g, float *b, float *a, qboolean *applycolor)
6631 int texturesurfaceindex;
6634 float *v, *c, *c2, alpha;
6635 vec3_t ambientcolor;
6636 vec3_t diffusecolor;
6640 VectorCopy(rsurface.modellight_lightdir, lightdir);
6641 f = 0.5f * r_refdef.lightmapintensity;
6642 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
6643 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
6644 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
6645 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
6646 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
6647 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
6649 if (VectorLength2(diffusecolor) > 0 && rsurface.normal3f)
6651 // generate color arrays for the surfaces in this list
6652 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6654 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6655 int numverts = surface->num_vertices;
6656 v = rsurface.vertex3f + 3 * surface->num_firstvertex;
6657 c2 = rsurface.normal3f + 3 * surface->num_firstvertex;
6658 c = rsurface.array_color4f + 4 * surface->num_firstvertex;
6659 // q3-style directional shading
6660 for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
6662 if ((f = DotProduct(c2, lightdir)) > 0)
6663 VectorMA(ambientcolor, f, diffusecolor, c);
6665 VectorCopy(ambientcolor, c);
6673 rsurface.lightmapcolor4f = rsurface.array_color4f;
6674 rsurface.lightmapcolor4f_bufferobject = 0;
6675 rsurface.lightmapcolor4f_bufferoffset = 0;
6676 *applycolor = false;
6680 *r = ambientcolor[0];
6681 *g = ambientcolor[1];
6682 *b = ambientcolor[2];
6683 rsurface.lightmapcolor4f = NULL;
6684 rsurface.lightmapcolor4f_bufferobject = 0;
6685 rsurface.lightmapcolor4f_bufferoffset = 0;
6689 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
6691 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &r, &g, &b, &a, &applycolor);
6692 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
6693 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
6694 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
6695 GL_Color(r, g, b, a);
6696 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6699 void RSurf_SetupDepthAndCulling(void)
6701 // submodels are biased to avoid z-fighting with world surfaces that they
6702 // may be exactly overlapping (avoids z-fighting artifacts on certain
6703 // doors and things in Quake maps)
6704 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
6705 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
6706 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
6707 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
6710 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, msurface_t **texturesurfacelist)
6712 // transparent sky would be ridiculous
6713 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
6715 R_SetupGenericShader(false);
6718 skyrendernow = false;
6719 // we have to force off the water clipping plane while rendering sky
6723 // restore entity matrix
6724 R_Mesh_Matrix(&rsurface.matrix);
6726 RSurf_SetupDepthAndCulling();
6728 // LordHavoc: HalfLife maps have freaky skypolys so don't use
6729 // skymasking on them, and Quake3 never did sky masking (unlike
6730 // software Quake and software Quake2), so disable the sky masking
6731 // in Quake3 maps as it causes problems with q3map2 sky tricks,
6732 // and skymasking also looks very bad when noclipping outside the
6733 // level, so don't use it then either.
6734 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
6736 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
6737 R_Mesh_ColorPointer(NULL, 0, 0);
6738 R_Mesh_ResetTextureState();
6739 if (skyrendermasked)
6741 R_SetupDepthOrShadowShader();
6742 // depth-only (masking)
6743 GL_ColorMask(0,0,0,0);
6744 // just to make sure that braindead drivers don't draw
6745 // anything despite that colormask...
6746 GL_BlendFunc(GL_ZERO, GL_ONE);
6750 R_SetupGenericShader(false);
6752 GL_BlendFunc(GL_ONE, GL_ZERO);
6754 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6755 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6756 if (skyrendermasked)
6757 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
6759 R_Mesh_ResetTextureState();
6760 GL_Color(1, 1, 1, 1);
6763 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6765 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION)))
6768 R_Mesh_TexMatrix(0, &rsurface.texture->currenttexmatrix);
6769 R_Mesh_TexMatrix(1, &rsurface.texture->currentbackgroundtexmatrix);
6770 R_Mesh_TexBind(GL20TU_NORMAL, R_GetTexture(rsurface.texture->currentskinframe->nmap));
6771 R_Mesh_TexBind(GL20TU_COLOR, R_GetTexture(rsurface.texture->basetexture));
6772 R_Mesh_TexBind(GL20TU_GLOSS, R_GetTexture(rsurface.texture->glosstexture));
6773 R_Mesh_TexBind(GL20TU_GLOW, R_GetTexture(rsurface.texture->currentskinframe->glow));
6774 if (rsurface.texture->backgroundcurrentskinframe)
6776 R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->nmap));
6777 R_Mesh_TexBind(GL20TU_SECONDARY_COLOR, R_GetTexture(rsurface.texture->backgroundbasetexture));
6778 R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS, R_GetTexture(rsurface.texture->backgroundglosstexture));
6779 R_Mesh_TexBind(GL20TU_SECONDARY_GLOW, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->glow));
6781 if(rsurface.texture->colormapping)
6783 R_Mesh_TexBind(GL20TU_PANTS, R_GetTexture(rsurface.texture->currentskinframe->pants));
6784 R_Mesh_TexBind(GL20TU_SHIRT, R_GetTexture(rsurface.texture->currentskinframe->shirt));
6786 R_Mesh_TexBind(GL20TU_FOGMASK, R_GetTexture(r_texture_fogattenuation));
6787 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
6788 R_Mesh_ColorPointer(NULL, 0, 0);
6790 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
6792 if (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6794 // render background
6795 GL_BlendFunc(GL_ONE, GL_ZERO);
6797 GL_AlphaTest(false);
6799 GL_Color(1, 1, 1, 1);
6800 R_Mesh_ColorPointer(NULL, 0, 0);
6802 R_SetupSurfaceShader(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
6803 if (r_glsl_permutation)
6805 RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
6806 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
6807 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
6808 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
6809 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
6810 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
6811 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);
6813 GL_LockArrays(0, 0);
6815 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
6816 GL_DepthMask(false);
6817 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
6818 R_Mesh_ColorPointer(NULL, 0, 0);
6820 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
6821 R_Mesh_TexBind(GL20TU_REFRACTION, R_GetTexture(r_texture_white)); // changed per surface
6822 R_Mesh_TexBind(GL20TU_REFLECTION, R_GetTexture(r_texture_white)); // changed per surface
6825 R_SetupSurfaceShader(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE);
6826 if (!r_glsl_permutation)
6829 RSurf_PrepareVerticesForBatch(r_glsl_permutation->loc_Texture_Normal >= 0 || r_glsl_permutation->loc_LightDir >= 0, r_glsl_permutation->loc_Texture_Normal >= 0, texturenumsurfaces, texturesurfacelist);
6830 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
6831 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
6832 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
6833 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
6834 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
6836 if (r_glsl_permutation->loc_Texture_Refraction >= 0)
6838 GL_BlendFunc(GL_ONE, GL_ZERO);
6840 GL_AlphaTest(false);
6844 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
6845 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
6846 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
6849 if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
6851 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
6852 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);
6854 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, GL20TU_LIGHTMAP, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? GL20TU_DELUXEMAP : -1);
6858 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
6859 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);
6861 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6863 GL_LockArrays(0, 0);
6866 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6868 // OpenGL 1.3 path - anything not completely ancient
6869 int texturesurfaceindex;
6870 qboolean applycolor;
6874 const texturelayer_t *layer;
6875 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
6877 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
6880 int layertexrgbscale;
6881 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
6883 if (layerindex == 0)
6887 GL_AlphaTest(false);
6888 qglDepthFunc(GL_EQUAL);CHECKGLERROR
6891 GL_DepthMask(layer->depthmask && writedepth);
6892 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
6893 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
6895 layertexrgbscale = 4;
6896 VectorScale(layer->color, 0.25f, layercolor);
6898 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
6900 layertexrgbscale = 2;
6901 VectorScale(layer->color, 0.5f, layercolor);
6905 layertexrgbscale = 1;
6906 VectorScale(layer->color, 1.0f, layercolor);
6908 layercolor[3] = layer->color[3];
6909 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
6910 R_Mesh_ColorPointer(NULL, 0, 0);
6911 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
6912 switch (layer->type)
6914 case TEXTURELAYERTYPE_LITTEXTURE:
6915 memset(&m, 0, sizeof(m));
6916 m.tex[0] = R_GetTexture(r_texture_white);
6917 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
6918 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
6919 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
6920 m.tex[1] = R_GetTexture(layer->texture);
6921 m.texmatrix[1] = layer->texmatrix;
6922 m.texrgbscale[1] = layertexrgbscale;
6923 m.pointer_texcoord[1] = rsurface.texcoordtexture2f;
6924 m.pointer_texcoord_bufferobject[1] = rsurface.texcoordtexture2f_bufferobject;
6925 m.pointer_texcoord_bufferoffset[1] = rsurface.texcoordtexture2f_bufferoffset;
6926 R_Mesh_TextureState(&m);
6927 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
6928 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
6929 else if (rsurface.uselightmaptexture)
6930 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
6932 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
6934 case TEXTURELAYERTYPE_TEXTURE:
6935 memset(&m, 0, sizeof(m));
6936 m.tex[0] = R_GetTexture(layer->texture);
6937 m.texmatrix[0] = layer->texmatrix;
6938 m.texrgbscale[0] = layertexrgbscale;
6939 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6940 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6941 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6942 R_Mesh_TextureState(&m);
6943 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
6945 case TEXTURELAYERTYPE_FOG:
6946 memset(&m, 0, sizeof(m));
6947 m.texrgbscale[0] = layertexrgbscale;
6950 m.tex[0] = R_GetTexture(layer->texture);
6951 m.texmatrix[0] = layer->texmatrix;
6952 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6953 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6954 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6956 R_Mesh_TextureState(&m);
6957 // generate a color array for the fog pass
6958 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
6959 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6963 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6964 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)
6966 f = 1 - FogPoint_Model(v);
6967 c[0] = layercolor[0];
6968 c[1] = layercolor[1];
6969 c[2] = layercolor[2];
6970 c[3] = f * layercolor[3];
6973 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6976 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
6978 GL_LockArrays(0, 0);
6981 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
6983 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
6984 GL_AlphaTest(false);
6988 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6990 // OpenGL 1.1 - crusty old voodoo path
6991 int texturesurfaceindex;
6995 const texturelayer_t *layer;
6996 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
6998 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
7000 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7002 if (layerindex == 0)
7006 GL_AlphaTest(false);
7007 qglDepthFunc(GL_EQUAL);CHECKGLERROR
7010 GL_DepthMask(layer->depthmask && writedepth);
7011 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
7012 R_Mesh_ColorPointer(NULL, 0, 0);
7013 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
7014 switch (layer->type)
7016 case TEXTURELAYERTYPE_LITTEXTURE:
7017 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
7019 // two-pass lit texture with 2x rgbscale
7020 // first the lightmap pass
7021 memset(&m, 0, sizeof(m));
7022 m.tex[0] = R_GetTexture(r_texture_white);
7023 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
7024 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
7025 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
7026 R_Mesh_TextureState(&m);
7027 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7028 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
7029 else if (rsurface.uselightmaptexture)
7030 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
7032 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
7033 GL_LockArrays(0, 0);
7034 // then apply the texture to it
7035 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
7036 memset(&m, 0, sizeof(m));
7037 m.tex[0] = R_GetTexture(layer->texture);
7038 m.texmatrix[0] = layer->texmatrix;
7039 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7040 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7041 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7042 R_Mesh_TextureState(&m);
7043 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);
7047 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
7048 memset(&m, 0, sizeof(m));
7049 m.tex[0] = R_GetTexture(layer->texture);
7050 m.texmatrix[0] = layer->texmatrix;
7051 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7052 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7053 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7054 R_Mesh_TextureState(&m);
7055 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7056 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);
7058 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);
7061 case TEXTURELAYERTYPE_TEXTURE:
7062 // singletexture unlit texture with transparency support
7063 memset(&m, 0, sizeof(m));
7064 m.tex[0] = R_GetTexture(layer->texture);
7065 m.texmatrix[0] = layer->texmatrix;
7066 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7067 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7068 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7069 R_Mesh_TextureState(&m);
7070 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);
7072 case TEXTURELAYERTYPE_FOG:
7073 // singletexture fogging
7074 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
7077 memset(&m, 0, sizeof(m));
7078 m.tex[0] = R_GetTexture(layer->texture);
7079 m.texmatrix[0] = layer->texmatrix;
7080 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7081 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7082 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7083 R_Mesh_TextureState(&m);
7086 R_Mesh_ResetTextureState();
7087 // generate a color array for the fog pass
7088 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7092 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7093 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)
7095 f = 1 - FogPoint_Model(v);
7096 c[0] = layer->color[0];
7097 c[1] = layer->color[1];
7098 c[2] = layer->color[2];
7099 c[3] = f * layer->color[3];
7102 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7105 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
7107 GL_LockArrays(0, 0);
7110 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7112 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
7113 GL_AlphaTest(false);
7117 static void R_DrawTextureSurfaceList_ShowSurfaces3(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
7121 GL_AlphaTest(false);
7122 R_Mesh_ColorPointer(NULL, 0, 0);
7123 R_Mesh_ResetTextureState();
7124 R_SetupGenericShader(false);
7126 if(rsurface.texture && rsurface.texture->currentskinframe)
7128 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
7129 c[3] *= rsurface.texture->currentalpha;
7139 if (rsurface.texture->currentskinframe->pants || rsurface.texture->currentskinframe->shirt)
7141 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
7142 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
7143 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
7146 // brighten it up (as texture value 127 means "unlit")
7147 c[0] *= 2 * r_refdef.view.colorscale;
7148 c[1] *= 2 * r_refdef.view.colorscale;
7149 c[2] *= 2 * r_refdef.view.colorscale;
7151 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
7152 c[3] *= r_wateralpha.value;
7154 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
7156 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7157 GL_DepthMask(false);
7159 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
7161 GL_BlendFunc(GL_ONE, GL_ONE);
7162 GL_DepthMask(false);
7164 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7166 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
7167 GL_DepthMask(false);
7169 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7171 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
7172 GL_DepthMask(false);
7176 GL_BlendFunc(GL_ONE, GL_ZERO);
7177 GL_DepthMask(writedepth);
7180 rsurface.lightmapcolor4f = NULL;
7182 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7184 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7186 rsurface.lightmapcolor4f = NULL;
7187 rsurface.lightmapcolor4f_bufferobject = 0;
7188 rsurface.lightmapcolor4f_bufferoffset = 0;
7190 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7192 qboolean applycolor = true;
7195 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
7197 r_refdef.lightmapintensity = 1;
7198 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &one, &one, &one, &one, &applycolor);
7199 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
7203 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7205 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
7206 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
7207 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
7210 if(!rsurface.lightmapcolor4f)
7211 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(texturenumsurfaces, texturesurfacelist);
7213 RSurf_DrawBatch_GL11_ApplyAmbient(texturenumsurfaces, texturesurfacelist);
7214 RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, c[0], c[1], c[2], c[3]);
7215 if(r_refdef.fogenabled)
7216 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(texturenumsurfaces, texturesurfacelist);
7218 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
7219 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7222 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
7225 RSurf_SetupDepthAndCulling();
7226 if (r_showsurfaces.integer == 3)
7227 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
7228 else if (r_glsl.integer && gl_support_fragment_shader)
7229 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth);
7230 else if (gl_combine.integer && r_textureunits.integer >= 2)
7231 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
7233 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
7237 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
7240 RSurf_SetupDepthAndCulling();
7241 if (r_showsurfaces.integer == 3)
7242 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
7243 else if (r_glsl.integer && gl_support_fragment_shader)
7244 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth);
7245 else if (gl_combine.integer && r_textureunits.integer >= 2)
7246 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
7248 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
7252 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7255 int texturenumsurfaces, endsurface;
7257 msurface_t *surface;
7258 msurface_t *texturesurfacelist[1024];
7260 // if the model is static it doesn't matter what value we give for
7261 // wantnormals and wanttangents, so this logic uses only rules applicable
7262 // to a model, knowing that they are meaningless otherwise
7263 if (ent == r_refdef.scene.worldentity)
7264 RSurf_ActiveWorldEntity();
7265 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
7266 RSurf_ActiveModelEntity(ent, false, false);
7268 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
7270 for (i = 0;i < numsurfaces;i = j)
7273 surface = rsurface.modelsurfaces + surfacelist[i];
7274 texture = surface->texture;
7275 rsurface.texture = R_GetCurrentTexture(texture);
7276 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
7277 // scan ahead until we find a different texture
7278 endsurface = min(i + 1024, numsurfaces);
7279 texturenumsurfaces = 0;
7280 texturesurfacelist[texturenumsurfaces++] = surface;
7281 for (;j < endsurface;j++)
7283 surface = rsurface.modelsurfaces + surfacelist[j];
7284 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
7286 texturesurfacelist[texturenumsurfaces++] = surface;
7288 // render the range of surfaces
7289 if (ent == r_refdef.scene.worldentity)
7290 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false);
7292 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false);
7294 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7295 GL_AlphaTest(false);
7298 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly)
7300 const entity_render_t *queueentity = r_refdef.scene.worldentity;
7304 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
7306 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
7308 RSurf_SetupDepthAndCulling();
7309 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7310 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7312 else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
7314 RSurf_SetupDepthAndCulling();
7315 GL_AlphaTest(false);
7316 R_Mesh_ColorPointer(NULL, 0, 0);
7317 R_Mesh_ResetTextureState();
7318 R_SetupGenericShader(false);
7319 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7321 GL_BlendFunc(GL_ONE, GL_ZERO);
7322 GL_Color(0, 0, 0, 1);
7323 GL_DepthTest(writedepth);
7324 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7326 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
7328 RSurf_SetupDepthAndCulling();
7329 GL_AlphaTest(false);
7330 R_Mesh_ColorPointer(NULL, 0, 0);
7331 R_Mesh_ResetTextureState();
7332 R_SetupGenericShader(false);
7333 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7335 GL_BlendFunc(GL_ONE, GL_ZERO);
7337 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
7339 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
7340 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
7341 else if (!rsurface.texture->currentnumlayers)
7343 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
7345 // transparent surfaces get pushed off into the transparent queue
7346 int surfacelistindex;
7347 const msurface_t *surface;
7348 vec3_t tempcenter, center;
7349 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
7351 surface = texturesurfacelist[surfacelistindex];
7352 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
7353 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
7354 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
7355 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
7356 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
7361 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
7362 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST));
7367 void R_QueueWorldSurfaceList(int numsurfaces, msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly)
7371 // break the surface list down into batches by texture and use of lightmapping
7372 for (i = 0;i < numsurfaces;i = j)
7375 // texture is the base texture pointer, rsurface.texture is the
7376 // current frame/skin the texture is directing us to use (for example
7377 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
7378 // use skin 1 instead)
7379 texture = surfacelist[i]->texture;
7380 rsurface.texture = R_GetCurrentTexture(texture);
7381 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
7382 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
7384 // if this texture is not the kind we want, skip ahead to the next one
7385 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
7389 // simply scan ahead until we find a different texture or lightmap state
7390 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
7392 // render the range of surfaces
7393 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly);
7397 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity)
7402 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
7404 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
7406 RSurf_SetupDepthAndCulling();
7407 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7408 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7410 else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
7412 RSurf_SetupDepthAndCulling();
7413 GL_AlphaTest(false);
7414 R_Mesh_ColorPointer(NULL, 0, 0);
7415 R_Mesh_ResetTextureState();
7416 R_SetupGenericShader(false);
7417 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7419 GL_BlendFunc(GL_ONE, GL_ZERO);
7420 GL_Color(0, 0, 0, 1);
7421 GL_DepthTest(writedepth);
7422 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7424 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
7426 RSurf_SetupDepthAndCulling();
7427 GL_AlphaTest(false);
7428 R_Mesh_ColorPointer(NULL, 0, 0);
7429 R_Mesh_ResetTextureState();
7430 R_SetupGenericShader(false);
7431 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7433 GL_BlendFunc(GL_ONE, GL_ZERO);
7435 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
7437 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
7438 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
7439 else if (!rsurface.texture->currentnumlayers)
7441 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
7443 // transparent surfaces get pushed off into the transparent queue
7444 int surfacelistindex;
7445 const msurface_t *surface;
7446 vec3_t tempcenter, center;
7447 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
7449 surface = texturesurfacelist[surfacelistindex];
7450 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
7451 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
7452 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
7453 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
7454 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
7459 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
7460 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST));
7465 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly)
7469 // break the surface list down into batches by texture and use of lightmapping
7470 for (i = 0;i < numsurfaces;i = j)
7473 // texture is the base texture pointer, rsurface.texture is the
7474 // current frame/skin the texture is directing us to use (for example
7475 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
7476 // use skin 1 instead)
7477 texture = surfacelist[i]->texture;
7478 rsurface.texture = R_GetCurrentTexture(texture);
7479 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
7480 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
7482 // if this texture is not the kind we want, skip ahead to the next one
7483 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
7487 // simply scan ahead until we find a different texture or lightmap state
7488 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
7490 // render the range of surfaces
7491 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent);
7495 float locboxvertex3f[6*4*3] =
7497 1,0,1, 1,0,0, 1,1,0, 1,1,1,
7498 0,1,1, 0,1,0, 0,0,0, 0,0,1,
7499 1,1,1, 1,1,0, 0,1,0, 0,1,1,
7500 0,0,1, 0,0,0, 1,0,0, 1,0,1,
7501 0,0,1, 1,0,1, 1,1,1, 0,1,1,
7502 1,0,0, 0,0,0, 0,1,0, 1,1,0
7505 unsigned short locboxelements[6*2*3] =
7515 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7518 cl_locnode_t *loc = (cl_locnode_t *)ent;
7520 float vertex3f[6*4*3];
7522 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7523 GL_DepthMask(false);
7524 GL_DepthRange(0, 1);
7525 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7527 GL_CullFace(GL_NONE);
7528 R_Mesh_Matrix(&identitymatrix);
7530 R_Mesh_VertexPointer(vertex3f, 0, 0);
7531 R_Mesh_ColorPointer(NULL, 0, 0);
7532 R_Mesh_ResetTextureState();
7533 R_SetupGenericShader(false);
7536 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
7537 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
7538 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
7539 surfacelist[0] < 0 ? 0.5f : 0.125f);
7541 if (VectorCompare(loc->mins, loc->maxs))
7543 VectorSet(size, 2, 2, 2);
7544 VectorMA(loc->mins, -0.5f, size, mins);
7548 VectorCopy(loc->mins, mins);
7549 VectorSubtract(loc->maxs, loc->mins, size);
7552 for (i = 0;i < 6*4*3;)
7553 for (j = 0;j < 3;j++, i++)
7554 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
7556 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, locboxelements, 0, 0);
7559 void R_DrawLocs(void)
7562 cl_locnode_t *loc, *nearestloc;
7564 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
7565 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
7567 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
7568 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
7572 void R_DrawDebugModel(entity_render_t *ent)
7574 int i, j, k, l, flagsmask;
7575 const int *elements;
7577 msurface_t *surface;
7578 dp_model_t *model = ent->model;
7581 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
7583 R_Mesh_ColorPointer(NULL, 0, 0);
7584 R_Mesh_ResetTextureState();
7585 R_SetupGenericShader(false);
7586 GL_DepthRange(0, 1);
7587 GL_DepthTest(!r_showdisabledepthtest.integer);
7588 GL_DepthMask(false);
7589 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7591 if (r_showcollisionbrushes.value > 0 && model->brush.num_brushes)
7593 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
7594 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
7596 if (brush->colbrushf && brush->colbrushf->numtriangles)
7598 R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
7599 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);
7600 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, 0);
7603 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
7605 if (surface->num_collisiontriangles)
7607 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
7608 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);
7609 R_Mesh_Draw(0, surface->num_collisionvertices, 0, surface->num_collisiontriangles, surface->data_collisionelement3i, NULL, 0, 0);
7614 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7616 if (r_showtris.integer || r_shownormals.integer)
7618 if (r_showdisabledepthtest.integer)
7620 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7621 GL_DepthMask(false);
7625 GL_BlendFunc(GL_ONE, GL_ZERO);
7628 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
7630 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
7632 rsurface.texture = R_GetCurrentTexture(surface->texture);
7633 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
7635 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
7636 if (r_showtris.value > 0)
7638 if (!rsurface.texture->currentlayers->depthmask)
7639 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
7640 else if (ent == r_refdef.scene.worldentity)
7641 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
7643 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
7644 elements = (ent->model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
7645 R_Mesh_VertexPointer(rsurface.vertex3f, 0, 0);
7646 R_Mesh_ColorPointer(NULL, 0, 0);
7647 R_Mesh_TexCoordPointer(0, 0, NULL, 0, 0);
7648 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7649 //R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, ent->model->surfmesh.data_element3i, NULL, 0, 0);
7650 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
7651 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7654 if (r_shownormals.value < 0)
7657 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
7659 VectorCopy(rsurface.vertex3f + l * 3, v);
7660 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
7661 qglVertex3f(v[0], v[1], v[2]);
7662 VectorMA(v, -r_shownormals.value, rsurface.svector3f + l * 3, v);
7663 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
7664 qglVertex3f(v[0], v[1], v[2]);
7669 if (r_shownormals.value > 0)
7672 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
7674 VectorCopy(rsurface.vertex3f + l * 3, v);
7675 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
7676 qglVertex3f(v[0], v[1], v[2]);
7677 VectorMA(v, r_shownormals.value, rsurface.svector3f + l * 3, v);
7678 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
7679 qglVertex3f(v[0], v[1], v[2]);
7684 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
7686 VectorCopy(rsurface.vertex3f + l * 3, v);
7687 GL_Color(0, r_refdef.view.colorscale, 0, 1);
7688 qglVertex3f(v[0], v[1], v[2]);
7689 VectorMA(v, r_shownormals.value, rsurface.tvector3f + l * 3, v);
7690 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
7691 qglVertex3f(v[0], v[1], v[2]);
7696 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
7698 VectorCopy(rsurface.vertex3f + l * 3, v);
7699 GL_Color(0, 0, r_refdef.view.colorscale, 1);
7700 qglVertex3f(v[0], v[1], v[2]);
7701 VectorMA(v, r_shownormals.value, rsurface.normal3f + l * 3, v);
7702 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
7703 qglVertex3f(v[0], v[1], v[2]);
7710 rsurface.texture = NULL;
7714 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
7715 int r_maxsurfacelist = 0;
7716 msurface_t **r_surfacelist = NULL;
7717 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug)
7719 int i, j, endj, f, flagsmask;
7721 dp_model_t *model = r_refdef.scene.worldmodel;
7722 msurface_t *surfaces;
7723 unsigned char *update;
7724 int numsurfacelist = 0;
7728 if (r_maxsurfacelist < model->num_surfaces)
7730 r_maxsurfacelist = model->num_surfaces;
7732 Mem_Free(r_surfacelist);
7733 r_surfacelist = (msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
7736 RSurf_ActiveWorldEntity();
7738 surfaces = model->data_surfaces;
7739 update = model->brushq1.lightmapupdateflags;
7741 // update light styles on this submodel
7742 if (!skysurfaces && !depthonly && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
7744 model_brush_lightstyleinfo_t *style;
7745 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
7747 if (style->value != r_refdef.scene.lightstylevalue[style->style])
7749 int *list = style->surfacelist;
7750 style->value = r_refdef.scene.lightstylevalue[style->style];
7751 for (j = 0;j < style->numsurfaces;j++)
7752 update[list[j]] = true;
7757 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
7761 R_DrawDebugModel(r_refdef.scene.worldentity);
7762 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7768 rsurface.uselightmaptexture = false;
7769 rsurface.texture = NULL;
7770 rsurface.rtlight = NULL;
7772 // add visible surfaces to draw list
7773 for (i = 0;i < model->nummodelsurfaces;i++)
7775 j = model->sortedmodelsurfaces[i];
7776 if (r_refdef.viewcache.world_surfacevisible[j])
7777 r_surfacelist[numsurfacelist++] = surfaces + j;
7779 // update lightmaps if needed
7781 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
7782 if (r_refdef.viewcache.world_surfacevisible[j])
7784 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
7785 // don't do anything if there were no surfaces
7786 if (!numsurfacelist)
7788 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7791 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly);
7792 GL_AlphaTest(false);
7794 // add to stats if desired
7795 if (r_speeds.integer && !skysurfaces && !depthonly)
7797 r_refdef.stats.world_surfaces += numsurfacelist;
7798 for (j = 0;j < numsurfacelist;j++)
7799 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
7801 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7804 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug)
7806 int i, j, endj, f, flagsmask;
7808 dp_model_t *model = ent->model;
7809 msurface_t *surfaces;
7810 unsigned char *update;
7811 int numsurfacelist = 0;
7815 if (r_maxsurfacelist < model->num_surfaces)
7817 r_maxsurfacelist = model->num_surfaces;
7819 Mem_Free(r_surfacelist);
7820 r_surfacelist = (msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
7823 // if the model is static it doesn't matter what value we give for
7824 // wantnormals and wanttangents, so this logic uses only rules applicable
7825 // to a model, knowing that they are meaningless otherwise
7826 if (ent == r_refdef.scene.worldentity)
7827 RSurf_ActiveWorldEntity();
7828 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
7829 RSurf_ActiveModelEntity(ent, false, false);
7831 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader && !depthonly);
7833 surfaces = model->data_surfaces;
7834 update = model->brushq1.lightmapupdateflags;
7836 // update light styles
7837 if (!skysurfaces && !depthonly && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
7839 model_brush_lightstyleinfo_t *style;
7840 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
7842 if (style->value != r_refdef.scene.lightstylevalue[style->style])
7844 int *list = style->surfacelist;
7845 style->value = r_refdef.scene.lightstylevalue[style->style];
7846 for (j = 0;j < style->numsurfaces;j++)
7847 update[list[j]] = true;
7852 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
7856 R_DrawDebugModel(ent);
7857 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7863 rsurface.uselightmaptexture = false;
7864 rsurface.texture = NULL;
7865 rsurface.rtlight = NULL;
7867 // add visible surfaces to draw list
7868 for (i = 0;i < model->nummodelsurfaces;i++)
7869 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
7870 // don't do anything if there were no surfaces
7871 if (!numsurfacelist)
7873 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7876 // update lightmaps if needed
7878 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
7880 R_BuildLightMap(ent, surfaces + j);
7881 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly);
7882 GL_AlphaTest(false);
7884 // add to stats if desired
7885 if (r_speeds.integer && !skysurfaces && !depthonly)
7887 r_refdef.stats.entities_surfaces += numsurfacelist;
7888 for (j = 0;j < numsurfacelist;j++)
7889 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
7891 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity