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_drawafterrtlighting = {CVAR_SAVE, "r_shadows_drawafterrtlighting", "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];
169 r_viewport_t viewport;
173 r_waterstate_t r_waterstate;
175 /// shadow volume bsp struct with automatically growing nodes buffer
178 rtexture_t *r_texture_blanknormalmap;
179 rtexture_t *r_texture_white;
180 rtexture_t *r_texture_grey128;
181 rtexture_t *r_texture_black;
182 rtexture_t *r_texture_notexture;
183 rtexture_t *r_texture_whitecube;
184 rtexture_t *r_texture_normalizationcube;
185 rtexture_t *r_texture_fogattenuation;
186 rtexture_t *r_texture_gammaramps;
187 unsigned int r_texture_gammaramps_serial;
188 //rtexture_t *r_texture_fogintensity;
190 unsigned int r_queries[R_MAX_OCCLUSION_QUERIES];
191 unsigned int r_numqueries;
192 unsigned int r_maxqueries;
194 char r_qwskincache[MAX_SCOREBOARD][MAX_QPATH];
195 skinframe_t *r_qwskincache_skinframe[MAX_SCOREBOARD];
197 /// vertex coordinates for a quad that covers the screen exactly
198 const float r_screenvertex3f[12] =
206 extern void R_DrawModelShadows(void);
208 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
211 for (i = 0;i < verts;i++)
222 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
225 for (i = 0;i < verts;i++)
235 // FIXME: move this to client?
238 if (gamemode == GAME_NEHAHRA)
240 Cvar_Set("gl_fogenable", "0");
241 Cvar_Set("gl_fogdensity", "0.2");
242 Cvar_Set("gl_fogred", "0.3");
243 Cvar_Set("gl_foggreen", "0.3");
244 Cvar_Set("gl_fogblue", "0.3");
246 r_refdef.fog_density = 0;
247 r_refdef.fog_red = 0;
248 r_refdef.fog_green = 0;
249 r_refdef.fog_blue = 0;
250 r_refdef.fog_alpha = 1;
251 r_refdef.fog_start = 0;
252 r_refdef.fog_end = 0;
255 float FogForDistance(vec_t dist)
257 unsigned int fogmasktableindex = (unsigned int)(dist * r_refdef.fogmasktabledistmultiplier);
258 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
261 float FogPoint_World(const vec3_t p)
263 return FogForDistance(VectorDistance((p), r_refdef.view.origin));
266 float FogPoint_Model(const vec3_t p)
268 return FogForDistance(VectorDistance((p), rsurface.modelorg) * Matrix4x4_ScaleFromMatrix(&rsurface.matrix));
271 static void R_BuildBlankTextures(void)
273 unsigned char data[4];
274 data[2] = 128; // normal X
275 data[1] = 128; // normal Y
276 data[0] = 255; // normal Z
277 data[3] = 128; // height
278 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
283 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
288 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
293 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
296 static void R_BuildNoTexture(void)
299 unsigned char pix[16][16][4];
300 // this makes a light grey/dark grey checkerboard texture
301 for (y = 0;y < 16;y++)
303 for (x = 0;x < 16;x++)
305 if ((y < 8) ^ (x < 8))
321 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, NULL);
324 static void R_BuildWhiteCube(void)
326 unsigned char data[6*1*1*4];
327 memset(data, 255, sizeof(data));
328 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_CLAMP | TEXF_PERSISTENT, NULL);
331 static void R_BuildNormalizationCube(void)
335 vec_t s, t, intensity;
337 unsigned char data[6][NORMSIZE][NORMSIZE][4];
338 for (side = 0;side < 6;side++)
340 for (y = 0;y < NORMSIZE;y++)
342 for (x = 0;x < NORMSIZE;x++)
344 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
345 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
380 intensity = 127.0f / sqrt(DotProduct(v, v));
381 data[side][y][x][2] = (unsigned char)(128.0f + intensity * v[0]);
382 data[side][y][x][1] = (unsigned char)(128.0f + intensity * v[1]);
383 data[side][y][x][0] = (unsigned char)(128.0f + intensity * v[2]);
384 data[side][y][x][3] = 255;
388 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, &data[0][0][0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_CLAMP | TEXF_PERSISTENT, NULL);
391 static void R_BuildFogTexture(void)
395 unsigned char data1[FOGWIDTH][4];
396 //unsigned char data2[FOGWIDTH][4];
399 r_refdef.fogmasktable_start = r_refdef.fog_start;
400 r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
401 r_refdef.fogmasktable_range = r_refdef.fogrange;
402 r_refdef.fogmasktable_density = r_refdef.fog_density;
404 r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
405 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
407 d = (x * r - r_refdef.fogmasktable_start);
408 if(developer.integer >= 100)
409 Con_Printf("%f ", d);
411 if (r_fog_exp2.integer)
412 alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
414 alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
415 if(developer.integer >= 100)
416 Con_Printf(" : %f ", alpha);
417 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
418 if(developer.integer >= 100)
419 Con_Printf(" = %f\n", alpha);
420 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
423 for (x = 0;x < FOGWIDTH;x++)
425 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
430 //data2[x][0] = 255 - b;
431 //data2[x][1] = 255 - b;
432 //data2[x][2] = 255 - b;
435 if (r_texture_fogattenuation)
437 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, FOGWIDTH, 1);
438 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, FOGWIDTH, 1);
442 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);
443 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
447 static const char *builtinshaderstring =
448 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
449 "// written by Forest 'LordHavoc' Hale\n"
450 "#ifdef USESHADOWMAPRECT\n"
451 "#extension GL_ARB_texture_rectangle : enable\n"
453 "#ifdef USESHADOWMAPCUBE\n"
454 "#extension GL_EXT_gpu_shader4 : enable\n"
457 "// common definitions between vertex shader and fragment shader:\n"
459 "//#ifdef __GLSL_CG_DATA_TYPES\n"
460 "//# define myhalf half\n"
461 "//# define myhalf2 half2\n"
462 "//# define myhalf3 half3\n"
463 "//# define myhalf4 half4\n"
465 "# define myhalf float\n"
466 "# define myhalf2 vec2\n"
467 "# define myhalf3 vec3\n"
468 "# define myhalf4 vec4\n"
471 "#ifdef MODE_DEPTH_OR_SHADOW\n"
473 "# ifdef VERTEX_SHADER\n"
476 " gl_Position = ftransform();\n"
481 "#ifdef MODE_SHOWDEPTH\n"
482 "# ifdef VERTEX_SHADER\n"
485 " gl_Position = ftransform();\n"
486 " gl_FrontColor = vec4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
489 "# ifdef FRAGMENT_SHADER\n"
492 " gl_FragColor = gl_Color;\n"
496 "#else // !MODE_SHOWDEPTH\n"
498 "#ifdef MODE_POSTPROCESS\n"
499 "# ifdef VERTEX_SHADER\n"
502 " gl_FrontColor = gl_Color;\n"
503 " gl_Position = ftransform();\n"
504 " gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;\n"
506 " gl_TexCoord[1] = gl_TextureMatrix[1] * gl_MultiTexCoord1;\n"
510 "# ifdef FRAGMENT_SHADER\n"
512 "uniform sampler2D Texture_First;\n"
514 "uniform sampler2D Texture_Second;\n"
516 "#ifdef USEGAMMARAMPS\n"
517 "uniform sampler2D Texture_GammaRamps;\n"
519 "#ifdef USESATURATION\n"
520 "uniform float Saturation;\n"
522 "#ifdef USEVIEWTINT\n"
523 "uniform vec4 TintColor;\n"
525 "//uncomment these if you want to use them:\n"
526 "uniform vec4 UserVec1;\n"
527 "// uniform vec4 UserVec2;\n"
528 "// uniform vec4 UserVec3;\n"
529 "// uniform vec4 UserVec4;\n"
530 "// uniform float ClientTime;\n"
531 "uniform vec2 PixelSize;\n"
534 " gl_FragColor = texture2D(Texture_First, gl_TexCoord[0].xy);\n"
536 " gl_FragColor += texture2D(Texture_Second, gl_TexCoord[1].xy);\n"
538 "#ifdef USEVIEWTINT\n"
539 " gl_FragColor = mix(gl_FragColor, TintColor, TintColor.a);\n"
542 "#ifdef USEPOSTPROCESSING\n"
543 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
544 "// 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"
545 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2(-0.987688, -0.156434)) * UserVec1.y;\n"
546 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2(-0.156434, -0.891007)) * UserVec1.y;\n"
547 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2( 0.891007, -0.453990)) * UserVec1.y;\n"
548 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2( 0.707107, 0.707107)) * UserVec1.y;\n"
549 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2(-0.453990, 0.891007)) * UserVec1.y;\n"
550 " gl_FragColor /= (1 + 5 * UserVec1.y);\n"
553 "#ifdef USESATURATION\n"
554 " //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
555 " myhalf y = dot(gl_FragColor.rgb, vec3(0.299, 0.587, 0.114));\n"
556 " //gl_FragColor = vec3(y) + (gl_FragColor.rgb - vec3(y)) * Saturation;\n"
557 " gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n" // TODO: test this on ATI
560 "#ifdef USEGAMMARAMPS\n"
561 " gl_FragColor.r = texture2D(Texture_GammaRamps, vec2(gl_FragColor.r, 0)).r;\n"
562 " gl_FragColor.g = texture2D(Texture_GammaRamps, vec2(gl_FragColor.g, 0)).g;\n"
563 " gl_FragColor.b = texture2D(Texture_GammaRamps, vec2(gl_FragColor.b, 0)).b;\n"
570 "#ifdef MODE_GENERIC\n"
571 "# ifdef VERTEX_SHADER\n"
574 " gl_FrontColor = gl_Color;\n"
575 "# ifdef USEDIFFUSE\n"
576 " gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;\n"
578 "# ifdef USESPECULAR\n"
579 " gl_TexCoord[1] = gl_TextureMatrix[1] * gl_MultiTexCoord1;\n"
581 " gl_Position = ftransform();\n"
584 "# ifdef FRAGMENT_SHADER\n"
586 "# ifdef USEDIFFUSE\n"
587 "uniform sampler2D Texture_First;\n"
589 "# ifdef USESPECULAR\n"
590 "uniform sampler2D Texture_Second;\n"
595 " gl_FragColor = gl_Color;\n"
596 "# ifdef USEDIFFUSE\n"
597 " gl_FragColor *= texture2D(Texture_First, gl_TexCoord[0].xy);\n"
600 "# ifdef USESPECULAR\n"
601 " vec4 tex2 = texture2D(Texture_Second, gl_TexCoord[1].xy);\n"
603 "# ifdef USECOLORMAPPING\n"
604 " gl_FragColor *= tex2;\n"
607 " gl_FragColor += tex2;\n"
609 "# ifdef USEVERTEXTEXTUREBLEND\n"
610 " gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
615 "#else // !MODE_GENERIC\n"
617 "varying vec2 TexCoord;\n"
618 "#ifdef USEVERTEXTEXTUREBLEND\n"
619 "varying vec2 TexCoord2;\n"
621 "varying vec2 TexCoordLightmap;\n"
623 "#ifdef MODE_LIGHTSOURCE\n"
624 "varying vec3 CubeVector;\n"
627 "#ifdef MODE_LIGHTSOURCE\n"
628 "varying vec3 LightVector;\n"
630 "#ifdef MODE_LIGHTDIRECTION\n"
631 "varying vec3 LightVector;\n"
634 "varying vec3 EyeVector;\n"
636 "varying vec3 EyeVectorModelSpace;\n"
639 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
640 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
641 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
643 "#ifdef MODE_WATER\n"
644 "varying vec4 ModelViewProjectionPosition;\n"
646 "#ifdef MODE_REFRACTION\n"
647 "varying vec4 ModelViewProjectionPosition;\n"
649 "#ifdef USEREFLECTION\n"
650 "varying vec4 ModelViewProjectionPosition;\n"
657 "// vertex shader specific:\n"
658 "#ifdef VERTEX_SHADER\n"
660 "uniform vec3 LightPosition;\n"
661 "uniform vec3 EyePosition;\n"
662 "uniform vec3 LightDir;\n"
664 "// 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"
668 " gl_FrontColor = gl_Color;\n"
669 " // copy the surface texcoord\n"
670 " TexCoord = vec2(gl_TextureMatrix[0] * gl_MultiTexCoord0);\n"
671 "#ifdef USEVERTEXTEXTUREBLEND\n"
672 " TexCoord2 = vec2(gl_TextureMatrix[1] * gl_MultiTexCoord0);\n"
674 "#ifndef MODE_LIGHTSOURCE\n"
675 "# ifndef MODE_LIGHTDIRECTION\n"
676 " TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
680 "#ifdef MODE_LIGHTSOURCE\n"
681 " // transform vertex position into light attenuation/cubemap space\n"
682 " // (-1 to +1 across the light box)\n"
683 " CubeVector = vec3(gl_TextureMatrix[3] * gl_Vertex);\n"
685 " // transform unnormalized light direction into tangent space\n"
686 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
687 " // normalize it per pixel)\n"
688 " vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
689 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
690 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
691 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
694 "#ifdef MODE_LIGHTDIRECTION\n"
695 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
696 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
697 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
700 " // transform unnormalized eye direction into tangent space\n"
702 " vec3 EyeVectorModelSpace;\n"
704 " EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
705 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
706 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
707 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
709 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
710 " VectorS = gl_MultiTexCoord1.xyz;\n"
711 " VectorT = gl_MultiTexCoord2.xyz;\n"
712 " VectorR = gl_MultiTexCoord3.xyz;\n"
715 "//#if defined(MODE_WATER) || defined(MODE_REFRACTION) || defined(USEREFLECTION)\n"
716 "// ModelViewProjectionPosition = gl_Vertex * gl_ModelViewProjectionMatrix;\n"
717 "// //ModelViewProjectionPosition_svector = (gl_Vertex + vec4(gl_MultiTexCoord1.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
718 "// //ModelViewProjectionPosition_tvector = (gl_Vertex + vec4(gl_MultiTexCoord2.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
721 "// transform vertex to camera space, using ftransform to match non-VS\n"
723 " gl_Position = ftransform();\n"
725 "#ifdef MODE_WATER\n"
726 " ModelViewProjectionPosition = gl_Position;\n"
728 "#ifdef MODE_REFRACTION\n"
729 " ModelViewProjectionPosition = gl_Position;\n"
731 "#ifdef USEREFLECTION\n"
732 " ModelViewProjectionPosition = gl_Position;\n"
736 "#endif // VERTEX_SHADER\n"
741 "// fragment shader specific:\n"
742 "#ifdef FRAGMENT_SHADER\n"
744 "// 13 textures, we can only use up to 16 on DX9-class hardware\n"
745 "uniform sampler2D Texture_Normal;\n"
746 "uniform sampler2D Texture_Color;\n"
747 "uniform sampler2D Texture_Gloss;\n"
748 "uniform sampler2D Texture_Glow;\n"
749 "uniform sampler2D Texture_SecondaryNormal;\n"
750 "uniform sampler2D Texture_SecondaryColor;\n"
751 "uniform sampler2D Texture_SecondaryGloss;\n"
752 "uniform sampler2D Texture_SecondaryGlow;\n"
753 "uniform sampler2D Texture_Pants;\n"
754 "uniform sampler2D Texture_Shirt;\n"
755 "uniform sampler2D Texture_FogMask;\n"
756 "uniform sampler2D Texture_Lightmap;\n"
757 "uniform sampler2D Texture_Deluxemap;\n"
758 "uniform sampler2D Texture_Refraction;\n"
759 "uniform sampler2D Texture_Reflection;\n"
760 "uniform sampler2D Texture_Attenuation;\n"
761 "uniform samplerCube Texture_Cube;\n"
763 "#define showshadowmap 0\n"
764 "#define useshadowsamplerrect 0\n"
765 "#define useshadowsampler2d 0\n"
766 "#define useshadowsamplercube 1\n"
768 "#ifdef USESHADOWMAPRECT\n"
769 "# if useshadowsamplerrect\n"
770 "uniform sampler2DRectShadow Texture_ShadowMapRect;\n"
772 "uniform sampler2DRect Texture_ShadowMapRect;\n"
776 "#ifdef USESHADOWMAP2D\n"
777 "# if useshadowsampler2d\n"
778 "uniform sampler2DShadow Texture_ShadowMap2D;\n"
780 "uniform sampler2D Texture_ShadowMap2D;\n"
784 "#ifdef USESHADOWMAPCUBE\n"
785 "# if useshadowsamplercube\n"
786 "uniform samplerCubeShadow Texture_ShadowMapCube;\n"
788 "uniform samplerCube Texture_ShadowMapCube;\n"
792 "uniform myhalf3 LightColor;\n"
793 "uniform myhalf3 AmbientColor;\n"
794 "uniform myhalf3 DiffuseColor;\n"
795 "uniform myhalf3 SpecularColor;\n"
796 "uniform myhalf3 Color_Pants;\n"
797 "uniform myhalf3 Color_Shirt;\n"
798 "uniform myhalf3 FogColor;\n"
800 "uniform myhalf4 TintColor;\n"
803 "//#ifdef MODE_WATER\n"
804 "uniform vec4 DistortScaleRefractReflect;\n"
805 "uniform vec4 ScreenScaleRefractReflect;\n"
806 "uniform vec4 ScreenCenterRefractReflect;\n"
807 "uniform myhalf4 RefractColor;\n"
808 "uniform myhalf4 ReflectColor;\n"
809 "uniform myhalf ReflectFactor;\n"
810 "uniform myhalf ReflectOffset;\n"
812 "//# ifdef MODE_REFRACTION\n"
813 "//uniform vec4 DistortScaleRefractReflect;\n"
814 "//uniform vec4 ScreenScaleRefractReflect;\n"
815 "//uniform vec4 ScreenCenterRefractReflect;\n"
816 "//uniform myhalf4 RefractColor;\n"
817 "//# ifdef USEREFLECTION\n"
818 "//uniform myhalf4 ReflectColor;\n"
821 "//# ifdef USEREFLECTION\n"
822 "//uniform vec4 DistortScaleRefractReflect;\n"
823 "//uniform vec4 ScreenScaleRefractReflect;\n"
824 "//uniform vec4 ScreenCenterRefractReflect;\n"
825 "//uniform myhalf4 ReflectColor;\n"
830 "uniform myhalf GlowScale;\n"
831 "uniform myhalf SceneBrightness;\n"
833 "uniform float OffsetMapping_Scale;\n"
834 "uniform float OffsetMapping_Bias;\n"
835 "uniform float FogRangeRecip;\n"
837 "uniform myhalf AmbientScale;\n"
838 "uniform myhalf DiffuseScale;\n"
839 "uniform myhalf SpecularScale;\n"
840 "uniform myhalf SpecularPower;\n"
842 "#ifdef USEOFFSETMAPPING\n"
843 "vec2 OffsetMapping(vec2 TexCoord)\n"
845 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
846 " // 14 sample relief mapping: linear search and then binary search\n"
847 " // this basically steps forward a small amount repeatedly until it finds\n"
848 " // itself inside solid, then jitters forward and back using decreasing\n"
849 " // amounts to find the impact\n"
850 " //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
851 " //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
852 " vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
853 " vec3 RT = vec3(TexCoord, 1);\n"
854 " OffsetVector *= 0.1;\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);\n"
863 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
864 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) - 0.5);\n"
865 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5 - 0.25);\n"
866 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25 - 0.125);\n"
867 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125 - 0.0625);\n"
868 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
871 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
872 " // this basically moves forward the full distance, and then backs up based\n"
873 " // on height of samples\n"
874 " //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
875 " //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
876 " vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
877 " TexCoord += OffsetVector;\n"
878 " OffsetVector *= 0.333;\n"
879 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
880 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
881 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
882 " return TexCoord;\n"
885 "#endif // USEOFFSETMAPPING\n"
887 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
888 "//float ShadowMap_TextureSize = 1024.0;\n"
889 "//float ShadowMap_BorderSize = 6.0;\n"
890 "//float ShadowMap_NearClip = 0.0001;\n"
891 "//float ShadowMap_FarClip = 1.0;\n"
892 "//float ShadowMap_Bias = ShadowMap_NearClip * 64.0 / ShadowMap_TextureSize;\n"
893 "//vec2 ShadowMap_TextureScale = vec2(0.5, 0.25);\n"
894 "//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"
895 "uniform float ShadowMap_Bias;\n"
896 "uniform vec2 ShadowMap_TextureScale;\n"
897 "uniform vec4 ShadowMap_Parameters;\n"
900 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
901 "vec3 GetShadowMapTC2D(vec3 dir)\n"
903 " vec3 adir = abs(dir);\n"
908 " if (adir.x > adir.y)\n"
910 " if (adir.x > adir.z)\n"
912 " d = 0.5 / adir.x;\n"
913 " if (dir.x >= 0.0)\n"
916 " tc = vec3(-dir.z, -dir.y, -dir.x);\n"
917 " offset = vec3(0.5, 0.5, 0.5);\n"
922 " tc = vec3( dir.z, -dir.y, dir.x);\n"
923 " offset = vec3(1.5, 0.5, 0.5);\n"
928 " d = 0.5 / adir.z;\n"
929 " if (dir.z >= 0.0)\n"
932 " tc = vec3( dir.x, -dir.y, -dir.z);\n"
933 " offset = vec3(0.5, 2.5, 0.5);\n"
938 " tc = vec3(-dir.x, -dir.y, dir.z);\n"
939 " offset = vec3(1.5, 2.5, 0.5);\n"
945 " if (adir.y > adir.z)\n"
947 " d = 0.5 / adir.y;\n"
948 " if (dir.y >= 0.0)\n"
951 " tc = vec3( dir.x, dir.z, -dir.y);\n"
952 " offset = vec3(0.5, 1.5, 0.5);\n"
957 " tc = vec3( dir.x, -dir.z, dir.y);\n"
958 " offset = vec3(1.5, 1.5, 0.5);\n"
963 " d = 0.5 / adir.z;\n"
964 " if (dir.z >= 0.0)\n"
967 " tc = vec3(dir.x, -dir.y, -dir.z);\n"
968 " offset = vec3(0.5, 2.5, 0.5);\n"
973 " tc = vec3(-dir.x, -dir.y, dir.z);\n"
974 " offset = vec3(1.5, 2.5, 0.5);\n"
978 " tc = tc * ShadowMap_Parameters.xyz * d + offset;\n"
979 " tc.xy *= ShadowMap_TextureScale;\n"
980 " tc.z += ShadowMap_Parameters.w * d - ShadowMap_Bias * d;\n"
982 " // experimental method by eihrul, needs overhaul\n"
983 " vec3 ma = vec3(0.0, 0.0, 1.0);\n"
984 " if (adir.x > adir.y)\n"
986 " if (adir.x > adir.z)\n"
987 " ma = vec3(1.0, 0.0, 0.0);\n"
989 " else if (adir.y > adir.z)\n"
990 " ma = vec3(0.0, 1.0, 0.0);\n"
992 " tc.xy = dir.xy - ma.xy*(dir.xy - dir.z);\n"
993 " tc.xy = (tc.xy/dot(ma, dir))*0.5 + 0.5;\n"
994 " tc.z = dot(ma, adir);\n"
995 " tc.xy = (tc.xy * tcscale + offset) * vec2(0.5, 0.25);\n"
1000 "#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
1002 "#ifdef USESHADOWMAPCUBE\n"
1003 "vec4 GetShadowMapTCCube(vec3 dir)\n"
1005 " vec3 adir = abs(dir);\n"
1006 " float sidedist = max(adir.x, max(adir.y, adir.z));\n"
1007 " return vec4(dir, 0.5 - 0.5 * (ShadowMap_Parameters.z - (-ShadowMap_Bias + ShadowMap_Parameters.w) / sidedist));\n"
1011 "#if !showshadowmap\n"
1012 "# ifdef USESHADOWMAPRECT\n"
1013 "float ShadowMapCompare(vec3 dir)\n"
1015 " vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1017 "# if useshadowsamplerrect\n"
1018 " f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).a;\n"
1020 " f = step(shadowmaptc.z, texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
1026 "# ifdef USESHADOWMAP2D\n"
1027 "float ShadowMapCompare(vec3 dir)\n"
1029 " vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1031 "# if useshadowsampler2d\n"
1032 " f = shadow2D(Texture_ShadowMap2D, shadowmaptc).a;\n"
1034 " f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy).r);\n"
1040 "# ifdef USESHADOWMAPCUBE\n"
1041 "float ShadowMapCompare(vec3 dir)\n"
1043 " // apply depth texture cubemap as light filter\n"
1044 " vec4 shadowmaptc = GetShadowMapTCCube(dir);\n"
1046 "# if useshadowsamplercube\n"
1047 " f = shadowCube(Texture_ShadowMapCube, shadowmaptc).a;\n"
1049 " f = step(shadowmaptc.w, textureCube(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
1057 "#ifdef MODE_WATER\n"
1062 "#ifdef USEOFFSETMAPPING\n"
1063 " // apply offsetmapping\n"
1064 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1065 "#define TexCoord TexCoordOffset\n"
1068 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1069 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1070 " vec4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1071 " vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xyxy * DistortScaleRefractReflect;\n"
1072 " // FIXME temporary hack to detect the case that the reflection\n"
1073 " // gets blackened at edges due to leaving the area that contains actual\n"
1075 " // Remove this 'ack once we have a better way to stop this thing from\n"
1077 " float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1078 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1079 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1080 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1081 " ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
1082 " f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1083 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1084 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1085 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1086 " ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
1087 " float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
1088 " gl_FragColor = mix(texture2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, texture2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
1091 "#else // !MODE_WATER\n"
1092 "#ifdef MODE_REFRACTION\n"
1094 "// refraction pass\n"
1097 "#ifdef USEOFFSETMAPPING\n"
1098 " // apply offsetmapping\n"
1099 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1100 "#define TexCoord TexCoordOffset\n"
1103 " vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
1104 " //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
1105 " vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
1106 " vec2 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
1107 " // FIXME temporary hack to detect the case that the reflection\n"
1108 " // gets blackened at edges due to leaving the area that contains actual\n"
1110 " // Remove this 'ack once we have a better way to stop this thing from\n"
1112 " float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1113 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1114 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1115 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1116 " ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1117 " gl_FragColor = texture2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
1120 "#else // !MODE_REFRACTION\n"
1123 "#ifdef USEOFFSETMAPPING\n"
1124 " // apply offsetmapping\n"
1125 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1126 "#define TexCoord TexCoordOffset\n"
1129 " // combine the diffuse textures (base, pants, shirt)\n"
1130 " myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
1131 "#ifdef USECOLORMAPPING\n"
1132 " color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
1134 "#ifdef USEVERTEXTEXTUREBLEND\n"
1135 " myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
1136 " //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
1137 " //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
1138 " color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
1140 " //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
1143 "#ifdef USEDIFFUSE\n"
1144 " // get the surface normal and the gloss color\n"
1145 "# ifdef USEVERTEXTEXTUREBLEND\n"
1146 " myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
1147 "# ifdef USESPECULAR\n"
1148 " myhalf3 glosscolor = mix(myhalf3(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf3(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
1151 " myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
1152 "# ifdef USESPECULAR\n"
1153 " myhalf3 glosscolor = myhalf3(texture2D(Texture_Gloss, TexCoord));\n"
1160 "#ifdef MODE_LIGHTSOURCE\n"
1161 " // light source\n"
1163 " // calculate surface normal, light normal, and specular normal\n"
1164 " // compute color intensity for the two textures (colormap and glossmap)\n"
1165 " // scale by light color and attenuation as efficiently as possible\n"
1166 " // (do as much scalar math as possible rather than vector math)\n"
1167 "# ifdef USEDIFFUSE\n"
1168 " // get the light normal\n"
1169 " myhalf3 diffusenormal = myhalf3(normalize(LightVector));\n"
1171 "# ifdef USESPECULAR\n"
1172 "# ifndef USEEXACTSPECULARMATH\n"
1173 " myhalf3 specularnormal = normalize(diffusenormal + myhalf3(normalize(EyeVector)));\n"
1176 " // calculate directional shading\n"
1177 "# ifdef USEEXACTSPECULARMATH\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(reflect(diffusenormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower)) * glosscolor);\n"
1180 " 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"
1183 "# ifdef USEDIFFUSE\n"
1184 " // calculate directional shading\n"
1185 " color.rgb = color.rgb * (myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0))) * (AmbientScale + DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0))));\n"
1187 " // calculate directionless shading\n"
1188 " color.rgb = color.rgb * myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1192 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1193 "#if !showshadowmap\n"
1194 " color.rgb *= ShadowMapCompare(CubeVector);\n"
1198 "# ifdef USECUBEFILTER\n"
1199 " // apply light cubemap filter\n"
1200 " //color.rgb *= normalize(CubeVector) * 0.5 + 0.5;//vec3(textureCube(Texture_Cube, CubeVector));\n"
1201 " color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
1203 "#endif // MODE_LIGHTSOURCE\n"
1208 "#ifdef MODE_LIGHTDIRECTION\n"
1209 " // directional model lighting\n"
1210 "# ifdef USEDIFFUSE\n"
1211 " // get the light normal\n"
1212 " myhalf3 diffusenormal = myhalf3(normalize(LightVector));\n"
1214 "# ifdef USESPECULAR\n"
1215 " // calculate directional shading\n"
1216 " color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
1217 "# ifdef USEEXACTSPECULARMATH\n"
1218 " color.rgb += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(myhalf(max(float(dot(reflect(diffusenormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1220 " myhalf3 specularnormal = normalize(diffusenormal + myhalf3(normalize(EyeVector)));\n"
1221 " color.rgb += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1224 "# ifdef USEDIFFUSE\n"
1226 " // calculate directional shading\n"
1227 " color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
1229 " color.rgb *= AmbientColor;\n"
1232 "#endif // MODE_LIGHTDIRECTION\n"
1237 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1238 " // deluxemap lightmapping using light vectors in modelspace (evil q3map2)\n"
1240 " // get the light normal\n"
1241 " myhalf3 diffusenormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1242 " myhalf3 diffusenormal;\n"
1243 " diffusenormal.x = dot(diffusenormal_modelspace, myhalf3(VectorS));\n"
1244 " diffusenormal.y = dot(diffusenormal_modelspace, myhalf3(VectorT));\n"
1245 " diffusenormal.z = dot(diffusenormal_modelspace, myhalf3(VectorR));\n"
1246 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1247 " // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
1248 " // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
1249 " // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
1250 " // to map the luxels to coordinates on the draw surfaces), which also causes\n"
1251 " // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
1252 " // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
1253 " // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
1254 " // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
1255 " myhalf3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal) / max(0.25, diffusenormal.z)), 0.0)));\n"
1256 " // 0.25 supports up to 75.5 degrees normal/deluxe angle\n"
1257 "# ifdef USESPECULAR\n"
1258 "# ifdef USEEXACTSPECULARMATH\n"
1259 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(reflect(normalize(diffusenormal), surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1261 " myhalf3 specularnormal = myhalf3(normalize(diffusenormal + myhalf3(normalize(EyeVector))));\n"
1262 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1266 " // apply lightmap color\n"
1267 " color.rgb = color.rgb * AmbientScale + tempcolor * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1268 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1273 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1274 " // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1276 " // get the light normal\n"
1277 " myhalf3 diffusenormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1278 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1279 " myhalf3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal) / diffusenormal.z), 0.0)));\n"
1280 "# ifdef USESPECULAR\n"
1281 "# ifdef USEEXACTSPECULARMATH\n"
1282 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(reflect(diffusenormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1284 " myhalf3 specularnormal = myhalf3(normalize(diffusenormal + myhalf3(normalize(EyeVector))));\n"
1285 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1289 " // apply lightmap color\n"
1290 " color.rgb = color.rgb * AmbientScale + tempcolor * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1291 "#endif // MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1296 "#ifdef MODE_LIGHTMAP\n"
1297 " // apply lightmap color\n"
1298 " color.rgb = color.rgb * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * DiffuseScale + color.rgb * AmbientScale;\n"
1299 "#endif // MODE_LIGHTMAP\n"
1304 "#ifdef MODE_VERTEXCOLOR\n"
1305 " // apply lightmap color\n"
1306 " color.rgb = color.rgb * myhalf3(gl_Color.rgb) * DiffuseScale + color.rgb * AmbientScale;\n"
1307 "#endif // MODE_VERTEXCOLOR\n"
1312 "#ifdef MODE_FLATCOLOR\n"
1313 "#endif // MODE_FLATCOLOR\n"
1321 " color *= TintColor;\n"
1324 "#ifdef USEVERTEXTEXTUREBLEND\n"
1325 " color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend);\n"
1327 " color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * GlowScale;\n"
1331 " color.rgb *= SceneBrightness;\n"
1333 " // apply fog after Contrastboost/SceneBrightness because its color is already modified appropriately\n"
1335 " color.rgb = mix(FogColor, color.rgb, myhalf(texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*FogRangeRecip, 0.0))));\n"
1338 " // 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"
1339 "#ifdef USEREFLECTION\n"
1340 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1341 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1342 " vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
1343 " vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
1344 " // FIXME temporary hack to detect the case that the reflection\n"
1345 " // gets blackened at edges due to leaving the area that contains actual\n"
1347 " // Remove this 'ack once we have a better way to stop this thing from\n"
1349 " float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1350 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1351 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1352 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1353 " ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1354 " color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
1357 " gl_FragColor = vec4(color);\n"
1359 "#if showshadowmap\n"
1360 "# ifdef USESHADOWMAPRECT\n"
1361 "# if useshadowsamplerrect\n"
1362 " gl_FragColor = shadow2DRect(Texture_ShadowMapRect, GetShadowMapTC2D(CubeVector).xyz);\n"
1364 " gl_FragColor = texture2DRect(Texture_ShadowMapRect, GetShadowMapTC2D(CubeVector).xy);\n"
1368 "# ifdef USESHADOWMAP2D\n"
1369 "# if useshadowsampler2d\n"
1370 " gl_FragColor = shadow2D(Texture_ShadowMap2D, GetShadowMapTC2D(CubeVector).xyz);\n"
1372 " gl_FragColor = texture2D(Texture_ShadowMap2D, GetShadowMapTC2D(CubeVector).xy);\n"
1376 "# ifdef USESHADOWMAPCUBE\n"
1377 "# if useshadowsamplercube\n"
1378 " gl_FragColor = shadowCube(Texture_ShadowMapCube, GetShadowMapTCCube(CubeVector));\n"
1380 " gl_FragColor = textureCube(Texture_ShadowMapCube, GetShadowMapTCCube(CubeVector).xyz);\n"
1385 "#endif // !MODE_REFRACTION\n"
1386 "#endif // !MODE_WATER\n"
1388 "#endif // FRAGMENT_SHADER\n"
1390 "#endif // !MODE_GENERIC\n"
1391 "#endif // !MODE_POSTPROCESS\n"
1392 "#endif // !MODE_SHOWDEPTH\n"
1393 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1396 typedef struct shaderpermutationinfo_s
1398 const char *pretext;
1401 shaderpermutationinfo_t;
1403 typedef struct shadermodeinfo_s
1405 const char *vertexfilename;
1406 const char *geometryfilename;
1407 const char *fragmentfilename;
1408 const char *pretext;
1413 typedef enum shaderpermutation_e
1415 SHADERPERMUTATION_DIFFUSE = 1<<0, ///< (lightsource) whether to use directional shading
1416 SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, ///< indicates this is a two-layer material blend based on vertex alpha (q3bsp)
1417 SHADERPERMUTATION_VIEWTINT = 1<<1, ///< view tint (postprocessing only)
1418 SHADERPERMUTATION_COLORMAPPING = 1<<2, ///< indicates this is a colormapped skin
1419 SHADERPERMUTATION_SATURATION = 1<<2, ///< saturation (postprocessing only)
1420 SHADERPERMUTATION_FOG = 1<<3, ///< tint the color by fog color or black if using additive blend mode
1421 SHADERPERMUTATION_GAMMARAMPS = 1<<3, ///< gamma (postprocessing only)
1422 SHADERPERMUTATION_CUBEFILTER = 1<<4, ///< (lightsource) use cubemap light filter
1423 SHADERPERMUTATION_GLOW = 1<<5, ///< (lightmap) blend in an additive glow texture
1424 SHADERPERMUTATION_BLOOM = 1<<5, ///< bloom (postprocessing only)
1425 SHADERPERMUTATION_SPECULAR = 1<<6, ///< (lightsource or deluxemapping) render specular effects
1426 SHADERPERMUTATION_POSTPROCESSING = 1<<6, ///< user defined postprocessing (postprocessing only)
1427 SHADERPERMUTATION_EXACTSPECULARMATH = 1<<7, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
1428 SHADERPERMUTATION_REFLECTION = 1<<8, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
1429 SHADERPERMUTATION_OFFSETMAPPING = 1<<9, ///< adjust texcoords to roughly simulate a displacement mapped surface
1430 SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<10, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
1431 SHADERPERMUTATION_SHADOWMAPRECT = 1<<11, ///< (lightsource) use shadowmap rectangle texture as light filter
1432 SHADERPERMUTATION_SHADOWMAPCUBE = 1<<12, ///< (lightsource) use shadowmap cubemap texture as light filter
1433 SHADERPERMUTATION_SHADOWMAP2D = 1<<13, ///< (lightsource) use shadowmap rectangle texture as light filter
1434 SHADERPERMUTATION_LIMIT = 1<<14, ///< size of permutations array
1435 SHADERPERMUTATION_COUNT = 14 ///< size of shaderpermutationinfo array
1437 shaderpermutation_t;
1439 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
1440 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
1442 {"#define USEDIFFUSE\n", " diffuse"},
1443 {"#define USEVERTEXTEXTUREBLEND\n#define USEVIEWTINT\n", " vertextextureblend/tint"},
1444 {"#define USECOLORMAPPING\n#define USESATURATION\n", " colormapping/saturation"},
1445 {"#define USEFOG\n#define USEGAMMARAMPS\n", " fog/gammaramps"},
1446 {"#define USECUBEFILTER\n", " cubefilter"},
1447 {"#define USEGLOW\n#define USEBLOOM\n", " glow/bloom"},
1448 {"#define USESPECULAR\n#define USEPOSTPROCESSING", " specular/postprocessing"},
1449 {"#define USEEXACTSPECULARMATH\n", " exactspecularmath"},
1450 {"#define USEREFLECTION\n", " reflection"},
1451 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
1452 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
1453 {"#define USESHADOWMAPRECT\n", " shadowmaprect"},
1454 {"#define USESHADOWMAPCUBE\n", " shadowmapcube"},
1455 {"#define USESHADOWMAP2D\n", " shadowmap2d"},
1458 /// this enum is multiplied by SHADERPERMUTATION_MODEBASE
1459 typedef enum shadermode_e
1461 SHADERMODE_GENERIC, ///< (particles/HUD/etc) vertex color, optionally multiplied by one texture
1462 SHADERMODE_POSTPROCESS, ///< postprocessing shader (r_glsl_postprocess)
1463 SHADERMODE_DEPTH_OR_SHADOW, ///< (depthfirst/shadows) vertex shader only
1464 SHADERMODE_FLATCOLOR, ///< (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
1465 SHADERMODE_VERTEXCOLOR, ///< (lightmap) modulate texture by vertex colors (q3bsp)
1466 SHADERMODE_LIGHTMAP, ///< (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
1467 SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, ///< (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
1468 SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, ///< (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
1469 SHADERMODE_LIGHTDIRECTION, ///< (lightmap) use directional pixel shading from fixed light direction (q3bsp)
1470 SHADERMODE_LIGHTSOURCE, ///< (lightsource) use directional pixel shading from light source (rtlight)
1471 SHADERMODE_REFRACTION, ///< refract background (the material is rendered normally after this pass)
1472 SHADERMODE_WATER, ///< refract background and reflection (the material is rendered normally after this pass)
1473 SHADERMODE_SHOWDEPTH, ///< (debugging) renders depth as color
1478 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
1479 shadermodeinfo_t shadermodeinfo[SHADERMODE_COUNT] =
1481 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
1482 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
1483 {"glsl/default.glsl", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
1484 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
1485 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
1486 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
1487 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
1488 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
1489 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
1490 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
1491 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
1492 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
1493 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
1496 typedef struct r_glsl_permutation_s
1498 /// indicates if we have tried compiling this permutation already
1500 /// 0 if compilation failed
1502 /// locations of detected uniforms in program object, or -1 if not found
1503 int loc_Texture_First;
1504 int loc_Texture_Second;
1505 int loc_Texture_GammaRamps;
1506 int loc_Texture_Normal;
1507 int loc_Texture_Color;
1508 int loc_Texture_Gloss;
1509 int loc_Texture_Glow;
1510 int loc_Texture_SecondaryNormal;
1511 int loc_Texture_SecondaryColor;
1512 int loc_Texture_SecondaryGloss;
1513 int loc_Texture_SecondaryGlow;
1514 int loc_Texture_Pants;
1515 int loc_Texture_Shirt;
1516 int loc_Texture_FogMask;
1517 int loc_Texture_Lightmap;
1518 int loc_Texture_Deluxemap;
1519 int loc_Texture_Attenuation;
1520 int loc_Texture_Cube;
1521 int loc_Texture_Refraction;
1522 int loc_Texture_Reflection;
1523 int loc_Texture_ShadowMapRect;
1524 int loc_Texture_ShadowMapCube;
1525 int loc_Texture_ShadowMap2D;
1527 int loc_LightPosition;
1528 int loc_EyePosition;
1529 int loc_Color_Pants;
1530 int loc_Color_Shirt;
1531 int loc_FogRangeRecip;
1532 int loc_AmbientScale;
1533 int loc_DiffuseScale;
1534 int loc_SpecularScale;
1535 int loc_SpecularPower;
1537 int loc_SceneBrightness; // or: Scenebrightness * ContrastBoost
1538 int loc_OffsetMapping_Scale;
1540 int loc_AmbientColor;
1541 int loc_DiffuseColor;
1542 int loc_SpecularColor;
1544 int loc_ContrastBoostCoeff; ///< 1 - 1/ContrastBoost
1545 int loc_GammaCoeff; ///< 1 / gamma
1546 int loc_DistortScaleRefractReflect;
1547 int loc_ScreenScaleRefractReflect;
1548 int loc_ScreenCenterRefractReflect;
1549 int loc_RefractColor;
1550 int loc_ReflectColor;
1551 int loc_ReflectFactor;
1552 int loc_ReflectOffset;
1560 int loc_ShadowMap_Bias;
1561 int loc_ShadowMap_TextureScale;
1562 int loc_ShadowMap_Parameters;
1564 r_glsl_permutation_t;
1566 /// information about each possible shader permutation
1567 r_glsl_permutation_t r_glsl_permutations[SHADERMODE_COUNT][SHADERPERMUTATION_LIMIT];
1568 /// currently selected permutation
1569 r_glsl_permutation_t *r_glsl_permutation;
1571 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
1574 if (!filename || !filename[0])
1576 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1579 if (printfromdisknotice)
1580 Con_DPrint("from disk... ");
1581 return shaderstring;
1583 else if (!strcmp(filename, "glsl/default.glsl"))
1585 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(builtinshaderstring) + 1);
1586 memcpy(shaderstring, builtinshaderstring, strlen(builtinshaderstring) + 1);
1588 return shaderstring;
1591 static void R_GLSL_CompilePermutation(unsigned int mode, unsigned int permutation)
1594 shadermodeinfo_t *modeinfo = shadermodeinfo + mode;
1595 r_glsl_permutation_t *p = &r_glsl_permutations[mode][permutation];
1596 int vertstrings_count = 0;
1597 int geomstrings_count = 0;
1598 int fragstrings_count = 0;
1599 char *vertexstring, *geometrystring, *fragmentstring;
1600 const char *vertstrings_list[32+3];
1601 const char *geomstrings_list[32+3];
1602 const char *fragstrings_list[32+3];
1603 char permutationname[256];
1610 permutationname[0] = 0;
1611 vertexstring = R_GLSL_GetText(modeinfo->vertexfilename, true);
1612 geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1613 fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1615 strlcat(permutationname, shadermodeinfo[mode].vertexfilename, sizeof(permutationname));
1617 // the first pretext is which type of shader to compile as
1618 // (later these will all be bound together as a program object)
1619 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1620 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1621 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1623 // the second pretext is the mode (for example a light source)
1624 vertstrings_list[vertstrings_count++] = shadermodeinfo[mode].pretext;
1625 geomstrings_list[geomstrings_count++] = shadermodeinfo[mode].pretext;
1626 fragstrings_list[fragstrings_count++] = shadermodeinfo[mode].pretext;
1627 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1629 // now add all the permutation pretexts
1630 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1632 if (permutation & (1<<i))
1634 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1635 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1636 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1637 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1641 // keep line numbers correct
1642 vertstrings_list[vertstrings_count++] = "\n";
1643 geomstrings_list[geomstrings_count++] = "\n";
1644 fragstrings_list[fragstrings_count++] = "\n";
1648 // now append the shader text itself
1649 vertstrings_list[vertstrings_count++] = vertexstring;
1650 geomstrings_list[geomstrings_count++] = geometrystring;
1651 fragstrings_list[fragstrings_count++] = fragmentstring;
1653 // if any sources were NULL, clear the respective list
1655 vertstrings_count = 0;
1656 if (!geometrystring)
1657 geomstrings_count = 0;
1658 if (!fragmentstring)
1659 fragstrings_count = 0;
1661 // compile the shader program
1662 if (vertstrings_count + geomstrings_count + fragstrings_count)
1663 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1667 qglUseProgramObjectARB(p->program);CHECKGLERROR
1668 // look up all the uniform variable names we care about, so we don't
1669 // have to look them up every time we set them
1670 p->loc_Texture_First = qglGetUniformLocationARB(p->program, "Texture_First");
1671 p->loc_Texture_Second = qglGetUniformLocationARB(p->program, "Texture_Second");
1672 p->loc_Texture_GammaRamps = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
1673 p->loc_Texture_Normal = qglGetUniformLocationARB(p->program, "Texture_Normal");
1674 p->loc_Texture_Color = qglGetUniformLocationARB(p->program, "Texture_Color");
1675 p->loc_Texture_Gloss = qglGetUniformLocationARB(p->program, "Texture_Gloss");
1676 p->loc_Texture_Glow = qglGetUniformLocationARB(p->program, "Texture_Glow");
1677 p->loc_Texture_SecondaryNormal = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
1678 p->loc_Texture_SecondaryColor = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
1679 p->loc_Texture_SecondaryGloss = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
1680 p->loc_Texture_SecondaryGlow = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
1681 p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
1682 p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
1683 p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
1684 p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
1685 p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
1686 p->loc_Texture_Refraction = qglGetUniformLocationARB(p->program, "Texture_Refraction");
1687 p->loc_Texture_Reflection = qglGetUniformLocationARB(p->program, "Texture_Reflection");
1688 p->loc_Texture_Attenuation = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
1689 p->loc_Texture_Cube = qglGetUniformLocationARB(p->program, "Texture_Cube");
1690 p->loc_Texture_ShadowMapRect = qglGetUniformLocationARB(p->program, "Texture_ShadowMapRect");
1691 p->loc_Texture_ShadowMapCube = qglGetUniformLocationARB(p->program, "Texture_ShadowMapCube");
1692 p->loc_Texture_ShadowMap2D = qglGetUniformLocationARB(p->program, "Texture_ShadowMap2D");
1693 p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
1694 p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
1695 p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
1696 p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants");
1697 p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt");
1698 p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip");
1699 p->loc_AmbientScale = qglGetUniformLocationARB(p->program, "AmbientScale");
1700 p->loc_DiffuseScale = qglGetUniformLocationARB(p->program, "DiffuseScale");
1701 p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
1702 p->loc_SpecularScale = qglGetUniformLocationARB(p->program, "SpecularScale");
1703 p->loc_GlowScale = qglGetUniformLocationARB(p->program, "GlowScale");
1704 p->loc_SceneBrightness = qglGetUniformLocationARB(p->program, "SceneBrightness");
1705 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
1706 p->loc_TintColor = qglGetUniformLocationARB(p->program, "TintColor");
1707 p->loc_AmbientColor = qglGetUniformLocationARB(p->program, "AmbientColor");
1708 p->loc_DiffuseColor = qglGetUniformLocationARB(p->program, "DiffuseColor");
1709 p->loc_SpecularColor = qglGetUniformLocationARB(p->program, "SpecularColor");
1710 p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
1711 p->loc_ContrastBoostCoeff = qglGetUniformLocationARB(p->program, "ContrastBoostCoeff");
1712 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
1713 p->loc_ScreenScaleRefractReflect = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
1714 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
1715 p->loc_RefractColor = qglGetUniformLocationARB(p->program, "RefractColor");
1716 p->loc_ReflectColor = qglGetUniformLocationARB(p->program, "ReflectColor");
1717 p->loc_ReflectFactor = qglGetUniformLocationARB(p->program, "ReflectFactor");
1718 p->loc_ReflectOffset = qglGetUniformLocationARB(p->program, "ReflectOffset");
1719 p->loc_GammaCoeff = qglGetUniformLocationARB(p->program, "GammaCoeff");
1720 p->loc_UserVec1 = qglGetUniformLocationARB(p->program, "UserVec1");
1721 p->loc_UserVec2 = qglGetUniformLocationARB(p->program, "UserVec2");
1722 p->loc_UserVec3 = qglGetUniformLocationARB(p->program, "UserVec3");
1723 p->loc_UserVec4 = qglGetUniformLocationARB(p->program, "UserVec4");
1724 p->loc_ClientTime = qglGetUniformLocationARB(p->program, "ClientTime");
1725 p->loc_PixelSize = qglGetUniformLocationARB(p->program, "PixelSize");
1726 p->loc_Saturation = qglGetUniformLocationARB(p->program, "Saturation");
1727 p->loc_ShadowMap_Bias = qglGetUniformLocationARB(p->program, "ShadowMap_Bias");
1728 p->loc_ShadowMap_TextureScale = qglGetUniformLocationARB(p->program, "ShadowMap_TextureScale");
1729 p->loc_ShadowMap_Parameters = qglGetUniformLocationARB(p->program, "ShadowMap_Parameters");
1730 // initialize the samplers to refer to the texture units we use
1731 if (p->loc_Texture_First >= 0) qglUniform1iARB(p->loc_Texture_First , GL20TU_FIRST);
1732 if (p->loc_Texture_Second >= 0) qglUniform1iARB(p->loc_Texture_Second , GL20TU_SECOND);
1733 if (p->loc_Texture_GammaRamps >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps , GL20TU_GAMMARAMPS);
1734 if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal , GL20TU_NORMAL);
1735 if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color , GL20TU_COLOR);
1736 if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss , GL20TU_GLOSS);
1737 if (p->loc_Texture_Glow >= 0) qglUniform1iARB(p->loc_Texture_Glow , GL20TU_GLOW);
1738 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
1739 if (p->loc_Texture_SecondaryColor >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
1740 if (p->loc_Texture_SecondaryGloss >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
1741 if (p->loc_Texture_SecondaryGlow >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow , GL20TU_SECONDARY_GLOW);
1742 if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants , GL20TU_PANTS);
1743 if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt , GL20TU_SHIRT);
1744 if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask , GL20TU_FOGMASK);
1745 if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap , GL20TU_LIGHTMAP);
1746 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap , GL20TU_DELUXEMAP);
1747 if (p->loc_Texture_Attenuation >= 0) qglUniform1iARB(p->loc_Texture_Attenuation , GL20TU_ATTENUATION);
1748 if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube , GL20TU_CUBE);
1749 if (p->loc_Texture_Refraction >= 0) qglUniform1iARB(p->loc_Texture_Refraction , GL20TU_REFRACTION);
1750 if (p->loc_Texture_Reflection >= 0) qglUniform1iARB(p->loc_Texture_Reflection , GL20TU_REFLECTION);
1751 if (p->loc_Texture_ShadowMapRect >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapRect , GL20TU_SHADOWMAPRECT);
1752 if (p->loc_Texture_ShadowMapCube >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapCube , GL20TU_SHADOWMAPCUBE);
1753 if (p->loc_Texture_ShadowMap2D >= 0) qglUniform1iARB(p->loc_Texture_ShadowMap2D , GL20TU_SHADOWMAP2D);
1755 if (developer.integer)
1756 Con_Printf("GLSL shader %s compiled.\n", permutationname);
1759 Con_Printf("GLSL shader %s failed! some features may not work properly.\n", permutationname);
1763 Mem_Free(vertexstring);
1765 Mem_Free(geometrystring);
1767 Mem_Free(fragmentstring);
1770 void R_GLSL_Restart_f(void)
1773 unsigned int permutation;
1774 for (mode = 0;mode < SHADERMODE_COUNT;mode++)
1775 for (permutation = 0;permutation < SHADERPERMUTATION_LIMIT;permutation++)
1776 if (r_glsl_permutations[mode][permutation].program)
1777 GL_Backend_FreeProgram(r_glsl_permutations[mode][permutation].program);
1778 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
1781 void R_GLSL_DumpShader_f(void)
1785 qfile_t *file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1788 Con_Printf("failed to write to glsl/default.glsl\n");
1792 FS_Print(file, "/* The engine may define the following macros:\n");
1793 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1794 for (i = 0;i < SHADERMODE_COUNT;i++)
1795 FS_Print(file, shadermodeinfo[i].pretext);
1796 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1797 FS_Print(file, shaderpermutationinfo[i].pretext);
1798 FS_Print(file, "*/\n");
1799 FS_Print(file, builtinshaderstring);
1802 Con_Printf("glsl/default.glsl written\n");
1805 void R_SetupShader_SetPermutation(unsigned int mode, unsigned int permutation)
1807 r_glsl_permutation_t *perm = &r_glsl_permutations[mode][permutation];
1808 if (r_glsl_permutation != perm)
1810 r_glsl_permutation = perm;
1811 if (!r_glsl_permutation->program)
1813 if (!r_glsl_permutation->compiled)
1814 R_GLSL_CompilePermutation(mode, permutation);
1815 if (!r_glsl_permutation->program)
1817 // remove features until we find a valid permutation
1819 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1821 // reduce i more quickly whenever it would not remove any bits
1822 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1823 if (!(permutation & j))
1826 r_glsl_permutation = &r_glsl_permutations[mode][permutation];
1827 if (!r_glsl_permutation->compiled)
1828 R_GLSL_CompilePermutation(mode, permutation);
1829 if (r_glsl_permutation->program)
1832 if (i >= SHADERPERMUTATION_COUNT)
1834 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");
1835 Cvar_SetValueQuick(&r_glsl, 0);
1836 R_GLSL_Restart_f(); // unload shaders
1837 return; // no bit left to clear
1842 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
1846 void R_SetupGenericShader(qboolean usetexture)
1848 if (gl_support_fragment_shader)
1850 if (r_glsl.integer && r_glsl_usegeneric.integer)
1851 R_SetupShader_SetPermutation(SHADERMODE_GENERIC, usetexture ? SHADERPERMUTATION_DIFFUSE : 0);
1852 else if (r_glsl_permutation)
1854 r_glsl_permutation = NULL;
1855 qglUseProgramObjectARB(0);CHECKGLERROR
1860 void R_SetupGenericTwoTextureShader(int texturemode)
1862 if (gl_support_fragment_shader)
1864 if (r_glsl.integer && r_glsl_usegeneric.integer)
1865 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))));
1866 else if (r_glsl_permutation)
1868 r_glsl_permutation = NULL;
1869 qglUseProgramObjectARB(0);CHECKGLERROR
1872 if (!r_glsl_permutation)
1874 if (texturemode == GL_DECAL && gl_combine.integer)
1875 texturemode = GL_INTERPOLATE_ARB;
1876 R_Mesh_TexCombine(1, texturemode, texturemode, 1, 1);
1880 void R_SetupDepthOrShadowShader(void)
1882 if (gl_support_fragment_shader)
1884 if (r_glsl.integer && r_glsl_usegeneric.integer)
1885 R_SetupShader_SetPermutation(SHADERMODE_DEPTH_OR_SHADOW, 0);
1886 else if (r_glsl_permutation)
1888 r_glsl_permutation = NULL;
1889 qglUseProgramObjectARB(0);CHECKGLERROR
1894 void R_SetupShowDepthShader(void)
1896 if (gl_support_fragment_shader)
1898 if (r_glsl.integer && r_glsl_usegeneric.integer)
1899 R_SetupShader_SetPermutation(SHADERMODE_SHOWDEPTH, 0);
1900 else if (r_glsl_permutation)
1902 r_glsl_permutation = NULL;
1903 qglUseProgramObjectARB(0);CHECKGLERROR
1908 extern rtexture_t *r_shadow_attenuationgradienttexture;
1909 extern rtexture_t *r_shadow_attenuation2dtexture;
1910 extern rtexture_t *r_shadow_attenuation3dtexture;
1911 extern qboolean r_shadow_usingshadowmaprect;
1912 extern qboolean r_shadow_usingshadowmapcube;
1913 extern qboolean r_shadow_usingshadowmap2d;
1914 extern float r_shadow_shadowmap_bias;
1915 extern float r_shadow_shadowmap_texturescale[2];
1916 extern float r_shadow_shadowmap_parameters[4];
1917 void R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass)
1919 // select a permutation of the lighting shader appropriate to this
1920 // combination of texture, entity, light source, and fogging, only use the
1921 // minimum features necessary to avoid wasting rendering time in the
1922 // fragment shader on features that are not being used
1923 unsigned int permutation = 0;
1924 unsigned int mode = 0;
1925 // TODO: implement geometry-shader based shadow volumes someday
1926 if (r_glsl_offsetmapping.integer)
1928 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
1929 if (r_glsl_offsetmapping_reliefmapping.integer)
1930 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
1932 if (rsurfacepass == RSURFPASS_BACKGROUND)
1934 // distorted background
1935 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
1936 mode = SHADERMODE_WATER;
1938 mode = SHADERMODE_REFRACTION;
1940 else if (rsurfacepass == RSURFPASS_RTLIGHT)
1943 mode = SHADERMODE_LIGHTSOURCE;
1944 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1945 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1946 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
1947 permutation |= SHADERPERMUTATION_CUBEFILTER;
1948 if (diffusescale > 0)
1949 permutation |= SHADERPERMUTATION_DIFFUSE;
1950 if (specularscale > 0)
1951 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
1952 if (r_refdef.fogenabled)
1953 permutation |= SHADERPERMUTATION_FOG;
1954 if (rsurface.texture->colormapping)
1955 permutation |= SHADERPERMUTATION_COLORMAPPING;
1956 if (r_shadow_usingshadowmaprect)
1957 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
1958 if (r_shadow_usingshadowmapcube)
1959 permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
1960 if (r_shadow_usingshadowmap2d)
1961 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
1963 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
1965 // unshaded geometry (fullbright or ambient model lighting)
1966 mode = SHADERMODE_FLATCOLOR;
1967 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1968 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1969 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
1970 permutation |= SHADERPERMUTATION_GLOW;
1971 if (r_refdef.fogenabled)
1972 permutation |= SHADERPERMUTATION_FOG;
1973 if (rsurface.texture->colormapping)
1974 permutation |= SHADERPERMUTATION_COLORMAPPING;
1975 if (r_glsl_offsetmapping.integer)
1977 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
1978 if (r_glsl_offsetmapping_reliefmapping.integer)
1979 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
1981 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1982 permutation |= SHADERPERMUTATION_REFLECTION;
1984 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
1986 // directional model lighting
1987 mode = SHADERMODE_LIGHTDIRECTION;
1988 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1989 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1990 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
1991 permutation |= SHADERPERMUTATION_GLOW;
1992 permutation |= SHADERPERMUTATION_DIFFUSE;
1993 if (specularscale > 0)
1994 permutation |= SHADERPERMUTATION_SPECULAR;
1995 if (r_refdef.fogenabled)
1996 permutation |= SHADERPERMUTATION_FOG;
1997 if (rsurface.texture->colormapping)
1998 permutation |= SHADERPERMUTATION_COLORMAPPING;
1999 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2000 permutation |= SHADERPERMUTATION_REFLECTION;
2002 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2004 // ambient model lighting
2005 mode = SHADERMODE_LIGHTDIRECTION;
2006 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2007 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2008 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2009 permutation |= SHADERPERMUTATION_GLOW;
2010 if (r_refdef.fogenabled)
2011 permutation |= SHADERPERMUTATION_FOG;
2012 if (rsurface.texture->colormapping)
2013 permutation |= SHADERPERMUTATION_COLORMAPPING;
2014 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2015 permutation |= SHADERPERMUTATION_REFLECTION;
2020 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2022 // deluxemapping (light direction texture)
2023 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2024 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2026 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2027 permutation |= SHADERPERMUTATION_DIFFUSE;
2028 if (specularscale > 0)
2029 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2031 else if (r_glsl_deluxemapping.integer >= 2)
2033 // fake deluxemapping (uniform light direction in tangentspace)
2034 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2035 permutation |= SHADERPERMUTATION_DIFFUSE;
2036 if (specularscale > 0)
2037 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2039 else if (rsurface.uselightmaptexture)
2041 // ordinary lightmapping (q1bsp, q3bsp)
2042 mode = SHADERMODE_LIGHTMAP;
2046 // ordinary vertex coloring (q3bsp)
2047 mode = SHADERMODE_VERTEXCOLOR;
2049 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2050 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2051 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2052 permutation |= SHADERPERMUTATION_GLOW;
2053 if (r_refdef.fogenabled)
2054 permutation |= SHADERPERMUTATION_FOG;
2055 if (rsurface.texture->colormapping)
2056 permutation |= SHADERPERMUTATION_COLORMAPPING;
2057 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2058 permutation |= SHADERPERMUTATION_REFLECTION;
2060 if(permutation & SHADERPERMUTATION_SPECULAR)
2061 if(r_shadow_glossexact.integer)
2062 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
2063 R_SetupShader_SetPermutation(mode, permutation);
2064 if (mode == SHADERMODE_LIGHTSOURCE)
2066 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2067 if (permutation & SHADERPERMUTATION_DIFFUSE)
2069 if (r_glsl_permutation->loc_TintColor >= 0) qglUniform4fARB(r_glsl_permutation->loc_TintColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2], rsurface.texture->lightmapcolor[3]);
2070 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, ambientscale);
2071 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, diffusescale);
2072 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, specularscale);
2076 // ambient only is simpler
2077 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]);
2078 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, 1);
2079 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, 0);
2080 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, 0);
2082 // additive passes are only darkened by fog, not tinted
2083 if (r_glsl_permutation->loc_FogColor >= 0)
2084 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2085 if (r_glsl_permutation->loc_ShadowMap_Bias >= 0) qglUniform1fARB(r_glsl_permutation->loc_ShadowMap_Bias, r_shadow_shadowmap_bias);
2086 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]);
2087 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]);
2091 if (mode == SHADERMODE_LIGHTDIRECTION)
2093 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);
2094 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);
2095 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);
2096 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]);
2100 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_refdef.scene.ambient * 1.0f / 128.0f);
2101 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_refdef.lightmapintensity);
2102 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, r_refdef.lightmapintensity * specularscale);
2104 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]);
2105 if (r_glsl_permutation->loc_GlowScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_GlowScale, r_hdr_glowintensity.value);
2106 // additive passes are only darkened by fog, not tinted
2107 if (r_glsl_permutation->loc_FogColor >= 0)
2109 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
2110 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2112 qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2114 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);
2115 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]);
2116 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]);
2117 if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f);
2118 if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f);
2119 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2120 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2122 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_refdef.view.colorscale);
2123 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.modelorg[0], rsurface.modelorg[1], rsurface.modelorg[2]);
2124 if (r_glsl_permutation->loc_Color_Pants >= 0)
2126 if (rsurface.texture->currentskinframe->pants)
2127 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2129 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2131 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2133 if (rsurface.texture->currentskinframe->shirt)
2134 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2136 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2138 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, r_refdef.fograngerecip * Matrix4x4_ScaleFromMatrix(&rsurface.matrix));
2139 if(permutation & SHADERPERMUTATION_EXACTSPECULARMATH)
2141 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * 0.25);
2145 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower);
2147 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
2151 #define SKINFRAME_HASH 1024
2155 int loadsequence; // incremented each level change
2156 memexpandablearray_t array;
2157 skinframe_t *hash[SKINFRAME_HASH];
2160 r_skinframe_t r_skinframe;
2162 void R_SkinFrame_PrepareForPurge(void)
2164 r_skinframe.loadsequence++;
2165 // wrap it without hitting zero
2166 if (r_skinframe.loadsequence >= 200)
2167 r_skinframe.loadsequence = 1;
2170 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
2174 // mark the skinframe as used for the purging code
2175 skinframe->loadsequence = r_skinframe.loadsequence;
2178 void R_SkinFrame_Purge(void)
2182 for (i = 0;i < SKINFRAME_HASH;i++)
2184 for (s = r_skinframe.hash[i];s;s = s->next)
2186 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
2188 if (s->merged == s->base)
2190 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
2191 R_PurgeTexture(s->stain );s->stain = NULL;
2192 R_PurgeTexture(s->merged);s->merged = NULL;
2193 R_PurgeTexture(s->base );s->base = NULL;
2194 R_PurgeTexture(s->pants );s->pants = NULL;
2195 R_PurgeTexture(s->shirt );s->shirt = NULL;
2196 R_PurgeTexture(s->nmap );s->nmap = NULL;
2197 R_PurgeTexture(s->gloss );s->gloss = NULL;
2198 R_PurgeTexture(s->glow );s->glow = NULL;
2199 R_PurgeTexture(s->fog );s->fog = NULL;
2200 s->loadsequence = 0;
2206 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
2208 char basename[MAX_QPATH];
2210 Image_StripImageExtension(name, basename, sizeof(basename));
2212 if( last == NULL ) {
2214 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
2215 item = r_skinframe.hash[hashindex];
2220 // linearly search through the hash bucket
2221 for( ; item ; item = item->next ) {
2222 if( !strcmp( item->basename, basename ) ) {
2229 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
2233 char basename[MAX_QPATH];
2235 Image_StripImageExtension(name, basename, sizeof(basename));
2237 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
2238 for (item = r_skinframe.hash[hashindex];item;item = item->next)
2239 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
2243 rtexture_t *dyntexture;
2244 // check whether its a dynamic texture
2245 dyntexture = CL_GetDynTexture( basename );
2246 if (!add && !dyntexture)
2248 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
2249 memset(item, 0, sizeof(*item));
2250 strlcpy(item->basename, basename, sizeof(item->basename));
2251 item->base = dyntexture; // either NULL or dyntexture handle
2252 item->textureflags = textureflags;
2253 item->comparewidth = comparewidth;
2254 item->compareheight = compareheight;
2255 item->comparecrc = comparecrc;
2256 item->next = r_skinframe.hash[hashindex];
2257 r_skinframe.hash[hashindex] = item;
2259 else if( item->base == NULL )
2261 rtexture_t *dyntexture;
2262 // check whether its a dynamic texture
2263 // 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]
2264 dyntexture = CL_GetDynTexture( basename );
2265 item->base = dyntexture; // either NULL or dyntexture handle
2268 R_SkinFrame_MarkUsed(item);
2272 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
2274 unsigned long long avgcolor[5], wsum; \
2282 for(pix = 0; pix < cnt; ++pix) \
2285 for(comp = 0; comp < 3; ++comp) \
2287 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
2290 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
2292 for(comp = 0; comp < 3; ++comp) \
2293 avgcolor[comp] += getpixel * w; \
2296 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
2297 avgcolor[4] += getpixel; \
2299 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
2301 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
2302 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
2303 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
2304 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
2307 skinframe_t *R_SkinFrame_LoadExternal_CheckAlpha(const char *name, int textureflags, qboolean complain, qboolean *has_alpha)
2309 // FIXME: it should be possible to disable loading various layers using
2310 // cvars, to prevent wasted loading time and memory usage if the user does
2312 qboolean loadnormalmap = true;
2313 qboolean loadgloss = true;
2314 qboolean loadpantsandshirt = true;
2315 qboolean loadglow = true;
2317 unsigned char *pixels;
2318 unsigned char *bumppixels;
2319 unsigned char *basepixels = NULL;
2320 int basepixels_width;
2321 int basepixels_height;
2322 skinframe_t *skinframe;
2326 if (cls.state == ca_dedicated)
2329 // return an existing skinframe if already loaded
2330 // if loading of the first image fails, don't make a new skinframe as it
2331 // would cause all future lookups of this to be missing
2332 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
2333 if (skinframe && skinframe->base)
2336 basepixels = loadimagepixelsbgra(name, complain, true);
2337 if (basepixels == NULL)
2340 if (developer_loading.integer)
2341 Con_Printf("loading skin \"%s\"\n", name);
2343 // we've got some pixels to store, so really allocate this new texture now
2345 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
2346 skinframe->stain = NULL;
2347 skinframe->merged = NULL;
2348 skinframe->base = r_texture_notexture;
2349 skinframe->pants = NULL;
2350 skinframe->shirt = NULL;
2351 skinframe->nmap = r_texture_blanknormalmap;
2352 skinframe->gloss = NULL;
2353 skinframe->glow = NULL;
2354 skinframe->fog = NULL;
2356 basepixels_width = image_width;
2357 basepixels_height = image_height;
2358 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);
2360 if (textureflags & TEXF_ALPHA)
2362 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
2363 if (basepixels[j] < 255)
2365 if (j < basepixels_width * basepixels_height * 4)
2367 // has transparent pixels
2369 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
2370 for (j = 0;j < image_width * image_height * 4;j += 4)
2375 pixels[j+3] = basepixels[j+3];
2377 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);
2382 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
2383 //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]);
2385 // _norm is the name used by tenebrae and has been adopted as standard
2388 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false)) != NULL)
2390 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);
2394 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false)) != NULL)
2396 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
2397 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
2398 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);
2400 Mem_Free(bumppixels);
2402 else if (r_shadow_bumpscale_basetexture.value > 0)
2404 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
2405 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
2406 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);
2410 // _luma is supported for tenebrae compatibility
2411 // (I think it's a very stupid name, but oh well)
2412 // _glow is the preferred name
2413 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;}
2414 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;}
2415 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;}
2416 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;}
2419 Mem_Free(basepixels);
2424 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
2427 return R_SkinFrame_LoadExternal_CheckAlpha(name, textureflags, complain, &has_alpha);
2430 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)
2435 for (i = 0;i < width*height;i++)
2436 if (((unsigned char *)&palette[in[i]])[3] > 0)
2438 if (i == width*height)
2441 return R_LoadTexture2D (r_main_texturepool, name, width, height, in, TEXTYPE_PALETTE, textureflags, palette);
2444 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
2445 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
2448 unsigned char *temp1, *temp2;
2449 skinframe_t *skinframe;
2451 if (cls.state == ca_dedicated)
2454 // if already loaded just return it, otherwise make a new skinframe
2455 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
2456 if (skinframe && skinframe->base)
2459 skinframe->stain = NULL;
2460 skinframe->merged = NULL;
2461 skinframe->base = r_texture_notexture;
2462 skinframe->pants = NULL;
2463 skinframe->shirt = NULL;
2464 skinframe->nmap = r_texture_blanknormalmap;
2465 skinframe->gloss = NULL;
2466 skinframe->glow = NULL;
2467 skinframe->fog = NULL;
2469 // if no data was provided, then clearly the caller wanted to get a blank skinframe
2473 if (developer_loading.integer)
2474 Con_Printf("loading 32bit skin \"%s\"\n", name);
2476 if (r_shadow_bumpscale_basetexture.value > 0)
2478 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
2479 temp2 = temp1 + width * height * 4;
2480 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
2481 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
2484 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, skinframe->textureflags, NULL);
2485 if (textureflags & TEXF_ALPHA)
2487 for (i = 3;i < width * height * 4;i += 4)
2488 if (skindata[i] < 255)
2490 if (i < width * height * 4)
2492 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
2493 memcpy(fogpixels, skindata, width * height * 4);
2494 for (i = 0;i < width * height * 4;i += 4)
2495 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
2496 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, skinframe->textureflags, NULL);
2497 Mem_Free(fogpixels);
2501 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
2502 //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]);
2507 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
2510 unsigned char *temp1, *temp2;
2511 unsigned int *palette;
2512 skinframe_t *skinframe;
2514 if (cls.state == ca_dedicated)
2517 // if already loaded just return it, otherwise make a new skinframe
2518 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
2519 if (skinframe && skinframe->base)
2522 palette = (loadglowtexture ? palette_bgra_nofullbrights : ((skinframe->textureflags & TEXF_ALPHA) ? palette_bgra_transparent : palette_bgra_complete));
2524 skinframe->stain = NULL;
2525 skinframe->merged = NULL;
2526 skinframe->base = r_texture_notexture;
2527 skinframe->pants = NULL;
2528 skinframe->shirt = NULL;
2529 skinframe->nmap = r_texture_blanknormalmap;
2530 skinframe->gloss = NULL;
2531 skinframe->glow = NULL;
2532 skinframe->fog = NULL;
2534 // if no data was provided, then clearly the caller wanted to get a blank skinframe
2538 if (developer_loading.integer)
2539 Con_Printf("loading quake skin \"%s\"\n", name);
2541 if (r_shadow_bumpscale_basetexture.value > 0)
2543 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
2544 temp2 = temp1 + width * height * 4;
2545 // use either a custom palette or the quake palette
2546 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
2547 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
2548 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
2551 // use either a custom palette, or the quake palette
2552 skinframe->base = skinframe->merged = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_merged", skinframe->basename), palette, skinframe->textureflags, true); // all
2553 if (loadglowtexture)
2554 skinframe->glow = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_glow", skinframe->basename), palette_bgra_onlyfullbrights, skinframe->textureflags, false); // glow
2555 if (loadpantsandshirt)
2557 skinframe->pants = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_pants", skinframe->basename), palette_bgra_pantsaswhite, skinframe->textureflags, false); // pants
2558 skinframe->shirt = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_shirt", skinframe->basename), palette_bgra_shirtaswhite, skinframe->textureflags, false); // shirt
2560 if (skinframe->pants || skinframe->shirt)
2561 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
2562 if (textureflags & TEXF_ALPHA)
2564 for (i = 0;i < width * height;i++)
2565 if (((unsigned char *)palette_bgra_alpha)[skindata[i]*4+3] < 255)
2567 if (i < width * height)
2568 skinframe->fog = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_fog", skinframe->basename), palette_bgra_alpha, skinframe->textureflags, true); // fog mask
2571 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
2572 //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]);
2577 skinframe_t *R_SkinFrame_LoadMissing(void)
2579 skinframe_t *skinframe;
2581 if (cls.state == ca_dedicated)
2584 skinframe = R_SkinFrame_Find("missing", TEXF_PRECACHE | TEXF_FORCENEAREST, 0, 0, 0, true);
2585 skinframe->stain = NULL;
2586 skinframe->merged = NULL;
2587 skinframe->base = r_texture_notexture;
2588 skinframe->pants = NULL;
2589 skinframe->shirt = NULL;
2590 skinframe->nmap = r_texture_blanknormalmap;
2591 skinframe->gloss = NULL;
2592 skinframe->glow = NULL;
2593 skinframe->fog = NULL;
2595 skinframe->avgcolor[0] = rand() / RAND_MAX;
2596 skinframe->avgcolor[1] = rand() / RAND_MAX;
2597 skinframe->avgcolor[2] = rand() / RAND_MAX;
2598 skinframe->avgcolor[3] = 1;
2603 void gl_main_start(void)
2607 memset(r_queries, 0, sizeof(r_queries));
2609 memset(r_qwskincache, 0, sizeof(r_qwskincache));
2610 memset(r_qwskincache_skinframe, 0, sizeof(r_qwskincache_skinframe));
2612 // set up r_skinframe loading system for textures
2613 memset(&r_skinframe, 0, sizeof(r_skinframe));
2614 r_skinframe.loadsequence = 1;
2615 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
2617 r_main_texturepool = R_AllocTexturePool();
2618 R_BuildBlankTextures();
2620 if (gl_texturecubemap)
2623 R_BuildNormalizationCube();
2625 r_texture_fogattenuation = NULL;
2626 r_texture_gammaramps = NULL;
2627 //r_texture_fogintensity = NULL;
2628 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
2629 memset(&r_waterstate, 0, sizeof(r_waterstate));
2630 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
2631 memset(&r_svbsp, 0, sizeof (r_svbsp));
2633 r_refdef.fogmasktable_density = 0;
2636 extern rtexture_t *loadingscreentexture;
2637 void gl_main_shutdown(void)
2640 qglDeleteQueriesARB(r_maxqueries, r_queries);
2644 memset(r_queries, 0, sizeof(r_queries));
2646 memset(r_qwskincache, 0, sizeof(r_qwskincache));
2647 memset(r_qwskincache_skinframe, 0, sizeof(r_qwskincache_skinframe));
2649 // clear out the r_skinframe state
2650 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
2651 memset(&r_skinframe, 0, sizeof(r_skinframe));
2654 Mem_Free(r_svbsp.nodes);
2655 memset(&r_svbsp, 0, sizeof (r_svbsp));
2656 R_FreeTexturePool(&r_main_texturepool);
2657 loadingscreentexture = NULL;
2658 r_texture_blanknormalmap = NULL;
2659 r_texture_white = NULL;
2660 r_texture_grey128 = NULL;
2661 r_texture_black = NULL;
2662 r_texture_whitecube = NULL;
2663 r_texture_normalizationcube = NULL;
2664 r_texture_fogattenuation = NULL;
2665 r_texture_gammaramps = NULL;
2666 //r_texture_fogintensity = NULL;
2667 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
2668 memset(&r_waterstate, 0, sizeof(r_waterstate));
2672 extern void CL_ParseEntityLump(char *entitystring);
2673 void gl_main_newmap(void)
2675 // FIXME: move this code to client
2677 char *entities, entname[MAX_QPATH];
2680 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
2681 l = (int)strlen(entname) - 4;
2682 if (l >= 0 && !strcmp(entname + l, ".bsp"))
2684 memcpy(entname + l, ".ent", 5);
2685 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
2687 CL_ParseEntityLump(entities);
2692 if (cl.worldmodel->brush.entities)
2693 CL_ParseEntityLump(cl.worldmodel->brush.entities);
2697 void GL_Main_Init(void)
2699 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
2701 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
2702 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
2703 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
2704 if (gamemode == GAME_NEHAHRA)
2706 Cvar_RegisterVariable (&gl_fogenable);
2707 Cvar_RegisterVariable (&gl_fogdensity);
2708 Cvar_RegisterVariable (&gl_fogred);
2709 Cvar_RegisterVariable (&gl_foggreen);
2710 Cvar_RegisterVariable (&gl_fogblue);
2711 Cvar_RegisterVariable (&gl_fogstart);
2712 Cvar_RegisterVariable (&gl_fogend);
2713 Cvar_RegisterVariable (&gl_skyclip);
2715 Cvar_RegisterVariable(&r_motionblur);
2716 Cvar_RegisterVariable(&r_motionblur_maxblur);
2717 Cvar_RegisterVariable(&r_motionblur_bmin);
2718 Cvar_RegisterVariable(&r_motionblur_vmin);
2719 Cvar_RegisterVariable(&r_motionblur_vmax);
2720 Cvar_RegisterVariable(&r_motionblur_vcoeff);
2721 Cvar_RegisterVariable(&r_motionblur_randomize);
2722 Cvar_RegisterVariable(&r_damageblur);
2723 Cvar_RegisterVariable(&r_animcache);
2724 Cvar_RegisterVariable(&r_depthfirst);
2725 Cvar_RegisterVariable(&r_useinfinitefarclip);
2726 Cvar_RegisterVariable(&r_nearclip);
2727 Cvar_RegisterVariable(&r_showbboxes);
2728 Cvar_RegisterVariable(&r_showsurfaces);
2729 Cvar_RegisterVariable(&r_showtris);
2730 Cvar_RegisterVariable(&r_shownormals);
2731 Cvar_RegisterVariable(&r_showlighting);
2732 Cvar_RegisterVariable(&r_showshadowvolumes);
2733 Cvar_RegisterVariable(&r_showcollisionbrushes);
2734 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
2735 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
2736 Cvar_RegisterVariable(&r_showdisabledepthtest);
2737 Cvar_RegisterVariable(&r_drawportals);
2738 Cvar_RegisterVariable(&r_drawentities);
2739 Cvar_RegisterVariable(&r_cullentities_trace);
2740 Cvar_RegisterVariable(&r_cullentities_trace_samples);
2741 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
2742 Cvar_RegisterVariable(&r_cullentities_trace_delay);
2743 Cvar_RegisterVariable(&r_drawviewmodel);
2744 Cvar_RegisterVariable(&r_speeds);
2745 Cvar_RegisterVariable(&r_fullbrights);
2746 Cvar_RegisterVariable(&r_wateralpha);
2747 Cvar_RegisterVariable(&r_dynamic);
2748 Cvar_RegisterVariable(&r_fullbright);
2749 Cvar_RegisterVariable(&r_shadows);
2750 Cvar_RegisterVariable(&r_shadows_darken);
2751 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
2752 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
2753 Cvar_RegisterVariable(&r_shadows_throwdistance);
2754 Cvar_RegisterVariable(&r_shadows_throwdirection);
2755 Cvar_RegisterVariable(&r_q1bsp_skymasking);
2756 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
2757 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
2758 Cvar_RegisterVariable(&r_fog_exp2);
2759 Cvar_RegisterVariable(&r_drawfog);
2760 Cvar_RegisterVariable(&r_textureunits);
2761 Cvar_RegisterVariable(&r_glsl);
2762 Cvar_RegisterVariable(&r_glsl_deluxemapping);
2763 Cvar_RegisterVariable(&r_glsl_offsetmapping);
2764 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
2765 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
2766 Cvar_RegisterVariable(&r_glsl_postprocess);
2767 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
2768 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
2769 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
2770 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
2771 Cvar_RegisterVariable(&r_glsl_usegeneric);
2772 Cvar_RegisterVariable(&r_water);
2773 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
2774 Cvar_RegisterVariable(&r_water_clippingplanebias);
2775 Cvar_RegisterVariable(&r_water_refractdistort);
2776 Cvar_RegisterVariable(&r_water_reflectdistort);
2777 Cvar_RegisterVariable(&r_lerpsprites);
2778 Cvar_RegisterVariable(&r_lerpmodels);
2779 Cvar_RegisterVariable(&r_lerplightstyles);
2780 Cvar_RegisterVariable(&r_waterscroll);
2781 Cvar_RegisterVariable(&r_bloom);
2782 Cvar_RegisterVariable(&r_bloom_colorscale);
2783 Cvar_RegisterVariable(&r_bloom_brighten);
2784 Cvar_RegisterVariable(&r_bloom_blur);
2785 Cvar_RegisterVariable(&r_bloom_resolution);
2786 Cvar_RegisterVariable(&r_bloom_colorexponent);
2787 Cvar_RegisterVariable(&r_bloom_colorsubtract);
2788 Cvar_RegisterVariable(&r_hdr);
2789 Cvar_RegisterVariable(&r_hdr_scenebrightness);
2790 Cvar_RegisterVariable(&r_hdr_glowintensity);
2791 Cvar_RegisterVariable(&r_hdr_range);
2792 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
2793 Cvar_RegisterVariable(&developer_texturelogging);
2794 Cvar_RegisterVariable(&gl_lightmaps);
2795 Cvar_RegisterVariable(&r_test);
2796 Cvar_RegisterVariable(&r_batchmode);
2797 Cvar_RegisterVariable(&r_glsl_saturation);
2798 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
2799 Cvar_SetValue("r_fullbrights", 0);
2800 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
2802 Cvar_RegisterVariable(&r_track_sprites);
2803 Cvar_RegisterVariable(&r_track_sprites_flags);
2804 Cvar_RegisterVariable(&r_track_sprites_scalew);
2805 Cvar_RegisterVariable(&r_track_sprites_scaleh);
2808 extern void R_Textures_Init(void);
2809 extern void GL_Draw_Init(void);
2810 extern void GL_Main_Init(void);
2811 extern void R_Shadow_Init(void);
2812 extern void R_Sky_Init(void);
2813 extern void GL_Surf_Init(void);
2814 extern void R_Particles_Init(void);
2815 extern void R_Explosion_Init(void);
2816 extern void gl_backend_init(void);
2817 extern void Sbar_Init(void);
2818 extern void R_LightningBeams_Init(void);
2819 extern void Mod_RenderInit(void);
2821 void Render_Init(void)
2833 R_LightningBeams_Init();
2842 extern char *ENGINE_EXTENSIONS;
2845 gl_renderer = (const char *)qglGetString(GL_RENDERER);
2846 gl_vendor = (const char *)qglGetString(GL_VENDOR);
2847 gl_version = (const char *)qglGetString(GL_VERSION);
2848 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
2852 if (!gl_platformextensions)
2853 gl_platformextensions = "";
2855 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
2856 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
2857 Con_Printf("GL_VERSION: %s\n", gl_version);
2858 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
2859 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
2861 VID_CheckExtensions();
2863 // LordHavoc: report supported extensions
2864 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
2866 // clear to black (loading plaque will be seen over this)
2868 qglClearColor(0,0,0,1);CHECKGLERROR
2869 qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
2872 int R_CullBox(const vec3_t mins, const vec3_t maxs)
2876 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
2878 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
2881 p = r_refdef.view.frustum + i;
2886 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2890 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2894 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2898 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2902 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2906 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2910 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2914 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2922 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
2926 for (i = 0;i < numplanes;i++)
2933 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2937 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2941 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2945 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2949 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2953 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2957 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2961 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2969 //==================================================================================
2971 // LordHavoc: animcache written by Echon, refactored and reformatted by me
2974 * Animation cache helps save re-animating a player mesh if it's re-rendered again in a given frame
2975 * (reflections, lighting, etc). All animation cache becomes invalid on the next frame and is flushed
2976 * (well, over-wrote). The memory for each cache is kept around to save on allocation thrashing.
2979 typedef struct r_animcache_entity_s
2986 qboolean wantnormals;
2987 qboolean wanttangents;
2989 r_animcache_entity_t;
2991 typedef struct r_animcache_s
2993 r_animcache_entity_t entity[MAX_EDICTS*2];
2999 static r_animcache_t r_animcachestate;
3001 void R_AnimCache_Free(void)
3004 for (idx=0 ; idx<r_animcachestate.maxindex ; idx++)
3006 r_animcachestate.entity[idx].maxvertices = 0;
3007 Mem_Free(r_animcachestate.entity[idx].vertex3f);
3008 r_animcachestate.entity[idx].vertex3f = NULL;
3009 r_animcachestate.entity[idx].normal3f = NULL;
3010 r_animcachestate.entity[idx].svector3f = NULL;
3011 r_animcachestate.entity[idx].tvector3f = NULL;
3013 r_animcachestate.currentindex = 0;
3014 r_animcachestate.maxindex = 0;
3017 void R_AnimCache_ResizeEntityCache(const int cacheIdx, const int numvertices)
3021 r_animcache_entity_t *cache = &r_animcachestate.entity[cacheIdx];
3023 if (cache->maxvertices >= numvertices)
3026 // Release existing memory
3027 if (cache->vertex3f)
3028 Mem_Free(cache->vertex3f);
3030 // Pad by 1024 verts
3031 cache->maxvertices = (numvertices + 1023) & ~1023;
3032 arraySize = cache->maxvertices * 3;
3034 // Allocate, even if we don't need this memory in this instance it will get ignored and potentially used later
3035 base = (float *)Mem_Alloc(r_main_mempool, arraySize * sizeof(float) * 4);
3036 r_animcachestate.entity[cacheIdx].vertex3f = base;
3037 r_animcachestate.entity[cacheIdx].normal3f = base + arraySize;
3038 r_animcachestate.entity[cacheIdx].svector3f = base + arraySize*2;
3039 r_animcachestate.entity[cacheIdx].tvector3f = base + arraySize*3;
3041 // Con_Printf("allocated cache for %i (%f KB)\n", cacheIdx, (arraySize*sizeof(float)*4)/1024.0f);
3044 void R_AnimCache_NewFrame(void)
3048 if (r_animcache.integer && r_drawentities.integer)
3049 r_animcachestate.maxindex = sizeof(r_animcachestate.entity) / sizeof(r_animcachestate.entity[0]);
3050 else if (r_animcachestate.maxindex)
3053 r_animcachestate.currentindex = 0;
3055 for (i = 0;i < r_refdef.scene.numentities;i++)
3056 r_refdef.scene.entities[i]->animcacheindex = -1;
3059 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
3061 dp_model_t *model = ent->model;
3062 r_animcache_entity_t *c;
3063 // see if it's already cached this frame
3064 if (ent->animcacheindex >= 0)
3066 // add normals/tangents if needed
3067 c = r_animcachestate.entity + ent->animcacheindex;
3069 wantnormals = false;
3070 if (c->wanttangents)
3071 wanttangents = false;
3072 if (wantnormals || wanttangents)
3073 model->AnimateVertices(model, ent->frameblend, NULL, wantnormals ? c->normal3f : NULL, wanttangents ? c->svector3f : NULL, wanttangents ? c->tvector3f : NULL);
3077 // see if this ent is worth caching
3078 if (r_animcachestate.maxindex <= r_animcachestate.currentindex)
3080 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0))
3082 // assign it a cache entry and make sure the arrays are big enough
3083 R_AnimCache_ResizeEntityCache(r_animcachestate.currentindex, model->surfmesh.num_vertices);
3084 ent->animcacheindex = r_animcachestate.currentindex++;
3085 c = r_animcachestate.entity + ent->animcacheindex;
3086 c->wantnormals = wantnormals;
3087 c->wanttangents = wanttangents;
3088 model->AnimateVertices(model, ent->frameblend, c->vertex3f, wantnormals ? c->normal3f : NULL, wanttangents ? c->svector3f : NULL, wanttangents ? c->tvector3f : NULL);
3093 void R_AnimCache_CacheVisibleEntities(void)
3096 qboolean wantnormals;
3097 qboolean wanttangents;
3099 if (!r_animcachestate.maxindex)
3102 wantnormals = !r_showsurfaces.integer;
3103 wanttangents = !r_showsurfaces.integer && (r_glsl.integer || r_refdef.scene.rtworld || r_refdef.scene.rtdlight);
3105 // TODO: thread this?
3107 for (i = 0;i < r_refdef.scene.numentities;i++)
3109 if (!r_refdef.viewcache.entityvisible[i])
3111 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
3115 //==================================================================================
3117 static void R_View_UpdateEntityLighting (void)
3120 entity_render_t *ent;
3121 vec3_t tempdiffusenormal;
3123 for (i = 0;i < r_refdef.scene.numentities;i++)
3125 ent = r_refdef.scene.entities[i];
3127 // skip unseen models
3128 if (!r_refdef.viewcache.entityvisible[i] && r_shadows.integer != 1)
3132 if (ent->model && ent->model->brush.num_leafs)
3134 // TODO: use modellight for r_ambient settings on world?
3135 VectorSet(ent->modellight_ambient, 0, 0, 0);
3136 VectorSet(ent->modellight_diffuse, 0, 0, 0);
3137 VectorSet(ent->modellight_lightdir, 0, 0, 1);
3141 // fetch the lighting from the worldmodel data
3142 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));
3143 VectorClear(ent->modellight_diffuse);
3144 VectorClear(tempdiffusenormal);
3145 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
3148 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
3149 r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
3152 VectorSet(ent->modellight_ambient, 1, 1, 1);
3154 // move the light direction into modelspace coordinates for lighting code
3155 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
3156 if(VectorLength2(ent->modellight_lightdir) == 0)
3157 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
3158 VectorNormalize(ent->modellight_lightdir);
3162 static void R_View_UpdateEntityVisible (void)
3165 entity_render_t *ent;
3167 if (!r_drawentities.integer)
3170 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : ((chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL : RENDER_EXTERIORMODEL);
3171 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
3173 // worldmodel can check visibility
3174 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
3175 for (i = 0;i < r_refdef.scene.numentities;i++)
3177 ent = r_refdef.scene.entities[i];
3178 if (!(ent->flags & renderimask))
3179 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)))
3180 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))
3181 r_refdef.viewcache.entityvisible[i] = true;
3183 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight)
3185 for (i = 0;i < r_refdef.scene.numentities;i++)
3187 ent = r_refdef.scene.entities[i];
3188 if(r_refdef.viewcache.entityvisible[i] && !(ent->effects & EF_NODEPTHTEST) && !(ent->flags & RENDER_VIEWMODEL) && !(ent->model && (ent->model->name[0] == '*')))
3190 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))
3191 ent->last_trace_visibility = realtime;
3192 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
3193 r_refdef.viewcache.entityvisible[i] = 0;
3200 // no worldmodel or it can't check visibility
3201 for (i = 0;i < r_refdef.scene.numentities;i++)
3203 ent = r_refdef.scene.entities[i];
3204 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));
3209 /// only used if skyrendermasked, and normally returns false
3210 int R_DrawBrushModelsSky (void)
3213 entity_render_t *ent;
3215 if (!r_drawentities.integer)
3219 for (i = 0;i < r_refdef.scene.numentities;i++)
3221 if (!r_refdef.viewcache.entityvisible[i])
3223 ent = r_refdef.scene.entities[i];
3224 if (!ent->model || !ent->model->DrawSky)
3226 ent->model->DrawSky(ent);
3232 static void R_DrawNoModel(entity_render_t *ent);
3233 static void R_DrawModels(void)
3236 entity_render_t *ent;
3238 if (!r_drawentities.integer)
3241 for (i = 0;i < r_refdef.scene.numentities;i++)
3243 if (!r_refdef.viewcache.entityvisible[i])
3245 ent = r_refdef.scene.entities[i];
3246 r_refdef.stats.entities++;
3247 if (ent->model && ent->model->Draw != NULL)
3248 ent->model->Draw(ent);
3254 static void R_DrawModelsDepth(void)
3257 entity_render_t *ent;
3259 if (!r_drawentities.integer)
3262 for (i = 0;i < r_refdef.scene.numentities;i++)
3264 if (!r_refdef.viewcache.entityvisible[i])
3266 ent = r_refdef.scene.entities[i];
3267 if (ent->model && ent->model->DrawDepth != NULL)
3268 ent->model->DrawDepth(ent);
3272 static void R_DrawModelsDebug(void)
3275 entity_render_t *ent;
3277 if (!r_drawentities.integer)
3280 for (i = 0;i < r_refdef.scene.numentities;i++)
3282 if (!r_refdef.viewcache.entityvisible[i])
3284 ent = r_refdef.scene.entities[i];
3285 if (ent->model && ent->model->DrawDebug != NULL)
3286 ent->model->DrawDebug(ent);
3290 static void R_DrawModelsAddWaterPlanes(void)
3293 entity_render_t *ent;
3295 if (!r_drawentities.integer)
3298 for (i = 0;i < r_refdef.scene.numentities;i++)
3300 if (!r_refdef.viewcache.entityvisible[i])
3302 ent = r_refdef.scene.entities[i];
3303 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
3304 ent->model->DrawAddWaterPlanes(ent);
3308 static void R_View_SetFrustum(void)
3311 double slopex, slopey;
3312 vec3_t forward, left, up, origin;
3314 // we can't trust r_refdef.view.forward and friends in reflected scenes
3315 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
3318 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
3319 r_refdef.view.frustum[0].normal[1] = 0 - 0;
3320 r_refdef.view.frustum[0].normal[2] = -1 - 0;
3321 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
3322 r_refdef.view.frustum[1].normal[1] = 0 + 0;
3323 r_refdef.view.frustum[1].normal[2] = -1 + 0;
3324 r_refdef.view.frustum[2].normal[0] = 0 - 0;
3325 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
3326 r_refdef.view.frustum[2].normal[2] = -1 - 0;
3327 r_refdef.view.frustum[3].normal[0] = 0 + 0;
3328 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
3329 r_refdef.view.frustum[3].normal[2] = -1 + 0;
3333 zNear = r_refdef.nearclip;
3334 nudge = 1.0 - 1.0 / (1<<23);
3335 r_refdef.view.frustum[4].normal[0] = 0 - 0;
3336 r_refdef.view.frustum[4].normal[1] = 0 - 0;
3337 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
3338 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
3339 r_refdef.view.frustum[5].normal[0] = 0 + 0;
3340 r_refdef.view.frustum[5].normal[1] = 0 + 0;
3341 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
3342 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
3348 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
3349 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
3350 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
3351 r_refdef.view.frustum[0].dist = m[15] - m[12];
3353 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
3354 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
3355 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
3356 r_refdef.view.frustum[1].dist = m[15] + m[12];
3358 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
3359 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
3360 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
3361 r_refdef.view.frustum[2].dist = m[15] - m[13];
3363 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
3364 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
3365 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
3366 r_refdef.view.frustum[3].dist = m[15] + m[13];
3368 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
3369 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
3370 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
3371 r_refdef.view.frustum[4].dist = m[15] - m[14];
3373 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
3374 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
3375 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
3376 r_refdef.view.frustum[5].dist = m[15] + m[14];
3379 if (r_refdef.view.useperspective)
3381 slopex = 1.0 / r_refdef.view.frustum_x;
3382 slopey = 1.0 / r_refdef.view.frustum_y;
3383 VectorMA(forward, -slopex, left, r_refdef.view.frustum[0].normal);
3384 VectorMA(forward, slopex, left, r_refdef.view.frustum[1].normal);
3385 VectorMA(forward, -slopey, up , r_refdef.view.frustum[2].normal);
3386 VectorMA(forward, slopey, up , r_refdef.view.frustum[3].normal);
3387 VectorCopy(forward, r_refdef.view.frustum[4].normal);
3389 // Leaving those out was a mistake, those were in the old code, and they
3390 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
3391 // I couldn't reproduce it after adding those normalizations. --blub
3392 VectorNormalize(r_refdef.view.frustum[0].normal);
3393 VectorNormalize(r_refdef.view.frustum[1].normal);
3394 VectorNormalize(r_refdef.view.frustum[2].normal);
3395 VectorNormalize(r_refdef.view.frustum[3].normal);
3397 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
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[0]);
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[1]);
3400 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]);
3401 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]);
3403 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
3404 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
3405 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
3406 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
3407 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
3411 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
3412 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
3413 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
3414 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
3415 VectorCopy(forward, r_refdef.view.frustum[4].normal);
3416 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
3417 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
3418 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
3419 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
3420 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
3422 r_refdef.view.numfrustumplanes = 5;
3424 if (r_refdef.view.useclipplane)
3426 r_refdef.view.numfrustumplanes = 6;
3427 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
3430 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
3431 PlaneClassify(r_refdef.view.frustum + i);
3433 // LordHavoc: note to all quake engine coders, Quake had a special case
3434 // for 90 degrees which assumed a square view (wrong), so I removed it,
3435 // Quake2 has it disabled as well.
3437 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
3438 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
3439 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
3440 //PlaneClassify(&frustum[0]);
3442 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
3443 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
3444 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
3445 //PlaneClassify(&frustum[1]);
3447 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
3448 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
3449 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
3450 //PlaneClassify(&frustum[2]);
3452 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
3453 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
3454 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
3455 //PlaneClassify(&frustum[3]);
3458 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
3459 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
3460 //PlaneClassify(&frustum[4]);
3463 void R_View_Update(void)
3465 R_View_SetFrustum();
3466 R_View_WorldVisibility(r_refdef.view.useclipplane);
3467 R_View_UpdateEntityVisible();
3468 R_View_UpdateEntityLighting();
3471 void R_SetupView(qboolean allowwaterclippingplane)
3473 const double *customclipplane = NULL;
3475 if (r_refdef.view.useclipplane && allowwaterclippingplane)
3477 // LordHavoc: couldn't figure out how to make this approach the
3478 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
3479 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
3480 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
3481 dist = r_refdef.view.clipplane.dist;
3482 plane[0] = r_refdef.view.clipplane.normal[0];
3483 plane[1] = r_refdef.view.clipplane.normal[1];
3484 plane[2] = r_refdef.view.clipplane.normal[2];
3486 customclipplane = plane;
3489 if (!r_refdef.view.useperspective)
3490 R_Viewport_InitOrtho(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, vid.height - r_refdef.view.height - 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);
3491 else if (gl_stencil && r_useinfinitefarclip.integer)
3492 R_Viewport_InitPerspectiveInfinite(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, vid.height - r_refdef.view.height - 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);
3494 R_Viewport_InitPerspective(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, vid.height - r_refdef.view.height - 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);
3495 R_SetViewport(&r_refdef.view.viewport);
3498 void R_ResetViewRendering2D(void)
3500 r_viewport_t viewport;
3503 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
3504 R_Viewport_InitOrtho(&viewport, &identitymatrix, r_refdef.view.x, vid.height - r_refdef.view.height - r_refdef.view.y, r_refdef.view.width, r_refdef.view.height, 0, 0, 1, 1, -10, 100, NULL);
3505 R_SetViewport(&viewport);
3506 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
3507 GL_Color(1, 1, 1, 1);
3508 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
3509 GL_BlendFunc(GL_ONE, GL_ZERO);
3510 GL_AlphaTest(false);
3511 GL_ScissorTest(false);
3512 GL_DepthMask(false);
3513 GL_DepthRange(0, 1);
3514 GL_DepthTest(false);
3515 R_Mesh_Matrix(&identitymatrix);
3516 R_Mesh_ResetTextureState();
3517 GL_PolygonOffset(0, 0);
3518 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
3519 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3520 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
3521 qglStencilMask(~0);CHECKGLERROR
3522 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
3523 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
3524 GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
3525 R_SetupGenericShader(true);
3528 void R_ResetViewRendering3D(void)
3533 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.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, vid.width * r_water_resolutionmultiplier.value, vid.width);
3567 waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.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 // when doing a reduced render (HDR) we want to use a smaller area
3605 waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
3606 waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
3608 if (r_waterstate.waterwidth)
3610 r_waterstate.enabled = true;
3612 // set up variables that will be used in shader setup
3613 r_waterstate.screenscale[0] = 0.5f * (float)waterwidth / (float)texturewidth;
3614 r_waterstate.screenscale[1] = 0.5f * (float)waterheight / (float)textureheight;
3615 r_waterstate.screencenter[0] = 0.5f * (float)waterwidth / (float)texturewidth;
3616 r_waterstate.screencenter[1] = 0.5f * (float)waterheight / (float)textureheight;
3619 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
3620 r_waterstate.numwaterplanes = 0;
3623 void R_Water_AddWaterPlane(msurface_t *surface)
3625 int triangleindex, planeindex;
3631 r_waterstate_waterplane_t *p;
3632 texture_t *t = R_GetCurrentTexture(surface->texture);
3633 // just use the first triangle with a valid normal for any decisions
3634 VectorClear(normal);
3635 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
3637 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
3638 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
3639 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
3640 TriangleNormal(vert[0], vert[1], vert[2], normal);
3641 if (VectorLength2(normal) >= 0.001)
3645 VectorCopy(normal, plane.normal);
3646 VectorNormalize(plane.normal);
3647 plane.dist = DotProduct(vert[0], plane.normal);
3648 PlaneClassify(&plane);
3649 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
3651 // skip backfaces (except if nocullface is set)
3652 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
3654 VectorNegate(plane.normal, plane.normal);
3656 PlaneClassify(&plane);
3660 // find a matching plane if there is one
3661 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
3662 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
3664 if (planeindex >= r_waterstate.maxwaterplanes)
3665 return; // nothing we can do, out of planes
3667 // if this triangle does not fit any known plane rendered this frame, add one
3668 if (planeindex >= r_waterstate.numwaterplanes)
3670 // store the new plane
3671 r_waterstate.numwaterplanes++;
3673 // clear materialflags and pvs
3674 p->materialflags = 0;
3675 p->pvsvalid = false;
3677 // merge this surface's materialflags into the waterplane
3678 p->materialflags |= t->currentmaterialflags;
3679 // merge this surface's PVS into the waterplane
3680 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
3681 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
3682 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
3684 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
3689 static void R_Water_ProcessPlanes(void)
3691 r_refdef_view_t originalview;
3692 r_refdef_view_t myview;
3694 r_waterstate_waterplane_t *p;
3696 originalview = r_refdef.view;
3698 // make sure enough textures are allocated
3699 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
3701 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
3703 if (!p->texture_refraction)
3704 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);
3705 if (!p->texture_refraction)
3709 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
3711 if (!p->texture_reflection)
3712 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);
3713 if (!p->texture_reflection)
3719 r_refdef.view = originalview;
3720 r_refdef.view.showdebug = false;
3721 r_refdef.view.width = r_waterstate.waterwidth;
3722 r_refdef.view.height = r_waterstate.waterheight;
3723 r_refdef.view.useclipplane = true;
3724 myview = r_refdef.view;
3725 r_waterstate.renderingscene = true;
3726 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
3728 // render the normal view scene and copy into texture
3729 // (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)
3730 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
3732 r_refdef.view = myview;
3733 r_refdef.view.clipplane = p->plane;
3734 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
3735 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
3736 PlaneClassify(&r_refdef.view.clipplane);
3738 R_ResetViewRendering3D();
3739 R_ClearScreen(r_refdef.fogenabled);
3743 // copy view into the screen texture
3744 R_Mesh_TexBind(0, R_GetTexture(p->texture_refraction));
3745 GL_ActiveTexture(0);
3747 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);CHECKGLERROR
3750 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
3752 r_refdef.view = myview;
3753 // render reflected scene and copy into texture
3754 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
3755 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
3756 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
3757 r_refdef.view.clipplane = p->plane;
3758 // reverse the cullface settings for this render
3759 r_refdef.view.cullface_front = GL_FRONT;
3760 r_refdef.view.cullface_back = GL_BACK;
3761 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
3763 r_refdef.view.usecustompvs = true;
3765 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
3767 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
3770 R_ResetViewRendering3D();
3771 R_ClearScreen(r_refdef.fogenabled);
3775 R_Mesh_TexBind(0, R_GetTexture(p->texture_reflection));
3776 GL_ActiveTexture(0);
3778 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);CHECKGLERROR
3781 r_waterstate.renderingscene = false;
3782 r_refdef.view = originalview;
3783 R_ResetViewRendering3D();
3784 R_ClearScreen(r_refdef.fogenabled);
3788 r_refdef.view = originalview;
3789 r_waterstate.renderingscene = false;
3790 Cvar_SetValueQuick(&r_water, 0);
3791 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
3795 void R_Bloom_StartFrame(void)
3797 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
3799 // set bloomwidth and bloomheight to the bloom resolution that will be
3800 // used (often less than the screen resolution for faster rendering)
3801 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
3802 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
3803 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
3804 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, gl_max_texture_size);
3805 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, gl_max_texture_size);
3807 // calculate desired texture sizes
3808 if (gl_support_arb_texture_non_power_of_two)
3810 screentexturewidth = r_refdef.view.width;
3811 screentextureheight = r_refdef.view.height;
3812 bloomtexturewidth = r_bloomstate.bloomwidth;
3813 bloomtextureheight = r_bloomstate.bloomheight;
3817 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
3818 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
3819 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
3820 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
3823 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))
3825 Cvar_SetValueQuick(&r_hdr, 0);
3826 Cvar_SetValueQuick(&r_bloom, 0);
3827 Cvar_SetValueQuick(&r_motionblur, 0);
3828 Cvar_SetValueQuick(&r_damageblur, 0);
3831 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)))
3832 screentexturewidth = screentextureheight = 0;
3833 if (!r_hdr.integer && !r_bloom.integer)
3834 bloomtexturewidth = bloomtextureheight = 0;
3836 // allocate textures as needed
3837 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
3839 if (r_bloomstate.texture_screen)
3840 R_FreeTexture(r_bloomstate.texture_screen);
3841 r_bloomstate.texture_screen = NULL;
3842 r_bloomstate.screentexturewidth = screentexturewidth;
3843 r_bloomstate.screentextureheight = screentextureheight;
3844 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
3845 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);
3847 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
3849 if (r_bloomstate.texture_bloom)
3850 R_FreeTexture(r_bloomstate.texture_bloom);
3851 r_bloomstate.texture_bloom = NULL;
3852 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
3853 r_bloomstate.bloomtextureheight = bloomtextureheight;
3854 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
3855 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);
3858 // when doing a reduced render (HDR) we want to use a smaller area
3859 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
3860 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
3861 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
3862 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
3863 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
3865 // set up a texcoord array for the full resolution screen image
3866 // (we have to keep this around to copy back during final render)
3867 r_bloomstate.screentexcoord2f[0] = 0;
3868 r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
3869 r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
3870 r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
3871 r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
3872 r_bloomstate.screentexcoord2f[5] = 0;
3873 r_bloomstate.screentexcoord2f[6] = 0;
3874 r_bloomstate.screentexcoord2f[7] = 0;
3876 // set up a texcoord array for the reduced resolution bloom image
3877 // (which will be additive blended over the screen image)
3878 r_bloomstate.bloomtexcoord2f[0] = 0;
3879 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3880 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3881 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3882 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3883 r_bloomstate.bloomtexcoord2f[5] = 0;
3884 r_bloomstate.bloomtexcoord2f[6] = 0;
3885 r_bloomstate.bloomtexcoord2f[7] = 0;
3887 if (r_hdr.integer || r_bloom.integer)
3889 r_bloomstate.enabled = true;
3890 r_bloomstate.hdr = r_hdr.integer != 0;
3893 R_Viewport_InitOrtho(&r_bloomstate.viewport, &identitymatrix, r_refdef.view.x, vid.height - r_bloomstate.bloomheight - r_refdef.view.y, r_bloomstate.bloomwidth, r_bloomstate.bloomheight, 0, 0, 1, 1, -10, 100, NULL);
3896 void R_Bloom_CopyBloomTexture(float colorscale)
3898 r_refdef.stats.bloom++;
3900 // scale down screen texture to the bloom texture size
3902 R_SetViewport(&r_bloomstate.viewport);
3903 GL_BlendFunc(GL_ONE, GL_ZERO);
3904 GL_Color(colorscale, colorscale, colorscale, 1);
3905 // TODO: optimize with multitexture or GLSL
3906 R_SetupGenericShader(true);
3907 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
3908 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
3909 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3910 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3912 // we now have a bloom image in the framebuffer
3913 // copy it into the bloom image texture for later processing
3914 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3915 GL_ActiveTexture(0);
3917 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
3918 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
3921 void R_Bloom_CopyHDRTexture(void)
3923 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3924 GL_ActiveTexture(0);
3926 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);CHECKGLERROR
3927 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
3930 void R_Bloom_MakeTexture(void)
3933 float xoffset, yoffset, r, brighten;
3935 r_refdef.stats.bloom++;
3937 R_ResetViewRendering2D();
3938 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3939 R_Mesh_ColorPointer(NULL, 0, 0);
3940 R_SetupGenericShader(true);
3942 // we have a bloom image in the framebuffer
3944 R_SetViewport(&r_bloomstate.viewport);
3946 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
3949 r = bound(0, r_bloom_colorexponent.value / x, 1);
3950 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
3951 GL_Color(r, r, r, 1);
3952 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3953 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3954 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3955 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3957 // copy the vertically blurred bloom view to a texture
3958 GL_ActiveTexture(0);
3960 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
3961 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
3964 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
3965 brighten = r_bloom_brighten.value;
3967 brighten *= r_hdr_range.value;
3968 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3969 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
3971 for (dir = 0;dir < 2;dir++)
3973 // blend on at multiple vertical offsets to achieve a vertical blur
3974 // TODO: do offset blends using GLSL
3975 GL_BlendFunc(GL_ONE, GL_ZERO);
3976 for (x = -range;x <= range;x++)
3978 if (!dir){xoffset = 0;yoffset = x;}
3979 else {xoffset = x;yoffset = 0;}
3980 xoffset /= (float)r_bloomstate.bloomtexturewidth;
3981 yoffset /= (float)r_bloomstate.bloomtextureheight;
3982 // compute a texcoord array with the specified x and y offset
3983 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
3984 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3985 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3986 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3987 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3988 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
3989 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
3990 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
3991 // this r value looks like a 'dot' particle, fading sharply to
3992 // black at the edges
3993 // (probably not realistic but looks good enough)
3994 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
3995 //r = (dir ? 1.0f : brighten)/(range*2+1);
3996 r = (dir ? 1.0f : brighten)/(range*2+1)*(1 - x*x/(float)(range*range));
3997 GL_Color(r, r, r, 1);
3998 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3999 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4000 GL_BlendFunc(GL_ONE, GL_ONE);
4003 // copy the vertically blurred bloom view to a texture
4004 GL_ActiveTexture(0);
4006 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
4007 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
4010 // apply subtract last
4011 // (just like it would be in a GLSL shader)
4012 if (r_bloom_colorsubtract.value > 0 && gl_support_ext_blend_subtract)
4014 GL_BlendFunc(GL_ONE, GL_ZERO);
4015 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4016 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4017 GL_Color(1, 1, 1, 1);
4018 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4019 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4021 GL_BlendFunc(GL_ONE, GL_ONE);
4022 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
4023 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
4024 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4025 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
4026 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4027 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4028 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
4030 // copy the darkened bloom view to a texture
4031 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4032 GL_ActiveTexture(0);
4034 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
4035 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
4039 void R_HDR_RenderBloomTexture(void)
4041 int oldwidth, oldheight;
4042 float oldcolorscale;
4044 oldcolorscale = r_refdef.view.colorscale;
4045 oldwidth = r_refdef.view.width;
4046 oldheight = r_refdef.view.height;
4047 r_refdef.view.width = r_bloomstate.bloomwidth;
4048 r_refdef.view.height = r_bloomstate.bloomheight;
4050 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
4051 // TODO: add exposure compensation features
4052 // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
4054 r_refdef.view.showdebug = false;
4055 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
4057 R_ResetViewRendering3D();
4059 R_ClearScreen(r_refdef.fogenabled);
4060 if (r_timereport_active)
4061 R_TimeReport("HDRclear");
4064 if (r_timereport_active)
4065 R_TimeReport("visibility");
4067 // only do secondary renders with HDR if r_hdr is 2 or higher
4068 r_waterstate.numwaterplanes = 0;
4069 if (r_waterstate.enabled && r_hdr.integer >= 2)
4070 R_RenderWaterPlanes();
4072 r_refdef.view.showdebug = true;
4074 r_waterstate.numwaterplanes = 0;
4076 R_ResetViewRendering2D();
4078 R_Bloom_CopyHDRTexture();
4079 R_Bloom_MakeTexture();
4081 // restore the view settings
4082 r_refdef.view.width = oldwidth;
4083 r_refdef.view.height = oldheight;
4084 r_refdef.view.colorscale = oldcolorscale;
4086 R_ResetViewRendering3D();
4088 R_ClearScreen(r_refdef.fogenabled);
4089 if (r_timereport_active)
4090 R_TimeReport("viewclear");
4093 static void R_BlendView(void)
4095 if (r_bloomstate.texture_screen)
4097 // make sure the buffer is available
4098 if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
4100 R_ResetViewRendering2D();
4101 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4102 R_Mesh_ColorPointer(NULL, 0, 0);
4103 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4104 GL_ActiveTexture(0);CHECKGLERROR
4106 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
4108 // declare variables
4110 static float avgspeed;
4112 speed = VectorLength(cl.movement_velocity);
4114 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
4115 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
4117 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
4118 speed = bound(0, speed, 1);
4119 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
4121 // calculate values into a standard alpha
4122 cl.motionbluralpha = 1 - exp(-
4124 (r_motionblur.value * speed / 80)
4126 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
4129 max(0.0001, cl.time - cl.oldtime) // fps independent
4132 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
4133 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
4135 if (cl.motionbluralpha > 0)
4137 R_SetupGenericShader(true);
4138 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4139 GL_Color(1, 1, 1, cl.motionbluralpha);
4140 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4141 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
4142 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4143 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4147 // copy view into the screen texture
4148 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);CHECKGLERROR
4149 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4152 if (r_glsl.integer && gl_support_fragment_shader && (r_bloomstate.texture_screen || r_bloomstate.texture_bloom))
4154 unsigned int permutation =
4155 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
4156 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
4157 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
4158 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
4159 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
4161 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
4163 // render simple bloom effect
4164 // copy the screen and shrink it and darken it for the bloom process
4165 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
4166 // make the bloom texture
4167 R_Bloom_MakeTexture();
4170 R_ResetViewRendering2D();
4171 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4172 R_Mesh_ColorPointer(NULL, 0, 0);
4173 GL_Color(1, 1, 1, 1);
4174 GL_BlendFunc(GL_ONE, GL_ZERO);
4175 R_SetupShader_SetPermutation(SHADERMODE_POSTPROCESS, permutation);
4176 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4177 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
4178 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_bloom));
4179 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4180 if (r_glsl_permutation->loc_Texture_GammaRamps >= 0)
4181 R_Mesh_TexBind(GL20TU_GAMMARAMPS, R_GetTexture(r_texture_gammaramps));
4182 if (r_glsl_permutation->loc_TintColor >= 0)
4183 qglUniform4fARB(r_glsl_permutation->loc_TintColor, r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
4184 if (r_glsl_permutation->loc_ClientTime >= 0)
4185 qglUniform1fARB(r_glsl_permutation->loc_ClientTime, cl.time);
4186 if (r_glsl_permutation->loc_PixelSize >= 0)
4187 qglUniform2fARB(r_glsl_permutation->loc_PixelSize, 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
4188 if (r_glsl_permutation->loc_UserVec1 >= 0)
4190 float a=0, b=0, c=0, d=0;
4191 #if _MSC_VER >= 1400
4192 #define sscanf sscanf_s
4194 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &a, &b, &c, &d);
4195 qglUniform4fARB(r_glsl_permutation->loc_UserVec1, a, b, c, d);
4197 if (r_glsl_permutation->loc_UserVec2 >= 0)
4199 float a=0, b=0, c=0, d=0;
4200 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &a, &b, &c, &d);
4201 qglUniform4fARB(r_glsl_permutation->loc_UserVec2, a, b, c, d);
4203 if (r_glsl_permutation->loc_UserVec3 >= 0)
4205 float a=0, b=0, c=0, d=0;
4206 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &a, &b, &c, &d);
4207 qglUniform4fARB(r_glsl_permutation->loc_UserVec3, a, b, c, d);
4209 if (r_glsl_permutation->loc_UserVec4 >= 0)
4211 float a=0, b=0, c=0, d=0;
4212 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &a, &b, &c, &d);
4213 qglUniform4fARB(r_glsl_permutation->loc_UserVec4, a, b, c, d);
4215 if (r_glsl_permutation->loc_Saturation >= 0)
4216 qglUniform1fARB(r_glsl_permutation->loc_Saturation, r_glsl_saturation.value);
4217 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4218 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4224 if (r_bloomstate.texture_bloom && r_bloomstate.hdr)
4226 // render high dynamic range bloom effect
4227 // the bloom texture was made earlier this render, so we just need to
4228 // blend it onto the screen...
4229 R_ResetViewRendering2D();
4230 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4231 R_Mesh_ColorPointer(NULL, 0, 0);
4232 R_SetupGenericShader(true);
4233 GL_Color(1, 1, 1, 1);
4234 GL_BlendFunc(GL_ONE, GL_ONE);
4235 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4236 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4237 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4238 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4240 else if (r_bloomstate.texture_bloom)
4242 // render simple bloom effect
4243 // copy the screen and shrink it and darken it for the bloom process
4244 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
4245 // make the bloom texture
4246 R_Bloom_MakeTexture();
4247 // put the original screen image back in place and blend the bloom
4249 R_ResetViewRendering2D();
4250 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4251 R_Mesh_ColorPointer(NULL, 0, 0);
4252 GL_Color(1, 1, 1, 1);
4253 GL_BlendFunc(GL_ONE, GL_ZERO);
4254 // do both in one pass if possible
4255 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4256 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4257 if (r_textureunits.integer >= 2 && gl_combine.integer)
4259 R_SetupGenericTwoTextureShader(GL_ADD);
4260 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_screen));
4261 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.screentexcoord2f, 0, 0);
4265 R_SetupGenericShader(true);
4266 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4267 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4268 // now blend on the bloom texture
4269 GL_BlendFunc(GL_ONE, GL_ONE);
4270 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4271 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
4273 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4274 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4276 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
4278 // apply a color tint to the whole view
4279 R_ResetViewRendering2D();
4280 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4281 R_Mesh_ColorPointer(NULL, 0, 0);
4282 R_SetupGenericShader(false);
4283 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4284 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
4285 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4289 matrix4x4_t r_waterscrollmatrix;
4291 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
4293 if (r_refdef.fog_density)
4295 r_refdef.fogcolor[0] = r_refdef.fog_red;
4296 r_refdef.fogcolor[1] = r_refdef.fog_green;
4297 r_refdef.fogcolor[2] = r_refdef.fog_blue;
4301 VectorCopy(r_refdef.fogcolor, fogvec);
4302 // color.rgb *= ContrastBoost * SceneBrightness;
4303 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
4304 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
4305 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
4306 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
4311 void R_UpdateVariables(void)
4315 r_refdef.scene.ambient = r_ambient.value;
4317 r_refdef.farclip = 4096;
4318 if (r_refdef.scene.worldmodel)
4319 r_refdef.farclip += r_refdef.scene.worldmodel->radius * 2;
4320 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
4322 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
4323 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
4324 r_refdef.polygonfactor = 0;
4325 r_refdef.polygonoffset = 0;
4326 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
4327 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
4329 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
4330 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
4331 r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
4332 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && gl_stencil;
4333 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
4334 if (r_showsurfaces.integer)
4336 r_refdef.scene.rtworld = false;
4337 r_refdef.scene.rtworldshadows = false;
4338 r_refdef.scene.rtdlight = false;
4339 r_refdef.scene.rtdlightshadows = false;
4340 r_refdef.lightmapintensity = 0;
4343 if (gamemode == GAME_NEHAHRA)
4345 if (gl_fogenable.integer)
4347 r_refdef.oldgl_fogenable = true;
4348 r_refdef.fog_density = gl_fogdensity.value;
4349 r_refdef.fog_red = gl_fogred.value;
4350 r_refdef.fog_green = gl_foggreen.value;
4351 r_refdef.fog_blue = gl_fogblue.value;
4352 r_refdef.fog_alpha = 1;
4353 r_refdef.fog_start = 0;
4354 r_refdef.fog_end = gl_skyclip.value;
4356 else if (r_refdef.oldgl_fogenable)
4358 r_refdef.oldgl_fogenable = false;
4359 r_refdef.fog_density = 0;
4360 r_refdef.fog_red = 0;
4361 r_refdef.fog_green = 0;
4362 r_refdef.fog_blue = 0;
4363 r_refdef.fog_alpha = 0;
4364 r_refdef.fog_start = 0;
4365 r_refdef.fog_end = 0;
4369 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
4370 r_refdef.fog_start = max(0, r_refdef.fog_start);
4371 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
4373 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
4375 if (r_refdef.fog_density && r_drawfog.integer)
4377 r_refdef.fogenabled = true;
4378 // this is the point where the fog reaches 0.9986 alpha, which we
4379 // consider a good enough cutoff point for the texture
4380 // (0.9986 * 256 == 255.6)
4381 if (r_fog_exp2.integer)
4382 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
4384 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
4385 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
4386 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
4387 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
4388 // fog color was already set
4389 // update the fog texture
4390 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)
4391 R_BuildFogTexture();
4394 r_refdef.fogenabled = false;
4396 if(r_glsl.integer && v_glslgamma.integer && !vid_gammatables_trivial)
4398 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
4400 // build GLSL gamma texture
4401 #define RAMPWIDTH 256
4402 unsigned short ramp[RAMPWIDTH * 3];
4403 unsigned char rampbgr[RAMPWIDTH][4];
4406 r_texture_gammaramps_serial = vid_gammatables_serial;
4408 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
4409 for(i = 0; i < RAMPWIDTH; ++i)
4411 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
4412 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
4413 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
4416 if (r_texture_gammaramps)
4418 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
4422 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);
4428 // remove GLSL gamma texture
4432 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
4433 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
4439 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
4440 if( scenetype != r_currentscenetype ) {
4441 // store the old scenetype
4442 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
4443 r_currentscenetype = scenetype;
4444 // move in the new scene
4445 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
4454 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
4456 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
4457 if( scenetype == r_currentscenetype ) {
4458 return &r_refdef.scene;
4460 return &r_scenes_store[ scenetype ];
4469 void R_RenderView(void)
4471 if (r_timereport_active)
4472 R_TimeReport("start");
4473 r_frame++; // used only by R_GetCurrentTexture
4474 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
4476 R_AnimCache_NewFrame();
4478 if (r_refdef.view.isoverlay)
4480 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
4481 GL_Clear( GL_DEPTH_BUFFER_BIT );
4482 R_TimeReport("depthclear");
4484 r_refdef.view.showdebug = false;
4486 r_waterstate.enabled = false;
4487 r_waterstate.numwaterplanes = 0;
4495 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0/* || !r_refdef.scene.worldmodel*/)
4496 return; //Host_Error ("R_RenderView: NULL worldmodel");
4498 r_refdef.view.colorscale = r_hdr_scenebrightness.value;
4500 // break apart the view matrix into vectors for various purposes
4501 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
4502 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
4503 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
4504 VectorNegate(r_refdef.view.left, r_refdef.view.right);
4505 // make an inverted copy of the view matrix for tracking sprites
4506 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
4508 R_Shadow_UpdateWorldLightSelection();
4510 R_Bloom_StartFrame();
4511 R_Water_StartFrame();
4514 if (r_timereport_active)
4515 R_TimeReport("viewsetup");
4517 R_ResetViewRendering3D();
4519 if (r_refdef.view.clear || r_refdef.fogenabled)
4521 R_ClearScreen(r_refdef.fogenabled);
4522 if (r_timereport_active)
4523 R_TimeReport("viewclear");
4525 r_refdef.view.clear = true;
4527 // this produces a bloom texture to be used in R_BlendView() later
4529 R_HDR_RenderBloomTexture();
4531 r_refdef.view.showdebug = true;
4534 if (r_timereport_active)
4535 R_TimeReport("visibility");
4537 r_waterstate.numwaterplanes = 0;
4538 if (r_waterstate.enabled)
4539 R_RenderWaterPlanes();
4542 r_waterstate.numwaterplanes = 0;
4545 if (r_timereport_active)
4546 R_TimeReport("blendview");
4548 GL_Scissor(0, 0, vid.width, vid.height);
4549 GL_ScissorTest(false);
4553 void R_RenderWaterPlanes(void)
4555 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
4557 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
4558 if (r_timereport_active)
4559 R_TimeReport("waterworld");
4562 // don't let sound skip if going slow
4563 if (r_refdef.scene.extraupdate)
4566 R_DrawModelsAddWaterPlanes();
4567 if (r_timereport_active)
4568 R_TimeReport("watermodels");
4570 if (r_waterstate.numwaterplanes)
4572 R_Water_ProcessPlanes();
4573 if (r_timereport_active)
4574 R_TimeReport("waterscenes");
4578 extern void R_DrawLightningBeams (void);
4579 extern void VM_CL_AddPolygonsToMeshQueue (void);
4580 extern void R_DrawPortals (void);
4581 extern cvar_t cl_locs_show;
4582 static void R_DrawLocs(void);
4583 static void R_DrawEntityBBoxes(void);
4584 void R_RenderScene(void)
4586 r_refdef.stats.renders++;
4590 // don't let sound skip if going slow
4591 if (r_refdef.scene.extraupdate)
4594 R_MeshQueue_BeginScene();
4598 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);
4600 if (cl.csqc_vidvars.drawworld)
4602 // don't let sound skip if going slow
4603 if (r_refdef.scene.extraupdate)
4606 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
4608 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
4609 if (r_timereport_active)
4610 R_TimeReport("worldsky");
4613 if (R_DrawBrushModelsSky() && r_timereport_active)
4614 R_TimeReport("bmodelsky");
4617 R_AnimCache_CacheVisibleEntities();
4619 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
4621 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
4622 if (r_timereport_active)
4623 R_TimeReport("worlddepth");
4625 if (r_depthfirst.integer >= 2)
4627 R_DrawModelsDepth();
4628 if (r_timereport_active)
4629 R_TimeReport("modeldepth");
4632 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
4634 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
4635 if (r_timereport_active)
4636 R_TimeReport("world");
4639 // don't let sound skip if going slow
4640 if (r_refdef.scene.extraupdate)
4644 if (r_timereport_active)
4645 R_TimeReport("models");
4647 // don't let sound skip if going slow
4648 if (r_refdef.scene.extraupdate)
4651 if (r_shadows.integer > 0 && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
4653 R_DrawModelShadows();
4654 R_ResetViewRendering3D();
4655 // don't let sound skip if going slow
4656 if (r_refdef.scene.extraupdate)
4660 R_ShadowVolumeLighting(false);
4661 if (r_timereport_active)
4662 R_TimeReport("rtlights");
4664 // don't let sound skip if going slow
4665 if (r_refdef.scene.extraupdate)
4668 if (r_shadows.integer > 0 && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
4670 R_DrawModelShadows();
4671 R_ResetViewRendering3D();
4672 // don't let sound skip if going slow
4673 if (r_refdef.scene.extraupdate)
4677 if (cl.csqc_vidvars.drawworld)
4679 R_DrawLightningBeams();
4680 if (r_timereport_active)
4681 R_TimeReport("lightning");
4684 if (r_timereport_active)
4685 R_TimeReport("decals");
4688 if (r_timereport_active)
4689 R_TimeReport("particles");
4692 if (r_timereport_active)
4693 R_TimeReport("explosions");
4696 R_SetupGenericShader(true);
4697 VM_CL_AddPolygonsToMeshQueue();
4699 if (r_refdef.view.showdebug)
4701 if (cl_locs_show.integer)
4704 if (r_timereport_active)
4705 R_TimeReport("showlocs");
4708 if (r_drawportals.integer)
4711 if (r_timereport_active)
4712 R_TimeReport("portals");
4715 if (r_showbboxes.value > 0)
4717 R_DrawEntityBBoxes();
4718 if (r_timereport_active)
4719 R_TimeReport("bboxes");
4723 R_SetupGenericShader(true);
4724 R_MeshQueue_RenderTransparent();
4725 if (r_timereport_active)
4726 R_TimeReport("drawtrans");
4728 R_SetupGenericShader(true);
4730 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))
4732 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
4733 if (r_timereport_active)
4734 R_TimeReport("worlddebug");
4735 R_DrawModelsDebug();
4736 if (r_timereport_active)
4737 R_TimeReport("modeldebug");
4740 R_SetupGenericShader(true);
4742 if (cl.csqc_vidvars.drawworld)
4745 if (r_timereport_active)
4746 R_TimeReport("coronas");
4749 // don't let sound skip if going slow
4750 if (r_refdef.scene.extraupdate)
4753 R_ResetViewRendering2D();
4756 static const unsigned short bboxelements[36] =
4766 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
4769 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
4770 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4771 GL_DepthMask(false);
4772 GL_DepthRange(0, 1);
4773 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
4774 R_Mesh_Matrix(&identitymatrix);
4775 R_Mesh_ResetTextureState();
4777 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
4778 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
4779 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
4780 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
4781 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
4782 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
4783 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
4784 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
4785 R_FillColors(color4f, 8, cr, cg, cb, ca);
4786 if (r_refdef.fogenabled)
4788 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
4790 f1 = FogPoint_World(v);
4792 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
4793 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
4794 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
4797 R_Mesh_VertexPointer(vertex3f, 0, 0);
4798 R_Mesh_ColorPointer(color4f, 0, 0);
4799 R_Mesh_ResetTextureState();
4800 R_SetupGenericShader(false);
4801 R_Mesh_Draw(0, 8, 0, 12, NULL, bboxelements, 0, 0);
4804 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
4808 prvm_edict_t *edict;
4809 prvm_prog_t *prog_save = prog;
4811 // this function draws bounding boxes of server entities
4815 GL_CullFace(GL_NONE);
4816 R_SetupGenericShader(false);
4820 for (i = 0;i < numsurfaces;i++)
4822 edict = PRVM_EDICT_NUM(surfacelist[i]);
4823 switch ((int)edict->fields.server->solid)
4825 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
4826 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
4827 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
4828 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
4829 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
4830 default: Vector4Set(color, 0, 0, 0, 0.50);break;
4832 color[3] *= r_showbboxes.value;
4833 color[3] = bound(0, color[3], 1);
4834 GL_DepthTest(!r_showdisabledepthtest.integer);
4835 GL_CullFace(r_refdef.view.cullface_front);
4836 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
4842 static void R_DrawEntityBBoxes(void)
4845 prvm_edict_t *edict;
4847 prvm_prog_t *prog_save = prog;
4849 // this function draws bounding boxes of server entities
4855 for (i = 0;i < prog->num_edicts;i++)
4857 edict = PRVM_EDICT_NUM(i);
4858 if (edict->priv.server->free)
4860 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
4861 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
4863 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
4865 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
4866 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
4872 unsigned short nomodelelements[24] =
4884 float nomodelvertex3f[6*3] =
4894 float nomodelcolor4f[6*4] =
4896 0.0f, 0.0f, 0.5f, 1.0f,
4897 0.0f, 0.0f, 0.5f, 1.0f,
4898 0.0f, 0.5f, 0.0f, 1.0f,
4899 0.0f, 0.5f, 0.0f, 1.0f,
4900 0.5f, 0.0f, 0.0f, 1.0f,
4901 0.5f, 0.0f, 0.0f, 1.0f
4904 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
4909 // this is only called once per entity so numsurfaces is always 1, and
4910 // surfacelist is always {0}, so this code does not handle batches
4911 R_Mesh_Matrix(&ent->matrix);
4913 if (ent->flags & EF_ADDITIVE)
4915 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
4916 GL_DepthMask(false);
4918 else if (ent->alpha < 1)
4920 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4921 GL_DepthMask(false);
4925 GL_BlendFunc(GL_ONE, GL_ZERO);
4928 GL_DepthRange(0, (ent->flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
4929 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
4930 GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
4931 GL_CullFace((ent->effects & EF_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
4932 R_SetupGenericShader(false);
4933 R_Mesh_VertexPointer(nomodelvertex3f, 0, 0);
4934 if (r_refdef.fogenabled)
4937 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
4938 R_Mesh_ColorPointer(color4f, 0, 0);
4939 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4940 f1 = FogPoint_World(org);
4942 for (i = 0, c = color4f;i < 6;i++, c += 4)
4944 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
4945 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
4946 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
4950 else if (ent->alpha != 1)
4952 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
4953 R_Mesh_ColorPointer(color4f, 0, 0);
4954 for (i = 0, c = color4f;i < 6;i++, c += 4)
4958 R_Mesh_ColorPointer(nomodelcolor4f, 0, 0);
4959 R_Mesh_ResetTextureState();
4960 R_Mesh_Draw(0, 6, 0, 8, NULL, nomodelelements, 0, 0);
4963 void R_DrawNoModel(entity_render_t *ent)
4966 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4967 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
4968 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
4970 // R_DrawNoModelCallback(ent, 0);
4973 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
4975 vec3_t right1, right2, diff, normal;
4977 VectorSubtract (org2, org1, normal);
4979 // calculate 'right' vector for start
4980 VectorSubtract (r_refdef.view.origin, org1, diff);
4981 CrossProduct (normal, diff, right1);
4982 VectorNormalize (right1);
4984 // calculate 'right' vector for end
4985 VectorSubtract (r_refdef.view.origin, org2, diff);
4986 CrossProduct (normal, diff, right2);
4987 VectorNormalize (right2);
4989 vert[ 0] = org1[0] + width * right1[0];
4990 vert[ 1] = org1[1] + width * right1[1];
4991 vert[ 2] = org1[2] + width * right1[2];
4992 vert[ 3] = org1[0] - width * right1[0];
4993 vert[ 4] = org1[1] - width * right1[1];
4994 vert[ 5] = org1[2] - width * right1[2];
4995 vert[ 6] = org2[0] - width * right2[0];
4996 vert[ 7] = org2[1] - width * right2[1];
4997 vert[ 8] = org2[2] - width * right2[2];
4998 vert[ 9] = org2[0] + width * right2[0];
4999 vert[10] = org2[1] + width * right2[1];
5000 vert[11] = org2[2] + width * right2[2];
5003 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
5005 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)
5007 // NOTE: this must not call qglDepthFunc (see r_shadow.c, R_BeginCoronaQuery) thanks to ATI
5011 if (r_refdef.fogenabled && !depthdisable) // TODO maybe make the unfog effect a separate flag?
5012 fog = FogPoint_World(origin);
5014 R_Mesh_Matrix(&identitymatrix);
5015 GL_BlendFunc(blendfunc1, blendfunc2);
5017 GL_CullFace(GL_NONE);
5019 GL_DepthMask(false);
5020 GL_DepthRange(0, depthshort ? 0.0625 : 1);
5021 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5022 GL_DepthTest(!depthdisable);
5024 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
5025 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
5026 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
5027 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
5028 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
5029 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
5030 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
5031 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
5032 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
5033 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
5034 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
5035 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
5037 R_Mesh_VertexPointer(vertex3f, 0, 0);
5038 R_Mesh_ColorPointer(NULL, 0, 0);
5039 R_Mesh_ResetTextureState();
5040 R_SetupGenericShader(true);
5041 R_Mesh_TexBind(0, R_GetTexture(texture));
5042 R_Mesh_TexCoordPointer(0, 2, spritetexcoord2f, 0, 0);
5043 // FIXME: fixed function path can't properly handle r_refdef.view.colorscale > 1
5044 GL_Color(cr * fog * r_refdef.view.colorscale, cg * fog * r_refdef.view.colorscale, cb * fog * r_refdef.view.colorscale, ca);
5045 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
5047 if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
5049 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
5050 GL_BlendFunc(blendfunc1, GL_ONE);
5052 GL_Color(r_refdef.fogcolor[0] * fog, r_refdef.fogcolor[1] * fog, r_refdef.fogcolor[2] * fog, ca);
5053 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
5057 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
5062 VectorSet(v, x, y, z);
5063 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
5064 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
5066 if (i == mesh->numvertices)
5068 if (mesh->numvertices < mesh->maxvertices)
5070 VectorCopy(v, vertex3f);
5071 mesh->numvertices++;
5073 return mesh->numvertices;
5079 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
5083 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
5084 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
5085 e = mesh->element3i + mesh->numtriangles * 3;
5086 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
5088 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
5089 if (mesh->numtriangles < mesh->maxtriangles)
5094 mesh->numtriangles++;
5096 element[1] = element[2];
5100 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
5104 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
5105 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
5106 e = mesh->element3i + mesh->numtriangles * 3;
5107 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
5109 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
5110 if (mesh->numtriangles < mesh->maxtriangles)
5115 mesh->numtriangles++;
5117 element[1] = element[2];
5121 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
5122 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
5124 int planenum, planenum2;
5127 mplane_t *plane, *plane2;
5129 double temppoints[2][256*3];
5130 // figure out how large a bounding box we need to properly compute this brush
5132 for (w = 0;w < numplanes;w++)
5133 maxdist = max(maxdist, planes[w].dist);
5134 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
5135 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
5136 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
5140 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
5141 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
5143 if (planenum2 == planenum)
5145 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);
5148 if (tempnumpoints < 3)
5150 // generate elements forming a triangle fan for this polygon
5151 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
5155 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)
5157 texturelayer_t *layer;
5158 layer = t->currentlayers + t->currentnumlayers++;
5160 layer->depthmask = depthmask;
5161 layer->blendfunc1 = blendfunc1;
5162 layer->blendfunc2 = blendfunc2;
5163 layer->texture = texture;
5164 layer->texmatrix = *matrix;
5165 layer->color[0] = r * r_refdef.view.colorscale;
5166 layer->color[1] = g * r_refdef.view.colorscale;
5167 layer->color[2] = b * r_refdef.view.colorscale;
5168 layer->color[3] = a;
5171 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
5174 index = parms[2] + r_refdef.scene.time * parms[3];
5175 index -= floor(index);
5179 case Q3WAVEFUNC_NONE:
5180 case Q3WAVEFUNC_NOISE:
5181 case Q3WAVEFUNC_COUNT:
5184 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
5185 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
5186 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
5187 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
5188 case Q3WAVEFUNC_TRIANGLE:
5190 f = index - floor(index);
5201 return (float)(parms[0] + parms[1] * f);
5204 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
5209 matrix4x4_t matrix, temp;
5210 switch(tcmod->tcmod)
5214 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
5215 matrix = r_waterscrollmatrix;
5217 matrix = identitymatrix;
5219 case Q3TCMOD_ENTITYTRANSLATE:
5220 // this is used in Q3 to allow the gamecode to control texcoord
5221 // scrolling on the entity, which is not supported in darkplaces yet.
5222 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
5224 case Q3TCMOD_ROTATE:
5225 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
5226 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
5227 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
5230 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
5232 case Q3TCMOD_SCROLL:
5233 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
5235 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
5236 w = (int) tcmod->parms[0];
5237 h = (int) tcmod->parms[1];
5238 f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
5240 idx = (int) floor(f * w * h);
5241 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
5243 case Q3TCMOD_STRETCH:
5244 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
5245 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
5247 case Q3TCMOD_TRANSFORM:
5248 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
5249 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
5250 VectorSet(tcmat + 6, 0 , 0 , 1);
5251 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
5252 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
5254 case Q3TCMOD_TURBULENT:
5255 // this is handled in the RSurf_PrepareVertices function
5256 matrix = identitymatrix;
5260 Matrix4x4_Concat(texmatrix, &matrix, &temp);
5263 texture_t *R_GetCurrentTexture(texture_t *t)
5266 const entity_render_t *ent = rsurface.entity;
5267 dp_model_t *model = ent->model;
5268 q3shaderinfo_layer_tcmod_t *tcmod;
5270 if (t->update_lastrenderframe == r_frame && t->update_lastrenderentity == (void *)ent)
5271 return t->currentframe;
5272 t->update_lastrenderframe = r_frame;
5273 t->update_lastrenderentity = (void *)ent;
5275 // switch to an alternate material if this is a q1bsp animated material
5277 texture_t *texture = t;
5278 int s = ent->skinnum;
5279 if ((unsigned int)s >= (unsigned int)model->numskins)
5281 if (model->skinscenes)
5283 if (model->skinscenes[s].framecount > 1)
5284 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
5286 s = model->skinscenes[s].firstframe;
5289 t = t + s * model->num_surfaces;
5292 // use an alternate animation if the entity's frame is not 0,
5293 // and only if the texture has an alternate animation
5294 if (ent->framegroupblend[0].frame != 0 && t->anim_total[1])
5295 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
5297 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
5299 texture->currentframe = t;
5302 // update currentskinframe to be a qw skin or animation frame
5303 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"))
5305 if (strcmp(r_qwskincache[i], cl.scores[i].qw_skin))
5307 strlcpy(r_qwskincache[i], cl.scores[i].qw_skin, sizeof(r_qwskincache[i]));
5308 if (developer_loading.integer)
5309 Con_Printf("loading skins/%s\n", r_qwskincache[i]);
5310 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);
5312 t->currentskinframe = r_qwskincache_skinframe[i];
5313 if (t->currentskinframe == NULL)
5314 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->shadertime)) % t->numskinframes];
5316 else if (t->numskinframes >= 2)
5317 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->shadertime)) % t->numskinframes];
5318 if (t->backgroundnumskinframes >= 2)
5319 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - ent->shadertime)) % t->backgroundnumskinframes];
5321 t->currentmaterialflags = t->basematerialflags;
5322 t->currentalpha = ent->alpha;
5323 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
5324 t->currentalpha *= r_wateralpha.value;
5325 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
5326 t->currentalpha *= t->r_water_wateralpha;
5327 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
5328 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION);
5329 if (!(ent->flags & RENDER_LIGHT))
5330 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
5331 else if (rsurface.modeltexcoordlightmap2f == NULL)
5333 // pick a model lighting mode
5334 if (VectorLength2(ent->modellight_diffuse) >= (1.0f / 256.0f))
5335 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
5337 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
5339 if (ent->effects & EF_ADDITIVE)
5340 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
5341 else if (t->currentalpha < 1)
5342 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
5343 if (ent->effects & EF_DOUBLESIDED)
5344 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
5345 if (ent->effects & EF_NODEPTHTEST)
5346 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
5347 if (ent->flags & RENDER_VIEWMODEL)
5348 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
5349 if (t->backgroundnumskinframes)
5350 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
5351 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
5353 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER))
5354 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
5357 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER);
5359 // there is no tcmod
5360 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
5362 t->currenttexmatrix = r_waterscrollmatrix;
5363 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
5367 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
5368 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
5371 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
5372 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
5373 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
5374 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
5376 t->colormapping = VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f);
5377 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
5378 t->glosstexture = r_texture_black;
5379 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
5380 t->backgroundglosstexture = r_texture_black;
5381 t->specularpower = r_shadow_glossexponent.value;
5382 // TODO: store reference values for these in the texture?
5383 t->specularscale = 0;
5384 if (r_shadow_gloss.integer > 0)
5386 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
5388 if (r_shadow_glossintensity.value > 0)
5390 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
5391 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
5392 t->specularscale = r_shadow_glossintensity.value;
5395 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
5397 t->glosstexture = r_texture_white;
5398 t->backgroundglosstexture = r_texture_white;
5399 t->specularscale = r_shadow_gloss2intensity.value;
5403 // lightmaps mode looks bad with dlights using actual texturing, so turn
5404 // off the colormap and glossmap, but leave the normalmap on as it still
5405 // accurately represents the shading involved
5406 if (gl_lightmaps.integer)
5408 t->basetexture = r_texture_grey128;
5409 t->backgroundbasetexture = NULL;
5410 t->specularscale = 0;
5411 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
5414 Vector4Set(t->lightmapcolor, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
5415 VectorClear(t->dlightcolor);
5416 t->currentnumlayers = 0;
5417 if (t->currentmaterialflags & MATERIALFLAG_WALL)
5420 int blendfunc1, blendfunc2;
5422 if (t->currentmaterialflags & MATERIALFLAG_ADD)
5424 blendfunc1 = GL_SRC_ALPHA;
5425 blendfunc2 = GL_ONE;
5427 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
5429 blendfunc1 = GL_SRC_ALPHA;
5430 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
5432 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
5434 blendfunc1 = t->customblendfunc[0];
5435 blendfunc2 = t->customblendfunc[1];
5439 blendfunc1 = GL_ONE;
5440 blendfunc2 = GL_ZERO;
5442 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
5443 if (r_refdef.fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED))
5444 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
5445 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
5447 // fullbright is not affected by r_refdef.lightmapintensity
5448 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]);
5449 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
5450 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]);
5451 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
5452 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]);
5456 vec3_t ambientcolor;
5458 // set the color tint used for lights affecting this surface
5459 VectorSet(t->dlightcolor, ent->colormod[0] * t->lightmapcolor[3], ent->colormod[1] * t->lightmapcolor[3], ent->colormod[2] * t->lightmapcolor[3]);
5461 // q3bsp has no lightmap updates, so the lightstylevalue that
5462 // would normally be baked into the lightmap must be
5463 // applied to the color
5464 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
5465 if (ent->model->type == mod_brushq3)
5466 colorscale *= r_refdef.scene.rtlightstylevalue[0];
5467 colorscale *= r_refdef.lightmapintensity;
5468 VectorScale(t->lightmapcolor, r_refdef.scene.ambient * (1.0f / 64.0f), ambientcolor);
5469 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
5470 // basic lit geometry
5471 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]);
5472 // add pants/shirt if needed
5473 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
5474 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]);
5475 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
5476 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]);
5477 // now add ambient passes if needed
5478 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
5480 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]);
5481 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
5482 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]);
5483 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
5484 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]);
5487 if (t->currentskinframe->glow != NULL && !gl_lightmaps.integer)
5488 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]);
5489 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
5491 // if this is opaque use alpha blend which will darken the earlier
5494 // if this is an alpha blended material, all the earlier passes
5495 // were darkened by fog already, so we only need to add the fog
5496 // color ontop through the fog mask texture
5498 // if this is an additive blended material, all the earlier passes
5499 // were darkened by fog already, and we should not add fog color
5500 // (because the background was not darkened, there is no fog color
5501 // that was lost behind it).
5502 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]);
5506 return t->currentframe;
5509 rsurfacestate_t rsurface;
5511 void R_Mesh_ResizeArrays(int newvertices)
5514 if (rsurface.array_size >= newvertices)
5516 if (rsurface.array_modelvertex3f)
5517 Mem_Free(rsurface.array_modelvertex3f);
5518 rsurface.array_size = (newvertices + 1023) & ~1023;
5519 base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
5520 rsurface.array_modelvertex3f = base + rsurface.array_size * 0;
5521 rsurface.array_modelsvector3f = base + rsurface.array_size * 3;
5522 rsurface.array_modeltvector3f = base + rsurface.array_size * 6;
5523 rsurface.array_modelnormal3f = base + rsurface.array_size * 9;
5524 rsurface.array_deformedvertex3f = base + rsurface.array_size * 12;
5525 rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
5526 rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
5527 rsurface.array_deformednormal3f = base + rsurface.array_size * 21;
5528 rsurface.array_texcoord3f = base + rsurface.array_size * 24;
5529 rsurface.array_color4f = base + rsurface.array_size * 27;
5530 rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
5533 void RSurf_ActiveWorldEntity(void)
5535 dp_model_t *model = r_refdef.scene.worldmodel;
5536 //if (rsurface.entity == r_refdef.scene.worldentity)
5538 rsurface.entity = r_refdef.scene.worldentity;
5539 if (rsurface.array_size < model->surfmesh.num_vertices)
5540 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
5541 rsurface.matrix = identitymatrix;
5542 rsurface.inversematrix = identitymatrix;
5543 R_Mesh_Matrix(&identitymatrix);
5544 VectorCopy(r_refdef.view.origin, rsurface.modelorg);
5545 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
5546 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
5547 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
5548 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
5549 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
5550 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
5551 rsurface.frameblend[0].lerp = 1;
5552 rsurface.basepolygonfactor = r_refdef.polygonfactor;
5553 rsurface.basepolygonoffset = r_refdef.polygonoffset;
5554 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
5555 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
5556 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
5557 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
5558 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
5559 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
5560 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
5561 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
5562 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
5563 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
5564 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
5565 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
5566 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
5567 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
5568 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
5569 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
5570 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
5571 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
5572 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
5573 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
5574 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
5575 rsurface.modelelement3i = model->surfmesh.data_element3i;
5576 rsurface.modelelement3s = model->surfmesh.data_element3s;
5577 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
5578 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
5579 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
5580 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
5581 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
5582 rsurface.modelsurfaces = model->data_surfaces;
5583 rsurface.generatedvertex = false;
5584 rsurface.vertex3f = rsurface.modelvertex3f;
5585 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
5586 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
5587 rsurface.svector3f = rsurface.modelsvector3f;
5588 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
5589 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
5590 rsurface.tvector3f = rsurface.modeltvector3f;
5591 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
5592 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
5593 rsurface.normal3f = rsurface.modelnormal3f;
5594 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
5595 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
5596 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
5599 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
5601 dp_model_t *model = ent->model;
5602 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
5604 rsurface.entity = (entity_render_t *)ent;
5605 if (rsurface.array_size < model->surfmesh.num_vertices)
5606 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
5607 rsurface.matrix = ent->matrix;
5608 rsurface.inversematrix = ent->inversematrix;
5609 R_Mesh_Matrix(&rsurface.matrix);
5610 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.modelorg);
5611 rsurface.modellight_ambient[0] = ent->modellight_ambient[0] * ent->colormod[0];
5612 rsurface.modellight_ambient[1] = ent->modellight_ambient[1] * ent->colormod[1];
5613 rsurface.modellight_ambient[2] = ent->modellight_ambient[2] * ent->colormod[2];
5614 rsurface.modellight_diffuse[0] = ent->modellight_diffuse[0] * ent->colormod[0];
5615 rsurface.modellight_diffuse[1] = ent->modellight_diffuse[1] * ent->colormod[1];
5616 rsurface.modellight_diffuse[2] = ent->modellight_diffuse[2] * ent->colormod[2];
5617 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
5618 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
5619 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
5620 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
5621 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
5622 rsurface.basepolygonfactor = r_refdef.polygonfactor;
5623 rsurface.basepolygonoffset = r_refdef.polygonoffset;
5624 if (ent->model->brush.submodel)
5626 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
5627 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
5629 if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
5631 if (R_AnimCache_GetEntity((entity_render_t *)ent, wantnormals, wanttangents))
5633 rsurface.modelvertex3f = r_animcachestate.entity[ent->animcacheindex].vertex3f;
5634 rsurface.modelsvector3f = wanttangents ? r_animcachestate.entity[ent->animcacheindex].svector3f : NULL;
5635 rsurface.modeltvector3f = wanttangents ? r_animcachestate.entity[ent->animcacheindex].tvector3f : NULL;
5636 rsurface.modelnormal3f = wantnormals ? r_animcachestate.entity[ent->animcacheindex].normal3f : NULL;
5638 else if (wanttangents)
5640 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
5641 rsurface.modelsvector3f = rsurface.array_modelsvector3f;
5642 rsurface.modeltvector3f = rsurface.array_modeltvector3f;
5643 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
5644 model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
5646 else if (wantnormals)
5648 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
5649 rsurface.modelsvector3f = NULL;
5650 rsurface.modeltvector3f = NULL;
5651 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
5652 model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
5656 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
5657 rsurface.modelsvector3f = NULL;
5658 rsurface.modeltvector3f = NULL;
5659 rsurface.modelnormal3f = NULL;
5660 model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, NULL, NULL, NULL);
5662 rsurface.modelvertex3f_bufferobject = 0;
5663 rsurface.modelvertex3f_bufferoffset = 0;
5664 rsurface.modelsvector3f_bufferobject = 0;
5665 rsurface.modelsvector3f_bufferoffset = 0;
5666 rsurface.modeltvector3f_bufferobject = 0;
5667 rsurface.modeltvector3f_bufferoffset = 0;
5668 rsurface.modelnormal3f_bufferobject = 0;
5669 rsurface.modelnormal3f_bufferoffset = 0;
5670 rsurface.generatedvertex = true;
5674 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
5675 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
5676 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
5677 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
5678 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
5679 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
5680 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
5681 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
5682 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
5683 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
5684 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
5685 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
5686 rsurface.generatedvertex = false;
5688 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
5689 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
5690 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
5691 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
5692 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
5693 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
5694 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
5695 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
5696 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
5697 rsurface.modelelement3i = model->surfmesh.data_element3i;
5698 rsurface.modelelement3s = model->surfmesh.data_element3s;
5699 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
5700 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
5701 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
5702 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
5703 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
5704 rsurface.modelsurfaces = model->data_surfaces;
5705 rsurface.vertex3f = rsurface.modelvertex3f;
5706 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
5707 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
5708 rsurface.svector3f = rsurface.modelsvector3f;
5709 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
5710 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
5711 rsurface.tvector3f = rsurface.modeltvector3f;
5712 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
5713 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
5714 rsurface.normal3f = rsurface.modelnormal3f;
5715 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
5716 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
5717 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
5720 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
5721 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, msurface_t **texturesurfacelist)
5724 int texturesurfaceindex;
5729 const float *v1, *in_tc;
5731 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
5733 q3shaderinfo_deform_t *deform;
5734 // 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
5735 if (rsurface.generatedvertex)
5737 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
5738 generatenormals = true;
5739 for (i = 0;i < Q3MAXDEFORMS;i++)
5741 if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
5743 generatetangents = true;
5744 generatenormals = true;
5746 if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
5747 generatenormals = true;
5749 if (generatenormals && !rsurface.modelnormal3f)
5751 rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
5752 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
5753 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
5754 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
5756 if (generatetangents && !rsurface.modelsvector3f)
5758 rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
5759 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
5760 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
5761 rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
5762 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
5763 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
5764 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);
5767 rsurface.vertex3f = rsurface.modelvertex3f;
5768 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
5769 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
5770 rsurface.svector3f = rsurface.modelsvector3f;
5771 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
5772 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
5773 rsurface.tvector3f = rsurface.modeltvector3f;
5774 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
5775 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
5776 rsurface.normal3f = rsurface.modelnormal3f;
5777 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
5778 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
5779 // if vertices are deformed (sprite flares and things in maps, possibly
5780 // water waves, bulges and other deformations), generate them into
5781 // rsurface.deform* arrays from whatever the rsurface.* arrays point to
5782 // (may be static model data or generated data for an animated model, or
5783 // the previous deform pass)
5784 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
5786 switch (deform->deform)
5789 case Q3DEFORM_PROJECTIONSHADOW:
5790 case Q3DEFORM_TEXT0:
5791 case Q3DEFORM_TEXT1:
5792 case Q3DEFORM_TEXT2:
5793 case Q3DEFORM_TEXT3:
5794 case Q3DEFORM_TEXT4:
5795 case Q3DEFORM_TEXT5:
5796 case Q3DEFORM_TEXT6:
5797 case Q3DEFORM_TEXT7:
5800 case Q3DEFORM_AUTOSPRITE:
5801 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
5802 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
5803 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
5804 VectorNormalize(newforward);
5805 VectorNormalize(newright);
5806 VectorNormalize(newup);
5807 // make deformed versions of only the model vertices used by the specified surfaces
5808 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5810 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5811 // a single autosprite surface can contain multiple sprites...
5812 for (j = 0;j < surface->num_vertices - 3;j += 4)
5814 VectorClear(center);
5815 for (i = 0;i < 4;i++)
5816 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
5817 VectorScale(center, 0.25f, center);
5818 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, forward);
5819 VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
5820 VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
5821 for (i = 0;i < 4;i++)
5823 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
5824 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
5827 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);
5828 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);
5830 rsurface.vertex3f = rsurface.array_deformedvertex3f;
5831 rsurface.vertex3f_bufferobject = 0;
5832 rsurface.vertex3f_bufferoffset = 0;
5833 rsurface.svector3f = rsurface.array_deformedsvector3f;
5834 rsurface.svector3f_bufferobject = 0;
5835 rsurface.svector3f_bufferoffset = 0;
5836 rsurface.tvector3f = rsurface.array_deformedtvector3f;
5837 rsurface.tvector3f_bufferobject = 0;
5838 rsurface.tvector3f_bufferoffset = 0;
5839 rsurface.normal3f = rsurface.array_deformednormal3f;
5840 rsurface.normal3f_bufferobject = 0;
5841 rsurface.normal3f_bufferoffset = 0;
5843 case Q3DEFORM_AUTOSPRITE2:
5844 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
5845 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
5846 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
5847 VectorNormalize(newforward);
5848 VectorNormalize(newright);
5849 VectorNormalize(newup);
5850 // make deformed versions of only the model vertices used by the specified surfaces
5851 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5853 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5854 const float *v1, *v2;
5864 memset(shortest, 0, sizeof(shortest));
5865 // a single autosprite surface can contain multiple sprites...
5866 for (j = 0;j < surface->num_vertices - 3;j += 4)
5868 VectorClear(center);
5869 for (i = 0;i < 4;i++)
5870 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
5871 VectorScale(center, 0.25f, center);
5872 // find the two shortest edges, then use them to define the
5873 // axis vectors for rotating around the central axis
5874 for (i = 0;i < 6;i++)
5876 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
5877 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
5879 Debug_PolygonBegin(NULL, 0);
5880 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
5881 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);
5882 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
5885 l = VectorDistance2(v1, v2);
5886 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
5888 l += (1.0f / 1024.0f);
5889 if (shortest[0].length2 > l || i == 0)
5891 shortest[1] = shortest[0];
5892 shortest[0].length2 = l;
5893 shortest[0].v1 = v1;
5894 shortest[0].v2 = v2;
5896 else if (shortest[1].length2 > l || i == 1)
5898 shortest[1].length2 = l;
5899 shortest[1].v1 = v1;
5900 shortest[1].v2 = v2;
5903 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
5904 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
5906 Debug_PolygonBegin(NULL, 0);
5907 Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
5908 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);
5909 Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
5912 // this calculates the right vector from the shortest edge
5913 // and the up vector from the edge midpoints
5914 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
5915 VectorNormalize(right);
5916 VectorSubtract(end, start, up);
5917 VectorNormalize(up);
5918 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
5919 VectorSubtract(rsurface.modelorg, center, forward);
5920 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
5921 VectorNegate(forward, forward);
5922 VectorReflect(forward, 0, up, forward);
5923 VectorNormalize(forward);
5924 CrossProduct(up, forward, newright);
5925 VectorNormalize(newright);
5927 Debug_PolygonBegin(NULL, 0);
5928 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);
5929 Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
5930 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
5934 Debug_PolygonBegin(NULL, 0);
5935 Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
5936 Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
5937 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
5940 // rotate the quad around the up axis vector, this is made
5941 // especially easy by the fact we know the quad is flat,
5942 // so we only have to subtract the center position and
5943 // measure distance along the right vector, and then
5944 // multiply that by the newright vector and add back the
5946 // we also need to subtract the old position to undo the
5947 // displacement from the center, which we do with a
5948 // DotProduct, the subtraction/addition of center is also
5949 // optimized into DotProducts here
5950 l = DotProduct(right, center);
5951 for (i = 0;i < 4;i++)
5953 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
5954 f = DotProduct(right, v1) - l;
5955 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
5958 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);
5959 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);
5961 rsurface.vertex3f = rsurface.array_deformedvertex3f;
5962 rsurface.vertex3f_bufferobject = 0;
5963 rsurface.vertex3f_bufferoffset = 0;
5964 rsurface.svector3f = rsurface.array_deformedsvector3f;
5965 rsurface.svector3f_bufferobject = 0;
5966 rsurface.svector3f_bufferoffset = 0;
5967 rsurface.tvector3f = rsurface.array_deformedtvector3f;
5968 rsurface.tvector3f_bufferobject = 0;
5969 rsurface.tvector3f_bufferoffset = 0;
5970 rsurface.normal3f = rsurface.array_deformednormal3f;
5971 rsurface.normal3f_bufferobject = 0;
5972 rsurface.normal3f_bufferoffset = 0;
5974 case Q3DEFORM_NORMAL:
5975 // deform the normals to make reflections wavey
5976 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5978 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5979 for (j = 0;j < surface->num_vertices;j++)
5982 float *normal = (rsurface.array_deformednormal3f + 3 * surface->num_firstvertex) + j*3;
5983 VectorScale((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
5984 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, normal);
5985 normal[0] += deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
5986 normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
5987 normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
5988 VectorNormalize(normal);
5990 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);
5992 rsurface.svector3f = rsurface.array_deformedsvector3f;
5993 rsurface.svector3f_bufferobject = 0;
5994 rsurface.svector3f_bufferoffset = 0;
5995 rsurface.tvector3f = rsurface.array_deformedtvector3f;
5996 rsurface.tvector3f_bufferobject = 0;
5997 rsurface.tvector3f_bufferoffset = 0;
5998 rsurface.normal3f = rsurface.array_deformednormal3f;
5999 rsurface.normal3f_bufferobject = 0;
6000 rsurface.normal3f_bufferoffset = 0;
6003 // deform vertex array to make wavey water and flags and such
6004 waveparms[0] = deform->waveparms[0];
6005 waveparms[1] = deform->waveparms[1];
6006 waveparms[2] = deform->waveparms[2];
6007 waveparms[3] = deform->waveparms[3];
6008 // this is how a divisor of vertex influence on deformation
6009 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
6010 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
6011 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6013 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6014 for (j = 0;j < surface->num_vertices;j++)
6016 float *vertex = (rsurface.array_deformedvertex3f + 3 * surface->num_firstvertex) + j*3;
6017 VectorCopy((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, vertex);
6018 // if the wavefunc depends on time, evaluate it per-vertex
6021 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
6022 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
6024 VectorMA(vertex, scale, (rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, vertex);
6027 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6028 rsurface.vertex3f_bufferobject = 0;
6029 rsurface.vertex3f_bufferoffset = 0;
6031 case Q3DEFORM_BULGE:
6032 // deform vertex array to make the surface have moving bulges
6033 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6035 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6036 for (j = 0;j < surface->num_vertices;j++)
6038 scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.scene.time * deform->parms[2])) * deform->parms[1];
6039 VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
6042 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6043 rsurface.vertex3f_bufferobject = 0;
6044 rsurface.vertex3f_bufferoffset = 0;
6047 // deform vertex array
6048 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
6049 VectorScale(deform->parms, scale, waveparms);
6050 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6052 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6053 for (j = 0;j < surface->num_vertices;j++)
6054 VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
6056 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6057 rsurface.vertex3f_bufferobject = 0;
6058 rsurface.vertex3f_bufferoffset = 0;
6062 // generate texcoords based on the chosen texcoord source
6063 switch(rsurface.texture->tcgen.tcgen)
6066 case Q3TCGEN_TEXTURE:
6067 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
6068 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordtexture2f_bufferobject;
6069 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
6071 case Q3TCGEN_LIGHTMAP:
6072 rsurface.texcoordtexture2f = rsurface.modeltexcoordlightmap2f;
6073 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
6074 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
6076 case Q3TCGEN_VECTOR:
6077 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6079 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6080 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)
6082 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
6083 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
6086 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
6087 rsurface.texcoordtexture2f_bufferobject = 0;
6088 rsurface.texcoordtexture2f_bufferoffset = 0;
6090 case Q3TCGEN_ENVIRONMENT:
6091 // make environment reflections using a spheremap
6092 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6094 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6095 const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
6096 const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
6097 float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
6098 for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
6100 // identical to Q3A's method, but executed in worldspace so
6101 // carried models can be shiny too
6103 float viewer[3], d, reflected[3], worldreflected[3];
6105 VectorSubtract(rsurface.modelorg, vertex, viewer);
6106 // VectorNormalize(viewer);
6108 d = DotProduct(normal, viewer);
6110 reflected[0] = normal[0]*2*d - viewer[0];
6111 reflected[1] = normal[1]*2*d - viewer[1];
6112 reflected[2] = normal[2]*2*d - viewer[2];
6113 // note: this is proportinal to viewer, so we can normalize later
6115 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
6116 VectorNormalize(worldreflected);
6118 // note: this sphere map only uses world x and z!
6119 // so positive and negative y will LOOK THE SAME.
6120 out_tc[0] = 0.5 + 0.5 * worldreflected[1];
6121 out_tc[1] = 0.5 - 0.5 * worldreflected[2];
6124 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
6125 rsurface.texcoordtexture2f_bufferobject = 0;
6126 rsurface.texcoordtexture2f_bufferoffset = 0;
6129 // the only tcmod that needs software vertex processing is turbulent, so
6130 // check for it here and apply the changes if needed
6131 // and we only support that as the first one
6132 // (handling a mixture of turbulent and other tcmods would be problematic
6133 // without punting it entirely to a software path)
6134 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
6136 amplitude = rsurface.texture->tcmods[0].parms[1];
6137 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
6138 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6140 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6141 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)
6143 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
6144 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
6147 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
6148 rsurface.texcoordtexture2f_bufferobject = 0;
6149 rsurface.texcoordtexture2f_bufferoffset = 0;
6151 rsurface.texcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
6152 rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
6153 rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
6154 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
6157 void RSurf_DrawBatch_Simple(int texturenumsurfaces, msurface_t **texturesurfacelist)
6160 const msurface_t *surface = texturesurfacelist[0];
6161 const msurface_t *surface2;
6166 // TODO: lock all array ranges before render, rather than on each surface
6167 if (texturenumsurfaces == 1)
6169 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6170 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 else if (r_batchmode.integer == 2)
6174 #define MAXBATCHTRIANGLES 4096
6175 int batchtriangles = 0;
6176 int batchelements[MAXBATCHTRIANGLES*3];
6177 for (i = 0;i < texturenumsurfaces;i = j)
6179 surface = texturesurfacelist[i];
6181 if (surface->num_triangles > MAXBATCHTRIANGLES)
6183 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);
6186 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
6187 batchtriangles = surface->num_triangles;
6188 firstvertex = surface->num_firstvertex;
6189 endvertex = surface->num_firstvertex + surface->num_vertices;
6190 for (;j < texturenumsurfaces;j++)
6192 surface2 = texturesurfacelist[j];
6193 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
6195 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
6196 batchtriangles += surface2->num_triangles;
6197 firstvertex = min(firstvertex, surface2->num_firstvertex);
6198 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
6200 surface2 = texturesurfacelist[j-1];
6201 numvertices = endvertex - firstvertex;
6202 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
6205 else if (r_batchmode.integer == 1)
6207 for (i = 0;i < texturenumsurfaces;i = j)
6209 surface = texturesurfacelist[i];
6210 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
6211 if (texturesurfacelist[j] != surface2)
6213 surface2 = texturesurfacelist[j-1];
6214 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
6215 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
6216 GL_LockArrays(surface->num_firstvertex, numvertices);
6217 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
6222 for (i = 0;i < texturenumsurfaces;i++)
6224 surface = texturesurfacelist[i];
6225 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6226 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);
6231 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit, int refractiontexunit, int reflectiontexunit)
6233 int i, planeindex, vertexindex;
6237 r_waterstate_waterplane_t *p, *bestp;
6238 msurface_t *surface;
6239 if (r_waterstate.renderingscene)
6241 for (i = 0;i < texturenumsurfaces;i++)
6243 surface = texturesurfacelist[i];
6244 if (lightmaptexunit >= 0)
6245 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6246 if (deluxemaptexunit >= 0)
6247 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6248 // pick the closest matching water plane
6251 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
6254 for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
6256 Matrix4x4_Transform(&rsurface.matrix, v, vert);
6257 d += fabs(PlaneDiff(vert, &p->plane));
6259 if (bestd > d || !bestp)
6267 if (refractiontexunit >= 0)
6268 R_Mesh_TexBind(refractiontexunit, R_GetTexture(bestp->texture_refraction));
6269 if (reflectiontexunit >= 0)
6270 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(bestp->texture_reflection));
6274 if (refractiontexunit >= 0)
6275 R_Mesh_TexBind(refractiontexunit, R_GetTexture(r_texture_black));
6276 if (reflectiontexunit >= 0)
6277 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(r_texture_black));
6279 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6280 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);
6284 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit)
6288 const msurface_t *surface = texturesurfacelist[0];
6289 const msurface_t *surface2;
6294 // TODO: lock all array ranges before render, rather than on each surface
6295 if (texturenumsurfaces == 1)
6297 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6298 if (deluxemaptexunit >= 0)
6299 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6300 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6301 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);
6303 else if (r_batchmode.integer == 2)
6305 #define MAXBATCHTRIANGLES 4096
6306 int batchtriangles = 0;
6307 int batchelements[MAXBATCHTRIANGLES*3];
6308 for (i = 0;i < texturenumsurfaces;i = j)
6310 surface = texturesurfacelist[i];
6311 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6312 if (deluxemaptexunit >= 0)
6313 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6315 if (surface->num_triangles > MAXBATCHTRIANGLES)
6317 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);
6320 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
6321 batchtriangles = surface->num_triangles;
6322 firstvertex = surface->num_firstvertex;
6323 endvertex = surface->num_firstvertex + surface->num_vertices;
6324 for (;j < texturenumsurfaces;j++)
6326 surface2 = texturesurfacelist[j];
6327 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
6329 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
6330 batchtriangles += surface2->num_triangles;
6331 firstvertex = min(firstvertex, surface2->num_firstvertex);
6332 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
6334 surface2 = texturesurfacelist[j-1];
6335 numvertices = endvertex - firstvertex;
6336 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
6339 else if (r_batchmode.integer == 1)
6342 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
6343 for (i = 0;i < texturenumsurfaces;i = j)
6345 surface = texturesurfacelist[i];
6346 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
6347 if (texturesurfacelist[j] != surface2)
6349 Con_Printf(" %i", j - i);
6352 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
6354 for (i = 0;i < texturenumsurfaces;i = j)
6356 surface = texturesurfacelist[i];
6357 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6358 if (deluxemaptexunit >= 0)
6359 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6360 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
6361 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
6364 Con_Printf(" %i", j - i);
6366 surface2 = texturesurfacelist[j-1];
6367 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
6368 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
6369 GL_LockArrays(surface->num_firstvertex, numvertices);
6370 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
6378 for (i = 0;i < texturenumsurfaces;i++)
6380 surface = texturesurfacelist[i];
6381 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6382 if (deluxemaptexunit >= 0)
6383 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6384 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6385 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);
6390 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
6393 int texturesurfaceindex;
6394 if (r_showsurfaces.integer == 2)
6396 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6398 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6399 for (j = 0;j < surface->num_triangles;j++)
6401 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_refdef.view.colorscale;
6402 GL_Color(f, f, f, 1);
6403 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle + j, 1, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
6409 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6411 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6412 int k = (int)(((size_t)surface) / sizeof(msurface_t));
6413 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);
6414 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6415 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);
6420 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(int texturenumsurfaces, msurface_t **texturesurfacelist)
6422 int texturesurfaceindex;
6425 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6427 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6428 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)
6436 rsurface.lightmapcolor4f = rsurface.array_color4f;
6437 rsurface.lightmapcolor4f_bufferobject = 0;
6438 rsurface.lightmapcolor4f_bufferoffset = 0;
6441 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, msurface_t **texturesurfacelist)
6443 int texturesurfaceindex;
6447 if (rsurface.lightmapcolor4f)
6449 // generate color arrays for the surfaces in this list
6450 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6452 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6453 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)
6455 f = FogPoint_Model(v);
6465 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6467 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6468 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)
6470 f = FogPoint_Model(v);
6478 rsurface.lightmapcolor4f = rsurface.array_color4f;
6479 rsurface.lightmapcolor4f_bufferobject = 0;
6480 rsurface.lightmapcolor4f_bufferoffset = 0;
6483 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(int texturenumsurfaces, msurface_t **texturesurfacelist)
6485 int texturesurfaceindex;
6489 if (!rsurface.lightmapcolor4f)
6491 // generate color arrays for the surfaces in this list
6492 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6494 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6495 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)
6497 f = FogPoint_Model(v);
6498 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
6499 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
6500 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
6504 rsurface.lightmapcolor4f = rsurface.array_color4f;
6505 rsurface.lightmapcolor4f_bufferobject = 0;
6506 rsurface.lightmapcolor4f_bufferoffset = 0;
6509 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a)
6511 int texturesurfaceindex;
6514 if (!rsurface.lightmapcolor4f)
6516 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6518 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6519 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)
6527 rsurface.lightmapcolor4f = rsurface.array_color4f;
6528 rsurface.lightmapcolor4f_bufferobject = 0;
6529 rsurface.lightmapcolor4f_bufferoffset = 0;
6532 static void RSurf_DrawBatch_GL11_ApplyAmbient(int texturenumsurfaces, msurface_t **texturesurfacelist)
6534 int texturesurfaceindex;
6537 if (!rsurface.lightmapcolor4f)
6539 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6541 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6542 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)
6544 c2[0] = c[0] + r_refdef.scene.ambient / 128.0;
6545 c2[1] = c[1] + r_refdef.scene.ambient / 128.0;
6546 c2[2] = c[2] + r_refdef.scene.ambient / 128.0;
6550 rsurface.lightmapcolor4f = rsurface.array_color4f;
6551 rsurface.lightmapcolor4f_bufferobject = 0;
6552 rsurface.lightmapcolor4f_bufferoffset = 0;
6555 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
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_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 0, -1);
6568 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
6570 // TODO: optimize applyfog && applycolor case
6571 // just apply fog if necessary, and tint the fog color array if necessary
6572 rsurface.lightmapcolor4f = NULL;
6573 rsurface.lightmapcolor4f_bufferobject = 0;
6574 rsurface.lightmapcolor4f_bufferoffset = 0;
6575 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
6576 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
6577 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
6578 GL_Color(r, g, b, a);
6579 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6582 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
6584 int texturesurfaceindex;
6588 if (texturesurfacelist[0]->lightmapinfo)
6590 // generate color arrays for the surfaces in this list
6591 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6593 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6594 for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
6596 if (surface->lightmapinfo->samples)
6598 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
6599 float scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
6600 VectorScale(lm, scale, c);
6601 if (surface->lightmapinfo->styles[1] != 255)
6603 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
6605 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
6606 VectorMA(c, scale, lm, c);
6607 if (surface->lightmapinfo->styles[2] != 255)
6610 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
6611 VectorMA(c, scale, lm, c);
6612 if (surface->lightmapinfo->styles[3] != 255)
6615 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
6616 VectorMA(c, scale, lm, c);
6626 rsurface.lightmapcolor4f = rsurface.array_color4f;
6627 rsurface.lightmapcolor4f_bufferobject = 0;
6628 rsurface.lightmapcolor4f_bufferoffset = 0;
6632 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
6633 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
6634 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
6636 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
6637 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
6638 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
6639 GL_Color(r, g, b, a);
6640 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6643 static void RSurf_DrawBatch_GL11_ApplyVertexShade(int texturenumsurfaces, msurface_t **texturesurfacelist, float *r, float *g, float *b, float *a, qboolean *applycolor)
6645 int texturesurfaceindex;
6648 float *v, *c, *c2, alpha;
6649 vec3_t ambientcolor;
6650 vec3_t diffusecolor;
6654 VectorCopy(rsurface.modellight_lightdir, lightdir);
6655 f = 0.5f * r_refdef.lightmapintensity;
6656 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
6657 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
6658 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
6659 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
6660 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
6661 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
6663 if (VectorLength2(diffusecolor) > 0 && rsurface.normal3f)
6665 // generate color arrays for the surfaces in this list
6666 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6668 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6669 int numverts = surface->num_vertices;
6670 v = rsurface.vertex3f + 3 * surface->num_firstvertex;
6671 c2 = rsurface.normal3f + 3 * surface->num_firstvertex;
6672 c = rsurface.array_color4f + 4 * surface->num_firstvertex;
6673 // q3-style directional shading
6674 for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
6676 if ((f = DotProduct(c2, lightdir)) > 0)
6677 VectorMA(ambientcolor, f, diffusecolor, c);
6679 VectorCopy(ambientcolor, c);
6687 rsurface.lightmapcolor4f = rsurface.array_color4f;
6688 rsurface.lightmapcolor4f_bufferobject = 0;
6689 rsurface.lightmapcolor4f_bufferoffset = 0;
6690 *applycolor = false;
6694 *r = ambientcolor[0];
6695 *g = ambientcolor[1];
6696 *b = ambientcolor[2];
6697 rsurface.lightmapcolor4f = NULL;
6698 rsurface.lightmapcolor4f_bufferobject = 0;
6699 rsurface.lightmapcolor4f_bufferoffset = 0;
6703 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
6705 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &r, &g, &b, &a, &applycolor);
6706 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
6707 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
6708 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
6709 GL_Color(r, g, b, a);
6710 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6713 void RSurf_SetupDepthAndCulling(void)
6715 // submodels are biased to avoid z-fighting with world surfaces that they
6716 // may be exactly overlapping (avoids z-fighting artifacts on certain
6717 // doors and things in Quake maps)
6718 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
6719 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
6720 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
6721 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
6724 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, msurface_t **texturesurfacelist)
6726 // transparent sky would be ridiculous
6727 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
6729 R_SetupGenericShader(false);
6732 skyrendernow = false;
6733 // we have to force off the water clipping plane while rendering sky
6737 // restore entity matrix
6738 R_Mesh_Matrix(&rsurface.matrix);
6740 RSurf_SetupDepthAndCulling();
6742 // LordHavoc: HalfLife maps have freaky skypolys so don't use
6743 // skymasking on them, and Quake3 never did sky masking (unlike
6744 // software Quake and software Quake2), so disable the sky masking
6745 // in Quake3 maps as it causes problems with q3map2 sky tricks,
6746 // and skymasking also looks very bad when noclipping outside the
6747 // level, so don't use it then either.
6748 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
6750 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
6751 R_Mesh_ColorPointer(NULL, 0, 0);
6752 R_Mesh_ResetTextureState();
6753 if (skyrendermasked)
6755 R_SetupDepthOrShadowShader();
6756 // depth-only (masking)
6757 GL_ColorMask(0,0,0,0);
6758 // just to make sure that braindead drivers don't draw
6759 // anything despite that colormask...
6760 GL_BlendFunc(GL_ZERO, GL_ONE);
6764 R_SetupGenericShader(false);
6766 GL_BlendFunc(GL_ONE, GL_ZERO);
6768 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6769 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6770 if (skyrendermasked)
6771 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
6773 R_Mesh_ResetTextureState();
6774 GL_Color(1, 1, 1, 1);
6777 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6779 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION)))
6782 R_Mesh_TexMatrix(0, &rsurface.texture->currenttexmatrix);
6783 R_Mesh_TexMatrix(1, &rsurface.texture->currentbackgroundtexmatrix);
6784 R_Mesh_TexBind(GL20TU_NORMAL, R_GetTexture(rsurface.texture->currentskinframe->nmap));
6785 R_Mesh_TexBind(GL20TU_COLOR, R_GetTexture(rsurface.texture->basetexture));
6786 R_Mesh_TexBind(GL20TU_GLOSS, R_GetTexture(rsurface.texture->glosstexture));
6787 R_Mesh_TexBind(GL20TU_GLOW, R_GetTexture(rsurface.texture->currentskinframe->glow));
6788 if (rsurface.texture->backgroundcurrentskinframe)
6790 R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->nmap));
6791 R_Mesh_TexBind(GL20TU_SECONDARY_COLOR, R_GetTexture(rsurface.texture->backgroundbasetexture));
6792 R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS, R_GetTexture(rsurface.texture->backgroundglosstexture));
6793 R_Mesh_TexBind(GL20TU_SECONDARY_GLOW, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->glow));
6795 if(rsurface.texture->colormapping)
6797 R_Mesh_TexBind(GL20TU_PANTS, R_GetTexture(rsurface.texture->currentskinframe->pants));
6798 R_Mesh_TexBind(GL20TU_SHIRT, R_GetTexture(rsurface.texture->currentskinframe->shirt));
6800 R_Mesh_TexBind(GL20TU_FOGMASK, R_GetTexture(r_texture_fogattenuation));
6801 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
6802 R_Mesh_ColorPointer(NULL, 0, 0);
6804 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
6806 if (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6808 // render background
6809 GL_BlendFunc(GL_ONE, GL_ZERO);
6811 GL_AlphaTest(false);
6813 GL_Color(1, 1, 1, 1);
6814 R_Mesh_ColorPointer(NULL, 0, 0);
6816 R_SetupSurfaceShader(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
6817 if (r_glsl_permutation)
6819 RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
6820 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
6821 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
6822 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
6823 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
6824 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
6825 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);
6827 GL_LockArrays(0, 0);
6829 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
6830 GL_DepthMask(false);
6831 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
6832 R_Mesh_ColorPointer(NULL, 0, 0);
6834 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
6835 R_Mesh_TexBind(GL20TU_REFRACTION, R_GetTexture(r_texture_white)); // changed per surface
6836 R_Mesh_TexBind(GL20TU_REFLECTION, R_GetTexture(r_texture_white)); // changed per surface
6839 R_SetupSurfaceShader(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE);
6840 if (!r_glsl_permutation)
6843 RSurf_PrepareVerticesForBatch(r_glsl_permutation->loc_Texture_Normal >= 0 || r_glsl_permutation->loc_LightDir >= 0, r_glsl_permutation->loc_Texture_Normal >= 0, texturenumsurfaces, texturesurfacelist);
6844 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
6845 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
6846 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
6847 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
6848 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
6850 if (r_glsl_permutation->loc_Texture_Refraction >= 0)
6852 GL_BlendFunc(GL_ONE, GL_ZERO);
6854 GL_AlphaTest(false);
6858 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
6859 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
6860 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
6863 if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
6865 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
6866 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);
6868 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, GL20TU_LIGHTMAP, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? GL20TU_DELUXEMAP : -1);
6872 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
6873 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);
6875 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6877 GL_LockArrays(0, 0);
6880 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6882 // OpenGL 1.3 path - anything not completely ancient
6883 int texturesurfaceindex;
6884 qboolean applycolor;
6888 const texturelayer_t *layer;
6889 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
6891 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
6894 int layertexrgbscale;
6895 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
6897 if (layerindex == 0)
6901 GL_AlphaTest(false);
6902 qglDepthFunc(GL_EQUAL);CHECKGLERROR
6905 GL_DepthMask(layer->depthmask && writedepth);
6906 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
6907 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
6909 layertexrgbscale = 4;
6910 VectorScale(layer->color, 0.25f, layercolor);
6912 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
6914 layertexrgbscale = 2;
6915 VectorScale(layer->color, 0.5f, layercolor);
6919 layertexrgbscale = 1;
6920 VectorScale(layer->color, 1.0f, layercolor);
6922 layercolor[3] = layer->color[3];
6923 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
6924 R_Mesh_ColorPointer(NULL, 0, 0);
6925 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
6926 switch (layer->type)
6928 case TEXTURELAYERTYPE_LITTEXTURE:
6929 memset(&m, 0, sizeof(m));
6930 m.tex[0] = R_GetTexture(r_texture_white);
6931 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
6932 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
6933 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
6934 m.tex[1] = R_GetTexture(layer->texture);
6935 m.texmatrix[1] = layer->texmatrix;
6936 m.texrgbscale[1] = layertexrgbscale;
6937 m.pointer_texcoord[1] = rsurface.texcoordtexture2f;
6938 m.pointer_texcoord_bufferobject[1] = rsurface.texcoordtexture2f_bufferobject;
6939 m.pointer_texcoord_bufferoffset[1] = rsurface.texcoordtexture2f_bufferoffset;
6940 R_Mesh_TextureState(&m);
6941 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
6942 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
6943 else if (rsurface.uselightmaptexture)
6944 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
6946 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
6948 case TEXTURELAYERTYPE_TEXTURE:
6949 memset(&m, 0, sizeof(m));
6950 m.tex[0] = R_GetTexture(layer->texture);
6951 m.texmatrix[0] = layer->texmatrix;
6952 m.texrgbscale[0] = layertexrgbscale;
6953 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6954 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6955 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6956 R_Mesh_TextureState(&m);
6957 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
6959 case TEXTURELAYERTYPE_FOG:
6960 memset(&m, 0, sizeof(m));
6961 m.texrgbscale[0] = layertexrgbscale;
6964 m.tex[0] = R_GetTexture(layer->texture);
6965 m.texmatrix[0] = layer->texmatrix;
6966 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6967 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6968 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6970 R_Mesh_TextureState(&m);
6971 // generate a color array for the fog pass
6972 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
6973 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6977 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6978 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)
6980 f = 1 - FogPoint_Model(v);
6981 c[0] = layercolor[0];
6982 c[1] = layercolor[1];
6983 c[2] = layercolor[2];
6984 c[3] = f * layercolor[3];
6987 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6990 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
6992 GL_LockArrays(0, 0);
6995 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
6997 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
6998 GL_AlphaTest(false);
7002 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
7004 // OpenGL 1.1 - crusty old voodoo path
7005 int texturesurfaceindex;
7009 const texturelayer_t *layer;
7010 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
7012 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
7014 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7016 if (layerindex == 0)
7020 GL_AlphaTest(false);
7021 qglDepthFunc(GL_EQUAL);CHECKGLERROR
7024 GL_DepthMask(layer->depthmask && writedepth);
7025 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
7026 R_Mesh_ColorPointer(NULL, 0, 0);
7027 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
7028 switch (layer->type)
7030 case TEXTURELAYERTYPE_LITTEXTURE:
7031 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
7033 // two-pass lit texture with 2x rgbscale
7034 // first the lightmap pass
7035 memset(&m, 0, sizeof(m));
7036 m.tex[0] = R_GetTexture(r_texture_white);
7037 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
7038 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
7039 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
7040 R_Mesh_TextureState(&m);
7041 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7042 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
7043 else if (rsurface.uselightmaptexture)
7044 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
7046 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
7047 GL_LockArrays(0, 0);
7048 // then apply the texture to it
7049 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
7050 memset(&m, 0, sizeof(m));
7051 m.tex[0] = R_GetTexture(layer->texture);
7052 m.texmatrix[0] = layer->texmatrix;
7053 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7054 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7055 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7056 R_Mesh_TextureState(&m);
7057 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);
7061 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
7062 memset(&m, 0, sizeof(m));
7063 m.tex[0] = R_GetTexture(layer->texture);
7064 m.texmatrix[0] = layer->texmatrix;
7065 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7066 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7067 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7068 R_Mesh_TextureState(&m);
7069 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7070 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);
7072 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);
7075 case TEXTURELAYERTYPE_TEXTURE:
7076 // singletexture unlit texture with transparency support
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);
7084 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);
7086 case TEXTURELAYERTYPE_FOG:
7087 // singletexture fogging
7088 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
7091 memset(&m, 0, sizeof(m));
7092 m.tex[0] = R_GetTexture(layer->texture);
7093 m.texmatrix[0] = layer->texmatrix;
7094 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7095 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7096 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7097 R_Mesh_TextureState(&m);
7100 R_Mesh_ResetTextureState();
7101 // generate a color array for the fog pass
7102 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7106 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7107 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)
7109 f = 1 - FogPoint_Model(v);
7110 c[0] = layer->color[0];
7111 c[1] = layer->color[1];
7112 c[2] = layer->color[2];
7113 c[3] = f * layer->color[3];
7116 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7119 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
7121 GL_LockArrays(0, 0);
7124 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7126 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
7127 GL_AlphaTest(false);
7131 static void R_DrawTextureSurfaceList_ShowSurfaces3(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
7135 GL_AlphaTest(false);
7136 R_Mesh_ColorPointer(NULL, 0, 0);
7137 R_Mesh_ResetTextureState();
7138 R_SetupGenericShader(false);
7140 if(rsurface.texture && rsurface.texture->currentskinframe)
7142 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
7143 c[3] *= rsurface.texture->currentalpha;
7153 if (rsurface.texture->currentskinframe->pants || rsurface.texture->currentskinframe->shirt)
7155 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
7156 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
7157 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
7160 // brighten it up (as texture value 127 means "unlit")
7161 c[0] *= 2 * r_refdef.view.colorscale;
7162 c[1] *= 2 * r_refdef.view.colorscale;
7163 c[2] *= 2 * r_refdef.view.colorscale;
7165 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
7166 c[3] *= r_wateralpha.value;
7168 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
7170 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7171 GL_DepthMask(false);
7173 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
7175 GL_BlendFunc(GL_ONE, GL_ONE);
7176 GL_DepthMask(false);
7178 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7180 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
7181 GL_DepthMask(false);
7183 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7185 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
7186 GL_DepthMask(false);
7190 GL_BlendFunc(GL_ONE, GL_ZERO);
7191 GL_DepthMask(writedepth);
7194 rsurface.lightmapcolor4f = NULL;
7196 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7198 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7200 rsurface.lightmapcolor4f = NULL;
7201 rsurface.lightmapcolor4f_bufferobject = 0;
7202 rsurface.lightmapcolor4f_bufferoffset = 0;
7204 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7206 qboolean applycolor = true;
7209 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
7211 r_refdef.lightmapintensity = 1;
7212 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &one, &one, &one, &one, &applycolor);
7213 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
7217 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7219 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
7220 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
7221 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
7224 if(!rsurface.lightmapcolor4f)
7225 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(texturenumsurfaces, texturesurfacelist);
7227 RSurf_DrawBatch_GL11_ApplyAmbient(texturenumsurfaces, texturesurfacelist);
7228 RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, c[0], c[1], c[2], c[3]);
7229 if(r_refdef.fogenabled)
7230 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(texturenumsurfaces, texturesurfacelist);
7232 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
7233 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7236 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
7239 RSurf_SetupDepthAndCulling();
7240 if (r_showsurfaces.integer == 3)
7241 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
7242 else if (r_glsl.integer && gl_support_fragment_shader)
7243 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth);
7244 else if (gl_combine.integer && r_textureunits.integer >= 2)
7245 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
7247 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
7251 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
7254 RSurf_SetupDepthAndCulling();
7255 if (r_showsurfaces.integer == 3)
7256 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
7257 else if (r_glsl.integer && gl_support_fragment_shader)
7258 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth);
7259 else if (gl_combine.integer && r_textureunits.integer >= 2)
7260 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
7262 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
7266 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7269 int texturenumsurfaces, endsurface;
7271 msurface_t *surface;
7272 msurface_t *texturesurfacelist[1024];
7274 // if the model is static it doesn't matter what value we give for
7275 // wantnormals and wanttangents, so this logic uses only rules applicable
7276 // to a model, knowing that they are meaningless otherwise
7277 if (ent == r_refdef.scene.worldentity)
7278 RSurf_ActiveWorldEntity();
7279 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
7280 RSurf_ActiveModelEntity(ent, false, false);
7282 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
7284 for (i = 0;i < numsurfaces;i = j)
7287 surface = rsurface.modelsurfaces + surfacelist[i];
7288 texture = surface->texture;
7289 rsurface.texture = R_GetCurrentTexture(texture);
7290 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
7291 // scan ahead until we find a different texture
7292 endsurface = min(i + 1024, numsurfaces);
7293 texturenumsurfaces = 0;
7294 texturesurfacelist[texturenumsurfaces++] = surface;
7295 for (;j < endsurface;j++)
7297 surface = rsurface.modelsurfaces + surfacelist[j];
7298 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
7300 texturesurfacelist[texturenumsurfaces++] = surface;
7302 // render the range of surfaces
7303 if (ent == r_refdef.scene.worldentity)
7304 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false);
7306 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false);
7308 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7309 GL_AlphaTest(false);
7312 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly)
7314 const entity_render_t *queueentity = r_refdef.scene.worldentity;
7318 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
7320 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
7322 RSurf_SetupDepthAndCulling();
7323 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7324 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7326 else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
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);
7336 GL_Color(0, 0, 0, 1);
7337 GL_DepthTest(writedepth);
7338 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7340 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
7342 RSurf_SetupDepthAndCulling();
7343 GL_AlphaTest(false);
7344 R_Mesh_ColorPointer(NULL, 0, 0);
7345 R_Mesh_ResetTextureState();
7346 R_SetupGenericShader(false);
7347 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7349 GL_BlendFunc(GL_ONE, GL_ZERO);
7351 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
7353 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
7354 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
7355 else if (!rsurface.texture->currentnumlayers)
7357 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
7359 // transparent surfaces get pushed off into the transparent queue
7360 int surfacelistindex;
7361 const msurface_t *surface;
7362 vec3_t tempcenter, center;
7363 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
7365 surface = texturesurfacelist[surfacelistindex];
7366 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
7367 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
7368 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
7369 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
7370 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
7375 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
7376 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST));
7381 void R_QueueWorldSurfaceList(int numsurfaces, msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly)
7385 // break the surface list down into batches by texture and use of lightmapping
7386 for (i = 0;i < numsurfaces;i = j)
7389 // texture is the base texture pointer, rsurface.texture is the
7390 // current frame/skin the texture is directing us to use (for example
7391 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
7392 // use skin 1 instead)
7393 texture = surfacelist[i]->texture;
7394 rsurface.texture = R_GetCurrentTexture(texture);
7395 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
7396 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
7398 // if this texture is not the kind we want, skip ahead to the next one
7399 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
7403 // simply scan ahead until we find a different texture or lightmap state
7404 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
7406 // render the range of surfaces
7407 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly);
7411 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity)
7416 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
7418 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
7420 RSurf_SetupDepthAndCulling();
7421 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7422 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7424 else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
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);
7434 GL_Color(0, 0, 0, 1);
7435 GL_DepthTest(writedepth);
7436 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7438 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
7440 RSurf_SetupDepthAndCulling();
7441 GL_AlphaTest(false);
7442 R_Mesh_ColorPointer(NULL, 0, 0);
7443 R_Mesh_ResetTextureState();
7444 R_SetupGenericShader(false);
7445 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7447 GL_BlendFunc(GL_ONE, GL_ZERO);
7449 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
7451 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
7452 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
7453 else if (!rsurface.texture->currentnumlayers)
7455 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
7457 // transparent surfaces get pushed off into the transparent queue
7458 int surfacelistindex;
7459 const msurface_t *surface;
7460 vec3_t tempcenter, center;
7461 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
7463 surface = texturesurfacelist[surfacelistindex];
7464 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
7465 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
7466 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
7467 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
7468 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
7473 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
7474 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST));
7479 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly)
7483 // break the surface list down into batches by texture and use of lightmapping
7484 for (i = 0;i < numsurfaces;i = j)
7487 // texture is the base texture pointer, rsurface.texture is the
7488 // current frame/skin the texture is directing us to use (for example
7489 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
7490 // use skin 1 instead)
7491 texture = surfacelist[i]->texture;
7492 rsurface.texture = R_GetCurrentTexture(texture);
7493 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
7494 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
7496 // if this texture is not the kind we want, skip ahead to the next one
7497 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
7501 // simply scan ahead until we find a different texture or lightmap state
7502 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
7504 // render the range of surfaces
7505 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent);
7509 float locboxvertex3f[6*4*3] =
7511 1,0,1, 1,0,0, 1,1,0, 1,1,1,
7512 0,1,1, 0,1,0, 0,0,0, 0,0,1,
7513 1,1,1, 1,1,0, 0,1,0, 0,1,1,
7514 0,0,1, 0,0,0, 1,0,0, 1,0,1,
7515 0,0,1, 1,0,1, 1,1,1, 0,1,1,
7516 1,0,0, 0,0,0, 0,1,0, 1,1,0
7519 unsigned short locboxelements[6*2*3] =
7529 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7532 cl_locnode_t *loc = (cl_locnode_t *)ent;
7534 float vertex3f[6*4*3];
7536 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7537 GL_DepthMask(false);
7538 GL_DepthRange(0, 1);
7539 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7541 GL_CullFace(GL_NONE);
7542 R_Mesh_Matrix(&identitymatrix);
7544 R_Mesh_VertexPointer(vertex3f, 0, 0);
7545 R_Mesh_ColorPointer(NULL, 0, 0);
7546 R_Mesh_ResetTextureState();
7547 R_SetupGenericShader(false);
7550 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
7551 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
7552 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
7553 surfacelist[0] < 0 ? 0.5f : 0.125f);
7555 if (VectorCompare(loc->mins, loc->maxs))
7557 VectorSet(size, 2, 2, 2);
7558 VectorMA(loc->mins, -0.5f, size, mins);
7562 VectorCopy(loc->mins, mins);
7563 VectorSubtract(loc->maxs, loc->mins, size);
7566 for (i = 0;i < 6*4*3;)
7567 for (j = 0;j < 3;j++, i++)
7568 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
7570 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, locboxelements, 0, 0);
7573 void R_DrawLocs(void)
7576 cl_locnode_t *loc, *nearestloc;
7578 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
7579 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
7581 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
7582 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
7586 void R_DrawDebugModel(entity_render_t *ent)
7588 int i, j, k, l, flagsmask;
7589 const int *elements;
7591 msurface_t *surface;
7592 dp_model_t *model = ent->model;
7595 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
7597 R_Mesh_ColorPointer(NULL, 0, 0);
7598 R_Mesh_ResetTextureState();
7599 R_SetupGenericShader(false);
7600 GL_DepthRange(0, 1);
7601 GL_DepthTest(!r_showdisabledepthtest.integer);
7602 GL_DepthMask(false);
7603 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7605 if (r_showcollisionbrushes.value > 0 && model->brush.num_brushes)
7607 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
7608 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
7610 if (brush->colbrushf && brush->colbrushf->numtriangles)
7612 R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
7613 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);
7614 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, 0);
7617 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
7619 if (surface->num_collisiontriangles)
7621 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
7622 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);
7623 R_Mesh_Draw(0, surface->num_collisionvertices, 0, surface->num_collisiontriangles, surface->data_collisionelement3i, NULL, 0, 0);
7628 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7630 if (r_showtris.integer || r_shownormals.integer)
7632 if (r_showdisabledepthtest.integer)
7634 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7635 GL_DepthMask(false);
7639 GL_BlendFunc(GL_ONE, GL_ZERO);
7642 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
7644 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
7646 rsurface.texture = R_GetCurrentTexture(surface->texture);
7647 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
7649 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
7650 if (r_showtris.value > 0)
7652 if (!rsurface.texture->currentlayers->depthmask)
7653 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
7654 else if (ent == r_refdef.scene.worldentity)
7655 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
7657 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
7658 elements = (ent->model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
7659 R_Mesh_VertexPointer(rsurface.vertex3f, 0, 0);
7660 R_Mesh_ColorPointer(NULL, 0, 0);
7661 R_Mesh_TexCoordPointer(0, 0, NULL, 0, 0);
7662 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7663 //R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, ent->model->surfmesh.data_element3i, NULL, 0, 0);
7664 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);
7665 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7668 if (r_shownormals.value < 0)
7671 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
7673 VectorCopy(rsurface.vertex3f + l * 3, v);
7674 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
7675 qglVertex3f(v[0], v[1], v[2]);
7676 VectorMA(v, -r_shownormals.value, rsurface.svector3f + l * 3, v);
7677 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
7678 qglVertex3f(v[0], v[1], v[2]);
7683 if (r_shownormals.value > 0)
7686 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
7688 VectorCopy(rsurface.vertex3f + l * 3, v);
7689 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
7690 qglVertex3f(v[0], v[1], v[2]);
7691 VectorMA(v, r_shownormals.value, rsurface.svector3f + l * 3, v);
7692 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
7693 qglVertex3f(v[0], v[1], v[2]);
7698 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
7700 VectorCopy(rsurface.vertex3f + l * 3, v);
7701 GL_Color(0, r_refdef.view.colorscale, 0, 1);
7702 qglVertex3f(v[0], v[1], v[2]);
7703 VectorMA(v, r_shownormals.value, rsurface.tvector3f + l * 3, v);
7704 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
7705 qglVertex3f(v[0], v[1], v[2]);
7710 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
7712 VectorCopy(rsurface.vertex3f + l * 3, v);
7713 GL_Color(0, 0, r_refdef.view.colorscale, 1);
7714 qglVertex3f(v[0], v[1], v[2]);
7715 VectorMA(v, r_shownormals.value, rsurface.normal3f + l * 3, v);
7716 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
7717 qglVertex3f(v[0], v[1], v[2]);
7724 rsurface.texture = NULL;
7728 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
7729 int r_maxsurfacelist = 0;
7730 msurface_t **r_surfacelist = NULL;
7731 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug)
7733 int i, j, endj, f, flagsmask;
7735 dp_model_t *model = r_refdef.scene.worldmodel;
7736 msurface_t *surfaces;
7737 unsigned char *update;
7738 int numsurfacelist = 0;
7742 if (r_maxsurfacelist < model->num_surfaces)
7744 r_maxsurfacelist = model->num_surfaces;
7746 Mem_Free(r_surfacelist);
7747 r_surfacelist = (msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
7750 RSurf_ActiveWorldEntity();
7752 surfaces = model->data_surfaces;
7753 update = model->brushq1.lightmapupdateflags;
7755 // update light styles on this submodel
7756 if (!skysurfaces && !depthonly && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
7758 model_brush_lightstyleinfo_t *style;
7759 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
7761 if (style->value != r_refdef.scene.lightstylevalue[style->style])
7763 int *list = style->surfacelist;
7764 style->value = r_refdef.scene.lightstylevalue[style->style];
7765 for (j = 0;j < style->numsurfaces;j++)
7766 update[list[j]] = true;
7771 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
7775 R_DrawDebugModel(r_refdef.scene.worldentity);
7776 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7782 rsurface.uselightmaptexture = false;
7783 rsurface.texture = NULL;
7784 rsurface.rtlight = NULL;
7786 // add visible surfaces to draw list
7787 for (i = 0;i < model->nummodelsurfaces;i++)
7789 j = model->sortedmodelsurfaces[i];
7790 if (r_refdef.viewcache.world_surfacevisible[j])
7791 r_surfacelist[numsurfacelist++] = surfaces + j;
7793 // update lightmaps if needed
7795 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
7796 if (r_refdef.viewcache.world_surfacevisible[j])
7798 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
7799 // don't do anything if there were no surfaces
7800 if (!numsurfacelist)
7802 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7805 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly);
7806 GL_AlphaTest(false);
7808 // add to stats if desired
7809 if (r_speeds.integer && !skysurfaces && !depthonly)
7811 r_refdef.stats.world_surfaces += numsurfacelist;
7812 for (j = 0;j < numsurfacelist;j++)
7813 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
7815 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7818 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug)
7820 int i, j, endj, f, flagsmask;
7822 dp_model_t *model = ent->model;
7823 msurface_t *surfaces;
7824 unsigned char *update;
7825 int numsurfacelist = 0;
7829 if (r_maxsurfacelist < model->num_surfaces)
7831 r_maxsurfacelist = model->num_surfaces;
7833 Mem_Free(r_surfacelist);
7834 r_surfacelist = (msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
7837 // if the model is static it doesn't matter what value we give for
7838 // wantnormals and wanttangents, so this logic uses only rules applicable
7839 // to a model, knowing that they are meaningless otherwise
7840 if (ent == r_refdef.scene.worldentity)
7841 RSurf_ActiveWorldEntity();
7842 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
7843 RSurf_ActiveModelEntity(ent, false, false);
7845 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader && !depthonly);
7847 surfaces = model->data_surfaces;
7848 update = model->brushq1.lightmapupdateflags;
7850 // update light styles
7851 if (!skysurfaces && !depthonly && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
7853 model_brush_lightstyleinfo_t *style;
7854 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
7856 if (style->value != r_refdef.scene.lightstylevalue[style->style])
7858 int *list = style->surfacelist;
7859 style->value = r_refdef.scene.lightstylevalue[style->style];
7860 for (j = 0;j < style->numsurfaces;j++)
7861 update[list[j]] = true;
7866 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
7870 R_DrawDebugModel(ent);
7871 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7877 rsurface.uselightmaptexture = false;
7878 rsurface.texture = NULL;
7879 rsurface.rtlight = NULL;
7881 // add visible surfaces to draw list
7882 for (i = 0;i < model->nummodelsurfaces;i++)
7883 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
7884 // don't do anything if there were no surfaces
7885 if (!numsurfacelist)
7887 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7890 // update lightmaps if needed
7892 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
7894 R_BuildLightMap(ent, surfaces + j);
7895 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly);
7896 GL_AlphaTest(false);
7898 // add to stats if desired
7899 if (r_speeds.integer && !skysurfaces && !depthonly)
7901 r_refdef.stats.entities_surfaces += numsurfacelist;
7902 for (j = 0;j < numsurfacelist;j++)
7903 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
7905 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity